diff --git a/components/flash/flash_map.hpp b/components/flash/flash_map.hpp new file mode 100644 index 0000000..f1a5eea --- /dev/null +++ b/components/flash/flash_map.hpp @@ -0,0 +1,39 @@ +#pragma once +#include "main.h" + +/******************************************************************************* + * STM32F407xx * + *******************************************************************************/ +#ifdef STM32F407xx + +/** + * @brief WARNING:需要注意407flash大小是有两款不同容量的,一款512K,一款1M + */ +#define Z_FLASH_MAX_SECTOR_NUM 11 + +#define Z_FLASH_SECTOR_00_ADDR 0x08000000 // off:0 +#define Z_FLASH_SECTOR_01_ADDR 0x08004000 // off:16k +#define Z_FLASH_SECTOR_02_ADDR 0x08008000 // off:32k +#define Z_FLASH_SECTOR_03_ADDR 0x0800C000 // off:48k +#define Z_FLASH_SECTOR_04_ADDR 0x08010000 // off:64k +#define Z_FLASH_SECTOR_05_ADDR 0x08020000 // off:128k +#define Z_FLASH_SECTOR_06_ADDR 0x08040000 // off:256k +#define Z_FLASH_SECTOR_07_ADDR 0x08060000 // off:384k +#define Z_FLASH_SECTOR_08_ADDR 0x08080000 // off:512k +#define Z_FLASH_SECTOR_09_ADDR 0x080A0000 // off:640k +#define Z_FLASH_SECTOR_10_ADDR 0x080C0000 // off:768k +#define Z_FLASH_SECTOR_11_ADDR 0x080E0000 // off:896k + +#define Z_FLASH_SECTOR_00_SIZE (16 * 1024) +#define Z_FLASH_SECTOR_01_SIZE (16 * 1024) +#define Z_FLASH_SECTOR_02_SIZE (16 * 1024) +#define Z_FLASH_SECTOR_03_SIZE (16 * 1024) +#define Z_FLASH_SECTOR_04_SIZE (64 * 1024) +#define Z_FLASH_SECTOR_05_SIZE (128 * 1024) +#define Z_FLASH_SECTOR_06_SIZE (128 * 1024) +#define Z_FLASH_SECTOR_07_SIZE (128 * 1024) +#define Z_FLASH_SECTOR_08_SIZE (128 * 1024) +#define Z_FLASH_SECTOR_09_SIZE (128 * 1024) +#define Z_FLASH_SECTOR_10_SIZE (128 * 1024) +#define Z_FLASH_SECTOR_11_SIZE (128 * 1024) +#endif diff --git a/components/flash/znvs.cpp b/components/flash/znvs.cpp new file mode 100644 index 0000000..47b60bf --- /dev/null +++ b/components/flash/znvs.cpp @@ -0,0 +1,157 @@ +#include "znvs.hpp" + +#include + +#include "sdk\components\flash\zsimple_flash.hpp" +#define TAG "config" + +using namespace iflytop; +using namespace std; +#define MARK_S 0x123456 +#define MARK_E 0x87654321 + +#define GET_CFG(typename) \ + cfg_t* cfg = get_cfg(key); \ + if (cfg == nullptr || cfg->type != kcfg_type_##typename) { \ + allocate_cfg(key, kcfg_type_##typename, (uint8_t*)&default_val, sizeof(default_val)); \ + cfg = get_cfg(key); \ + } \ + return *(typename*)cfg->val; + +#define SET_CFG(typename) \ + cfg_t* cfg = get_cfg(key); \ + if (cfg == nullptr || cfg->type != kcfg_type_##typename) { \ + allocate_cfg(key, kcfg_type_##typename, (uint8_t*)&val, sizeof(val)); \ + cfg = get_cfg(key); \ + } else { \ + *(typename*)cfg->val = val; \ + flush(); \ + } + +ZNVS& ZNVS::ins() { + static ZNVS instance; + return instance; +} +void ZNVS::initialize() { + zsimple_flash_init(IFLYTOP_NVS_CONFIG_FLASH_SECTOR); + zsimple_flash_read((uint8_t*)&m_cfg, sizeof(m_cfg)); + if (m_cfg.config_start != MARK_S || m_cfg.config_end != MARK_E) { + ZLOGW(TAG, "config uninitialized, initialize it"); + memset(&m_cfg, 0, sizeof(m_cfg)); + m_cfg.config_start = MARK_S; + m_cfg.config_end = MARK_E; + zsimple_flash_write((uint8_t*)&m_cfg, sizeof(m_cfg)); + } else { + ZLOGI(TAG, "config initialized"); + } +} + +void ZNVS::factory_reset() { + memset(&m_cfg, 0, sizeof(m_cfg)); + m_cfg.config_start = MARK_S; + m_cfg.config_end = MARK_E; + zsimple_flash_write((uint8_t*)&m_cfg, sizeof(m_cfg)); +} + +ZNVS::cfg_t* ZNVS::get_cfg(const char* key) { + for (int i = 0; i < IFLYTOP_NVS_CONFIG_MAX_ITEM_NUM; i++) { + if (strcmp(m_cfg.cfgs[i].key, key) == 0) { + return &m_cfg.cfgs[i]; + } + } + return nullptr; +} + +void ZNVS::allocate_cfg(const char* key, type_t type, uint8_t* default_val, uint8_t len) { + cfg_t* cfg = get_cfg(key); + for (int i = 0; i < IFLYTOP_NVS_CONFIG_MAX_ITEM_NUM; i++) { + if (m_cfg.cfgs[i].is_initialed == false) { + cfg = &m_cfg.cfgs[i]; + strcpy(cfg->key, key); + cfg->is_initialed = true; + cfg->type = (uint8_t)type; + memcpy(cfg->val, default_val, len); + /** + * @brief 刷新flash + * + * TODO:优化这里的代码,不要每次都刷新flash + */ + zsimple_flash_write((uint8_t*)&m_cfg, sizeof(m_cfg)); + break; + } + } +} + +ZNVS::cfg_t* ZNVS::get_and_create_cfg(const char* key, type_t type, uint8_t* default_val, uint8_t len) { + cfg_t* cfg = get_cfg(key); + if (cfg == nullptr) { + allocate_cfg(key, type, default_val, len); + cfg = get_cfg(key); + } + return cfg; +} + +void ZNVS::dumpcfg() { + ZLOGI(TAG, "=================dump nvs config =================="); + ZLOGI(TAG, "="); + for (int i = 0; i < IFLYTOP_NVS_CONFIG_MAX_ITEM_NUM; i++) { + if (m_cfg.cfgs[i].is_initialed) { + dumpcfg(&m_cfg.cfgs[i]); + } + } + ZLOGI(TAG, "============="); +} + +void ZNVS::dumpcfg(cfg_t* cfg) { + if (!cfg->is_initialed) return; + switch (cfg->type) { + case kcfg_type_int8_t: + ZLOGI(TAG, "= %s val:%d", cfg->key, *(int8_t*)cfg->val); + break; + case kcfg_type_int16_t: + ZLOGI(TAG, "= %s val:%d", cfg->key, *(int16_t*)cfg->val); + break; + case kcfg_type_int32_t: + ZLOGI(TAG, "= %s val:%d", cfg->key, *(int32_t*)cfg->val); + break; + + case kcfg_type_uint8_t: + ZLOGI(TAG, "= %s val:%u", cfg->key, *(int8_t*)cfg->val); + break; + case kcfg_type_uint16_t: + ZLOGI(TAG, "= %s val:%u", cfg->key, *(int16_t*)cfg->val); + break; + case kcfg_type_uint32_t: + ZLOGI(TAG, "= %s val:%u", cfg->key, *(int32_t*)cfg->val); + break; + case kcfg_type_float: + ZLOGI(TAG, "= %s val:%f", cfg->key, *(float*)cfg->val); + break; + case kcfg_type_bool: + ZLOGI(TAG, "= %s val:%d", cfg->key, *(bool*)cfg->val); + break; + default: + ZLOGI(TAG, "= %s val:unknow type", cfg->key); + break; + } + return; +} + +int8_t ZNVS::get_config_int8(const char* key, int8_t default_val) { GET_CFG(int8_t); } +void ZNVS::set_config_int8(const char* key, int8_t val) { SET_CFG(int8_t); } +uint8_t ZNVS::get_config_uint8(const char* key, uint8_t default_val) { GET_CFG(uint8_t); } +void ZNVS::set_config_uint8(const char* key, uint8_t val) { SET_CFG(uint8_t); } +int16_t ZNVS::get_config_int16(const char* key, int16_t default_val) { GET_CFG(int16_t); } +void ZNVS::set_config_int16(const char* key, int16_t val) { SET_CFG(int16_t); } +uint16_t ZNVS::get_config_uint16(const char* key, uint16_t default_val) { GET_CFG(uint16_t); } +void ZNVS::set_config_uint16(const char* key, uint16_t val) { SET_CFG(uint16_t); } +int32_t ZNVS::get_config_int32(const char* key, int32_t default_val) { GET_CFG(int32_t); } +void ZNVS::set_config_int32(const char* key, int32_t val) { SET_CFG(int32_t); } +uint32_t ZNVS::get_config_uint32(const char* key, uint32_t default_val) { GET_CFG(uint32_t); } +void ZNVS::set_config_uint32(const char* key, uint32_t val) { SET_CFG(uint32_t); } +float ZNVS::get_config_float(const char* key, float default_val) { GET_CFG(float); } +void ZNVS::set_config_float(const char* key, float val) { SET_CFG(float); } +bool ZNVS::get_config_bool(const char* key, bool default_val) { GET_CFG(bool); } +void ZNVS::set_config_bool(const char* key, bool val) { SET_CFG(bool); } + +void ZNVS::flush() { zsimple_flash_write((uint8_t*)&m_cfg, sizeof(m_cfg)); } diff --git a/components/flash/znvs.hpp b/components/flash/znvs.hpp new file mode 100644 index 0000000..fd4d75f --- /dev/null +++ b/components/flash/znvs.hpp @@ -0,0 +1,77 @@ +#pragma once +#include "project_configs.h" +#include "sdk/os/zos.hpp" + +namespace iflytop { +using namespace std; + +class ZNVS { + typedef enum { + kcfg_type_int8_t, + kcfg_type_uint8_t, + kcfg_type_int16_t, + kcfg_type_uint16_t, + kcfg_type_int32_t, + kcfg_type_uint32_t, + kcfg_type_float, + kcfg_type_bool, + } type_t; + +#pragma pack(1) + typedef struct { + char key[64]; + uint8_t val[8]; + uint8_t type; + bool is_initialed; + } cfg_t; + + typedef struct { + uint32_t config_start; + cfg_t cfgs[IFLYTOP_NVS_CONFIG_MAX_ITEM_NUM]; + uint32_t config_end; + } config_t; +#pragma pack() + + config_t m_cfg; + + public: + static ZNVS& ins(); + + void initialize(); + void factory_reset(); + void dumpcfg(); + + int8_t get_config_int8(const char* key, int8_t default_val); + void set_config_int8(const char* key, int8_t val); + + uint8_t get_config_uint8(const char* key, uint8_t default_val); + void set_config_uint8(const char* key, uint8_t val); + + int16_t get_config_int16(const char* key, int16_t default_val); + void set_config_int16(const char* key, int16_t val); + + uint16_t get_config_uint16(const char* key, uint16_t default_val); + void set_config_uint16(const char* key, uint16_t val); + + int32_t get_config_int32(const char* key, int32_t default_val); + void set_config_int32(const char* key, int32_t val); + + uint32_t get_config_uint32(const char* key, uint32_t default_val); + void set_config_uint32(const char* key, uint32_t val); + + float get_config_float(const char* key, float default_val); + void set_config_float(const char* key, float val); + + bool get_config_bool(const char* key, bool default_val); + void set_config_bool(const char* key, bool val); + + private: + void dumpcfg(cfg_t* cfg); + + cfg_t* get_cfg(const char* key); + void allocate_cfg(const char* key, type_t type, uint8_t* default_val, uint8_t len); + cfg_t* get_and_create_cfg(const char* key, type_t type, uint8_t* default_val, uint8_t len); + void flush(); +}; + +} // namespace iflytop \ No newline at end of file diff --git a/components/flash/zsimple_flash.cpp b/components/flash/zsimple_flash.cpp new file mode 100644 index 0000000..03cc4a2 --- /dev/null +++ b/components/flash/zsimple_flash.cpp @@ -0,0 +1,79 @@ +#include +#include + +#include "flash_map.hpp" +#include "main.h" +#include "project_configs.h" + +static uint32_t m_sector_num = 0; +namespace iflytop { +uint32_t* zsimple_flash_get_add(int sector_num) { + switch (sector_num) { + case 0: + return (uint32_t*)Z_FLASH_SECTOR_00_ADDR; + case 1: + return (uint32_t*)Z_FLASH_SECTOR_01_ADDR; + case 2: + return (uint32_t*)Z_FLASH_SECTOR_02_ADDR; + case 3: + return (uint32_t*)Z_FLASH_SECTOR_03_ADDR; + case 4: + return (uint32_t*)Z_FLASH_SECTOR_04_ADDR; + case 5: + return (uint32_t*)Z_FLASH_SECTOR_05_ADDR; + case 6: + return (uint32_t*)Z_FLASH_SECTOR_06_ADDR; + case 7: + return (uint32_t*)Z_FLASH_SECTOR_07_ADDR; + case 8: + return (uint32_t*)Z_FLASH_SECTOR_08_ADDR; + case 9: + return (uint32_t*)Z_FLASH_SECTOR_09_ADDR; + case 10: + return (uint32_t*)Z_FLASH_SECTOR_10_ADDR; + case 11: + return (uint32_t*)Z_FLASH_SECTOR_11_ADDR; + default: + assert_param(0); + } + return 0; +} + +static HAL_StatusTypeDef pri_earse_sector() { + HAL_StatusTypeDef status; + uint32_t sector_error_point; + FLASH_EraseInitTypeDef flash_erase_structer = { + // + .TypeErase = FLASH_TYPEERASE_SECTORS, // + .Sector = m_sector_num, // + .NbSectors = 1, // + .VoltageRange = FLASH_VOLTAGE_RANGE_3 // + }; + + HAL_FLASH_Unlock(); // 解锁 + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); // 清除一些错误标志 + status = HAL_FLASHEx_Erase(&flash_erase_structer, §or_error_point); + HAL_FLASH_Lock(); // 上锁 + return status; +} + +void zsimple_flash_init(uint32_t sector_num) { m_sector_num = sector_num; } +void zsimple_flash_read(uint8_t* data, size_t len) { memcpy(data, zsimple_flash_get_add(m_sector_num), len); } +void zsimple_flash_write(const uint8_t* data, size_t len) { + pri_earse_sector(); + + uint32_t* from = (uint32_t*)data; + uint32_t* to = (uint32_t*)zsimple_flash_get_add(m_sector_num); + uint32_t writesize = len / 4; + + HAL_StatusTypeDef status; + HAL_FLASH_Unlock(); // 解锁 + for (size_t i = 0; i < writesize; i++) { + status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, (uint32_t)to, *from); + from++; + to++; + } + HAL_FLASH_Lock(); // 上锁 +} + +} // namespace iflytop \ No newline at end of file diff --git a/components/flash/zsimple_flash.hpp b/components/flash/zsimple_flash.hpp new file mode 100644 index 0000000..0b284fb --- /dev/null +++ b/components/flash/zsimple_flash.hpp @@ -0,0 +1,8 @@ +#pragma once +#include +#include +namespace iflytop { +void zsimple_flash_init(uint32_t sector_num); +void zsimple_flash_read(uint8_t* data, size_t len); +void zsimple_flash_write(const uint8_t* data, size_t len); +} // namespace iflytop