Narasimma DLN
/
NUCLEO_F091RC_IAP_UART
Sample IAP test code for Nucleo_F091RC
Diff: stm_iap.cpp
- Revision:
- 0:de2687a62a94
diff -r 000000000000 -r de2687a62a94 stm_iap.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stm_iap.cpp Sat Jun 17 07:00:41 2017 +0000 @@ -0,0 +1,138 @@ +/** + * Author: Narasimma DLN + * Email: narasimma23@gmail.com + */ + +#include "stm_iap.h" + +static uint32_t flash_sectors[FLASH_SECTORS]; +static uint16_t *flash_size_addr = (uint16_t *)FLASH_SIZE_ADDR; + +static IAPCode check_error(void); +static void unlock_flash(bool unlock); + +// Get Flash Sectors +void get_flash_sectors(void) +{ + uint8_t i; + uint32_t _addr = FLASH_START_ADDR; + + for (i=0; i<FLASH_SECTORS; i++) { + flash_sectors[i] = _addr; + _addr += FLASH_SECTOR_SIZE; + } +} + +// Get Flash Size +uint32_t get_flash_size(void) { + return *flash_size_addr * 1024; +} + + +// Get Sector Number +uint8_t get_sector_number(uint32_t _addr) { + uint8_t retval = 0; + while(1) { + //If start address of next sector is higher than wanted address, return current value + if (_addr < flash_sectors[retval + 1]) + return retval; + + retval++; + } +} + +// Get Sector Size +uint32_t get_sector_size(uint32_t _addr) +{ + uint8_t sector = get_sector_number(_addr); + return flash_sectors[sector+1] - flash_sectors[sector]; +} + +static IAPCode check_error(void) +{ + //Wait until done + while (FLASH->SR & FLASH_SR_BSY); + + //Check for errors + if (FLASH->SR & FLASH_SR_WRPERR) + return WriteProtError; + if (FLASH->SR & FLASH_SR_PGERR) + return ProgrammingError; + + return Success; +} + +// Erase a Flash Sector +IAPCode erase_sector(int address) +{ + uint8_t sec_num = get_sector_number(address); + + unlock_flash(true); + + //Clear current errors + FLASH->SR = FLASH_SR_WRPERR | FLASH_SR_PGERR; + + //Run command + // Page 1 + FLASH->CR |= FLASH_CR_PER; + FLASH->AR = flash_sectors[sec_num]; + FLASH->CR |= FLASH_CR_STRT; + while (FLASH->SR & FLASH_SR_BSY); + + // Page 2 + FLASH->CR |= FLASH_CR_PER; + FLASH->AR = flash_sectors[sec_num] + FLASH_PAGE_SIZE; + FLASH->CR |= FLASH_CR_STRT; + while (FLASH->SR & FLASH_SR_BSY); + + if ((FLASH->SR & FLASH_SR_EOP) != 0) + FLASH->SR = FLASH_SR_EOP; + + FLASH->CR &= ~FLASH_CR_PER; + + unlock_flash(false); + IAPCode retval = check_error(); + + return retval; +} + +// Unlocking Flash +static void unlock_flash(bool unlock) +{ + if (unlock) { + __disable_irq(); + //Wait until not busy + while (FLASH->SR & FLASH_SR_BSY); + if ((FLASH->CR & FLASH_CR_LOCK) != 0) { + FLASH->KEYR = 0x45670123; + FLASH->KEYR = 0xCDEF89AB; + } + } else { + FLASH->CR |= FLASH_CR_LOCK; + __enable_irq(); + } +} + +// Programming Flash Memory +IAPCode program_flash(uint32_t address, uint16_t *data, unsigned int length) +{ + unlock_flash(true); + + FLASH->CR |= FLASH_CR_PG; + + uint16_t* write_addr = (uint16_t*)address; + for (int i = 0; i<length/2; i++) { + write_addr[i] = data[i]; + while (FLASH->SR & FLASH_SR_BSY); + } + + if ((FLASH->SR & FLASH_SR_EOP) != 0) + FLASH->SR = FLASH_SR_EOP; + + IAPCode retval = check_error(); + FLASH->CR &= ~FLASH_CR_PG; + + unlock_flash(false); + + return retval; +} \ No newline at end of file