/* * Copyright (c) 2016 RnDity Sp. z o.o. * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #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); }