zephyr/drivers/flash/flash_stm32f3x_priv.c
Erwan Gouriou 221087a72e flash: update stm32 flash_f3x to support LL clock control driver
After introducing STM32Cube based clock control driver for
stm32 family, update stm32f3xx flash driver to support it.
Clean up will be done afterwards.

Change-Id: I3260bb063f714fa29adbc71d8036f20479a99b34
Signed-off-by: Erwan Gouriou <erwan.gouriou@linaro.org>
2017-02-10 14:47:41 -06:00

209 lines
4.4 KiB
C

/*
* 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;
}
uint8_t flash_stm32_program_halfword(struct device *flash,
uint32_t address,
uint16_t data)
{
uint8_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 uint16_t *)address = data;
status = flash_stm32_wait_for_last_operation(flash,
FLASH_ER_PRG_TIMEOUT);
reg->cr &= ~FLASH_CR_PG;
}
return status;
}
uint8_t flash_stm32_program_word(struct device *flash,
uint32_t address,
uint32_t data)
{
uint8_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 uint16_t *)address = (uint16_t)data;
status = flash_stm32_wait_for_last_operation(flash,
FLASH_ER_PRG_TIMEOUT);
if (status == FLASH_COMPLETE) {
address += 2;
*(volatile uint16_t *)address = data >> 16;
status = flash_stm32_wait_for_last_operation(flash,
FLASH_ER_PRG_TIMEOUT);
}
reg->cr &= ~FLASH_CR_PG;
}
return status;
}
uint8_t flash_stm32_wait_for_last_operation(struct device *flash,
uint32_t timeout)
{
uint8_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;
}
uint8_t flash_stm32_get_status(struct device *flash)
{
uint8_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) != (uint32_t)0x00) {
status = FLASH_ERROR_WRITE_PROTECTION;
break;
}
if ((reg->sr & FLASH_SR_PGERR) != (uint32_t)0x00) {
status = FLASH_ERROR_PROGRAM;
break;
}
} while (0);
return status;
}
uint8_t flash_stm32_erase_page(struct device *flash,
uint32_t page_address)
{
uint8_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;
}
uint8_t flash_stm32_erase_all_pages(struct device *flash)
{
uint8_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, uint32_t address, size_t len)
{
uint8_t *addr = INT_TO_POINTER(address);
memcpy(data, addr, len);
}