Sample IAP test code for Nucleo_F091RC

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