437 lines
12 KiB
C
437 lines
12 KiB
C
/* -----------------------------------------------------------------------------
|
|
* Copyright (c) 2014 ARM Ltd.
|
|
*
|
|
* This software is provided 'as-is', without any express or implied warranty.
|
|
* In no event will the authors be held liable for any damages arising from
|
|
* the use of this software. Permission is granted to anyone to use this
|
|
* software for any purpose, including commercial applications, and to alter
|
|
* it and redistribute it freely, subject to the following restrictions:
|
|
*
|
|
* 1. The origin of this software must not be misrepresented; you must not
|
|
* claim that you wrote the original software. If you use this software in
|
|
* a product, an acknowledgment in the product documentation would be
|
|
* appreciated but is not required.
|
|
*
|
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
|
* misrepresented as being the original software.
|
|
*
|
|
* 3. This notice may not be removed or altered from any source distribution.
|
|
*
|
|
*
|
|
* $Date: 15. April 2014
|
|
* $Revision: V1.00
|
|
*
|
|
* Project: Flash Programming Functions for ST Microelectronics STM32F10x Flash
|
|
* --------------------------------------------------------------------------- */
|
|
|
|
/* History:
|
|
* Version 1.00
|
|
* Initial release
|
|
*/
|
|
|
|
#include "FlashOS.H" // FlashOS Structures
|
|
|
|
typedef volatile unsigned char vu8;
|
|
typedef volatile unsigned long vu32;
|
|
typedef volatile unsigned short vu16;
|
|
|
|
#define M8(adr) (*((vu8 *) (adr)))
|
|
#define M16(adr) (*((vu16 *) (adr)))
|
|
#define M32(adr) (*((vu32 *) (adr)))
|
|
|
|
// Peripheral Memory Map
|
|
#define IWDG_BASE 0x40003000
|
|
#define FLASH_BASE 0x40022000
|
|
|
|
#define IWDG ((IWDG_TypeDef *) IWDG_BASE)
|
|
#define FLASH ((FLASH_TypeDef*) FLASH_BASE)
|
|
|
|
// FLASH BANK size
|
|
#define BANK1_SIZE 0x00080000 // Bank1 Size = 512kB
|
|
|
|
// Independent WATCHDOG
|
|
typedef struct {
|
|
vu32 KR;
|
|
vu32 PR;
|
|
vu32 RLR;
|
|
vu32 SR;
|
|
} IWDG_TypeDef;
|
|
|
|
// Flash Registers
|
|
typedef struct {
|
|
vu32 ACR; // offset 0x000
|
|
vu32 KEYR; // offset 0x004
|
|
vu32 OPTKEYR; // offset 0x008
|
|
vu32 SR; // offset 0x00C
|
|
vu32 CR; // offset 0x010
|
|
vu32 AR; // offset 0x014
|
|
vu32 RESERVED0[1];
|
|
vu32 OBR; // offset 0x01C
|
|
vu32 WRPR; // offset 0x020
|
|
#ifdef STM32F10x_1024
|
|
vu32 RESERVED1[8];
|
|
vu32 KEYR2; // offset 0x044
|
|
vu32 RESERVED2[1];
|
|
vu32 SR2; // offset 0x04C
|
|
vu32 CR2; // offset 0x050
|
|
vu32 AR2; // offset 0x054
|
|
#endif
|
|
} FLASH_TypeDef;
|
|
|
|
|
|
// Flash Keys
|
|
#define RDPRT_KEY 0x5AA5
|
|
#define FLASH_KEY1 0x45670123
|
|
#define FLASH_KEY2 0xCDEF89AB
|
|
|
|
// Flash Control Register definitions
|
|
#define FLASH_PG 0x00000001
|
|
#define FLASH_PER 0x00000002
|
|
#define FLASH_MER 0x00000004
|
|
#define FLASH_OPTPG 0x00000010
|
|
#define FLASH_OPTER 0x00000020
|
|
#define FLASH_STRT 0x00000040
|
|
#define FLASH_LOCK 0x00000080
|
|
#define FLASH_OPTWRE 0x00000100
|
|
|
|
// Flash Status Register definitions
|
|
#define FLASH_BSY 0x00000001
|
|
#define FLASH_PGERR 0x00000004
|
|
#define FLASH_WRPRTERR 0x00000010
|
|
#define FLASH_EOP 0x00000020
|
|
|
|
|
|
unsigned long base_adr;
|
|
|
|
|
|
/*
|
|
* Initialize Flash Programming Functions
|
|
* Parameter: adr: Device Base Address
|
|
* clk: Clock Frequency (Hz)
|
|
* fnc: Function Code (1 - Erase, 2 - Program, 3 - Verify)
|
|
* Return Value: 0 - OK, 1 - Failed
|
|
*/
|
|
|
|
#ifdef FLASH_MEM
|
|
int Init (unsigned long adr, unsigned long clk, unsigned long fnc) {
|
|
|
|
base_adr = adr & ~(BANK1_SIZE - 1); // Align to Size Boundary
|
|
|
|
// Zero Wait State
|
|
FLASH->ACR = 0x00000000;
|
|
|
|
// Unlock Flash
|
|
FLASH->KEYR = FLASH_KEY1;
|
|
FLASH->KEYR = FLASH_KEY2;
|
|
#ifdef STM32F10x_1024
|
|
FLASH->KEYR2 = FLASH_KEY1; // Flash bank 2
|
|
FLASH->KEYR2 = FLASH_KEY2;
|
|
#endif
|
|
|
|
// Test if IWDG is running (IWDG in HW mode)
|
|
if ((FLASH->OBR & 0x04) == 0x00) {
|
|
// Set IWDG time out to ~32.768 second
|
|
IWDG->KR = 0x5555; // Enable write access to IWDG_PR and IWDG_RLR
|
|
IWDG->PR = 0x06; // Set prescaler to 256
|
|
IWDG->RLR = 4095; // Set reload value to 4095
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
#endif
|
|
|
|
#ifdef FLASH_OPT
|
|
int Init (unsigned long adr, unsigned long clk, unsigned long fnc) {
|
|
|
|
// Zero Wait State
|
|
FLASH->ACR = 0x00000000;
|
|
|
|
// Unlock Flash
|
|
FLASH->KEYR = FLASH_KEY1;
|
|
FLASH->KEYR = FLASH_KEY2;
|
|
|
|
// Unlock Option Bytes
|
|
FLASH->OPTKEYR = FLASH_KEY1;
|
|
FLASH->OPTKEYR = FLASH_KEY2;
|
|
|
|
// Test if IWDG is running (IWDG in HW mode)
|
|
if ((FLASH->OBR & 0x04) == 0x00) {
|
|
// Set IWDG time out to ~32.768 second
|
|
IWDG->KR = 0x5555; // Enable write access to IWDG_PR and IWDG_RLR
|
|
IWDG->PR = 0x06; // Set prescaler to 256
|
|
IWDG->RLR = 4095; // Set reload value to 4095
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
* De-Initialize Flash Programming Functions
|
|
* Parameter: fnc: Function Code (1 - Erase, 2 - Program, 3 - Verify)
|
|
* Return Value: 0 - OK, 1 - Failed
|
|
*/
|
|
|
|
#ifdef FLASH_MEM
|
|
int UnInit (unsigned long fnc) {
|
|
|
|
// Lock Flash
|
|
FLASH->CR |= FLASH_LOCK;
|
|
#ifdef STM32F10x_1024
|
|
FLASH->CR2 |= FLASH_LOCK; // Flash bank 2
|
|
#endif
|
|
|
|
return (0);
|
|
}
|
|
#endif
|
|
|
|
#ifdef FLASH_OPT
|
|
int UnInit (unsigned long fnc) {
|
|
|
|
// Lock Flash & Option Bytes
|
|
FLASH->CR &= ~FLASH_OPTWRE;
|
|
FLASH->CR |= FLASH_LOCK;
|
|
|
|
return (0);
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
* Erase complete Flash Memory
|
|
* Return Value: 0 - OK, 1 - Failed
|
|
*/
|
|
|
|
#ifdef FLASH_MEM
|
|
int EraseChip (void) {
|
|
|
|
FLASH->CR |= FLASH_MER; // Mass Erase Enabled
|
|
FLASH->CR |= FLASH_STRT; // Start Erase
|
|
|
|
while (FLASH->SR & FLASH_BSY) {
|
|
IWDG->KR = 0xAAAA; // Reload IWDG
|
|
}
|
|
|
|
FLASH->CR &= ~FLASH_MER; // Mass Erase Disabled
|
|
|
|
#ifdef STM32F10x_1024 // Flash bank 2
|
|
FLASH->CR2 |= FLASH_MER;
|
|
FLASH->CR2 |= FLASH_STRT;
|
|
|
|
while (FLASH->SR2 & FLASH_BSY) {
|
|
IWDG->KR = 0xAAAA;
|
|
}
|
|
|
|
FLASH->CR2 &= ~FLASH_MER;
|
|
#endif
|
|
|
|
return (0); // Done
|
|
}
|
|
#endif
|
|
|
|
#ifdef FLASH_OPT
|
|
int EraseChip (void) {
|
|
|
|
FLASH->CR |= FLASH_OPTER; // Option Byte Erase Enabled
|
|
FLASH->CR |= FLASH_STRT; // Start Erase
|
|
|
|
while (FLASH->SR & FLASH_BSY) {
|
|
IWDG->KR = 0xAAAA; // Reload IWDG
|
|
}
|
|
|
|
FLASH->CR &= ~FLASH_OPTER; // Option Byte Erase Disabled
|
|
|
|
// Unprotect Flash
|
|
|
|
FLASH->CR |= FLASH_OPTPG; // Option Byte Programming Enabled
|
|
|
|
M16(0x1FFFF800) = RDPRT_KEY; // Program Half Word: RDPRT Key
|
|
while (FLASH->SR & FLASH_BSY) {
|
|
IWDG->KR = 0xAAAA; // Reload IWDG
|
|
}
|
|
|
|
FLASH->CR &= ~FLASH_OPTPG; // Option Byte Programming Disabled
|
|
|
|
// Check for Errors
|
|
if (FLASH->SR & (FLASH_PGERR | FLASH_WRPRTERR)) {
|
|
FLASH->SR |= FLASH_PGERR | FLASH_WRPRTERR;
|
|
return (1); // Failed
|
|
}
|
|
|
|
return (0); // Done
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
* Erase Sector in Flash Memory
|
|
* Parameter: adr: Sector Address
|
|
* Return Value: 0 - OK, 1 - Failed
|
|
*/
|
|
|
|
#ifdef FLASH_MEM
|
|
int EraseSector (unsigned long adr) {
|
|
|
|
#ifdef STM32F10x_1024
|
|
if (adr < (base_adr + BANK1_SIZE)) { // Flash bank 2
|
|
#endif
|
|
FLASH->CR |= FLASH_PER; // Page Erase Enabled
|
|
FLASH->AR = adr; // Page Address
|
|
FLASH->CR |= FLASH_STRT; // Start Erase
|
|
|
|
while (FLASH->SR & FLASH_BSY) {
|
|
IWDG->KR = 0xAAAA; // Reload IWDG
|
|
}
|
|
|
|
FLASH->CR &= ~FLASH_PER; // Page Erase Disabled
|
|
#ifdef STM32F10x_1024
|
|
}
|
|
else { // Flash bank 2
|
|
FLASH->CR2 |= FLASH_PER;
|
|
FLASH->AR2 = adr;
|
|
FLASH->CR2 |= FLASH_STRT;
|
|
|
|
while (FLASH->SR2 & FLASH_BSY) {
|
|
IWDG->KR = 0xAAAA;
|
|
}
|
|
|
|
FLASH->CR2 &= ~FLASH_PER;
|
|
}
|
|
#endif
|
|
|
|
return (0); // Done
|
|
}
|
|
#endif
|
|
|
|
#ifdef FLASH_OPT
|
|
int EraseSector (unsigned long adr) {
|
|
|
|
FLASH->CR |= FLASH_OPTER; // Option Byte Erase Enabled
|
|
FLASH->CR |= FLASH_STRT; // Start Erase
|
|
|
|
while (FLASH->SR & FLASH_BSY) {
|
|
IWDG->KR = 0xAAAA; // Reload IWDG
|
|
}
|
|
|
|
FLASH->CR &= ~FLASH_OPTER; // Option Byte Erase Disabled
|
|
|
|
return (0); // Done
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
* Blank Check Checks if Memory is Blank
|
|
* Parameter: adr: Block Start Address
|
|
* sz: Block Size (in bytes)
|
|
* pat: Block Pattern
|
|
* Return Value: 0 - OK, 1 - Failed
|
|
*/
|
|
|
|
#ifdef FLASH_OPT
|
|
int BlankCheck (unsigned long adr, unsigned long sz, unsigned char pat) {
|
|
return (1); // Always Force Erase
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
* Program Page in Flash Memory
|
|
* Parameter: adr: Page Start Address
|
|
* sz: Page Size
|
|
* buf: Page Data
|
|
* Return Value: 0 - OK, 1 - Failed
|
|
*/
|
|
|
|
#ifdef FLASH_MEM
|
|
int ProgramPage (unsigned long adr, unsigned long sz, unsigned char *buf) {
|
|
|
|
sz = (sz + 1) & ~1; // Adjust size for Half Words
|
|
|
|
#ifdef STM32F10x_1024
|
|
if (adr < (base_adr + BANK1_SIZE)) { // Flash bank 2
|
|
#endif
|
|
while (sz) {
|
|
|
|
FLASH->CR |= FLASH_PG; // Programming Enabled
|
|
|
|
M16(adr) = *((unsigned short *)buf); // Program Half Word
|
|
while (FLASH->SR & FLASH_BSY);
|
|
|
|
FLASH->CR &= ~FLASH_PG; // Programming Disabled
|
|
|
|
// Check for Errors
|
|
if (FLASH->SR & (FLASH_PGERR | FLASH_WRPRTERR)) {
|
|
FLASH->SR |= FLASH_PGERR | FLASH_WRPRTERR;
|
|
return (1); // Failed
|
|
}
|
|
|
|
// Go to next Half Word
|
|
adr += 2;
|
|
buf += 2;
|
|
sz -= 2;
|
|
}
|
|
#ifdef STM32F10x_1024
|
|
}
|
|
else { // Flash bank 2
|
|
while (sz) {
|
|
|
|
FLASH->CR2 |= FLASH_PG;
|
|
|
|
M16(adr) = *((unsigned short *)buf);
|
|
while (FLASH->SR2 & FLASH_BSY);
|
|
|
|
FLASH->CR2 &= ~FLASH_PG;
|
|
|
|
// Check for Errors
|
|
if (FLASH->SR2 & (FLASH_PGERR | FLASH_WRPRTERR)) {
|
|
FLASH->SR2 |= FLASH_PGERR | FLASH_WRPRTERR;
|
|
return (1);
|
|
}
|
|
|
|
// Go to next Half Word
|
|
adr += 2;
|
|
buf += 2;
|
|
sz -= 2;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return (0); // Done
|
|
}
|
|
#endif
|
|
|
|
#ifdef FLASH_OPT
|
|
int ProgramPage (unsigned long adr, unsigned long sz, unsigned char *buf) {
|
|
|
|
sz = (sz + 1) & ~1; // Adjust size for Half Words
|
|
|
|
while (sz) {
|
|
|
|
FLASH->CR |= FLASH_OPTPG; // Option Byte Programming Enabled
|
|
|
|
M16(adr) = *((unsigned short *)buf); // Program Half Word
|
|
while (FLASH->SR & FLASH_BSY) {
|
|
IWDG->KR = 0xAAAA; // Reload IWDG
|
|
}
|
|
|
|
FLASH->CR &= ~FLASH_OPTPG; // Option Byte Programming Disabled
|
|
|
|
// Check for Errors
|
|
if (FLASH->SR & (FLASH_PGERR | FLASH_WRPRTERR)) {
|
|
FLASH->SR |= FLASH_PGERR | FLASH_WRPRTERR;
|
|
return (1); // Failed
|
|
}
|
|
|
|
// Go to next Half Word
|
|
adr += 2;
|
|
buf += 2;
|
|
sz -= 2;
|
|
|
|
}
|
|
|
|
return (0); // Done
|
|
}
|
|
#endif
|