mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
cpu/cc2538: add flashpage & flashpage_raw
This commit is contained in:
parent
54e8069110
commit
dcfc7f1158
@ -10,6 +10,8 @@ config CPU_FAM_CC2538
|
||||
select CPU_CORE_CORTEX_M3
|
||||
select HAS_CPU_CC2538
|
||||
select HAS_PERIPH_CPUID
|
||||
select HAS_PERIPH_FLASHPAGE
|
||||
select HAS_PERIPH_FLASHPAGE_RAW
|
||||
select HAS_PERIPH_GPIO
|
||||
select HAS_PERIPH_GPIO_IRQ
|
||||
select HAS_PERIPH_HWRNG
|
||||
|
@ -2,6 +2,8 @@ CPU_CORE = cortex-m3
|
||||
CPU_FAM = cc2538
|
||||
|
||||
FEATURES_PROVIDED += periph_cpuid
|
||||
FEATURES_PROVIDED += periph_flashpage
|
||||
FEATURES_PROVIDED += periph_flashpage_raw
|
||||
FEATURES_PROVIDED += periph_gpio periph_gpio_irq
|
||||
FEATURES_PROVIDED += periph_hwrng
|
||||
FEATURES_PROVIDED += periph_uart_modecfg
|
||||
|
@ -1 +1,26 @@
|
||||
|
||||
# Set ROM and RAM lengths according to CPU model
|
||||
ifneq (,$(filter cc2538nf11,$(CPU_MODEL)))
|
||||
ROM_LEN ?= 128K
|
||||
RAM_LEN ?= 16K
|
||||
endif
|
||||
ifneq (,$(filter cc2538nf23,$(CPU_MODEL)))
|
||||
ROM_LEN ?= 256K
|
||||
RAM_LEN ?= 32K
|
||||
endif
|
||||
ifneq (,$(filter cc2538nf53 cc2538sf53,$(CPU_MODEL)))
|
||||
ROM_LEN ?= 512K
|
||||
RAM_LEN ?= 32K
|
||||
endif
|
||||
|
||||
ROM_START_ADDR ?= 0x00200000
|
||||
RAM_START_ADDR ?= 0x20000000
|
||||
|
||||
KB := 1024
|
||||
ROM_LEN_K := $(shell echo $(ROM_LEN) | sed 's/K//')
|
||||
FLASHSIZE := $(shell echo $$(( $(ROM_LEN_K) * $(KB) )) )
|
||||
|
||||
# Set CFLAGS
|
||||
CFLAGS += -DCC2538_FLASHSIZE=$(FLASHSIZE)U
|
||||
|
||||
include $(RIOTMAKE)/arch/cortexm.inc.mk
|
||||
|
@ -43,6 +43,34 @@ extern "C" {
|
||||
#define CPU_HAS_BITBAND (1)
|
||||
/** @} */
|
||||
|
||||
|
||||
/**
|
||||
* @brief Flash page configuration
|
||||
* @{
|
||||
*/
|
||||
#define FLASHPAGE_SIZE (2048U)
|
||||
/* Last page holds the Customer Configuration Area (CCA), this holds
|
||||
the Bootloader Backdoor Configuration, Application Entry Point,
|
||||
flashpage lock bits. For safety disable writing to that page by
|
||||
default */
|
||||
#ifndef FLASHPAGE_CC2538_USE_CCA_PAGE
|
||||
#define FLASHPAGE_CC2538_USE_CCA_PAGE (0)
|
||||
#endif
|
||||
#if FLASHPAGE_CC2538_USE_CCA_PAGE
|
||||
#define FLASHPAGE_NUMOF ((CC2538_FLASHSIZE / FLASHPAGE_SIZE))
|
||||
#else
|
||||
#define FLASHPAGE_NUMOF ((CC2538_FLASHSIZE / FLASHPAGE_SIZE) -1)
|
||||
#endif
|
||||
#define FLASH_ERASE_STATE (0x1)
|
||||
|
||||
/* The minimum block size which can be written is 4B. However, the erase
|
||||
* block is always FLASHPAGE_SIZE.
|
||||
*/
|
||||
#define FLASHPAGE_RAW_BLOCKSIZE (4U)
|
||||
/* Writing should be always 4 bytes aligned */
|
||||
#define FLASHPAGE_RAW_ALIGNMENT (4U)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name OpenWSN timing constants
|
||||
*
|
||||
|
115
cpu/cc2538/periph/flashpage.c
Normal file
115
cpu/cc2538/periph/flashpage.c
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Inria
|
||||
*
|
||||
* 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_cc2538
|
||||
* @ingroup drivers_periph_flashpage
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Implementation of the peripheral flashpage interface
|
||||
*
|
||||
* @author Francisco Molina <francois-xavier.molina@inria.fr>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "cpu.h"
|
||||
#include "irq.h"
|
||||
#include "periph/flashpage.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
#define FLASH_CTRL_FCTL_BUSY 0x00000080
|
||||
#define FLASH_CTRL_FCTL_FULL 0x00000040
|
||||
#define FLASH_CTRL_FCTL_WRITE 0x00000002
|
||||
#define FLASH_CTRL_FCTL_ERASE 0x00000001
|
||||
#define FLASH_CTRL_FCTL_CM_MASK 0x0000000C
|
||||
|
||||
__attribute__ ((section (".ramfunc")))
|
||||
static inline void _erase(uint32_t *page_addr)
|
||||
{
|
||||
/* wait for ongoing operations*/
|
||||
DEBUG("[flashpage] erase: wait for ongoing operations\n");
|
||||
while (FLASH_CTRL_FCTL & FLASH_CTRL_FCTL_BUSY) {}
|
||||
|
||||
/* disable interrupts */
|
||||
int state = irq_disable();
|
||||
|
||||
/* Initialize Flash control register without changing the cache mode.*/
|
||||
FLASH_CTRL_FCTL &= FLASH_CTRL_FCTL_CM_MASK;
|
||||
|
||||
/* set page to erase*/
|
||||
FLASH_CTRL_FADDR = (uint32_t)page_addr;
|
||||
|
||||
/* starts the write-sequence state machine */
|
||||
DEBUG("[flashpage] erase: start erase sequence at %p\n", page_addr);
|
||||
FLASH_CTRL_FCTL |= FLASH_CTRL_FCTL_ERASE;
|
||||
|
||||
/* wait erase to complete */
|
||||
while (FLASH_CTRL_FCTL & FLASH_CTRL_FCTL_BUSY) {}
|
||||
|
||||
/* re-enable interrupts */
|
||||
irq_restore(state);
|
||||
}
|
||||
|
||||
__attribute__ ((section (".ramfunc")))
|
||||
void flashpage_write_raw(void *target_addr, const void *data, size_t len)
|
||||
{
|
||||
/* assert multiples of FLASHPAGE_RAW_BLOCKSIZE are written and no less of
|
||||
that length. */
|
||||
assert(!(len % FLASHPAGE_RAW_BLOCKSIZE));
|
||||
|
||||
/* ensure writes are aligned */
|
||||
assert(!(((unsigned)target_addr % FLASHPAGE_RAW_ALIGNMENT) ||
|
||||
((unsigned)data % FLASHPAGE_RAW_ALIGNMENT)));
|
||||
|
||||
/* ensure the length doesn't exceed the actual flash size */
|
||||
assert(((unsigned)target_addr + len) <=
|
||||
(CPU_FLASH_BASE + (FLASHPAGE_SIZE * FLASHPAGE_NUMOF)));
|
||||
|
||||
uint32_t *dst = target_addr;
|
||||
const uint32_t *data_addr = data;
|
||||
|
||||
/* disable interrupts and unlock flash */
|
||||
int state = irq_disable();
|
||||
|
||||
DEBUG("[flashpage_raw] write: to %p \n", dst);
|
||||
/* Initialize Flash control register without changing the cache mode.*/
|
||||
FLASH_CTRL_FCTL &= FLASH_CTRL_FCTL_CM_MASK;
|
||||
/* set start address*/
|
||||
FLASH_CTRL_FADDR = (uint32_t) dst;
|
||||
/* starts the write-sequence state machine */
|
||||
DEBUG("[flashpage_raw] write: now writing the data\n");
|
||||
FLASH_CTRL_FCTL |= FLASH_CTRL_FCTL_WRITE;
|
||||
for (unsigned i = 0; i < (len / FLASHPAGE_RAW_BLOCKSIZE); i++) {
|
||||
FLASH_CTRL_FWDATA = (uint32_t) *(data_addr++);
|
||||
/* wait for flash operation to complete */
|
||||
while (FLASH_CTRL_FCTL & FLASH_CTRL_FCTL_FULL) {}
|
||||
}
|
||||
/* re-enable interrupts */
|
||||
irq_restore(state);
|
||||
}
|
||||
|
||||
void flashpage_write(int page, const void *data)
|
||||
{
|
||||
assert((unsigned) page < FLASHPAGE_NUMOF);
|
||||
|
||||
uint32_t *page_addr = (uint32_t *)flashpage_addr(page);
|
||||
|
||||
/* erase page */
|
||||
_erase(page_addr);
|
||||
|
||||
/* write page */
|
||||
if (data != NULL) {
|
||||
flashpage_write_raw(page_addr, data, FLASHPAGE_SIZE);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user