This is an automated email from Gerrit. "Ahmed Haoues <ahmed.hao...@st.com>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/8883
-- gerrit commit 70edb53e2355d4720c9de32b79131cc81713a46a Author: HAOUES Ahmed <ahmed.hao...@st.com> Date: Tue May 27 11:42:42 2025 +0100 flash/bluenrg-x: support programming without loader fallback programming without loader when resources are not available while at there refactor reused code (wait for interrupt and command execution) Change-Id: I2cba0f53d3470bc324f4a72614c236cebf196f64 Signed-off-by: BOCHKATI Tarek <tarek.bouchk...@st.com> Signed-off-by: HAOUES Ahmed <ahmed.hao...@st.com> diff --git a/src/flash/nor/bluenrg-x.c b/src/flash/nor/bluenrg-x.c index a953e9b283..ccbbcc66eb 100644 --- a/src/flash/nor/bluenrg-x.c +++ b/src/flash/nor/bluenrg-x.c @@ -143,8 +143,45 @@ static inline int bluenrgx_write_flash_reg(struct flash_bank *bank, uint32_t reg return target_write_u32(bank->target, bluenrgx_get_flash_reg(bank, reg_offset), value); } -static int bluenrgx_erase(struct flash_bank *bank, unsigned int first, - unsigned int last) +static int bluenrgx_wait_for_interrupt(struct flash_bank *bank, uint32_t interrupt_flag) +{ + bool flag_raised = false; + for (unsigned int j = 0; j < 100; j++) { + uint32_t value; + if (bluenrgx_read_flash_reg(bank, FLASH_REG_IRQRAW, &value) != ERROR_OK) { + LOG_ERROR("Register read failed"); + return ERROR_FAIL; + } + + if (value & interrupt_flag) { + flag_raised = true; + break; + } + } + + /* clear the interrupt */ + if (flag_raised) { + if (bluenrgx_write_flash_reg(bank, FLASH_REG_IRQRAW, interrupt_flag) != ERROR_OK) { + LOG_ERROR("Cannot clear interrupt flag"); + return ERROR_FAIL; + } + + return ERROR_OK; + } + + LOG_ERROR("Erase command failed (timeout)"); + return ERROR_TIMEOUT_REACHED; +} + +static inline int bluenrgx_wait_for_command(struct flash_bank *bank) +{ + if (bluenrgx_wait_for_interrupt(bank, FLASH_INT_CMDSTART) == ERROR_OK) + return bluenrgx_wait_for_interrupt(bank, FLASH_INT_CMDDONE); + + return ERROR_FAIL; +} + +static int bluenrgx_erase(struct flash_bank *bank, unsigned int first, unsigned int last) { int retval = ERROR_OK; struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv; @@ -186,19 +223,8 @@ static int bluenrgx_erase(struct flash_bank *bank, unsigned int first, return ERROR_FAIL; } - for (unsigned int i = 0; i < 100; i++) { - uint32_t value; - if (bluenrgx_read_flash_reg(bank, FLASH_REG_IRQRAW, &value)) { - LOG_ERROR("Register write failed"); - return ERROR_FAIL; - } - if (value & FLASH_INT_CMDDONE) - break; - if (i == 99) { - LOG_ERROR("Mass erase command failed (timeout)"); - retval = ERROR_FAIL; - } - } + if (bluenrgx_wait_for_command(bank) != ERROR_OK) + return ERROR_FAIL; } else { command = FLASH_CMD_ERASE_PAGE; @@ -222,19 +248,8 @@ static int bluenrgx_erase(struct flash_bank *bank, unsigned int first, return ERROR_FAIL; } - for (unsigned int j = 0; j < 100; j++) { - uint32_t value; - if (bluenrgx_read_flash_reg(bank, FLASH_REG_IRQRAW, &value)) { - LOG_ERROR("Register write failed"); - return ERROR_FAIL; - } - if (value & FLASH_INT_CMDDONE) - break; - if (j == 99) { - LOG_ERROR("Erase command failed (timeout)"); - retval = ERROR_FAIL; - } - } + if (bluenrgx_wait_for_command(bank) != ERROR_OK) + return ERROR_FAIL; } } @@ -242,7 +257,7 @@ static int bluenrgx_erase(struct flash_bank *bank, unsigned int first, } -static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer, +static int bluenrgx_write_with_loader(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv; @@ -264,22 +279,6 @@ static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer, #include "../../../contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc" }; - /* check preconditions */ - if (!bluenrgx_info->probed) - return ERROR_FLASH_BANK_NOT_PROBED; - - if ((offset + count) > bank->size) { - LOG_ERROR("Requested write past beyond of flash size: (offset+count) = %" PRIu32 ", size=%" PRIu32, - (offset + count), - bank->size); - return ERROR_FLASH_DST_OUT_OF_BANK; - } - - if (bank->target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - if (target_alloc_working_area(target, sizeof(bluenrgx_flash_write_code), &write_algorithm) != ERROR_OK) { LOG_WARNING("no working area available, can't do block memory writes"); @@ -366,6 +365,7 @@ static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer, if (error != 0) LOG_ERROR("flash write failed = %08" PRIx32, error); } + if (retval == ERROR_OK) { uint32_t rp; /* Read back rp and check that is valid */ @@ -377,6 +377,7 @@ static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer, } } } + target_free_working_area(target, source); target_free_working_area(target, write_algorithm); target_free_working_area(target, write_algorithm_stack); @@ -391,6 +392,80 @@ static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer, return retval; } +static int bluenrgx_write_without_loader(struct flash_bank *bank, const uint8_t *buffer, + uint32_t offset, uint32_t count) +{ + struct target *target = bank->target; + unsigned int data_count = count / FLASH_DATA_WIDTH; + + while (data_count--) { + /* clear flags */ + if (bluenrgx_write_flash_reg(bank, FLASH_REG_IRQRAW, 0x3f) != ERROR_OK) { + LOG_ERROR("Register write failed"); + return ERROR_FAIL; + } + + if (bluenrgx_write_flash_reg(bank, FLASH_REG_ADDRESS, offset >> 2) != ERROR_OK) { + LOG_ERROR("Register write failed"); + return ERROR_FAIL; + } + + if (target_write_memory(target, bluenrgx_get_flash_reg(bank, FLASH_REG_DATA0), + FLASH_WORD_LEN, FLASH_DATA_WIDTH_W, buffer) != ERROR_OK) { + LOG_ERROR("Failed to write data"); + return ERROR_FAIL; + } + + if (bluenrgx_write_flash_reg(bank, FLASH_REG_COMMAND, FLASH_CMD_BURSTWRITE) != ERROR_OK) { + LOG_ERROR("Failed"); + return ERROR_FAIL; + } + + if (bluenrgx_wait_for_command(bank) != ERROR_OK) + return ERROR_FAIL; + + /* increment offset, and buffer */ + offset += FLASH_DATA_WIDTH; + buffer += FLASH_DATA_WIDTH; + } + + return ERROR_OK; +} + +static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer, + uint32_t offset, uint32_t count) +{ + struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv; + int retval = ERROR_OK; + + /* check preconditions */ + if (!bluenrgx_info->probed) + return ERROR_FLASH_BANK_NOT_PROBED; + + if ((offset + count) > bank->size) { + LOG_ERROR("Requested write past beyond of flash size: (offset+count) = %" PRIu32 ", size=%" PRIu32, + (offset + count), + bank->size); + return ERROR_FLASH_DST_OUT_OF_BANK; + } + + if (bank->target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + assert(offset % FLASH_WORD_LEN == 0); + assert(count % FLASH_WORD_LEN == 0); + + retval = bluenrgx_write_with_loader(bank, buffer, offset, count); + /* if resources are not available write without a loader */ + if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { + LOG_WARNING("falling back to programming without a flash loader (slower)"); + retval = bluenrgx_write_without_loader(bank, buffer, offset, count); + } + return retval; +} + static int bluenrgx_probe(struct flash_bank *bank) { struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv; @@ -428,7 +503,7 @@ static int bluenrgx_probe(struct flash_bank *bank) return retval; bank->size = (size_info + 1) * FLASH_WORD_LEN; - bank->num_sectors = bank->size/FLASH_PAGE_SIZE(bluenrgx_info); + bank->num_sectors = bank->size / FLASH_PAGE_SIZE(bluenrgx_info); bank->sectors = realloc(bank->sectors, sizeof(struct flash_sector) * bank->num_sectors); for (unsigned int i = 0; i < bank->num_sectors; i++) { diff --git a/src/flash/nor/bluenrg-x.h b/src/flash/nor/bluenrg-x.h index 720cb6e618..03c66cd81a 100644 --- a/src/flash/nor/bluenrg-x.h +++ b/src/flash/nor/bluenrg-x.h @@ -28,7 +28,12 @@ #define FLASH_CMD_WRITE 0x33 #define FLASH_CMD_BURSTWRITE 0xCC #define FLASH_INT_CMDDONE 0x01 +#define FLASH_INT_CMDSTART 0x02 +/* Flash Controller constants */ #define FLASH_WORD_LEN 4 +#define FLASH_DATA_WIDTH_W 4 +#define FLASH_DATA_WIDTH 16 + #endif /* OPENOCD_FLASH_NOR_BLUENRGX_H */ --