mirror of
https://github.com/andreili/katapult.git
synced 2025-08-23 19:34:06 +02:00
stm32: Avoid read-modify-write operations in flash.c
Avoid read-modify-write operations on the FLASH->CR register. Write out the desired valid explicitly. Use writew() and writel() to write the flash bytes out to avoid gcc reordering the memory write relative to the flash register writes. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
8316d2f0af
commit
9f9a872176
@ -5,6 +5,7 @@
|
||||
// This file may be distributed under the terms of the GNU GPLv3 license.
|
||||
|
||||
#include "autoconf.h" // CONFIG_MACH_STM32F103
|
||||
#include "board/io.h" // writew
|
||||
#include "flash.h" // flash_write_page
|
||||
#include "internal.h" // FLASH
|
||||
|
||||
@ -27,32 +28,37 @@ flash_get_page_size(void)
|
||||
return CONFIG_MAX_FLASH_PAGE_SIZE;
|
||||
}
|
||||
|
||||
static void
|
||||
wait_flash(void)
|
||||
{
|
||||
while (FLASH->SR & FLASH_SR_BSY)
|
||||
;
|
||||
}
|
||||
|
||||
static void
|
||||
unlock_flash(void)
|
||||
{
|
||||
// Unlock Flash Erase
|
||||
FLASH->KEYR = FLASH_KEY1;
|
||||
FLASH->KEYR = FLASH_KEY2;
|
||||
while (FLASH->SR & FLASH_SR_BSY);
|
||||
if (FLASH->CR & FLASH_CR_LOCK) {
|
||||
// Unlock Flash Erase
|
||||
FLASH->KEYR = FLASH_KEY1;
|
||||
FLASH->KEYR = FLASH_KEY2;
|
||||
}
|
||||
wait_flash();
|
||||
}
|
||||
|
||||
void
|
||||
flash_complete(void)
|
||||
static void
|
||||
lock_flash(void)
|
||||
{
|
||||
// Lock flash when done
|
||||
FLASH->CR |= FLASH_CR_LOCK;
|
||||
FLASH->CR = FLASH_CR_LOCK;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
flash_write_stm32f4xx(uint32_t page_address, uint32_t *data)
|
||||
{
|
||||
#if CONFIG_MACH_STM32F4
|
||||
uint32_t flash_page_size = flash_get_page_size();
|
||||
uint32_t* page = (uint32_t*)(page_address);
|
||||
|
||||
if (FLASH->CR & FLASH_CR_LOCK)
|
||||
unlock_flash();
|
||||
|
||||
uint8_t need_erase = 0;
|
||||
uint32_t offset_addr = page_address - CONFIG_FLASH_START;
|
||||
uint32_t sector_index = offset_addr / STM32F4_MAX_SECTOR_SIZE;
|
||||
@ -67,36 +73,29 @@ flash_write_stm32f4xx(uint32_t page_address, uint32_t *data)
|
||||
need_erase = ((page_address % STM32F4_MAX_SECTOR_SIZE) == 0);
|
||||
sector_index += 4;
|
||||
}
|
||||
while (FLASH->SR & FLASH_SR_BSY);
|
||||
FLASH->CR &= ~FLASH_CR_PSIZE;
|
||||
FLASH->CR &= ~FLASH_CR_SNB;
|
||||
|
||||
// make sure flash is unlocked
|
||||
unlock_flash();
|
||||
|
||||
// Erase page
|
||||
if (need_erase) {
|
||||
FLASH->CR |= FLASH_CR_PSIZE_1;
|
||||
FLASH->CR |= FLASH_CR_SER | ((sector_index & 0xF) << 3);
|
||||
FLASH->CR |= FLASH_CR_STRT;
|
||||
while (FLASH->SR & FLASH_SR_BSY);
|
||||
FLASH->CR &= ~FLASH_CR_SNB;
|
||||
do {
|
||||
FLASH->CR &= ~FLASH_CR_SER;
|
||||
} while(FLASH->CR & FLASH_CR_SER);
|
||||
FLASH->CR = (FLASH_CR_PSIZE_1 | FLASH_CR_STRT | FLASH_CR_SER
|
||||
| ((sector_index & 0xF) << 3));
|
||||
wait_flash();
|
||||
}
|
||||
|
||||
FLASH->CR |= FLASH_CR_PSIZE_1;
|
||||
FLASH->CR |= FLASH_CR_PG;
|
||||
for (uint16_t i = 0; i < flash_page_size / 4; i++)
|
||||
{
|
||||
page[i] = data[i];
|
||||
while (FLASH->SR & FLASH_SR_BSY);
|
||||
// Write page
|
||||
FLASH->CR = FLASH_CR_PSIZE_1 | FLASH_CR_PG;
|
||||
for (int i = 0; i < flash_page_size / 4; i++) {
|
||||
writel(&page[i], data[i]);
|
||||
wait_flash();
|
||||
}
|
||||
do {
|
||||
FLASH->CR &= ~FLASH_CR_PG;
|
||||
} while(FLASH->CR & FLASH_CR_PG);
|
||||
|
||||
FLASH->CR |= FLASH_CR_LOCK;
|
||||
lock_flash();
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
flash_write_stm32f1xx(uint32_t page_address, uint16_t *data)
|
||||
{
|
||||
#if CONFIG_MACH_STM32F0 || CONFIG_MACH_STM32F1
|
||||
@ -104,30 +103,22 @@ flash_write_stm32f1xx(uint32_t page_address, uint16_t *data)
|
||||
uint16_t* page = (uint16_t*)(page_address);
|
||||
|
||||
// make sure flash is unlocked
|
||||
if (FLASH->CR & FLASH_CR_LOCK)
|
||||
unlock_flash();
|
||||
unlock_flash();
|
||||
|
||||
// Erase page
|
||||
FLASH->CR |= FLASH_CR_PER;
|
||||
FLASH->AR = (uint32_t)page;
|
||||
FLASH->CR |= FLASH_CR_STRT;
|
||||
while (FLASH->SR & FLASH_SR_BSY);
|
||||
do {
|
||||
FLASH->CR &= ~FLASH_CR_PER;
|
||||
} while (FLASH->CR & FLASH_CR_PER);
|
||||
FLASH->CR = FLASH_CR_PER;
|
||||
FLASH->AR = page_address;
|
||||
FLASH->CR = FLASH_CR_PER | FLASH_CR_STRT;
|
||||
wait_flash();
|
||||
|
||||
// Write page
|
||||
FLASH->CR |= FLASH_CR_PG;
|
||||
for (uint16_t i = 0; i < flash_page_size / 2; i++)
|
||||
{
|
||||
page[i] = data[i];
|
||||
while (FLASH->SR & FLASH_SR_BSY);
|
||||
FLASH->CR = FLASH_CR_PG;
|
||||
for (int i = 0; i < flash_page_size / 2; i++) {
|
||||
writew(&page[i], data[i]);
|
||||
wait_flash();
|
||||
}
|
||||
do {
|
||||
FLASH->CR &= ~FLASH_CR_PG;
|
||||
} while (FLASH->CR & FLASH_CR_PG);
|
||||
|
||||
FLASH->CR |= FLASH_CR_LOCK;
|
||||
lock_flash();
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -140,3 +131,9 @@ flash_write_page(uint32_t page_address, void *data)
|
||||
flash_write_stm32f1xx(page_address, (uint16_t *)data);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
flash_complete(void)
|
||||
{
|
||||
lock_flash();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user