- Fixed USB issues. REPL & CIRCUITPY: drive now function correctly! - Fixed bugs with Internal Flash filesystem. Files now write & read back correctly. - Added copyright headers for all files.

This commit is contained in:
Hurst, Brandon 2024-09-05 17:48:38 -06:00 committed by Brandon Hurst
parent e6c4c78813
commit 0fa04e9ff1
27 changed files with 278 additions and 215 deletions

View file

@ -1,6 +1,7 @@
# This file is part of the CircuitPython project: https://circuitpython.org
#
# SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
# SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc.
#
# SPDX-License-Identifier: MIT

View file

@ -38,7 +38,9 @@ Universal instructions on flashing MAX32 devices this project can be found in th
In addition, a user may flash the device by calling `make` with the `flash-msdk` target from within the `ports/analog` directory, as below:
$ make BOARD=<target board> flash-msdk
```
$ make BOARD=<target board> flash-msdk
```
This requires the following:
- A MAX32625PICO is connected to the PC via USB
@ -48,4 +50,10 @@ This requires the following:
### Using the REPL
[**Section in Progress. USB support needs implementation & test.**]
Once the device is plugged in, it will enumerate via USB as both a USB Serial Device (CDC) and a Mass Storage Device (MSC). You can connect to the Python REPL with your favorite Serial Monitor program e.g. TeraTerm, VS Code, Putty, etc. Use any buadrate with 8-bit, No Parity, 1 Stop Bit (8N1) settings. From this point forward, you can run Python code on the MCU! If you want help with learning CircuitPython-specific code or learning Python in general, a good place to start is Adafruit's ["Welcome to CircuitPython"](https://learn.adafruit.com/welcome-to-circuitpython/) guide.
### Editing code.py
Python code may be executed from `code.py` the `CIRCUITPY:` drive. When editing this file, please be aware that some text editors will work better than others. A list of suggested text editors can be found at Adafruit's guide here: https://learn.adafruit.com/welcome-to-circuitpython/recommended-editors
Once you save `code.py`, it gets written back to the device you are running Circuitpython on, and will automatically run and output it's result to the REPL. You can also automatically reload and run code.py any time from the REPL by pressing CTRL+D.

View file

@ -1,6 +1,7 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc.
//
// SPDX-License-Identifier: MIT

View file

@ -1,6 +1,7 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries
// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc.
//
// SPDX-License-Identifier: MIT

View file

@ -12,3 +12,25 @@ For more info about AD-APARD32690-SL, visit our product webpages for datasheets,
[AD-APARD32690-SL Product Webpage](https://www.analog.com/en/resources/evaluation-hardware-and-software/evaluation-boards-kits/ad-apard32690-sl.html)
[AD-APARD32690-SL User Guide](https://wiki.analog.com/resources/eval/user-guides/ad-apard32690-sl)
#### Building for this board
To build for this board, ensure you are in the `ports/analog` directory and run the following command. Note that passing in the `-jN` flag, where N is the # of cores on your machine, can speed up compile times.
```
make BOARD=APARD
```
#### Flashing this board
To flash the board, run the following command if using the MAX32625PICO:
```
make BOARD=APARD flash-msdk
```
If using Segger JLink, please run the following command instead:
```
make BOARD=APARD flash-jlink
```

View file

@ -1,6 +1,6 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc
//
// SPDX-License-Identifier: MIT
@ -26,7 +26,7 @@ const int num_leds = (sizeof(led_pin) / sizeof(mxc_gpio_cfg_t));
// DEFAULT: Using the weak-defined supervisor/shared/board.c functions
/***** OPTIONAL BOARD-SPECIFIC FUNTIONS from supervisor/board.h *****/
/***** OPTIONAL BOARD-SPECIFIC FUNCTIONS from supervisor/board.h *****/
// Returns true if the user initiates safe mode in a board specific way.
// Also add BOARD_USER_SAFE_MODE in mpconfigboard.h to explain the board specific
// way.

View file

@ -1,6 +1,7 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices Inc.
//
// SPDX-License-Identifier: MIT
@ -20,18 +21,18 @@
#define FLASH_SIZE (0x300000) // 3MiB
#define FLASH_PAGE_SIZE (0x4000) // 16384 byte pages (16 KiB)
#define BOARD_HAS_CRYSTAL 1
#define BOARD_HAS_CRYSTAL 1
#define NUM_GPIO_PORTS 4
#define CONSOLE_UART MXC_UART0
#define NUM_GPIO_PORTS 4
#if INTERNAL_FLASH_FILESYSTEM
#define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_START_ADDR (0x102FC000) // for MAX32690
#define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE (64 * 1024) // 64K
// #if INTERNAL_FLASH_FILESYSTEM
#define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_START_ADDR (0x102E0000) // for MAX32690
#define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE (128 * 1024) // 64K
#define MAX32_FLASH_SIZE 0x300000 // 3 MiB
#define INTERNAL_FLASH_FILESYSTEM_SIZE 0x10000 // 64KiB
#define INTERNAL_FLASH_FILESYSTEM_START_ADDR 0x102FC000 // Load into the last MiB of code/data storage
#define INTERNAL_FLASH_FILESYSTEM_SIZE CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE
#define INTERNAL_FLASH_FILESYSTEM_START_ADDR 0x102E0000 // Load into the last MiB of code/data storage
#else
#define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE (0)
#endif
// #else
// #define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE (0)
// #endif

View file

@ -1,6 +1,7 @@
# This file is part of the CircuitPython project: https://circuitpython.org
#
# SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
# SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc
#
# SPDX-License-Identifier: MIT

View file

@ -1,6 +1,7 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc.
//
// SPDX-License-Identifier: MIT

View file

@ -1,3 +1,8 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc
//
// SPDX-License-Identifier: MIT
#include <stdbool.h>

View file

@ -1,3 +1,8 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc
//
// SPDX-License-Identifier: MIT
#pragma once

View file

@ -1,4 +1,8 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc
//
// SPDX-License-Identifier: MIT
#include <math.h>
#include "py/runtime.h"

View file

@ -2,6 +2,7 @@
//
// SPDX-FileCopyrightText: Copyright (c) 2016 Scott Shawcroft for Adafruit Industries
// SPDX-FileCopyrightText: Copyright (c) 2019 Lucian Copeland for Adafruit Industries
// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc
//
// SPDX-License-Identifier: MIT

View file

@ -1,9 +1,15 @@
/** This file is part of the CircuitPython project: https://circuitpython.org
*
* SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices Inc.
*
* SPDX-License-Identifier: MIT
*/
MEMORY {
ROM (rx) : ORIGIN = 0x00000000, LENGTH = 128K
FLASH (rx) : ORIGIN = 0x10000000, LENGTH = 3M
FLASH_FIRMWARE (rx) : ORIGIN = 0x10000000, LENGTH = 2992K
FLASH_ISR (rx) : ORIGIN = 0x102EC000, LENGTH = 16K
FLASH_FS (rx) : ORIGIN = 0x102FC000, LENGTH = 64K
FLASH_FS (rx) : ORIGIN = 0x102E0000, LENGTH = 128K
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 1M
}
/* Minimum flash page is 16K */

View file

@ -1,3 +1,8 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc.
//
// SPDX-License-Identifier: MIT
#ifndef MAX32_PORT_H
#define MAX32_PORT_H

View file

@ -1,6 +1,7 @@
# This file is part of the CircuitPython project: https://circuitpython.org
#
# SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
# SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc.
#
# SPDX-License-Identifier: MIT
@ -14,11 +15,6 @@ INTERNAL_LIBM ?= 1
CFLAGS += -DHAS_TRNG=1
INTERNAL_FLASH_FILESYSTEM = 1
SPI_FLASH_FILESYSTEM = 0
QSPI_FLASH_FILESYSTEM = 0
# TODO: Test/Debug FS
DISABLE_FILESYSTEM = 0
####################################################################################
# Suggested config for first-time porting

View file

@ -1,3 +1,8 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc
//
// SPDX-License-Identifier: MIT
#include "mphalport.h"
#include "py/mphal.h"

View file

@ -1,6 +1,6 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst
// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc
//
// SPDX-License-Identifier: MIT

View file

@ -0,0 +1,5 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc.
//
// SPDX-License-Identifier: MIT

View file

@ -1,3 +1,9 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc.
//
// SPDX-License-Identifier: MIT
#include "py/obj.h"
#include "py/mphal.h"
#include "peripherals/pins.h"

View file

@ -1,3 +1,9 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc.
//
// SPDX-License-Identifier: MIT
#pragma once
extern const mcu_pin_obj_t pin_P0_00;

View file

@ -1,4 +1,8 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc.
//
// SPDX-License-Identifier: MIT
#pragma once

View file

@ -1,3 +1,10 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc
//
// SPDX-License-Identifier: MIT
.syntax unified
.cpu cortex-m4
.thumb

View file

@ -1,8 +1,16 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
// SPDX-FileCopyrightText: Copyright (c) 2020 Lucian Copeland for Adafruit Industries
// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc.
//
// SPDX-License-Identifier: MIT
#include "supervisor/internal_flash.h"
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "extmod/vfs.h"
#include "extmod/vfs_fat.h"
@ -14,20 +22,19 @@
#include "supervisor/filesystem.h"
#include "supervisor/flash.h"
#include "supervisor/shared/safe_mode.h"
#if CIRCUITPY_USB_DEVICE
#include "supervisor/usb.h"
#endif
#include "mpconfigboard.h"
// MAX32 HAL Includes
#include "flc.h"
#include "flc_reva.h"
#include "icc.h" // includes icc_<dietype>.c for MSDK die type
#include "mxc_device.h"
/** TODO:
* Test!
*
/**
* NOTE:
* ANY function which modifies flash contents must execute from a crit section.
* This is because FLC functions are loc'd in RAM, and an ISR executing
@ -44,13 +51,10 @@
* Therefore only ICC0 need be used for the purpose of these functions.
*/
#define NO_CACHE 0xffffffff
#define MAX_CACHE 0x4000
typedef struct {
uint32_t base_addr;
uint32_t sector_size;
uint32_t num_sectors;
const uint32_t base_addr;
const uint32_t sector_size;
const uint32_t num_sectors;
} flash_layout_t;
#ifdef MAX32690
@ -58,15 +62,15 @@ typedef struct {
// FS Code will use INTERNAL_FLASH_FILESYSTEM_START_ADDR
// and won't conflict with ISR vector in first 16 KiB of flash
static const flash_layout_t flash_layout[] = {
{ 0x10000000, 0x4000, 192},
{ 0x10000000, FLASH_PAGE_SIZE, 192},
// { 0x10300000, 0x2000, 32 }, // RISC-V flash
};
// Cache a full 16K sector
static uint8_t _flash_cache[0x4000] __attribute__((aligned(4)));
#endif
// must be able to hold a full page (for re-writing upon erase)
static uint32_t page_buffer[FLASH_PAGE_SIZE / 4] = {0x0};
// Address of the flash sector currently being cached
static uint32_t _cache_addr_in_flash = NO_CACHE;
#else
#error "Invalid BOARD. Please set BOARD equal to any board under 'boards/'."
#endif
static inline int32_t block2addr(uint32_t block) {
if (block >= 0 && block < INTERNAL_FLASH_FILESYSTEM_NUM_BLOCKS) {
@ -135,165 +139,13 @@ uint32_t supervisor_flash_get_block_count(void) {
return INTERNAL_FLASH_FILESYSTEM_NUM_BLOCKS;
}
// Write back to Flash the page that is currently cached
void port_internal_flash_flush(void) {
// Flash has not been cached
if (_cache_addr_in_flash == NO_CACHE) {
return;
}
uint32_t sector_start, sector_size = 0xffffffff;
// Clear & enable flash interrupt flags
MXC_FLC_EnableInt(MXC_F_FLC_INTR_DONEIE | MXC_F_FLC_INTR_AFIE);
// Figure out the sector of flash we're targeting
if (flash_get_sector_info(_cache_addr_in_flash, &sector_start, &sector_size) == -1) {
// If not in valid sector, just release the cache and return
supervisor_flash_release_cache();
return;
}
// if invalid sector or sector size > the size of our cache, reset with flash fail
if (sector_size > sizeof(_flash_cache) || sector_start == 0xffffffff) {
reset_into_safe_mode(SAFE_MODE_FLASH_WRITE_FAIL);
}
// skip if the data in cache is the same as what's already there
if (memcmp(_flash_cache, (void *)_cache_addr_in_flash, FLASH_PAGE_SIZE) != 0) {
uint32_t error;
// buffer for the page of flash
uint32_t page_buffer[FLASH_PAGE_SIZE >> 2] = {
0xFFFFFFFF
}; // bytes per page / 4 bytes = # of uint32_t
// Unlock Flash
MXC_FLC0->ctrl = (MXC_FLC0->ctrl & ~MXC_F_FLC_REVA_CTRL_UNLOCK) | MXC_S_FLC_REVA_CTRL_UNLOCK_UNLOCKED;
/*** ERASE FLASH PAGE ***/
MXC_CRITICAL(
// buffer the page
MXC_FLC_Read(sector_start, page_buffer, sector_size);
// Erase page & error check
error = MXC_FLC_PageErase(sector_start);
);
if (error != E_NO_ERROR) {
// lock flash & reset
MXC_FLC0->ctrl = (MXC_FLC0->ctrl & ~MXC_F_FLC_REVA_CTRL_UNLOCK) | MXC_S_FLC_REVA_CTRL_UNLOCK_LOCKED;
reset_into_safe_mode(SAFE_MODE_FLASH_WRITE_FAIL);
}
/*** RE-WRITE FLASH PAGE w/ CACHE DATA ***/
MXC_CRITICAL(
// ret = program the flash page with cache data (for loop)
for (uint32_t i = 0; i < (sector_size >> 2); i++) {
error = MXC_FLC_Write32(_cache_addr_in_flash + 4 * i, _flash_cache[i]);
}
);
if (error != E_NO_ERROR) {
// lock flash & reset
MXC_FLC0->ctrl = (MXC_FLC0->ctrl & ~MXC_F_FLC_REVA_CTRL_UNLOCK) | MXC_S_FLC_REVA_CTRL_UNLOCK_LOCKED;
reset_into_safe_mode(SAFE_MODE_FLASH_WRITE_FAIL);
}
// Lock flash & exit
MXC_FLC0->ctrl = (MXC_FLC0->ctrl & ~MXC_F_FLC_REVA_CTRL_UNLOCK) | MXC_S_FLC_REVA_CTRL_UNLOCK_LOCKED;
} // finished flushing cache
// todo: verify no other flash operation (e.g. flushing HW cache) is needed to complete this
}
// Read flash blocks, using cache if it contains the right data
mp_uint_t supervisor_flash_read_blocks(uint8_t *dest, uint32_t block, uint32_t num_blocks) {
// Find the address of the block we want to read
int src_addr = block2addr(block);
if (src_addr == -1) {
// bad block num
return false;
}
uint32_t sector_size, sector_start;
if (flash_get_sector_info(src_addr, &sector_start, &sector_size) == -1) {
// bad sector idx
return false;
}
// Find how many blocks left in sector
uint32_t blocks_in_sector = (sector_size - (src_addr - sector_start)) / FILESYSTEM_BLOCK_SIZE;
// If the whole read is inside the cache, then read cache
if ( (num_blocks <= blocks_in_sector) && (_cache_addr_in_flash == sector_start) ) {
memcpy(dest, (_flash_cache + (src_addr - sector_start)), FILESYSTEM_BLOCK_SIZE * num_blocks);
} else {
// flush the cache & read the flash data directly
supervisor_flash_flush();
/** NOTE: The MXC_FLC_Read function executes from SRAM and does some more error checking
* than memcpy does. Will use it for now.
*/
MXC_FLC_Read((int)dest, (int *)src_addr, FILESYSTEM_BLOCK_SIZE * num_blocks);
}
return 0; // success
}
// Write to flash blocks, using cache if it is targeting the right page (and large enough)
// todo: most of this fn is taken from the ST driver.
// todo: look at other ports and see if I can adapt it at all
mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) {
uint32_t count=0;
uint32_t sector_size=0;
uint32_t sector_start=0;
while (num_blocks > 0) {
const int32_t dest_addr = block2addr(block_num);
// bad block number passed in
if (dest_addr == -1) {
return false;
}
// Implementation is from STM port
// NOTE: May replace later, but this port had a method
// that seemed to make sense across multiple devices.
if (flash_get_sector_info(dest_addr, &sector_start, &sector_size) == -1) {
reset_into_safe_mode(SAFE_MODE_FLASH_WRITE_FAIL);
}
// fail if sector size is greater than cache size
if (sector_size > sizeof(_flash_cache)) {
reset_into_safe_mode(SAFE_MODE_FLASH_WRITE_FAIL);
}
// Find the number of blocks left within this sector
// BLOCK_NUM = (SECTOR SIZE - BLOCK OFFSET within sector)) / BLOCK_SIZE
count = (sector_size - (dest_addr - sector_start)) / FILESYSTEM_BLOCK_SIZE;
count = MIN(num_blocks, count);
// if we're not at the start of a sector, copy the whole sector to cache
if (_cache_addr_in_flash != sector_start) {
// Flush cache first before we overwrite it
supervisor_flash_flush();
_cache_addr_in_flash = sector_start;
// Copy the whole sector into cache
memcpy(_flash_cache, (void *)sector_start, sector_size);
}
// Overwrite the cache with source data passed in
memcpy(_flash_cache + (dest_addr - sector_start), src, count * FILESYSTEM_BLOCK_SIZE);
block_num += count;
src += count * FILESYSTEM_BLOCK_SIZE;
num_blocks -= count;
}
return 0; // success
}
// Empty the fs cache
void supervisor_flash_release_cache(void) {
// Invalidate the current FS cache
_cache_addr_in_flash = NO_CACHE;
// Flush the hardware cache for ARM M4
// Flush all instruction cache
// ME18 has bug where top-level sysctrl flush bit only works one.
// Have to use low-level flush bits for each ICC instance.
MXC_ICC_Flush(MXC_ICC0);
MXC_ICC_Flush(MXC_ICC1);
// Clear the line fill buffer by reading 2 pages from flash
volatile uint32_t *line_addr;
@ -304,3 +156,92 @@ void supervisor_flash_release_cache(void) {
line = *line_addr;
(void)line; // Silence build warnings that this variable is not used.
}
// Read flash blocks, using cache if it contains the right data
// return 0 on success, non-zero on error
mp_uint_t supervisor_flash_read_blocks(uint8_t *dest, uint32_t block, uint32_t num_blocks) {
// Find the address of the block we want to read
int src_addr = block2addr(block);
if (src_addr == -1) {
// bad block num
return 1;
}
uint32_t sector_size, sector_start;
if (flash_get_sector_info(src_addr, &sector_start, &sector_size) == -1) {
// bad sector idx
return 2;
}
/** NOTE: The MXC_FLC_Read function executes from SRAM and does some more error checking
* than memcpy does. Will use it for now.
*/
MXC_FLC_Read( src_addr, dest, FILESYSTEM_BLOCK_SIZE * num_blocks );
return 0; // success
}
// Write to flash blocks
// return 0 on success, non-zero on error
mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) {
uint32_t error, blocks_left, count, page_start, page_size = 0;
while (num_blocks > 0) {
uint32_t dest_addr = block2addr(block_num);
// bad block number passed in
if (dest_addr == -1) {
return 1;
}
if (flash_get_sector_info(dest_addr, &page_start, &page_size) == -1) {
reset_into_safe_mode(SAFE_MODE_FLASH_WRITE_FAIL);
}
// Find the number of blocks left within this sector
// BLOCKS_LEFT = (SECTOR_SIZE - BLOCK_OFFSET within sector)) / BLOCK_SIZE
blocks_left = (page_size - (dest_addr - page_start)) / FILESYSTEM_BLOCK_SIZE;
count = MIN(num_blocks, blocks_left);
MXC_ICC_Disable(MXC_ICC0);
// Buffer the page of flash to erase
MXC_FLC_Read(page_start , page_buffer, page_size);
// Erase flash page
MXC_CRITICAL(
error = MXC_FLC_PageErase(dest_addr);
);
if (error != E_NO_ERROR) {
// lock flash & reset
MXC_FLC0->ctrl = (MXC_FLC0->ctrl & ~MXC_F_FLC_REVA_CTRL_UNLOCK) | MXC_S_FLC_REVA_CTRL_UNLOCK_LOCKED;
reset_into_safe_mode(SAFE_MODE_FLASH_WRITE_FAIL);
}
// Copy new src data into the page buffer
// fill the new data in at the offset dest_addr - page_start
// account for uint32_t page_buffer vs uint8_t src
memcpy( (page_buffer + (dest_addr - page_start) / 4), src, count * FILESYSTEM_BLOCK_SIZE);
// Write new page buffer back into flash
MXC_CRITICAL(
error = MXC_FLC_Write(page_start, page_size, page_buffer);
);
if (error != E_NO_ERROR) {
// lock flash & reset
MXC_FLC0->ctrl = (MXC_FLC0->ctrl & ~MXC_F_FLC_REVA_CTRL_UNLOCK) | MXC_S_FLC_REVA_CTRL_UNLOCK_LOCKED;
reset_into_safe_mode(SAFE_MODE_FLASH_WRITE_FAIL);
}
MXC_ICC_Enable(MXC_ICC0);
block_num += count;
src += count * FILESYSTEM_BLOCK_SIZE;
num_blocks -= count;
}
return 0; // success
}
// Empty the fs cache
void supervisor_flash_release_cache(void) {
supervisor_flash_flush();
}

View file

@ -1,3 +1,9 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc.
//
// SPDX-License-Identifier: MIT
#pragma once

View file

@ -2,6 +2,7 @@
//
// SPDX-FileCopyrightText: Copyright (c) 2017, 2018 Scott Shawcroft for Adafruit Industries
// SPDX-FileCopyrightText: Copyright (c) 2019 Lucian Copeland for Adafruit Industries
// SPDX-FileCopyrightText: Copyright (c) Brandon Hurst, Analog Devices, Inc.
//
// SPDX-License-Identifier: MIT
@ -9,25 +10,24 @@
#include <string.h>
#include "supervisor/shared/serial.h"
#include "uart.h"
#include "uart_regs.h"
#ifndef MAX32_SERIAL
#define MAX32_SERIAL 0
#endif
#if MAX32_SERIAL
// TODO: Switch this to using DEBUG_UART.
#ifdef MAX32690
#define CONSOLE_UART MXC_UART0
#endif
#endif
void port_serial_init(void) {
#if MAX32_SERIAL
// huart2.Instance = USART2;
// huart2.Init.BaudRate = 115200;
// huart2.Init.WordLength = UART_WORDLENGTH_8B;
// huart2.Init.StopBits = UART_STOPBITS_1;
// huart2.Init.Parity = UART_PARITY_NONE;
// huart2.Init.Mode = UART_MODE_TX_RX;
// huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
// huart2.Init.OverSampling = UART_OVERSAMPLING_16;
// if (HAL_UART_Init(&huart2) == HAL_OK) {
// stm32f4_peripherals_status_led(1, 1);
// }
MXC_GCR->clkctrl |= MXC_F_GCR_CLKCTRL_IBRO_EN;
while( !(MXC_GCR->clkctrl & MXC_F_GCR_CLKCTRL_IBRO_RDY) );
MXC_UART_Init(CONSOLE_UART, 115200, MXC_UART_IBRO_CLK);
#endif
}
@ -40,15 +40,27 @@ char port_serial_read(void) {
// uint8_t data;
// HAL_UART_Receive(&huart2, &data, 1, 500);
// return data;
uint8_t rData;
mxc_uart_req_t uart_req = {
.uart = CONSOLE_UART,
.rxCnt = 0,
.txCnt = 0,
.txData = NULL,
.rxData = &rData,
.txLen = 0,
.rxLen = 1
};
MXC_UART_Transaction(&uart_req);
return rData;
#else
return -1;
#endif
}
// There is no easy way to find the number of pending characters, so just say there's 1.
uint32_t port_serial_bytes_available(void) {
#if MAX32_SERIAL
// return __HAL_UART_GET_FLAG(&huart2, UART_FLAG_RXNE) ? 1 : 0;
return MXC_UART_GetRXFIFOAvailable(CONSOLE_UART);
#else
return 0;
#endif
@ -56,6 +68,15 @@ uint32_t port_serial_bytes_available(void) {
void port_serial_write_substring(const char *text, uint32_t len) {
#if MAX32_SERIAL
// HAL_UART_Transmit(&huart2, (uint8_t *)text, len, 5000);
mxc_uart_req_t uart_req = {
.uart = CONSOLE_UART,
.rxCnt = 0,
.txCnt = 0,
.txData = (const unsigned char *)text,
.rxData = NULL,
.txLen = len,
.rxLen = 0
};
MXC_UART_Transaction(&uart_req);
#endif
}

View file

@ -1,3 +1,9 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2018 hathach for Adafruit Industries
// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc
//
// SPDX-License-Identifier: MIT
#include "supervisor/usb.h"
#include "common-hal/microcontroller/Pin.h"
@ -16,7 +22,6 @@ void init_usb_hardware(void) {
// No need to add them to the never_reset list for mcu/Pin API.
// 1 ms SysTick initialized in board.c
// todo: consider moving SysTick initialization here?
// Enable requisite clocks & power for USB
MXC_SYS_ClockSourceEnable(MXC_SYS_CLOCK_IPO);
@ -26,10 +31,9 @@ void init_usb_hardware(void) {
// Supervisor calls TinyUSB's dcd_init,
// which initializes the USB PHY.
// Dep. on CIRCUITPY_TINYUSB and CIRCUITPY_USB_DEVICE
// Depending on CIRCUITPY_TINYUSB and CIRCUITPY_USB_DEVICE
// Interrupt enables are left to TUSB depending on the device class
// todo: confirm with testing!
}
void USB_IRQHandler(void)