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
Diff: flash.h
- Revision:
- 0:55c37ea095b0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/flash.h Thu Feb 13 16:27:38 2020 +0000
@@ -0,0 +1,109 @@
+#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