Skip to content

Commit d6cb4bf

Browse files
committed
Partition the first flash page
SAMD microcontrollers can protect the bootloader flash using at91samd bootloader [size] command In processors with big flash like SAMD21G18A the minimum flash partition is 256kB / 16 = 16kB, which is way bigger than minimum bootloader size. When a "load" is executed during gdb debugging session, if the .text section starts before 0x4000 (16kB), the entire first flash page gets erased. This fails if the page is protected via the bootloader command. This patch partitions the first flash page into logical smaller chunks, so the "load" command only erases the relevant pages. If the flash page is smaller/equal than the minimum bootloader size, do nothing.
1 parent f389067 commit d6cb4bf

File tree

1 file changed

+37
-7
lines changed

1 file changed

+37
-7
lines changed

src/flash/nor/at91samd.c

+37-7
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,14 @@ static int samd_protect_check(struct flash_bank *bank)
235235
return res;
236236

237237
/* Lock bits are active-low */
238-
for (int i = 0; i < bank->num_sectors; i++)
239-
bank->sectors[i].is_protected = !(lock & (1<<i));
238+
int boot_sectors = bank->num_sectors - SAMD_NUM_SECTORS;
239+
for (int i = 0; i < bank->num_sectors; i++) {
240+
if (i < boot_sectors) {
241+
bank->sectors[i].is_protected = !(lock & (1<<0));
242+
} else {
243+
bank->sectors[i].is_protected = !(lock & (1<<(i-boot_sectors)));
244+
}
245+
}
240246

241247
return ERROR_OK;
242248
}
@@ -304,17 +310,41 @@ static int samd_probe(struct flash_bank *bank)
304310
part->flash_kb, chip->num_pages, chip->page_size);
305311
}
306312

313+
/* Partition the first page into subpages, to allow debugging if boot sector is protected
314+
* The minimum boot page allowed is 2kb */
315+
int boot_sectors = chip->sector_size / 2048;
316+
int boot_offset = 0;
317+
318+
if (boot_sectors == 1) {
319+
boot_sectors = 0;
320+
}
321+
307322
/* Allocate the sector table */
308-
bank->num_sectors = SAMD_NUM_SECTORS;
323+
if (boot_sectors > 0) {
324+
LOG_INFO("SAMD: partitioning the first flash page into %d subpages",
325+
boot_sectors);
326+
bank->num_sectors = SAMD_NUM_SECTORS + boot_sectors - 1;
327+
boot_offset = chip->sector_size;
328+
} else {
329+
bank->num_sectors = SAMD_NUM_SECTORS;
330+
}
331+
309332
bank->sectors = calloc(bank->num_sectors, sizeof((bank->sectors)[0]));
310333
if (!bank->sectors)
311334
return ERROR_FAIL;
312335

313-
/* Fill out the sector information: all SAMD sectors are the same size and
314-
* there is always a fixed number of them. */
315-
for (int i = 0; i < bank->num_sectors; i++) {
336+
/* Will be skipped if SAMD_BOOT_SECTORS == 0 */
337+
for (int i = 0; i < boot_sectors; i++) {
338+
bank->sectors[i].size = chip->sector_size / boot_sectors;
339+
bank->sectors[i].offset = i * chip->sector_size / boot_sectors;
340+
/* mark as unknown */
341+
bank->sectors[i].is_erased = -1;
342+
bank->sectors[i].is_protected = -1;
343+
}
344+
345+
for (int i = boot_sectors; i < bank->num_sectors; i++) {
316346
bank->sectors[i].size = chip->sector_size;
317-
bank->sectors[i].offset = i * chip->sector_size;
347+
bank->sectors[i].offset = ((i - boot_sectors) * chip->sector_size ) + boot_offset;
318348
/* mark as unknown */
319349
bank->sectors[i].is_erased = -1;
320350
bank->sectors[i].is_protected = -1;

0 commit comments

Comments
 (0)