diff --git a/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv1/flash_lld.c b/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv1/flash_lld.c index 16a727ca5c..081969539f 100644 --- a/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv1/flash_lld.c +++ b/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv1/flash_lld.c @@ -33,38 +33,73 @@ SMT32FlashDriver STM32FLASH; // Unlock the FLASH control register access bool HAL_FLASH_Unlock(void) { - if (HAL_IS_BIT_SET(FLASH->CR, FLASH_CR_LOCK)) + bool status = true; + + if(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != RESET) { - /* Authorize the FLASH Registers access */ + // Authorize the FLASH Registers access WRITE_REG(FLASH->KEYR, FLASH_KEY1); WRITE_REG(FLASH->KEYR, FLASH_KEY2); - } - else - { - return false; + + // Verify Flash is unlocked + if(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != RESET) + { + status = false; + } } - return true; + return status; } // Locks the FLASH control register access bool HAL_FLASH_Lock(void) { - /* Set the LOCK Bit to lock the FLASH Registers access */ + // Set the LOCK Bit to lock the FLASH Registers access SET_BIT(FLASH->CR, FLASH_CR_LOCK); return true; } +bool FLASH_WaitForLastOperation(uint32_t timeout) +{ + (void)timeout; + + bool success = true; + + // Wait for the FLASH operation to complete by polling on BUSY flag to be reset. + // Even if the FLASH operation fails, the BUSY flag will be reset and an error flag will be set + // no need to overload this with a timeout workflow as the watchdog will quick-in if execution gets stuck + + while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)); + + // Check FLASH End of Operation flag + if( __HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP) ) + { + // Clear FLASH End of Operation pending bit + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP); + } + + if( __HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR) || + __HAL_FLASH_GET_FLAG(FLASH_FLAG_PGERR)) + { + // at this point we don't care about the details of the programming error + success = false; + } + + return success; +} + /////////////////////////////////////////////////////////////////////////////// // Driver exported functions. // /////////////////////////////////////////////////////////////////////////////// -void flash_lld_init() { +void flash_lld_init() +{ stm32FlashObjectInit(&STM32FLASH); } -void flash_lld_readBytes(uint32_t startAddress, uint32_t length, uint8_t* buffer) { +void flash_lld_readBytes(uint32_t startAddress, uint32_t length, uint8_t* buffer) +{ __IO uint8_t* cursor = (__IO uint8_t*)startAddress; __IO uint8_t* endAddress = (__IO uint8_t*)(startAddress + length); @@ -76,19 +111,24 @@ void flash_lld_readBytes(uint32_t startAddress, uint32_t length, uint8_t* buffer } } -int flash_lld_write(uint32_t startAddress, uint32_t length, const uint8_t* buffer) { - +int flash_lld_write(uint32_t startAddress, uint32_t length, const uint8_t* buffer) +{ + bool success = true; + __IO uint8_t* cursor = (__IO uint8_t*)startAddress; __IO uint8_t* endAddress = (__IO uint8_t*)(startAddress + length); // unlock the FLASH if(HAL_FLASH_Unlock()) { - // proceed to program the flash by setting the PG Bit - SET_BIT(FLASH->CR, FLASH_CR_PG); + // Clear pending flags (if any) + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); while(cursor < endAddress) { + // proceed to program the flash by setting the PG Bit + SET_BIT(FLASH->CR, FLASH_CR_PG); + // if buffer has enough data, program half-words (16 bits) in a single operation to speed up things // NOTE: assuming that the supply voltage is able to cope with half-word programming if((endAddress - cursor) >= 2) @@ -107,10 +147,17 @@ int flash_lld_write(uint32_t startAddress, uint32_t length, const uint8_t* buffe // update flash pointer by the 'extra' byte that was programmed cursor += 2; } - - // wait for program operation to be completed - // TODO: add a timeout here using an OS function - while(((FLASH->SR) & (FLASH_FLAG_BSY)) == (FLASH_FLAG_BSY)){}; + + // wait for any flash operation to be completed + // timeout set to 0 on purpose + // watchdog will quick-in if execution gets stuck + success = FLASH_WaitForLastOperation(0); + + if(!success) + { + // quit on failure + break; + } } // after the program operation is completed disable the PG Bit @@ -118,17 +165,13 @@ int flash_lld_write(uint32_t startAddress, uint32_t length, const uint8_t* buffe // lock the FLASH HAL_FLASH_Lock(); - - // done here - return true; } - // default to false - return false; + return success; } -int flash_lld_isErased(uint32_t startAddress, uint32_t length) { - +int flash_lld_isErased(uint32_t startAddress, uint32_t length) +{ __IO uint32_t* cursor = (__IO uint32_t*)startAddress; __IO uint32_t* endAddress = (__IO uint32_t*)(startAddress + length); @@ -152,32 +195,33 @@ uint8_t flash_lld_getSector(uint32_t address) return (address - FLASH_BASE) / F0_SERIES_SECTOR_SIZE; } -int flash_lld_erase(uint32_t address) { +int flash_lld_erase(uint32_t address) +{ + bool success = true; - // unlock the FLASH + //unlock the FLASH if(HAL_FLASH_Unlock()) { + // Clear pending flags (if any) + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); + // erase the page SET_BIT(FLASH->CR, FLASH_CR_PER); WRITE_REG(FLASH->AR, address); SET_BIT(FLASH->CR, FLASH_CR_STRT); - // wait for erase operation to be completed - // TODO: add a timeout here using an OS function - while(((FLASH->SR) & (FLASH_FLAG_BSY)) == (FLASH_FLAG_BSY)){}; + // wait for any flash operation to be completed + // watchdog will quick-in if execution gets stuck + success = FLASH_WaitForLastOperation(0); // after erase operation completed disable the PER Bit CLEAR_BIT(FLASH->CR, FLASH_CR_PER); // lock the FLASH HAL_FLASH_Lock(); - - // done here - return true; } - // default to false - return false; + return success; } #endif diff --git a/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv1/flash_lld.h b/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv1/flash_lld.h index 0e4186226d..8bcce8b4c9 100644 --- a/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv1/flash_lld.h +++ b/targets/CMSIS-OS/ChibiOS/nf-overlay/os/hal/ports/STM32/LLD/FLASHv1/flash_lld.h @@ -44,16 +44,12 @@ typedef struct SMT32FlashDriver { #define FLASH ((FLASH_TypeDef *) FLASH_R_BASE) #define HAL_IS_BIT_SET(REG, BIT) (((REG) & (BIT)) != RESET) -#define FLASH_FLAG_EOP FLASH_SR_EOP /*!< FLASH End of Operation flag */ -#define FLASH_FLAG_OPERR FLASH_SR_SOP /*!< FLASH operation Error flag */ -#define FLASH_FLAG_WRPERR FLASH_SR_WRPERR /*!< FLASH Write protected error flag */ -#define FLASH_FLAG_PGAERR FLASH_SR_PGAERR /*!< FLASH Programming Alignment error flag */ -#define FLASH_FLAG_PGPERR FLASH_SR_PGPERR /*!< FLASH Programming Parallelism error flag */ -#define FLASH_FLAG_PGSERR FLASH_SR_PGSERR /*!< FLASH Programming Sequence error flag */ -#if defined(FLASH_SR_RDERR) -#define FLASH_FLAG_RDERR FLASH_SR_RDERR /*!< Read Protection error flag (PCROP) */ -#endif /* FLASH_SR_RDERR */ -#define FLASH_FLAG_BSY FLASH_SR_BSY /*!< FLASH Busy flag */ +#define FLASH_FLAG_BSY FLASH_SR_BSY //!< FLASH Busy flag +#define FLASH_FLAG_PGERR FLASH_SR_PGERR //!< FLASH Programming error flag +#define FLASH_FLAG_WRPERR FLASH_SR_WRPERR //!< FLASH Write protected error flag +#define FLASH_FLAG_EOP FLASH_SR_EOP //!< FLASH End of Operation flag + +#define FLASH_FLAG_ALL_ERRORS ( FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR ) // FLASH_Program_Parallelism FLASH Program Parallelism #define FLASH_PSIZE_BYTE ((uint32_t)0x00000000U)