Skip to content

Commit 54a0ad7

Browse files
committed
correct uf2 app/sd size when writing and reading
1 parent 447207b commit 54a0ad7

File tree

4 files changed

+98
-70
lines changed

4 files changed

+98
-70
lines changed

src/usb/msc_uf2.c

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -174,16 +174,32 @@ void tud_msc_write10_complete_cb(uint8_t lun)
174174
// All block of uf2 file is complete --> complete DFU process
175175
if (_wr_state.numWritten >= _wr_state.numBlocks)
176176
{
177-
led_state(STATE_WRITING_FINISHED);
178-
179177
dfu_update_status_t update_status;
180-
181178
memset(&update_status, 0, sizeof(dfu_update_status_t ));
182-
update_status.status_code = DFU_UPDATE_APP_COMPLETE;
183-
update_status.app_crc = 0; // skip CRC checking with uf2 upgrade
184-
update_status.app_size = _wr_state.numBlocks*256;
179+
180+
if ( _wr_state.update_bootloader )
181+
{
182+
// update bootloader
183+
}else
184+
{
185+
// update App
186+
update_status.status_code = DFU_UF2_APP_COMPLETE;
187+
update_status.app_crc = 0; // skip CRC checking with uf2 upgrade
188+
update_status.app_size = _wr_state.numBlocks*256;
189+
190+
if ( _wr_state.has_sd && is_sd_existed() )
191+
{
192+
/* Since the Bootloader Setting still needs to know the SD and App size separately
193+
* to stay compatible with DFU CDC interface. We re-calculate it based on written
194+
* address and its contents ( SD_MAGIC matches )
195+
*/
196+
update_status.app_size -= SD_SIZE_GET(MBR_SIZE);
197+
}
198+
}
185199

186200
bootloader_dfu_update_process(update_status);
201+
202+
led_state(STATE_WRITING_FINISHED);
187203
}
188204
}
189205
}

src/usb/uf2/ghostfat.c

Lines changed: 74 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -156,19 +156,14 @@ static inline bool in_app_space (uint32_t addr)
156156
return USER_FLASH_START <= addr && addr < USER_FLASH_END;
157157
}
158158

159-
static inline bool in_uicr_space(uint32_t addr)
160-
{
161-
return addr == 0x10001000;
162-
}
163-
164159
static inline bool in_bootloader_space (uint32_t addr)
165160
{
166-
return USER_FLASH_END <= addr && addr < CFG_UF2_FLASH_SIZE;
161+
return CFG_UF2_BOOTLOADER_ADDR_START <= addr && addr < CFG_UF2_BOOTLOADER_ADDR_END;
167162
}
168163

169-
static inline bool in_softdevice_space (uint32_t addr)
164+
static inline bool in_uicr_space(uint32_t addr)
170165
{
171-
return addr < USER_FLASH_START;
166+
return addr == 0x10001000;
172167
}
173168

174169
//--------------------------------------------------------------------+
@@ -183,7 +178,7 @@ static uint32_t current_flash_size(void)
183178
uint32_t flash_sz = 0;
184179

185180
// return 1 block of 256 bytes
186-
if ( !bootloader_app_is_valid(DFU_BANK_0_REGION_START) )
181+
if ( !bootloader_app_is_valid() )
187182
{
188183
flash_sz = 256;
189184
}else
@@ -193,6 +188,9 @@ static uint32_t current_flash_size(void)
193188

194189
flash_sz = boot_setting->bank_0_size;
195190

191+
// Include SoftDevice (excluding MBR) for current.uf2
192+
if ( is_sd_existed() ) flash_sz += (SD_SIZE_GET(MBR_SIZE) - MBR_SIZE);
193+
196194
// Copy size must be multiple of 256 bytes
197195
// else we will got an issue copying current.uf2
198196
if (flash_sz & 0xff)
@@ -344,30 +342,63 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state)
344342

345343
if ( !is_uf2_block(bl) ) return -1;
346344

347-
PRINTF("Addr = 0x%08lX, payloadSize = %ld, Family = 0x%08lX\n", bl->targetAddr, bl->payloadSize, bl->familyID);
348-
#if 0
349-
uint32_t wr_addr;
350-
351345
switch ( bl->familyID )
352346
{
353347
case CFG_UF2_FAMILY_ID:
354-
// Upgrade application
355-
// Directly write over application -- > Target address is the written address
356-
if ( !in_app_space(bl->targetAddr) ) return -1;
348+
/* Upgrading Application
349+
*
350+
* Although SoftDevice is considered as part of application and the flashing is the same with/without it.
351+
* There are still 3 cases with slight differences in finishing procedure:
352+
* 1. Application with SoftDevice:
353+
* - starting address 0x0000
354+
* - since MBR is included in SD Hex file (then uf2 file), we must skip it
355+
* 2. Application only
356+
* a. For running with existing SoftDevice on the flash:
357+
* - starting address is right after SD e.g 0x26000
358+
* b. For running without SoftDevice e.g using other stack such as nimble or zephyr.
359+
* - starting address is right after MBR 0x1000
360+
*
361+
* ------------- -------------
362+
* | | | |
363+
* | Bootloader | | Bootloader |
364+
* BOOTLOADER_ADDR_START--|-------------| |-------------|
365+
* | | | |
366+
* | | | |
367+
* | Application | ---> | New |
368+
* | | | Application |
369+
* | | | |
370+
* | | | |
371+
* USER_FLASH_START--|-------------| |-------------|
372+
* | MBR | | MBR |
373+
* ------------- -------------
374+
*/
375+
if ( in_app_space(bl->targetAddr) )
376+
{
377+
PRINTF("Write addr = 0x%08lX, block = %ld (%ld of %ld)\r\n", bl->targetAddr, bl->blockNo, state->numWritten, bl->numBlocks);
357378

358-
wr_addr = bl->targetAddr;
379+
// writing to SD Info struct is used as SD detector
380+
if (bl->targetAddr == (SOFTDEVICE_INFO_STRUCT_ADDRESS & 0xff) ) state->has_sd = true;
381+
382+
flash_nrf5x_write(bl->targetAddr, bl->data, bl->payloadSize, true);
383+
}else if ( bl->targetAddr < USER_FLASH_START )
384+
{
385+
// do nothing if writing to MBR
386+
// keep going as successful write
387+
}else
388+
{
389+
return -1;
390+
}
359391
break;
360392

361393
case CFG_UF2_BOOTLOADER_ID:
362-
/* Upgrading SoftDevice + Bootloader combo
394+
/* Upgrading Bootloader (with/without SoftDevice)
363395
*
364396
* To prevent corruption/disconnection while transferring we don't directly write over
365-
* SoftDevice and Bootloader. Instead SD + Bootloader is written to Application region.
366-
* Once everything is received and verified.They are written to their respective address
397+
* Bootloader. Instead Bootloader is written to Application region.
398+
* Once everything is received and verified. It is written to its respective address
367399
*
368-
* Note: to simplify the upgrade process, we ASSUME
369-
* - Bootloader size is fixed and is the same as the old bootloader
370-
* - New SoftDevice can has different size than the old one
400+
* Note: to simplify the upgrade process, we ASSUME, Bootloader size is fixed and
401+
* is the same as the old bootloader
371402
*
372403
* ------------- ------------- -------------
373404
* | | | | + | New |
@@ -376,42 +407,41 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state)
376407
* | | | New | + | |
377408
* | | | Bootloader | + | |
378409
* | | | ++++++++ | | |
379-
* | Application | ---> | | | Invalid |
380-
* | | | | | Application |
381-
* | | | ++++++++ | | |
382-
* | | | New | | |
383-
* | | | SoftDevice | + |-------------|
384-
* USER_FLASH_START--|-------------| |-------------| + | |
385-
* | | | | + | |
386-
* | | | | + | New |
387-
* | SoftDevice | | SoftDevice | + | SoftDevice |
410+
* | Application | ---> | | | |
411+
* | | | | | |
412+
* | | | ++++++++ | | ++++++++ |
413+
* | | | New | | New |
414+
* | | | SoftDevice | | SoftDevice |
415+
* USER_FLASH_START--|-------------| |-------------| |-------------|
416+
* | MBR | | MBR | | MBR |
388417
* ------------- ------------- -------------
389418
*/
390-
391419
if ( in_uicr_space(bl->targetAddr) )
392420
{
393421
/* UCIR contains bootloader & MBR address as follow:
394-
* - 0x10001014: for bootloader address
395-
* - 0x10001018: for MBR
396-
* Both values are fixed if bootloader size is not change
422+
* - 0x10001014 bootloader address: only change of bootloader size changes
423+
* - 0x10001018 MBR Params: mostly fixed
424+
*
425+
* WARNING: incorrect value of these UCIR will break device
397426
*/
398427

399428
// Nothing to do since bootloader size is fixed
400429
return 512;
401430
}
402-
else if ( in_softdevice_space(bl->targetAddr) )
431+
else if ( in_bootloader_space(bl->targetAddr) )
403432
{
404433
// Right above the old SoftDevice
405-
wr_addr = USER_FLASH_START + bl->targetAddr;
406434
}
407-
else if ( in_bootloader_space(bl->targetAddr) )
435+
else if ( in_app_space(bl->targetAddr) )
408436
{
409437
// Right below the old Bootloader
410438
//wr_addr = USER_FLASH_START + bl->targetAddr;
439+
// writing to SD Info struct is used as SD detector
440+
// if (bl->targetAddr == SOFTDEVICE_INFO_STRUCT_ADDRESS) state->has_sd = true;
441+
411442
}
412443
else
413444
{
414-
415445
return -1;
416446
}
417447
break;
@@ -420,25 +450,10 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state)
420450
default: return -1;
421451
}
422452

423-
(void) wr_addr;
424-
#endif
425-
426-
// only accept block with same family id
427-
if ( (bl->familyID != CFG_UF2_FAMILY_ID) ) return -1;
428-
429-
if ( (bl->targetAddr < USER_FLASH_START) || (bl->targetAddr + bl->payloadSize > USER_FLASH_END) )
430-
{
431-
432-
}
433-
else
434-
{
435-
//PRINTF("Write block at %x", bl->targetAddr);
436-
flash_nrf5x_write(bl->targetAddr, bl->data, bl->payloadSize, true);
437-
}
438-
439-
if ( state && bl->numBlocks )
453+
//------------- Update written blocks -------------//
454+
if ( bl->numBlocks )
440455
{
441-
// Update state num blocks
456+
// Update state num blocks if needed
442457
if ( state->numBlocks != bl->numBlocks )
443458
{
444459
if ( bl->numBlocks >= MAX_BLOCKS || state->numBlocks )
@@ -460,13 +475,12 @@ int write_block (uint32_t block_no, uint8_t *data, WriteState *state)
460475
}
461476

462477
// flush last blocks
478+
// TODO numWritten can be smaller than numBlocks if return early
463479
if ( state->numWritten >= state->numBlocks )
464480
{
465481
flash_nrf5x_flush(true);
466482
}
467483
}
468-
469-
//PRINTF("wr %d=%d (of %d)", state->numWritten, bl->blockNo, bl->numBlocks);
470484
}
471485

472486
return 512;

src/usb/uf2/uf2.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ SOFTWARE.
5252
typedef struct {
5353
uint32_t numBlocks;
5454
uint32_t numWritten;
55+
bool has_sd; // if SD is included as part of uf2 file
56+
bool update_bootloader; // if updating bootloader
5557
uint8_t writtenMask[MAX_BLOCKS / 8 + 1];
5658
} WriteState;
5759

src/usb/uf2/uf2cfg.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,6 @@
77
#define CFG_UF2_NUM_BLOCKS 8000 // at least 4,1 MB for FAT16
88
#define CFG_UF2_FLASH_SIZE (1024*1024) // 1 MB
99

10-
// Softdevice Address Space
11-
#define CFG_UF2_SOFTDEVICE_ADDR_START MBR_SIZE // skip MBR included in SD hex
12-
#define CFG_UF2_SOFTDEVICE_ADDR_END SD_SIZE_GET(MBR_SIZE)
13-
1410
// Application Address Space
1511
#define USER_FLASH_START MBR_SIZE // skip MBR included in SD hex
1612
#define USER_FLASH_END 0xAD000

0 commit comments

Comments
 (0)