From 455881ee5838ae2a0244c34cc45a5072e8860b72 Mon Sep 17 00:00:00 2001 From: Vincent Dupont Date: Tue, 24 Jan 2017 14:53:11 +0100 Subject: [PATCH] cpu/stm32f0: add periph/flashpage driver --- cpu/stm32f0/periph/flashpage.c | 88 ++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 cpu/stm32f0/periph/flashpage.c diff --git a/cpu/stm32f0/periph/flashpage.c b/cpu/stm32f0/periph/flashpage.c new file mode 100644 index 0000000000..1e708a2b23 --- /dev/null +++ b/cpu/stm32f0/periph/flashpage.c @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2016 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup cpu_stm32f0 + * @{ + * + * @file + * @brief Low-level flash page driver implementation + * + * @author Hauke Petersen + * + * @} + */ + +#include "cpu.h" +#include "assert.h" +#include "periph/flashpage.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +void flashpage_write(int page, void *data) +{ + assert(page < FLASHPAGE_NUMOF); + + uint16_t *page_addr = flashpage_addr(page); + uint16_t *data_addr = (uint16_t *)data; + uint32_t hsi_state = (RCC->CR & RCC_CR_HSION); + + /* the internal RC oscillator (HSI) must be enabled */ + RCC->CR |= (RCC_CR_HSION); + while (!(RCC->CR & RCC_CR_HSIRDY)) {} + + /* unlock the flash module */ + DEBUG("[flashpage] unlocking the flash module\n"); + if (FLASH->CR & FLASH_CR_LOCK) { + FLASH->KEYR = FLASH_KEY1; + FLASH->KEYR = FLASH_KEY2; + } + + /* ERASE sequence */ + /* make sure no flash operation is ongoing */ + DEBUG("[flashpage] erase: waiting for any operation to finish\n"); + while (FLASH->SR & FLASH_SR_BSY) {} + /* set page erase bit and program page address */ + DEBUG("[flashpage] erase: setting the erase bit and page address\n"); + FLASH->CR |= FLASH_CR_PER; + FLASH->AR = (uint32_t)flashpage_addr(page); + DEBUG("address to erase: %p\n", flashpage_addr(page)); + /* trigger the page erase and wait for it to be finished */ + DEBUG("[flashpage] erase: trigger the page erase\n"); + FLASH->CR |= FLASH_CR_STRT; + DEBUG("[flashpage] erase: wait as long as device is busy\n"); + while (FLASH->SR & FLASH_SR_BSY) {} + /* reset PER bit */ + DEBUG("[flashpage] erase: resetting the page erase bit\n"); + FLASH->CR &= ~(FLASH_CR_PER); + + /* WRITE sequence */ + if (data != NULL) { + DEBUG("[flashpage] write: now writing the data\n"); + /* set PG bit and program page to flash */ + FLASH->CR |= FLASH_CR_PG; + for (unsigned i = 0; i < (FLASHPAGE_SIZE / 2); i++) { + *page_addr++ = data_addr[i]; + while (FLASH->SR & FLASH_SR_BSY) {} + } + /* clear program bit again */ + FLASH->CR &= ~(FLASH_CR_PG); + DEBUG("[flashpage] write: done writing data\n"); + } + + /* finally, lock the flash module again */ + DEBUG("flashpage] now locking the flash module again\n"); + FLASH->CR |= FLASH_CR_LOCK; + + /* restore the HSI state */ + if (!hsi_state) { + RCC->CR &= ~(RCC_CR_HSION); + while (RCC->CR & RCC_CR_HSIRDY) {} + } +}