flash/nor/stm32h7x: use of wait queue flag instead of the busy flag

Based on RM0433.rev5 > Section 3.3.9 : Flash program operations:
  QW1/2: this bit indicates that a write, erase or option byte change
  operation is pending in the write queue or command queue buffer.
  It remains high until the write operation is complete.
  It supersedes the BSY1/2 status bit.

On this basis, stm32x_wait_status_busy is renamed accordingly to be
  'stm32x_wait_flash_op_queue'

Note : In this commit there is a fix of SR_ERROR_MASK value in flash loader algo
Note : This modification is mandatory for revision X, and backward compatible
  with old revisions

Change-Id: I59d2973317d76b01fbb0fb5e4a472a47d0a7a5b5
Signed-off-by: Laurent LEMELE <laurent.lemele@st.com>
Signed-off-by: Tarek BOCHKATI <tarek.bouchkati@gmail.com>
Reviewed-on: http://openocd.zylin.com/4883
Tested-by: jenkins
Reviewed-by: Christopher Head <chead@zaber.com>
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
This commit is contained in:
Tarek BOCHKATI 2019-02-07 18:30:10 +01:00 committed by Tomas Vanek
parent f78a7046a9
commit 7ee618692f
3 changed files with 29 additions and 27 deletions

View File

@ -48,8 +48,8 @@
#define STM32_FLASH_CR_OFFSET 0x0C /* offset of CR register in FLASH struct */
#define STM32_FLASH_SR_OFFSET 0x10 /* offset of SR register in FLASH struct */
#define STM32_CR_PROG 0x00000032 /* PSIZE64 | PG */
#define STM32_SR_BUSY_MASK 0x00000001 /* BSY */
#define STM32_SR_ERROR_MASK 0x03ee0000 /* DBECCERR | SNECCERR | RDSERR | RDPERR | OPERR
#define STM32_SR_QW_MASK 0x00000004 /* QW */
#define STM32_SR_ERROR_MASK 0x07ee0000 /* DBECCERR | SNECCERR | RDSERR | RDPERR | OPERR
| INCERR | STRBERR | PGSERR | WRPERR */
.thumb_func
@ -73,6 +73,7 @@ wait_fifo:
mov r7, #8 /* program by 8 words = 32 bytes */
write_flash:
dsb
ldr r6, [r5], #0x04 /* read one word from src, increment ptr */
str r6, [r2], #0x04 /* write one word to dst, increment ptr */
dsb
@ -84,7 +85,7 @@ write_flash:
busy:
ldr r6, [r4, #STM32_FLASH_SR_OFFSET]
tst r6, #STM32_SR_BUSY_MASK
tst r6, #STM32_SR_QW_MASK
bne busy /* operation in progress, wait ... */
ldr r7, =STM32_SR_ERROR_MASK

View File

@ -1,7 +1,7 @@
/* Autogenerated with ../../../../src/helper/bin2char.sh */
0x45,0x68,0x06,0x68,0x26,0xb3,0x76,0x1b,0x42,0xbf,0x76,0x18,0x36,0x1a,0x08,0x3e,
0x20,0x2e,0xf6,0xd3,0x4f,0xf0,0x32,0x06,0xe6,0x60,0x4f,0xf0,0x08,0x07,0x55,0xf8,
0x04,0x6b,0x42,0xf8,0x04,0x6b,0xbf,0xf3,0x4f,0x8f,0x8d,0x42,0x28,0xbf,0x00,0xf1,
0x08,0x05,0x01,0x3f,0xf3,0xd1,0x26,0x69,0x16,0xf0,0x01,0x0f,0xfb,0xd1,0x05,0x4f,
0x3e,0x42,0x03,0xd1,0x45,0x60,0x01,0x3b,0xdb,0xd1,0x01,0xe0,0x00,0x27,0x47,0x60,
0x30,0x46,0x00,0xbe,0x00,0x00,0xee,0x03,
0x45,0x68,0x06,0x68,0x36,0xb3,0x76,0x1b,0x42,0xbf,0x76,0x18,0x36,0x1a,0x08,0x3e,
0x20,0x2e,0xf6,0xd3,0x4f,0xf0,0x32,0x06,0xe6,0x60,0x4f,0xf0,0x08,0x07,0xbf,0xf3,
0x4f,0x8f,0x55,0xf8,0x04,0x6b,0x42,0xf8,0x04,0x6b,0xbf,0xf3,0x4f,0x8f,0x8d,0x42,
0x28,0xbf,0x00,0xf1,0x08,0x05,0x01,0x3f,0xf1,0xd1,0x26,0x69,0x16,0xf0,0x04,0x0f,
0xfb,0xd1,0x05,0x4f,0x3e,0x42,0x03,0xd1,0x45,0x60,0x01,0x3b,0xd9,0xd1,0x01,0xe0,
0x00,0x27,0x47,0x60,0x30,0x46,0x00,0xbe,0x00,0x00,0xee,0x07,

View File

@ -61,6 +61,7 @@
/* FLASH_SR register bits */
#define FLASH_BSY (1 << 0) /* Operation in progress */
#define FLASH_QW (1 << 2) /* Operation queue in progress */
#define FLASH_WRPERR (1 << 17) /* Write protection error */
#define FLASH_PGSERR (1 << 18) /* Programming sequence error */
#define FLASH_STRBERR (1 << 19) /* Strobe error */
@ -132,7 +133,7 @@ struct stm32h7x_flash_bank {
};
static const struct stm32h7x_rev stm32_450_revs[] = {
{ 0x1000, "A" }, { 0x1001, "Z" }, { 0x1003, "Y" },
{ 0x1000, "A" }, { 0x1001, "Z" }, { 0x1003, "Y" }, { 0x2001, "X" },
};
static const struct stm32h7x_part_info stm32h7x_parts[] = {
@ -184,33 +185,33 @@ static inline int stm32x_get_flash_status(struct flash_bank *bank, uint32_t *sta
return target_read_u32(target, stm32x_get_flash_reg(bank, FLASH_SR), status);
}
static int stm32x_wait_status_busy(struct flash_bank *bank, int timeout)
static int stm32x_wait_flash_op_queue(struct flash_bank *bank, int timeout)
{
struct target *target = bank->target;
struct stm32h7x_flash_bank *stm32x_info = bank->driver_priv;
uint32_t status;
int retval;
/* wait for busy to clear */
/* wait for flash operations completion */
for (;;) {
retval = stm32x_get_flash_status(bank, &status);
if (retval != ERROR_OK) {
LOG_INFO("wait_status_busy, target_read_u32 : error : remote address 0x%x", stm32x_info->flash_base);
LOG_INFO("wait_flash_op_queue, target_read_u32 : error : remote address 0x%x", stm32x_info->flash_base);
return retval;
}
if ((status & FLASH_BSY) == 0)
if ((status & FLASH_QW) == 0)
break;
if (timeout-- <= 0) {
LOG_INFO("wait_status_busy, time out expired, status: 0x%" PRIx32 "", status);
LOG_INFO("wait_flash_op_queue, time out expired, status: 0x%" PRIx32 "", status);
return ERROR_FAIL;
}
alive_sleep(1);
}
if (status & FLASH_WRPERR) {
LOG_INFO("wait_status_busy, WRPERR : error : remote address 0x%x", stm32x_info->flash_base);
LOG_INFO("wait_flash_op_queue, WRPERR : error : remote address 0x%x", stm32x_info->flash_base);
retval = ERROR_FAIL;
}
@ -393,14 +394,14 @@ static int stm32x_write_options(struct flash_bank *bank)
uint32_t status;
retval = target_read_u32(target, FLASH_REG_BASE_B0 + FLASH_SR, &status);
if (retval != ERROR_OK) {
LOG_INFO("stm32x_write_options: wait_status_busy : error");
LOG_INFO("stm32x_write_options: wait_flash_op_queue : error");
return retval;
}
if ((status & FLASH_BSY) == 0)
if ((status & FLASH_QW) == 0)
break;
if (timeout-- <= 0) {
LOG_INFO("wait_status_busy, time out expired, status: 0x%" PRIx32 "", status);
LOG_INFO("wait_flash_op_queue, time out expired, status: 0x%" PRIx32 "", status);
return ERROR_FAIL;
}
alive_sleep(1);
@ -459,12 +460,12 @@ static int stm32x_erase(struct flash_bank *bank, int first, int last)
/*
Sector Erase
To erase a sector, follow the procedure below:
1. Check that no Flash memory operation is ongoing by checking the BSY bit in the
1. Check that no Flash memory operation is ongoing by checking the QW bit in the
FLASH_SR register
2. Set the SER bit and select the sector
you wish to erase (SNB) in the FLASH_CR register
3. Set the STRT bit in the FLASH_CR register
4. Wait for the BSY bit to be cleared
4. Wait for flash operations completion
*/
for (int i = first; i <= last; i++) {
LOG_DEBUG("erase sector %d", i);
@ -480,7 +481,7 @@ static int stm32x_erase(struct flash_bank *bank, int first, int last)
LOG_ERROR("Error erase sector %d", i);
return retval;
}
retval = stm32x_wait_status_busy(bank, FLASH_ERASE_TIMEOUT);
retval = stm32x_wait_flash_op_queue(bank, FLASH_ERASE_TIMEOUT);
if (retval != ERROR_OK) {
LOG_ERROR("erase time-out or operation error sector %d", i);
@ -687,11 +688,11 @@ static int stm32x_write(struct flash_bank *bank, const uint8_t *buffer,
/*
Standard programming
The Flash memory programming sequence is as follows:
1. Check that no main Flash memory operation is ongoing by checking the BSY bit in the
1. Check that no main Flash memory operation is ongoing by checking the QW bit in the
FLASH_SR register.
2. Set the PG bit in the FLASH_CR register
3. 8 x Word access (or Force Write FW)
4. Wait for the BSY bit to be cleared
4. Wait for flash operations completion
*/
while (blocks_remaining > 0) {
retval = target_write_u32(target, stm32x_get_flash_reg(bank, FLASH_CR), FLASH_PG | FLASH_PSIZE_64);
@ -702,7 +703,7 @@ static int stm32x_write(struct flash_bank *bank, const uint8_t *buffer,
if (retval != ERROR_OK)
goto flash_lock;
retval = stm32x_wait_status_busy(bank, FLASH_WRITE_TIMEOUT);
retval = stm32x_wait_flash_op_queue(bank, FLASH_WRITE_TIMEOUT);
if (retval != ERROR_OK)
goto flash_lock;
@ -725,7 +726,7 @@ static int stm32x_write(struct flash_bank *bank, const uint8_t *buffer,
if (retval != ERROR_OK)
goto flash_lock;
retval = stm32x_wait_status_busy(bank, FLASH_WRITE_TIMEOUT);
retval = stm32x_wait_flash_op_queue(bank, FLASH_WRITE_TIMEOUT);
if (retval != ERROR_OK)
goto flash_lock;
}
@ -1038,7 +1039,7 @@ static int stm32x_mass_erase(struct flash_bank *bank)
if (retval != ERROR_OK)
return retval;
retval = stm32x_wait_status_busy(bank, 30000);
retval = stm32x_wait_flash_op_queue(bank, 30000);
if (retval != ERROR_OK)
return retval;