This is an automated email from Gerrit. "Jérôme Pouiller <[email protected]>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/9459
-- gerrit commit 0728a6534feb6d94d62cf17383760f7725b04469 Author: Jérôme Pouiller <[email protected]> Date: Wed Feb 11 16:50:01 2026 +0100 flash/nor/efm32: Fix page size for user data bank On Series-0/1 devices, the user data bank is always only one sector and the size of the page is the same than the main flash bank. On Series-2, these parameters are stored in separated registers. Reported-by: Marc Schink <[email protected]> Change-Id: Ie6bbb61dcd8d94facde47200118ff585efc0d7fb Signed-off-by: Jérôme Pouiller <[email protected]> diff --git a/src/flash/nor/efm32.c b/src/flash/nor/efm32.c index dfbc788de6..36d5342d68 100644 --- a/src/flash/nor/efm32.c +++ b/src/flash/nor/efm32.c @@ -108,6 +108,7 @@ struct efm32_msc_offset { target_addr_t off_writecmd; target_addr_t off_addrb; target_addr_t off_wdata; + target_addr_t off_userdatasize; #define EFM32_MSC_STATUS_BUSY_MASK 0x0001 #define EFM32_MSC_STATUS_LOCKED_MASK 0x0002 @@ -139,6 +140,7 @@ static const struct efm32_msc_offset efm32_msc_offset[] = { .off_wdata = 0x0018, .off_status = 0x001c, .off_lock = 0x003c, + .off_userdatasize = 0x0000, /* Does not exist in Series 0/1 */ .flash_write_code = efm32_flash_write_code_s0_s1, .flash_write_code_len = sizeof(efm32_flash_write_code_s0_s1), }, @@ -149,6 +151,7 @@ static const struct efm32_msc_offset efm32_msc_offset[] = { .off_wdata = 0x0018, .off_status = 0x001c, .off_lock = 0x0040, + .off_userdatasize = 0x0000, /* Does not exist in Series 0/1 */ .flash_write_code = efm32_flash_write_code_s0_s1, .flash_write_code_len = sizeof(efm32_flash_write_code_s0_s1), }, @@ -159,6 +162,7 @@ static const struct efm32_msc_offset efm32_msc_offset[] = { .off_wdata = 0x0018, .off_status = 0x001c, .off_lock = 0x0040, + .off_userdatasize = 0x0034, .flash_write_code = efm32_flash_write_code_s2, .flash_write_code_len = sizeof(efm32_flash_write_code_s2), }, @@ -197,7 +201,6 @@ struct efm32_family_data { /* Page size in bytes, or 0 to read from msc_di->page_size */ int page_size; - }; struct efm32_info { @@ -210,6 +213,7 @@ struct efm32_info { uint16_t flash_sz_kib; uint16_t ram_sz_kib; uint16_t page_size; + uint16_t page_size_ud; }; struct efm32_flash_chip { @@ -311,21 +315,22 @@ static int efm32_read_info(struct flash_bank *bank) { struct efm32_flash_chip *efm32_info = bank->driver_priv; struct efm32_info *efm32_mcu_info = &efm32_info->info; - uint8_t tmp; + uint8_t tmp8; + uint32_t tmp32; size_t i; int ret; memset(efm32_mcu_info, 0, sizeof(struct efm32_info)); - ret = target_read_u8(bank->target, EFM32_DI_PART_FAMILY, &tmp); + ret = target_read_u8(bank->target, EFM32_DI_PART_FAMILY, &tmp8); if (ret != ERROR_OK) return ret; for (i = 0; i < ARRAY_SIZE(efm32_families); i++) { - if (efm32_families[i].part_id == tmp) + if (efm32_families[i].part_id == tmp8) efm32_mcu_info->family_data = &efm32_families[i]; } if (!efm32_mcu_info->family_data) { - LOG_ERROR("Unknown MCU family %d", tmp); + LOG_ERROR("Unknown MCU family %d", tmp8); return ERROR_FAIL; } @@ -379,11 +384,11 @@ static int efm32_read_info(struct flash_bank *bank) } else { ret = target_read_u8(bank->target, efm32_mcu_info->di_addr->page_size, - &tmp); + &tmp8); if (ret != ERROR_OK) return ret; - efm32_mcu_info->page_size = BIT(tmp) * 1024; + efm32_mcu_info->page_size = BIT(tmp8) * 1024; } if (efm32_mcu_info->page_size != 512 && efm32_mcu_info->page_size != 1024 && @@ -393,6 +398,17 @@ static int efm32_read_info(struct flash_bank *bank) LOG_ERROR("Invalid page size %u", efm32_mcu_info->page_size); return ERROR_FAIL; } + if (efm32_mcu_info->family_data->page_size != 2) { + efm32_mcu_info->page_size_ud = efm32_mcu_info->page_size; + } else { + ret = target_read_u32(bank->target, + efm32_mcu_info->di_addr->page_size, + &tmp32); + if (ret != ERROR_OK) + return ret; + + efm32_mcu_info->page_size_ud = FIELD_GET(0x0000FF00, tmp32) * 1024; + } return ERROR_OK; } @@ -1179,8 +1195,9 @@ static int efm32_probe(struct flash_bank *bank) { struct efm32_flash_chip *efm32_info = bank->driver_priv; struct efm32_info *efm32_mcu_info = &efm32_info->info; - uint32_t base_address = EFM32_FLASH_BASE_V2; int bank_index = efm32_get_bank_index(bank->base); + uint32_t base_address = EFM32_FLASH_BASE_V2; + uint32_t page_size, userdatasize; char strbuf[256]; int ret; @@ -1210,15 +1227,25 @@ static int efm32_probe(struct flash_bank *bank) bank->sectors = NULL; if (bank->base == base_address) { - bank->num_sectors = efm32_mcu_info->flash_sz_kib * 1024 / efm32_mcu_info->page_size; + page_size = efm32_mcu_info->page_size; + bank->num_sectors = efm32_mcu_info->flash_sz_kib * 1024 / page_size; assert(bank->num_sectors > 0); - } else { + } else if (efm32_info->info.family_data->series != 2) { + page_size = efm32_mcu_info->page_size_ud; bank->num_sectors = 1; + } else { + ret = efm32_read_reg_u32(bank, + efm32_info->info.msc_offset->off_userdatasize, + &userdatasize); + if (ret != ERROR_OK) { + LOG_ERROR("Failed to read page size"); + return ret; + } + page_size = efm32_mcu_info->page_size_ud; + bank->num_sectors = (userdatasize * 256) / page_size; } - bank->size = bank->num_sectors * efm32_mcu_info->page_size; - bank->sectors = alloc_block_array(0, - efm32_mcu_info->page_size, - bank->num_sectors); + bank->size = bank->num_sectors * page_size; + bank->sectors = alloc_block_array(0, page_size, bank->num_sectors); if (!bank->sectors) return ERROR_FAIL; --
