Kamil Cukrowski / Mbed 2 deprecated STM32_Button_Interrupt_dla_taty

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