Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvements in STM32 flash driver V1 #1467

Merged
merged 1 commit into from
Oct 30, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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)
Expand All @@ -107,28 +147,31 @@ 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
CLEAR_BIT(FLASH->CR, FLASH_CR_PG);

// 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);

Expand All @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down