mirror of
git://git.code.sf.net/p/openocd/code
synced 2025-08-15 11:36:46 +10:00
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.bochkati@st.com> Signed-off-by: HAOUES Ahmed <ahmed.haoues@st.com> Reviewed-on: https://review.openocd.org/c/openocd/+/8883 Tested-by: jenkins Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
This commit is contained in:
parent
37a0f013f8
commit
2da332fa83
@ -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");
|
||||
if (bluenrgx_wait_for_command(bank) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
if (value & FLASH_INT_CMDDONE)
|
||||
break;
|
||||
if (i == 99) {
|
||||
LOG_ERROR("Mass erase command failed (timeout)");
|
||||
retval = ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
command = FLASH_CMD_ERASE_PAGE;
|
||||
@ -222,27 +248,16 @@ 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");
|
||||
if (bluenrgx_wait_for_command(bank) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
if (value & FLASH_INT_CMDDONE)
|
||||
break;
|
||||
if (j == 99) {
|
||||
LOG_ERROR("Erase command failed (timeout)");
|
||||
retval = ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user