Skip to content

Commit d3880eb

Browse files
fix(fap): prefix N32G031 flash macros with N32_ to avoid CMSIS conflicts
furi_hal.h transitively pulls in STM32WB CMSIS headers which define FLASH_BASE (0x08000000), FLASH_KEY1, FLASH_KEY2, and possibly FLASH_PAGE_SIZE. Our N32G031 flash controller uses the same macro names for completely different values (FLASH_BASE=0x40022000 for the flash peripheral, not flash memory). Rename all FLASH_* internal macros to N32_* throughout n32g031_flash.c. No functional change; public API in n32g031_flash.h is unchanged. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent bfe9371 commit d3880eb

1 file changed

Lines changed: 68 additions & 63 deletions

File tree

n32g031_flash.c

Lines changed: 68 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@
2020
* Lock on error: the flash controller is locked (best-effort) even when an
2121
* intermediate step fails, to leave the target in a safe state.
2222
*
23+
* Note on naming: all macros describing the N32G031 flash controller use the
24+
* N32_ prefix to avoid collisions with STM32WB CMSIS definitions (which
25+
* define their own FLASH_BASE, FLASH_KEY1, FLASH_KEY2, etc.) pulled in
26+
* transitively through furi_hal.h.
27+
*
2328
* Author: generated for the Flipper Zero RAZ DC25000 vape-reflash project.
2429
*/
2530

@@ -31,46 +36,46 @@
3136
#include <string.h>
3237

3338
/* ============================================================================
34-
* Flash controller register addresses
39+
* Flash controller register addresses (N32G031 peripheral space)
3540
* ========================================================================= */
3641

37-
#define FLASH_BASE 0x40022000UL
38-
#define FLASH_AC (FLASH_BASE + 0x00U) /* Access control (wait states) */
39-
#define FLASH_KEY (FLASH_BASE + 0x04U) /* Unlock key register */
40-
#define FLASH_OPTKEY (FLASH_BASE + 0x08U) /* Option byte unlock key */
41-
#define FLASH_STS (FLASH_BASE + 0x0CU) /* Status register */
42-
#define FLASH_CTRL (FLASH_BASE + 0x10U) /* Control register */
43-
#define FLASH_ADD (FLASH_BASE + 0x14U) /* Page-erase address register */
44-
45-
/* FLASH_CTRL bits */
46-
#define FLASH_CTRL_PG (1UL << 0) /* Program enable */
47-
#define FLASH_CTRL_PER (1UL << 1) /* Page erase */
48-
#define FLASH_CTRL_MER (1UL << 2) /* Mass erase */
49-
#define FLASH_CTRL_STRT (1UL << 6) /* Start (trigger erase) */
50-
#define FLASH_CTRL_LOCK (1UL << 7) /* Lock bit (1 = locked; clear via keys) */
51-
52-
/* FLASH_STS bits */
53-
#define FLASH_STS_BSY (1UL << 0) /* Controller busy */
54-
#define FLASH_STS_PGERR (1UL << 2) /* Program error */
55-
#define FLASH_STS_WRPERR (1UL << 4) /* Write-protection error */
56-
#define FLASH_STS_EOP (1UL << 5) /* End of operation (write 1 to clear) */
42+
#define N32_FLASH_BASE 0x40022000UL
43+
#define N32_FLASH_AC (N32_FLASH_BASE + 0x00U) /* Access control (wait states) */
44+
#define N32_FLASH_KEY (N32_FLASH_BASE + 0x04U) /* Unlock key register */
45+
#define N32_FLASH_OPTKEY (N32_FLASH_BASE + 0x08U) /* Option byte unlock key */
46+
#define N32_FLASH_STS (N32_FLASH_BASE + 0x0CU) /* Status register */
47+
#define N32_FLASH_CTRL (N32_FLASH_BASE + 0x10U) /* Control register */
48+
#define N32_FLASH_ADD (N32_FLASH_BASE + 0x14U) /* Page-erase address register */
49+
50+
/* N32_FLASH_CTRL bits */
51+
#define N32_CTRL_PG (1UL << 0) /* Program enable */
52+
#define N32_CTRL_PER (1UL << 1) /* Page erase */
53+
#define N32_CTRL_MER (1UL << 2) /* Mass erase */
54+
#define N32_CTRL_STRT (1UL << 6) /* Start (trigger erase) */
55+
#define N32_CTRL_LOCK (1UL << 7) /* Lock bit (1 = locked; clear via keys) */
56+
57+
/* N32_FLASH_STS bits */
58+
#define N32_STS_BSY (1UL << 0) /* Controller busy */
59+
#define N32_STS_PGERR (1UL << 2) /* Program error */
60+
#define N32_STS_WRPERR (1UL << 4) /* Write-protection error */
61+
#define N32_STS_EOP (1UL << 5) /* End of operation (write 1 to clear) */
5762

5863
/* Unlock key sequence */
59-
#define FLASH_KEY1 0x45670123UL
60-
#define FLASH_KEY2 0xCDEF89ABUL
64+
#define N32_KEY1 0x45670123UL
65+
#define N32_KEY2 0xCDEF89ABUL
6166

6267
/* ============================================================================
6368
* Flash geometry
6469
* ========================================================================= */
6570

66-
#define FLASH_ORIGIN 0x08000000UL /* First byte of flash in address space */
67-
#define FLASH_PAGE_SIZE 1024U /* 1 KB per page */
68-
#define FLASH_TOTAL_PAGES 64U /* 64 pages = 64 KB */
71+
#define N32_FLASH_ORIGIN 0x08000000UL /* First byte of flash in target space */
72+
#define N32_PAGE_SIZE 1024U /* 1 KB per page */
73+
#define N32_TOTAL_PAGES 64U /* 64 pages = 64 KB */
6974

7075
/* NV region: pages 60-63 are reserved and must not be erased/written */
71-
#define FLASH_NV_FIRST_PAGE 60U /* First NV page (inclusive) */
72-
#define FLASH_MAX_USER_PAGES 60U /* Pages 0-59 are user-writable */
73-
#define FLASH_MAX_BYTES (FLASH_MAX_USER_PAGES * FLASH_PAGE_SIZE) /* 61440 */
76+
#define N32_NV_FIRST_PAGE 60U /* First NV page (inclusive) */
77+
#define N32_MAX_USER_PAGES 60U /* Pages 0-59 are user-writable */
78+
#define N32_MAX_BYTES (N32_MAX_USER_PAGES * N32_PAGE_SIZE) /* 61440 */
7479

7580
/* ============================================================================
7681
* Polling timeouts
@@ -120,17 +125,17 @@ static inline FlashResult flash_read32(uint32_t addr, uint32_t* out) {
120125
}
121126

122127
/**
123-
* flash_poll_bsy() — spin until FLASH_STS_BSY clears or timeout expires.
128+
* flash_poll_bsy() — spin until N32_FLASH_STS BSY clears or timeout expires.
124129
*
125130
* @param max_iters Maximum number of 100-µs polling iterations.
126131
* @return FLASH_OK, FLASH_ERR_TIMEOUT, or FLASH_ERR_SWD.
127132
*/
128133
static FlashResult flash_poll_bsy(uint32_t max_iters) {
129134
for(uint32_t i = 0; i < max_iters; i++) {
130135
uint32_t sts = 0;
131-
FlashResult r = flash_read32(FLASH_STS, &sts);
136+
FlashResult r = flash_read32(N32_FLASH_STS, &sts);
132137
if(r != FLASH_OK) return FLASH_ERR_SWD;
133-
if(!(sts & FLASH_STS_BSY)) return FLASH_OK;
138+
if(!(sts & N32_STS_BSY)) return FLASH_OK;
134139
furi_delay_us(POLL_DELAY_US);
135140
}
136141
return FLASH_ERR_TIMEOUT;
@@ -146,47 +151,47 @@ static FlashResult flash_poll_bsy(uint32_t max_iters) {
146151
*/
147152
static FlashResult flash_check_errors(FlashResult err_code) {
148153
uint32_t sts = 0;
149-
FlashResult r = flash_read32(FLASH_STS, &sts);
154+
FlashResult r = flash_read32(N32_FLASH_STS, &sts);
150155
if(r != FLASH_OK) return FLASH_ERR_SWD;
151156

152-
if(sts & FLASH_STS_WRPERR) return FLASH_ERR_PROTECTED;
153-
if(sts & FLASH_STS_PGERR) return err_code;
157+
if(sts & N32_STS_WRPERR) return FLASH_ERR_PROTECTED;
158+
if(sts & N32_STS_PGERR) return err_code;
154159
return FLASH_OK;
155160
}
156161

157162
/**
158-
* flash_clear_eop() — write 1 to FLASH_STS_EOP to acknowledge end-of-op.
163+
* flash_clear_eop() — write 1 to N32_STS_EOP to acknowledge end-of-op.
159164
*
160165
* This is a write-1-to-clear bit; writing EOP does not disturb other bits
161166
* because PGERR/WRPERR are also write-1-to-clear and we write only EOP.
162167
*/
163168
static FlashResult flash_clear_eop(void) {
164-
return flash_write32(FLASH_STS, FLASH_STS_EOP);
169+
return flash_write32(N32_FLASH_STS, N32_STS_EOP);
165170
}
166171

167172
/**
168173
* flash_unlock() — perform the two-key unlock sequence.
169174
*
170-
* After writing both keys, reads back FLASH_CTRL to verify the LOCK bit is
171-
* clear. Returns FLASH_ERR_UNLOCK if CTRL cannot be read or LOCK is still
175+
* After writing both keys, reads back N32_FLASH_CTRL to verify the LOCK bit
176+
* is clear. Returns FLASH_ERR_UNLOCK if CTRL cannot be read or LOCK is still
172177
* set (e.g. wrong key order, or controller already in an error state).
173178
*
174179
* @return FLASH_OK on success.
175180
*/
176181
static FlashResult flash_unlock(void) {
177182
FlashResult r;
178183

179-
r = flash_write32(FLASH_KEY, FLASH_KEY1);
184+
r = flash_write32(N32_FLASH_KEY, N32_KEY1);
180185
if(r != FLASH_OK) return FLASH_ERR_UNLOCK;
181186

182-
r = flash_write32(FLASH_KEY, FLASH_KEY2);
187+
r = flash_write32(N32_FLASH_KEY, N32_KEY2);
183188
if(r != FLASH_OK) return FLASH_ERR_UNLOCK;
184189

185190
/* Verify LOCK bit cleared */
186191
uint32_t ctrl = 0;
187-
r = flash_read32(FLASH_CTRL, &ctrl);
192+
r = flash_read32(N32_FLASH_CTRL, &ctrl);
188193
if(r != FLASH_OK) return FLASH_ERR_UNLOCK;
189-
if(ctrl & FLASH_CTRL_LOCK) return FLASH_ERR_UNLOCK;
194+
if(ctrl & N32_CTRL_LOCK) return FLASH_ERR_UNLOCK;
190195

191196
return FLASH_OK;
192197
}
@@ -200,11 +205,11 @@ static FlashResult flash_unlock(void) {
200205
*/
201206
static FlashResult flash_lock(void) {
202207
uint32_t ctrl = 0;
203-
FlashResult r = flash_read32(FLASH_CTRL, &ctrl);
208+
FlashResult r = flash_read32(N32_FLASH_CTRL, &ctrl);
204209
if(r != FLASH_OK) return FLASH_ERR_SWD;
205210

206-
ctrl |= FLASH_CTRL_LOCK;
207-
return flash_write32(FLASH_CTRL, ctrl);
211+
ctrl |= N32_CTRL_LOCK;
212+
return flash_write32(N32_FLASH_CTRL, ctrl);
208213
}
209214

210215
/**
@@ -218,24 +223,24 @@ static FlashResult flash_lock(void) {
218223
* 5. Clear EOP.
219224
* 6. Check PGERR / WRPERR.
220225
*
221-
* @param page_index 0-based page number; must be < FLASH_NV_FIRST_PAGE.
226+
* @param page_index 0-based page number; must be < N32_NV_FIRST_PAGE.
222227
* @return FLASH_OK, FLASH_ERR_ERASE, FLASH_ERR_PROTECTED, FLASH_ERR_SWD,
223228
* or FLASH_ERR_TIMEOUT.
224229
*/
225230
static FlashResult flash_erase_page(uint32_t page_index) {
226231
FlashResult r;
227-
uint32_t page_addr = FLASH_ORIGIN + (page_index * FLASH_PAGE_SIZE);
232+
uint32_t page_addr = N32_FLASH_ORIGIN + (page_index * N32_PAGE_SIZE);
228233

229234
/* Step 1: set PER mode */
230-
r = flash_write32(FLASH_CTRL, FLASH_CTRL_PER);
235+
r = flash_write32(N32_FLASH_CTRL, N32_CTRL_PER);
231236
if(r != FLASH_OK) return r;
232237

233238
/* Step 2: write the page address to ADD */
234-
r = flash_write32(FLASH_ADD, page_addr);
239+
r = flash_write32(N32_FLASH_ADD, page_addr);
235240
if(r != FLASH_OK) return r;
236241

237242
/* Step 3: trigger erase */
238-
r = flash_write32(FLASH_CTRL, FLASH_CTRL_PER | FLASH_CTRL_STRT);
243+
r = flash_write32(N32_FLASH_CTRL, N32_CTRL_PER | N32_CTRL_STRT);
239244
if(r != FLASH_OK) return r;
240245

241246
/* Step 4: poll busy */
@@ -269,7 +274,7 @@ static FlashResult flash_write_word(uint32_t flash_addr, uint32_t word) {
269274
FlashResult r;
270275

271276
/* Step 1: set PG mode */
272-
r = flash_write32(FLASH_CTRL, FLASH_CTRL_PG);
277+
r = flash_write32(N32_FLASH_CTRL, N32_CTRL_PG);
273278
if(r != FLASH_OK) return r;
274279

275280
/* Step 2: write word directly to flash address */
@@ -317,16 +322,16 @@ FlashResult n32_flash_program(
317322
/* ------------------------------------------------------------------
318323
* Parameter validation
319324
* ------------------------------------------------------------------ */
320-
if(len == 0 || len > FLASH_MAX_BYTES) {
325+
if(len == 0 || len > N32_MAX_BYTES) {
321326
return FLASH_ERR_SIZE;
322327
}
323328

324329
/* Number of pages that need to be erased to cover 'len' bytes */
325-
uint32_t pages_needed = (len + FLASH_PAGE_SIZE - 1) / FLASH_PAGE_SIZE;
330+
uint32_t pages_needed = (len + N32_PAGE_SIZE - 1) / N32_PAGE_SIZE;
326331
/* Clamp to the writable region — the size check above already ensures
327-
* pages_needed <= FLASH_MAX_USER_PAGES, but be explicit. */
328-
if(pages_needed > FLASH_MAX_USER_PAGES) {
329-
pages_needed = FLASH_MAX_USER_PAGES;
332+
* pages_needed <= N32_MAX_USER_PAGES, but be explicit. */
333+
if(pages_needed > N32_MAX_USER_PAGES) {
334+
pages_needed = N32_MAX_USER_PAGES;
330335
}
331336

332337
/* Number of 32-bit words to write (ceiling division).
@@ -346,7 +351,7 @@ FlashResult n32_flash_program(
346351
/* ------------------------------------------------------------------
347352
* Step 2: Page erase (pages 0 .. pages_needed-1)
348353
* ------------------------------------------------------------------ */
349-
uint32_t erase_total = pages_needed * FLASH_PAGE_SIZE;
354+
uint32_t erase_total = pages_needed * N32_PAGE_SIZE;
350355

351356
for(uint32_t page = 0; page < pages_needed; page++) {
352357
r = flash_erase_page(page);
@@ -355,14 +360,14 @@ FlashResult n32_flash_program(
355360
return r;
356361
}
357362
report_progress(cb, cb_ctx, "Erasing",
358-
(page + 1U) * FLASH_PAGE_SIZE,
363+
(page + 1U) * N32_PAGE_SIZE,
359364
erase_total);
360365
}
361366

362367
/* ------------------------------------------------------------------
363368
* Step 3: Program words
364369
* ------------------------------------------------------------------ */
365-
uint32_t progress_cb_threshold = FLASH_PAGE_SIZE; /* report every 1 KB */
370+
uint32_t progress_cb_threshold = N32_PAGE_SIZE; /* report every 1 KB */
366371
uint32_t bytes_since_last_cb = 0;
367372

368373
for(uint32_t i = 0; i < words_to_write; i++) {
@@ -377,7 +382,7 @@ FlashResult n32_flash_program(
377382
memcpy(&word, data + byte_offset, copy_bytes);
378383
/* Any remaining bytes in 'word' are already 0 (zero-initialised) */
379384

380-
uint32_t flash_addr = FLASH_ORIGIN + byte_offset;
385+
uint32_t flash_addr = N32_FLASH_ORIGIN + byte_offset;
381386
r = flash_write_word(flash_addr, word);
382387
if(r != FLASH_OK) {
383388
flash_lock(); /* best-effort */
@@ -396,7 +401,7 @@ FlashResult n32_flash_program(
396401
report_progress(cb, cb_ctx, "Flashing", prog_total, prog_total);
397402

398403
/* Clear PG mode before verify reads */
399-
r = flash_write32(FLASH_CTRL, 0UL);
404+
r = flash_write32(N32_FLASH_CTRL, 0UL);
400405
if(r != FLASH_OK) {
401406
flash_lock();
402407
return r;
@@ -416,7 +421,7 @@ FlashResult n32_flash_program(
416421
uint32_t copy_bytes = (bytes_left >= 4U) ? 4U : bytes_left;
417422
memcpy(&expected, data + byte_offset, copy_bytes);
418423

419-
uint32_t flash_addr = FLASH_ORIGIN + byte_offset;
424+
uint32_t flash_addr = N32_FLASH_ORIGIN + byte_offset;
420425
uint32_t actual = 0;
421426
r = flash_read32(flash_addr, &actual);
422427
if(r != FLASH_OK) {

0 commit comments

Comments
 (0)