blob: ee2a33a4fb6b598325da73232a2c1cc6444b2963 [file] [log] [blame]
/*
* Copyright (c) 2016 RnDity Sp. z o.o.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <clock_control/stm32_clock_control.h>
#include <misc/__assert.h>
#include <string.h>
#include "flash_stm32f3x.h"
void flash_stm32_unlock(struct device *flash)
{
const struct flash_stm32_dev_config *config = FLASH_CFG(flash);
volatile struct stm32_flash *reg = FLASH_STRUCT(config->base);
if ((reg->cr & FLASH_CR_LOCK) != 0) {
/* Authorize the FLASH Registers access */
reg->keyr = FLASH_KEY1;
reg->keyr = FLASH_KEY2;
}
}
void flash_stm32_lock(struct device *flash)
{
const struct flash_stm32_dev_config *config = FLASH_CFG(flash);
volatile struct stm32_flash *reg = FLASH_STRUCT(config->base);
reg->cr |= FLASH_CR_LOCK;
}
u8_t flash_stm32_program_halfword(struct device *flash,
u32_t address,
u16_t data)
{
u8_t status = FLASH_COMPLETE;
const struct flash_stm32_dev_config *config = FLASH_CFG(flash);
volatile struct stm32_flash *reg = FLASH_STRUCT(config->base);
__ASSERT_NO_MSG(IS_FLASH_PROGRAM_ADDRESS(address));
status = flash_stm32_wait_for_last_operation(flash,
FLASH_ER_PRG_TIMEOUT);
if (status == FLASH_COMPLETE) {
reg->cr |= FLASH_CR_PG;
*(volatile u16_t *)address = data;
status = flash_stm32_wait_for_last_operation(flash,
FLASH_ER_PRG_TIMEOUT);
reg->cr &= ~FLASH_CR_PG;
}
return status;
}
u8_t flash_stm32_program_word(struct device *flash,
u32_t address,
u32_t data)
{
u8_t status = FLASH_COMPLETE;
const struct flash_stm32_dev_config *config = FLASH_CFG(flash);
volatile struct stm32_flash *reg = FLASH_STRUCT(config->base);
__ASSERT_NO_MSG(IS_FLASH_PROGRAM_ADDRESS(address));
status = flash_stm32_wait_for_last_operation(flash,
FLASH_ER_PRG_TIMEOUT);
if (status == FLASH_COMPLETE) {
reg->cr |= FLASH_CR_PG;
*(volatile u16_t *)address = (u16_t)data;
status = flash_stm32_wait_for_last_operation(flash,
FLASH_ER_PRG_TIMEOUT);
if (status == FLASH_COMPLETE) {
address += 2;
*(volatile u16_t *)address = data >> 16;
status = flash_stm32_wait_for_last_operation(flash,
FLASH_ER_PRG_TIMEOUT);
}
reg->cr &= ~FLASH_CR_PG;
}
return status;
}
u8_t flash_stm32_wait_for_last_operation(struct device *flash,
u32_t timeout)
{
u8_t status = FLASH_COMPLETE;
/* Check for the FLASH Status */
status = flash_stm32_get_status(flash);
/* Wait for a FLASH operation to complete or a TIMEOUT to occur. */
while ((status == FLASH_BUSY) && (timeout != 0x00)) {
status = flash_stm32_get_status(flash);
timeout--;
}
if (timeout == 0x00) {
status = FLASH_TIMEOUT;
}
return status;
}
u8_t flash_stm32_get_status(struct device *flash)
{
u8_t status = FLASH_COMPLETE;
const struct flash_stm32_dev_config *config = FLASH_CFG(flash);
volatile struct stm32_flash *reg = FLASH_STRUCT(config->base);
do {
if ((reg->sr & FLASH_SR_BSY) == FLASH_SR_BSY) {
status = FLASH_BUSY;
break;
}
if ((reg->sr & FLASH_SR_WRPERR) != (u32_t)0x00) {
status = FLASH_ERROR_WRITE_PROTECTION;
break;
}
if ((reg->sr & FLASH_SR_PGERR) != (u32_t)0x00) {
status = FLASH_ERROR_PROGRAM;
break;
}
} while (0);
return status;
}
u8_t flash_stm32_erase_page(struct device *flash,
u32_t page_address)
{
u8_t status = FLASH_COMPLETE;
const struct flash_stm32_dev_config *config = FLASH_CFG(flash);
volatile struct stm32_flash *reg = FLASH_STRUCT(config->base);
__ASSERT_NO_MSG(IS_FLASH_PROGRAM_ADDRESS(page_address));
status = flash_stm32_wait_for_last_operation(flash,
FLASH_ER_PRG_TIMEOUT);
if (status == FLASH_COMPLETE) {
reg->cr |= FLASH_CR_PER;
reg->ar = page_address;
reg->cr |= FLASH_CR_STRT;
status = flash_stm32_wait_for_last_operation(flash,
FLASH_ER_PRG_TIMEOUT);
reg->cr &= ~FLASH_CR_PER;
}
return status;
}
u8_t flash_stm32_erase_all_pages(struct device *flash)
{
u8_t status = FLASH_COMPLETE;
const struct flash_stm32_dev_config *config = FLASH_CFG(flash);
volatile struct stm32_flash *reg = FLASH_STRUCT(config->base);
status = flash_stm32_wait_for_last_operation(flash,
FLASH_ER_PRG_TIMEOUT);
if (status == FLASH_COMPLETE) {
reg->cr |= FLASH_CR_MER;
reg->cr |= FLASH_CR_STRT;
status = flash_stm32_wait_for_last_operation(flash,
FLASH_ER_PRG_TIMEOUT);
reg->cr &= ~FLASH_CR_MER;
}
return status;
}
void flash_stm32_read_data(void *data, u32_t address, size_t len)
{
u8_t *addr = INT_TO_POINTER(address);
memcpy(data, addr, len);
}