Skip to content

Commit 84504f5

Browse files
BrentK-ADIhathach
authored andcommitted
Add MAX32666 Support
Add support for the MAX32666/5 with MAX32666EvKit and MAX32666FTHR boards.
1 parent aa366fe commit 84504f5

File tree

21 files changed

+1076
-6
lines changed

21 files changed

+1076
-6
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
# No specific build requirements for the board.
1+
# No specific build requirements for the board.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
# No specific build requirements for the board.
1+
# No specific build requirements for the board.

ports/max32666/Makefile

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# List of git submodules that is included as part of the UF2 version
2+
GIT_SUBMODULES = tinyusb
3+
4+
include ../make.mk
5+
include port.mk
6+
include ../rules.mk
7+
8+
#------------------------------------------
9+
# Self-update
10+
#------------------------------------------
11+
self-update: $(BUILD)/$(OUTNAME).bin
12+
$(PYTHON3) $(TOP)/lib/uf2/utils/uf2conv.py --carray $^ -o apps/self_update/_build/bootloader_bin.c
13+
$(MAKE) -C $(TOP)/$(PORT_DIR)/apps/self_update uf2
14+
15+
self-update-clean:
16+
$(MAKE) -C $(TOP)/$(PORT_DIR)/apps/self_update clean
17+
18+
#---------- Erase Firmware ----------
19+
# Compile apps/erase_firmware/erase_firmware.c
20+
erase-firmware:
21+
$(MAKE) -C $(TOP)/$(PORT_DIR)/apps/erase_firmware uf2
22+
23+
erase-firmware-clean:
24+
$(MAKE) -C $(TOP)/$(PORT_DIR)/apps/erase_firmware clean
25+
26+
#---------- Blinky ----------
27+
# Compile apps/blinky/blinky.c
28+
blinky:
29+
$(MAKE) -C $(TOP)/$(PORT_DIR)/apps/blinky uf2
30+
31+
blinky-clean:
32+
$(MAKE) -C $(TOP)/$(PORT_DIR)/apps/blinky clean
33+
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
PORT = max32666
2+
OUTNAME = blinky-$(BOARD)
3+
4+
BUILD_APPLICATION = 1
5+
BUILD_NO_TINYUSB = 1
6+
7+
include ../../../make.mk
8+
include ../../port.mk
9+
10+
SRC_C += \
11+
apps/blinky/blinky.c \
12+
13+
include ../../../rules.mk
14+
15+
uf2: $(BUILD)/$(OUTNAME).uf2
16+
17+
$(BUILD)/$(OUTNAME).uf2: $(BUILD)/$(OUTNAME).hex
18+
@echo CREATE $@
19+
$(PYTHON3) $(TOP)/lib/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID) -c -o $@ $^
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
PORT = max32666
2+
OUTNAME = erase_firmware-$(BOARD)
3+
4+
BUILD_APPLICATION = 1
5+
BUILD_NO_TINYUSB = 1
6+
7+
include ../../../make.mk
8+
include ../../port.mk
9+
10+
SRC_C += \
11+
apps/erase_firmware/erase_firmware.c \
12+
13+
include ../../../rules.mk
14+
15+
uf2: $(BUILD)/$(OUTNAME).uf2
16+
17+
$(BUILD)/$(OUTNAME).uf2: $(BUILD)/$(OUTNAME).hex
18+
@echo CREATE $@
19+
$(PYTHON3) $(TOP)/lib/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID) -c -o $@ $^
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
PORT = max32666
2+
OUTNAME = self-update-$(BOARD)
3+
4+
BUILD_APPLICATION = 1
5+
BUILD_NO_TINYUSB = 1
6+
7+
CFLAGS += -DTINYUF2_SELF_UPDATE
8+
9+
include ../../../make.mk
10+
include ../../port.mk
11+
12+
SRC_C += \
13+
apps/self_update/self_update.c \
14+
$(TOP)/$(PORT_DIR)/apps/self_update/_build/bootloader_bin.c \
15+
16+
include ../../../rules.mk
17+
18+
19+
uf2: $(BUILD)/$(OUTNAME).uf2
20+
21+
$(BUILD)/$(OUTNAME).uf2: $(BUILD)/$(OUTNAME).hex
22+
@echo CREATE $@
23+
$(PYTHON3) $(TOP)/lib/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID) -c -o $@ $^

ports/max32666/board_flash.c

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
/*
2+
* The MIT License (MIT)
3+
*
4+
* Copyright (c) 2025 Brent Kowal, Analog Devices, Inc
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
25+
#include "board_api.h"
26+
27+
// MAX MSDK Includes
28+
#include "flc.h"
29+
#include "gpio.h"
30+
#include "icc.h"
31+
#include "mxc_sys.h"
32+
#include "mxc_device.h"
33+
#include "uart.h"
34+
35+
/**
36+
* Implementation Notes:
37+
* 1) Per the MAX32 documentation, any operation which modifies the flash
38+
* contents should be wrapped with ICC Disable/Enable calls to prevent
39+
* invalid cache contents. You'll see these calls during erases and writes.
40+
*
41+
* 2) The MAX32 flash is divided up into pages of 8K which is significantly
42+
* larger than the UF2 block size. This poses a problem with erasing. Rather
43+
* than assuming data will be written sequentially and erasing a page the
44+
* first time its touched, this buffers pages in RAM allow sequential writes
45+
* to occur in RAM.
46+
*
47+
* When a page is first buffered its entire existing contents are copied into
48+
* RAM as the baseline, then overwritten by board_flash_write(). As a new
49+
* page is needed, the current page is erased in flash and the entire buffer
50+
* then written, and the process repeats itself copying the existing data of
51+
* the new page into RAM.
52+
*
53+
* Assuming everything is written sequentially, this should have no different
54+
* impact on flash cycles than erasing first. If things _aren't_ written
55+
* sequentially, or only a partial page is written and the other page data
56+
* needs to be preserved (maybe the application has some exotic setup with
57+
* multiple UF2 files) this effectively simulates a byte-level read/write
58+
* access of flash.
59+
*/
60+
61+
// A value to use to indicate no page is buffered
62+
#define INVALID_PAGE_ADDR 0xFFFFFFFFUL
63+
64+
// Current base address of the buffered page
65+
static uint32_t page_buffer_addr = INVALID_PAGE_ADDR;
66+
67+
// Page buffer. uint32_t to avoid some compile recast/alignment warnings
68+
static uint32_t page_buffer[BOARD_FLASH_PAGE_SIZE / sizeof(uint32_t)];
69+
70+
//--------------------------------------------------------------------+
71+
// Flash
72+
//--------------------------------------------------------------------+
73+
void board_flash_init(void) {
74+
page_buffer_addr = INVALID_PAGE_ADDR;
75+
}
76+
77+
uint32_t board_flash_size(void) {
78+
return BOARD_FLASH_SIZE;
79+
}
80+
81+
void board_flash_read(uint32_t addr, void* buffer, uint32_t len) {
82+
MXC_FLC_Read(addr, buffer, len);
83+
}
84+
85+
static void flash_erase_page(uint32_t page_addr) {
86+
MXC_ICC_Disable();
87+
MXC_CRITICAL(
88+
MXC_FLC_PageErase(page_addr);
89+
)
90+
MXC_ICC_Enable();
91+
}
92+
93+
static void flash_prepare_page_buffer(uint32_t addr) {
94+
//Get the base address for the page
95+
uint32_t page_addr = addr & MXC_FLASH_PAGE_MASK;
96+
97+
if(page_buffer_addr == page_addr) {
98+
//Already buffered. Nothing to do
99+
return;
100+
}
101+
102+
//Flush the current page buffer if active
103+
board_flash_flush();
104+
board_flash_read(page_addr, page_buffer, BOARD_FLASH_PAGE_SIZE);
105+
page_buffer_addr = page_addr;
106+
}
107+
108+
void board_flash_flush(void) {
109+
if(page_buffer_addr != INVALID_PAGE_ADDR) {
110+
flash_erase_page(page_buffer_addr);
111+
MXC_ICC_Disable();
112+
MXC_CRITICAL(
113+
MXC_FLC_Write(page_buffer_addr, BOARD_FLASH_PAGE_SIZE, page_buffer);
114+
)
115+
MXC_ICC_Enable();
116+
page_buffer_addr = INVALID_PAGE_ADDR;
117+
}
118+
}
119+
120+
121+
bool board_flash_write(uint32_t addr, void const* data, uint32_t len) {
122+
uint8_t* data_ptr = (uint8_t*)data;
123+
uint32_t page_offset;
124+
uint32_t to_write;
125+
126+
//Safety checks
127+
TUF2_ASSERT(addr >= BOARD_FLASH_ADDR_ZERO);
128+
TUF2_ASSERT(addr + len <= BOARD_FLASH_ADDR_LAST);
129+
130+
while(len) {
131+
//Make sure the correct page is buffered
132+
flash_prepare_page_buffer(addr);
133+
134+
//How many bytes into the page are we working
135+
page_offset = addr - page_buffer_addr;
136+
137+
//Determine how many bytes in the current page we can/should write
138+
to_write = TUF2_MIN(len, BOARD_FLASH_PAGE_SIZE-page_offset);
139+
140+
//Write into the buffer
141+
memcpy(((uint8_t*)page_buffer) + page_offset, data_ptr, to_write);
142+
143+
//Adjust all the pointers, addresses and lengths for the next iteration
144+
data_ptr += to_write;
145+
addr += to_write;
146+
len -= to_write;
147+
}
148+
return true;
149+
}
150+
151+
void board_flash_erase_app(void) {
152+
uint32_t page;
153+
for(page = BOARD_FLASH_APP_START_PAGE; page < BOARD_FLASH_NUM_PAGES; page++) {
154+
flash_erase_page(MXC_FLASH_PAGE_ADDR(page));
155+
}
156+
}
157+
158+
bool board_flash_protect_bootloader(bool protect) {
159+
// TODO implement later
160+
(void) protect;
161+
return false;
162+
}
163+
164+
165+
166+
#ifdef TINYUF2_SELF_UPDATE
167+
168+
// Run this function out of RAM. The linker file has a .flashprog section
169+
// to relocated this. Rather than putting all the support SDK calls in RAM as
170+
// well, just do the handful of register writes to clear the first application
171+
// page and reset the device
172+
//
173+
// The MAX32666 has 2 flash controls, one for each bank of flash. We only care
174+
// about MXC_FLC0 here to erase the first part of the application
175+
static void __attribute__((section(".flashprog"))) erase_app_reboot_from_ram(void) {
176+
while(MXC_FLC0->cn & MXC_F_FLC_CN_PEND); //Wait for busy to clear
177+
MXC_FLC0->clkdiv = SystemCoreClock / 1000000; //Set up the Flash clock
178+
MXC_FLC0->addr = BOARD_FLASH_APP_START; //Erase starting at the app
179+
MXC_FLC0->cn = //Unlock the flash to allow writing
180+
(MXC_FLC0->cn & ~MXC_F_FLC_CN_UNLOCK) | MXC_S_FLC_CN_UNLOCK_UNLOCKED;
181+
MXC_FLC0->cn = //Set the erase mode to page
182+
(MXC_FLC0->cn & ~MXC_F_FLC_CN_ERASE_CODE) | MXC_S_FLC_CN_ERASE_CODE_ERASEPAGE;
183+
MXC_FLC0->cn |= MXC_F_FLC_CN_PGE; //Erase the page
184+
while(MXC_FLC0->cn & MXC_F_FLC_CN_PEND); //Wait for busy to clear
185+
MXC_FLC0->cn = //Relock the flash
186+
(MXC_FLC0->cn & ~MXC_F_FLC_CN_UNLOCK) | MXC_S_FLC_CN_UNLOCK_LOCKED;
187+
MXC_GCR->rstr0 |= MXC_F_GCR_RSTR0_SYSTEM; //Reset the device
188+
}
189+
190+
void board_self_update( const uint8_t * bootloader_bin, uint32_t bootloader_len) {
191+
MXC_SYS_Crit_Enter(); //Disable interrupts for whole operation
192+
193+
if(bootloader_len > FLASH_BOOT_SIZE) {
194+
TUF2_LOG1("Bootloader size too large\n");
195+
} else if(memcmp((uint8_t*)BOARD_FLASH_ADDR_ZERO, bootloader_bin, bootloader_len) == 0) {
196+
TUF2_LOG1("Bootloader matches. Skipping re-flash\n");
197+
} else {
198+
#if TINYUF2_PROTECT_BOOTLOADER
199+
//Note: Don't protect bootloader when done, leave that to the new bootloader
200+
//since it may or may not enable protection.
201+
board_flash_protect_bootloader(false);
202+
#endif
203+
//Use our existing functions for flashing the bootloader. Application flash
204+
//is still valid, so all functions are available.
205+
board_flash_write(BOARD_FLASH_ADDR_ZERO, bootloader_bin, bootloader_len);
206+
board_flash_flush();
207+
}
208+
209+
//Invalidate this application and reboot. Must be done from RAM
210+
erase_app_reboot_from_ram();
211+
}
212+
#endif

0 commit comments

Comments
 (0)