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 */

-- 

Reply via email to