Files
edgetx-gx12/radio/src/targets/taranis/flash_driver.cpp
T

134 lines
3.1 KiB
C++

#include "../../opentx.h"
#include "stm32f2xx_flash.h"
//After reset, write is not allowed in the Flash control register (FLASH_CR) to protect the
//Flash memory against possible unwanted operations due, for example, to electric
//disturbances. The following sequence is used to unlock this register:
//1. Write KEY1 = 0x45670123 in the Flash key register (FLASH_KEYR)
//2. Write KEY2 = 0xCDEF89AB in the Flash key register (FLASH_KEYR)
//Any wrong sequence will return a bus error and lock up the FLASH_CR register until the
//next reset.
//The FLASH_CR register can be locked again by software by setting the LOCK bit in the
//FLASH_CR register.
void unlockFlash()
{
FLASH->KEYR = 0x45670123;
FLASH->KEYR = 0xCDEF89AB;
}
void lockFlash()
{
while (!FLASH->SR & FLASH_SR_BSY);
FLASH->CR |= FLASH_CR_LOCK;
}
void waitFlashIdle()
{
while (FLASH->SR & FLASH_FLAG_BSY) {
wdt_reset();
}
}
#define SECTOR_MASK ((uint32_t)0xFFFFFF07)
void eraseSector(uint32_t sector)
{
waitFlashIdle();
FLASH->CR &= CR_PSIZE_MASK;
FLASH->CR |= FLASH_PSIZE_WORD;
FLASH->CR &= SECTOR_MASK;
FLASH->CR |= FLASH_CR_SER | (sector << 3);
FLASH->CR |= FLASH_CR_STRT;
/* Wait for operation to be completed */
waitFlashIdle();
/* if the erase operation is completed, disable the SER Bit */
FLASH->CR &= (~FLASH_CR_SER);
FLASH->CR &= SECTOR_MASK;
}
void writeFlash(uint32_t *address, uint32_t *buffer) // page size is 256 bytes
{
if ((uint32_t) address == 0x08000000) {
eraseSector(0);
}
else if ((uint32_t) address == 0x08004000) {
eraseSector(1);
}
else if ((uint32_t) address == 0x08008000) {
eraseSector(2);
}
else if ((uint32_t) address == 0x0800C000) {
eraseSector(3);
}
else if ((uint32_t) address == 0x08010000) {
eraseSector(4);
}
else if ((uint32_t) address == 0x08020000) {
eraseSector(5);
}
else if ((uint32_t) address == 0x08040000) {
eraseSector(6);
}
else if ((uint32_t) address == 0x08060000) {
eraseSector(7);
}
for (uint32_t i=0; i<FLASH_PAGESIZE/4; i++) {
/* Device voltage range supposed to be [2.7V to 3.6V], the operation will
be done by word */
// Wait for last operation to be completed
waitFlashIdle();
FLASH->CR &= CR_PSIZE_MASK;
FLASH->CR |= FLASH_PSIZE_WORD;
FLASH->CR |= FLASH_CR_PG;
*address = *buffer;
/* Wait for operation to be completed */
waitFlashIdle();
FLASH->CR &= (~FLASH_CR_PG);
/* Check the written value */
if (*address != *buffer) {
/* Flash content doesn't match SRAM content */
return;
}
/* Increment FLASH destination address */
address += 1;
buffer += 1;
}
}
uint32_t isFirmwareStart(const void * buffer)
{
const uint32_t * block = (const uint32_t *)buffer;
if ((block[0] & 0xFFFC0000) != 0x20000000) {
return 0;
}
if ((block[1] & 0xFFF00000) != 0x08000000) {
return 0;
}
if ((block[2] & 0xFFF00000) != 0x08000000) {
return 0;
}
return 1;
}
uint32_t isBootloaderStart(const void * buffer)
{
const uint32_t * block = (const uint32_t *)buffer;
for (int i=0; i<256; i++) {
if (block[i] == 0x544F4F42/*BOOT*/) {
return 1;
}
}
return 0;
}