cpu/msp430_common: add flashpage_raw support
This commit is contained in:
parent
291727c9e7
commit
5368415c9a
@ -1,2 +1,3 @@
|
|||||||
FEATURES_PROVIDED += periph_flashpage
|
FEATURES_PROVIDED += periph_flashpage
|
||||||
|
FEATURES_PROVIDED += periph_flashpage_raw
|
||||||
FEATURES_PROVIDED += periph_pm
|
FEATURES_PROVIDED += periph_pm
|
||||||
|
|||||||
@ -41,6 +41,13 @@ extern "C" {
|
|||||||
#define CPU_FLASH_BASE (0x8000)
|
#define CPU_FLASH_BASE (0x8000)
|
||||||
#define FLASHPAGE_NUMOF (64U) /* 32K */
|
#define FLASHPAGE_NUMOF (64U) /* 32K */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* The minimum block size which can be written is 1B. However, the erase
|
||||||
|
* block is always FLASHPAGE_SIZE.
|
||||||
|
*/
|
||||||
|
#define FLASHPAGE_RAW_BLOCKSIZE (1U)
|
||||||
|
/* Writing should be always 2 byte aligned */
|
||||||
|
#define FLASHPAGE_RAW_ALIGNMENT (2U)
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -24,34 +24,79 @@
|
|||||||
#include "irq.h"
|
#include "irq.h"
|
||||||
#include "periph/flashpage.h"
|
#include "periph/flashpage.h"
|
||||||
|
|
||||||
|
static inline int _unlock(void)
|
||||||
|
{
|
||||||
|
int state;
|
||||||
|
state = irq_disable();
|
||||||
|
FCTL3 = FWKEY;
|
||||||
|
while (FCTL3 & BUSY) {}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void _lock(int state)
|
||||||
|
{
|
||||||
|
FCTL3 = (FWKEY | LOCK);
|
||||||
|
irq_restore(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void _erase(uint16_t *page_addr)
|
||||||
|
{
|
||||||
|
/* disable interrupts and unlock flash */
|
||||||
|
int state = _unlock();
|
||||||
|
|
||||||
|
/* erase page */
|
||||||
|
FCTL1 = (FWKEY | ERASE);
|
||||||
|
*page_addr = 0;
|
||||||
|
while (FCTL3 & BUSY) {}
|
||||||
|
|
||||||
|
/* lock flash and re-enable interrupts */
|
||||||
|
_lock(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
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)));
|
||||||
|
|
||||||
|
uint8_t *page_addr = target_addr;
|
||||||
|
const uint8_t *data_addr = data;
|
||||||
|
|
||||||
|
/* disable interrupts and unlock flash */
|
||||||
|
int state = _unlock();
|
||||||
|
|
||||||
|
/* enable write access, and write*/
|
||||||
|
FCTL1 = (FWKEY | WRT);
|
||||||
|
for (unsigned i = 0; i < len; i++) {
|
||||||
|
*(page_addr++) = *(data_addr++);
|
||||||
|
while (!(FCTL3 & WAIT)) {}
|
||||||
|
}
|
||||||
|
/* disable write access */
|
||||||
|
FCTL1 = (FWKEY);
|
||||||
|
|
||||||
|
/* lock flash and re-enable interrupts */
|
||||||
|
_lock(state);
|
||||||
|
}
|
||||||
|
|
||||||
void flashpage_write(int page, const void *data)
|
void flashpage_write(int page, const void *data)
|
||||||
{
|
{
|
||||||
assert((unsigned) page < FLASHPAGE_NUMOF);
|
assert((unsigned) page < FLASHPAGE_NUMOF);
|
||||||
|
|
||||||
const uint8_t *src = data;
|
uint16_t *page_addr = (uint16_t *)flashpage_addr(page);
|
||||||
uint8_t *dst = (uint8_t *)flashpage_addr(page);
|
|
||||||
unsigned istate;
|
|
||||||
|
|
||||||
/* disable interrupts and unlock flash */
|
|
||||||
istate = irq_disable();
|
|
||||||
FCTL3 = FWKEY;
|
|
||||||
while (FCTL3 & BUSY) {}
|
|
||||||
|
|
||||||
/* erase page */
|
/* erase page */
|
||||||
FCTL1 = (FWKEY | ERASE);
|
_erase(page_addr);
|
||||||
*dst = 0; /* erases the page */
|
|
||||||
while (FCTL3 & BUSY) {}
|
|
||||||
|
|
||||||
if (data) {
|
/* write page */
|
||||||
FCTL1 = (FWKEY | WRT);
|
if (data != NULL) {
|
||||||
for (unsigned i = 0; i < FLASHPAGE_SIZE; i++) {
|
flashpage_write_raw(page_addr, data, FLASHPAGE_SIZE);
|
||||||
*(dst++) = *(src++);
|
|
||||||
while (!(FCTL3 & WAIT)) {}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* lock flash and re-enable interrupts */
|
|
||||||
FCTL1 = (FWKEY);
|
|
||||||
FCTL3 = (FWKEY | LOCK);
|
|
||||||
irq_restore(istate);
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user