Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed DS18B20 TextLCD
flash.h
- Committer:
- KamilCuk
- Date:
- 2020-02-13
- Revision:
- 0:55c37ea095b0
File content as of revision 0:55c37ea095b0:
#ifndef FLASH_H
#define FLASH_H
#include "mbed.h"
#include <cassert>
#include <limits>
void lcd_println(const char *fmt, ...);
extern "C" void d(const char *fmt, ...);
namespace flash {
static inline void _page_erase(uint32_t page) {
uint32_t page_error = 0;
FLASH_EraseInitTypeDef s_eraseinit;
s_eraseinit.TypeErase = FLASH_TYPEERASE_PAGES;
s_eraseinit.PageAddress = page;
s_eraseinit.NbPages = 1;
const HAL_StatusTypeDef status =
HAL_FLASHEx_Erase(&s_eraseinit, &page_error);
if (status) d("ERR: HFP %d", status);
}
static const uintptr_t _page = 0x0800F400;
static const uint16_t _mark = 0xbeef + 1;
static inline void _write16(uintptr_t address, uint16_t val) {
// d("W %lx=%04x", _page + address, val);
const HAL_StatusTypeDef status =
HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, _page + address * 2, val);
if (status) d("ERR: HFP %d", status);
}
static inline uint16_t _read16(uintptr_t address) {
const uint16_t val = *(volatile uint16_t *)(_page + address * 2);
// d("RR %lx=%04x", _page + address, val);
return val;
}
static inline void write(const void *data, size_t len) {
assert(len < FLASH_PAGE_SIZE - 2);
assert(len < std::numeric_limits<uint16_t>::max());
HAL_FLASH_Unlock();
_page_erase(_page);
flash::_write16(0, _mark);
flash::_write16(1, len);
for (size_t i = 0; i < len; i += 2) {
uint16_t var = 0;
const size_t to_copy = 1 + (i + 2 < len);
memcpy(&var, data, to_copy);
flash::_write16(2 + i / 2, var);
data = (const char*)data + to_copy;
}
HAL_FLASH_Lock();
}
static inline int read(void *data, size_t len) {
assert(len < FLASH_PAGE_SIZE - 2);
assert(len < std::numeric_limits<uint16_t>::max());
const uint16_t read_mark = flash::_read16(0);
if (read_mark != _mark) {
memset(data, '0', len);
return -1;
}
const uint16_t read_len = flash::_read16(1);
if (read_len != len) {
memset(data, '0', len);
return -2;
}
for (size_t i = 0; i < len; i += 2) {
const uint16_t var = flash::_read16(2 + i / 2);
const size_t to_copy = 1 + (i + 2 < len);
memcpy(data, &var, to_copy);
data = (char*)data + to_copy;
}
return 0;
}
template<typename T>
static inline void write(const T &t) {
flash::write((const void*)&t, sizeof(t));
}
template<typename T>
static inline int read(T &t) {
return flash::read((void*)&t, sizeof(t));
}
static inline void test() {
lcd_println("testing flash");
lcd_println("testing flash 2");
wait(1);
while (1) {
char buf[6] = {0};
const int e = flash::read(buf, 5);
int i = atoi(buf);
if (i == 0) i = 12345;
lcd_println("FR%d %d: %s", e, i, buf);
snprintf(buf, sizeof(buf), "%d", i + 1);
lcd_println("FW: %s", buf);
flash::write(buf, 5);
wait(1);
}
}
};
#endif