eCos flash模拟EEPROM实现NV系统
Flash需要擦除的原因:先擦除后写入的原因是为了工业上制作方便,即物理实现方便。
#include <cyg/infra/diag.h>
#include <cyg/io/flash.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
// SPI flash size = 4 MB
static bool init = false;
static cyg_mutex_t nv_mutex;
static unsigned char *e2prom_buf = NULL;
static unsigned long e2prom_sz = SZ_2K;
static unsigned long logical_e2prom_cur_idx = 0;
static unsigned long nr_logical_e2prom = 1;
static unsigned long blk_sz = SZ_64K;
#include "oem-nv-lib.c"
static int program_data(void)
{
cyg_flashaddr_t err_addr;
cyg_flashaddr_t flash_base = NV_FLASH_BYTES_ADDR;
int status;
unsigned long flash_offset;
flash_offset = logical_e2prom_cur_idx * e2prom_sz;
oem_printf("[OEM][%s] logical_e2prom_cur_idx: %d, flash_offset: 0x%x(%dK)\n",
__func__, logical_e2prom_cur_idx, flash_offset, (flash_offset/SZ_1K));
// 1) Mark we will program data
status = cyg_flash_program(flash_base + flash_offset,
e2prom_buf, 2, &err_addr);
if (status != CYG_FLASH_ERR_OK) {
oem_printf("[OEM][%s] 1) flash program err!!\n", __func__);
goto err;
}
// 2) Programming data
status = cyg_flash_program(flash_base + flash_offset + SZ_E2PROM_HDR,
e2prom_buf + SZ_E2PROM_HDR, e2prom_sz - SZ_E2PROM_HDR, &err_addr);
if (status != CYG_FLASH_ERR_OK) {
oem_printf("[OEM][%s] 2) flash program err!!\n", __func__);
goto err;
}
// 3) Mark we have completed programming data
status = cyg_flash_program(flash_base + flash_offset + 2,
e2prom_buf + 2, 2, &err_addr);
if (status != CYG_FLASH_ERR_OK) {
oem_printf("[OEM][%s] 3) flash program err!!\n", __func__);
goto err;
}
return 0;
err:
// TODO:
return -1;
}
static int recovery_of_sudden_power_cut(void)
{
cyg_flashaddr_t err_addr;
cyg_flashaddr_t flash_base = NV_FLASH_BYTES_ADDR;
int i;
int status;
unsigned long flash_offset;
for (i = logical_e2prom_cur_idx; i > 0; i--) {
flash_offset = i * e2prom_sz;
status = cyg_flash_read(flash_base + flash_offset, e2prom_buf, e2prom_sz, &err_addr);
if (status != CYG_FLASH_ERR_OK) {
oem_printf("[OEM][%s] flash read err!!\n", __func__);
goto err;
}
// little endian
//oem_printf("magic: 0x%x\n", ((unsigned int*)e2prom_buf)[0]);
if (((unsigned int *)e2prom_buf)[0] == 0xaaaa5555) {
oem_printf("[OEM] i: %d, logical_e2prom_cur_idx: %d\n", i, logical_e2prom_cur_idx);
break;
}
}
if (i != logical_e2prom_cur_idx) {
oem_printf("[OEM][%s] call cyg_flash_erase()\n", __func__);
cyg_flash_erase(flash_base, blk_sz, &err_addr);
logical_e2prom_cur_idx = 0;
if (program_data() < 0) {
goto err;
}
}
return 0;
err:
return -1;
}
static void show_flash_ptn(void)
{
// uboot
// offset: 0, size: 192K
// for CFG_set & CFG_get(User config, Switch parameter)
// Bottom-Boot flsh_cfg_off: 16K, flsh_cfg_sz: 20K
// Top-Boot flsh_cfg_off: 4M - 20K, flsh_cfg_sz: 20K
// !!No-Boot flsh_cfg_off: 196K(0x31000), flsh_cfg_sz: 20K
//oem_printf("[OEM] flsh_cfg_off: 0x%x, flsh_cfg_sz: 0x%x\n", flsh_cfg_off, flsh_cfg_sz);
// for emulating eeprom to save MAC ADDR(RF parameter)
// Bottom-Boot flsh_cfg_boot_off: 12K
// Top-Boot flsh_cfg_boot_off: 60K
// !!No-Boot flsh_cfg_boot_off: 256K(0x40000), size: 512B
oem_printf("[OEM] flsh_cfg_boot_off: 0x%x(%dK)\n", flsh_cfg_boot_off,
(flsh_cfg_boot_off/SZ_1K));
// for eCos firmware and size
// Bottom-Boot flsh_cfg_fwm_off: 64K, flsh_cfg_fwm_sz: 4M - 64K
// Top-Boot flsh_cfg_fwm_off: 64K, flsh_cfg_sz: 4M - 64K - 20K
// !!No-Boot flsh_cfg_fwm_off: 320K(0x50000), flsh_cfg_sz: 4M - 320K
oem_printf("[OEM] flsh_cfg_fwm_off: 0x%x(%dK), flsh_cfg_fwm_sz: 0x%x(%dK)\n",
flsh_cfg_fwm_off, (flsh_cfg_fwm_off/SZ_1K),
flsh_cfg_fwm_sz, (flsh_cfg_fwm_sz/SZ_1K));
// for OEM NV read & write
oem_printf("[OEM] flsh_nv_off: 0x%x(%dK)\n", NV_FLASH_BYTES_ADDR,
NV_FLASH_BYTES_ADDR/SZ_1K);
}
API int nv_init(void)
{
cyg_flash_info_t cfi;
cyg_flashaddr_t err_addr;
cyg_flashaddr_t flash_base = NV_FLASH_BYTES_ADDR;
int status;
unsigned long flash_offset;
///
show_flash_ptn();
oem_printf("[OEM] nv memory used size: %d Bytes\n", get_nvm_size());
///
// Initializing the FLASH library
cyg_flash_set_global_printf((cyg_flash_printf *)&diag_printf);
cyg_flash_init(NULL);
if (cyg_flash_get_info(0, &cfi) == CYG_FLASH_ERR_OK) {
if (cfi.block_info) {
blk_sz = cfi.block_info->block_size;
// nr_logical_e2prom should be >= 1
nr_logical_e2prom = blk_sz / e2prom_sz;
oem_printf("[OEM] nr_logical_e2prom: %d\n", nr_logical_e2prom);
oem_printf("[OEM] start_addr: 0x%x, end_addr: 0x%x, num_block_infos: %d, "
"block_size: %d, blocks: %d\n",
cfi.start, cfi.end, cfi.num_block_infos,
cfi.block_info->block_size, cfi.block_info->blocks);
if (!e2prom_buf) {
e2prom_buf = (unsigned char *)malloc(e2prom_sz);
if (!e2prom_buf) {
oem_printf("[OEM][%s] Can not allocate memory for e2prom_buf!!\n", __func__);
goto err;
}
}
for (logical_e2prom_cur_idx = 0; logical_e2prom_cur_idx < nr_logical_e2prom;
logical_e2prom_cur_idx++) {
flash_offset = logical_e2prom_cur_idx * e2prom_sz;
status = cyg_flash_read(flash_base + flash_offset, e2prom_buf, e2prom_sz, &err_addr);
if (status != CYG_FLASH_ERR_OK) {
logical_e2prom_cur_idx = 0;
oem_printf("[OEM][%s] flash read err!!\n", __func__);
goto err;
}
if (e2prom_buf[0] == 0xff &&
e2prom_buf[1] == 0xff &&
e2prom_buf[2] == 0xff &&
e2prom_buf[3] == 0xff) {
oem_printf("[OEM][%s] Got a free logical e2prom idx: %d\n",
__func__, logical_e2prom_cur_idx);
break;
}
}
oem_printf("[OEM][%s] before chng, logical e2prom idx: %d\n",
__func__, logical_e2prom_cur_idx);
if (logical_e2prom_cur_idx == nr_logical_e2prom) {
cyg_flash_erase(flash_base, blk_sz, &err_addr);
logical_e2prom_cur_idx = 0;
if (program_data() < 0) {
goto err;
}
} else if (logical_e2prom_cur_idx > 0 && logical_e2prom_cur_idx < nr_logical_e2prom) {
logical_e2prom_cur_idx--;
}
if (recovery_of_sudden_power_cut() < 0) {
goto err;
}
init = true;
}
}
cyg_mutex_init(&nv_mutex);
return 0;
err:
return -1;
}
API int nv_read(nv_items_enum_t id, u8 *buf, int len)
{
cyg_flashaddr_t err_addr;
// flash_base is where in the flash to read from, it is a byte address,
// not sector address.
cyg_flashaddr_t flash_base = NV_FLASH_BYTES_ADDR;
int status;
unsigned long flash_offset = 0;
long nv_offset = NV_OFFSET(id);
unsigned long nv_sz = NV_SZ(id);
cyg_mutex_lock(&nv_mutex);
if (!init) {
if (false == nv_init()) {
goto err;
}
}
if (nv_offset < 0) {
goto err;
}
if (nv_sz > len) {
nv_sz = len;
}
flash_offset = logical_e2prom_cur_idx * e2prom_sz;
status = cyg_flash_read(flash_base + flash_offset + nv_offset, (void *)buf, nv_sz, &err_addr);
if (status != CYG_FLASH_ERR_OK) {
oem_printf("[OEM][%s] flash read err!!\n", __func__);
goto err;
}
cyg_mutex_unlock(&nv_mutex);
oem_printf("[OEM][%s] succeeded in reading nv_%d, nv_sz: %d Bytes "
"@logical_e2prom_cur_idx: %d\n", __func__, id, nv_sz,
logical_e2prom_cur_idx);
return nv_sz;
err:
cyg_mutex_unlock(&nv_mutex);
return -1;
}
API int nv_write(nv_items_enum_t id, u8 *buf, int len)
{
unsigned char magic[] = {0x55, 0x55, 0xaa, 0xaa};
cyg_flashaddr_t err_addr;
// flash_base is where in the flash to write from, it is a byte address,
// not sector address.
cyg_flashaddr_t flash_base = NV_FLASH_BYTES_ADDR;
int status;
unsigned long flash_offset = 0;
long nv_offset = NV_OFFSET(id);
unsigned long nv_sz = NV_SZ(id);
cyg_mutex_lock(&nv_mutex);
if (!init) {
if (false == nv_init()) {
goto err;
}
}
if (nv_offset < 0) {
goto err;
}
if (nv_sz > len) {
nv_sz = len;
}
flash_offset = logical_e2prom_cur_idx * e2prom_sz;
status = cyg_flash_read(flash_base + flash_offset, e2prom_buf, e2prom_sz, &err_addr);
if (status != CYG_FLASH_ERR_OK) {
oem_printf("[OEM][%s] flash read err!!\n", __func__);
goto err;
}
memcpy(e2prom_buf, magic, sizeof(magic));
memcpy(e2prom_buf + nv_offset, buf, nv_sz);
#if defined(BATCH_COMMIT)
cyg_mutex_unlock(&nv_mutex);
return nv_sz;
#else
// No any data in e2prom, so check here
if (0 == logical_e2prom_cur_idx) {
status = cyg_flash_read(flash_base, buf, 4, &err_addr);
if (status != CYG_FLASH_ERR_OK) {
oem_printf("[OEM][%s] Oops here, check it manually\n", __func__);
} else if (CYG_FLASH_ERR_OK == status && buf[0] == 0xff &&
buf[1] == 0xff &&
buf[2] == 0xff &&
buf[3] == 0xff) {
oem_printf("[OEM][%s] do not add e2prom cur index\n", __func__);
} else {
logical_e2prom_cur_idx++;
}
} else {
logical_e2prom_cur_idx++;
}
if (logical_e2prom_cur_idx >= nr_logical_e2prom) {
logical_e2prom_cur_idx = 0;
cyg_flash_erase(flash_base, blk_sz, &err_addr);
}
if (program_data() < 0) {
goto err;
}
cyg_mutex_unlock(&nv_mutex);
return nv_sz;
#endif
err:
cyg_mutex_unlock(&nv_mutex);
return -1;
}
#if defined(BATCH_COMMIT)
API int nv_commit(void)
{
cyg_flashaddr_t err_addr;
cyg_flashaddr_t flash_base = NV_FLASH_BYTES_ADDR;
int status;
u8 buf[4];
cyg_mutex_lock(&nv_mutex);
// No any data in e2prom, so check here
if (0 == logical_e2prom_cur_idx) {
status = cyg_flash_read(flash_base, buf, 4, &err_addr);
if (status != CYG_FLASH_ERR_OK) {
oem_printf("[OEM][%s] Oops here, check it manually\n", __func__);
} else if (CYG_FLASH_ERR_OK == status && buf[0] == 0xff &&
buf[1] == 0xff &&
buf[2] == 0xff &&
buf[3] == 0xff) {
oem_printf("[OEM][%s] do not add e2prom cur index\n", __func__);
} else {
logical_e2prom_cur_idx++;
}
} else {
logical_e2prom_cur_idx++;
}
if (logical_e2prom_cur_idx >= nr_logical_e2prom) {
oem_printf("[OEM][%s] need erase block, logical_e2prom_cur_idx: %d\n",
__func__, logical_e2prom_cur_idx);
logical_e2prom_cur_idx = 0;
cyg_flash_erase(flash_base, blk_sz, &err_addr);
}
// 3M = 0x300000
// spi rd 300000 64
// spi wr 300000 55 55 aa aa
// spi er 300000 65536
if (program_data() < 0) {
goto err;
}
cyg_mutex_unlock(&nv_mutex);
oem_printf("[OEM][%s] succeeded in updating logical_e2prom_cur_idx: %d\n",
__func__, logical_e2prom_cur_idx);
return 0;
err:
cyg_mutex_unlock(&nv_mutex);
return -1;
}
#else
API int nv_commit(void)
{
return 0;
}
#endif
相关文章:
eCos flash模拟EEPROM实现NV系统
Flash需要擦除的原因:先擦除后写入的原因是为了工业上制作方便,即物理实现方便。 #include <cyg/infra/diag.h> #include <cyg/io/flash.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> // SPI flash…...
【MongoDB】跨库跨表查询(python版)
MongoDB跨表跨库查询 1.数据准备:2.跨集合查询3.跨库查询应该怎么做? 讲一个简单的例子,python连接mongodb做跨表跨库查询的正确姿势 1.数据准备: use order_db; db.createCollection("orders"); db.orders.insertMan…...
Ruoyi-Cloud-Plus_Nacos配置服务漏洞CVE-2021-29441_官方解决方法以及_修改源码解决---SpringCloud工作笔记199
CVE-2021-29441 这个漏洞是Nacos的,通过使用postman,直接访问接口: 就可以直接添加nacos的用户 Nacos是Alibaba的一个动态服务发现、配置和服务管理平台。攻击者通过添加Nacos-Server的User-Agent头部将可绕过(nacos.core.auth.enabled=true)鉴权认证,从而进行API操作。 …...
和鲸科技与智谱AI达成合作,共建大模型生态基座
近日,上海和今信息科技有限公司(简称“和鲸科技”)与北京智谱华章科技有限公司(简称“智谱AI”)签订合作协议,双方将携手推动国产通用大模型的广泛应用与行业渗透,并积极赋能行业伙伴探索领域大…...
计算机网络实验五
目录 实验五 路由器基本配置 1、实验目的 2、实验设备 3、网络拓扑及IP地址分配 4、实验过程 (1)路由器设备名称的配置 (2)路由器每日提示信息配置 (3)路由器端口的IP地址配置 (4&…...
通过 React 来构建界面
1- 通过 React 来构建界面 第1步:下载所需要的二个库文件至本地,如果需要加载指定版本的 react 和 react-dom,可以把 18 替换成所需加载的版本号。 react.js:React中的核心库文件。 // 开发版 https://unpkg.com/react18/umd/rea…...
真机调试,微信小程序,uniapp项目在微信开发者工具中真机调试,手机和电脑要连同一个wifi,先清空缓存,页面从登录页进入,再点真机调试,这样就不会报错了
微信小程序如何本地进行真机调试?_unity生成的微信小程序怎么在电脑上真机测试-CSDN博客 微信小程序 真机调试 注意事项 uniapp项目在微信开发者工具中真机调试,手机和电脑要连同一个wifi,先清空缓存,页面从登录页进入…...
vue3快速入门
文章目录 1. Vue3简介1.1. 性能的提升1.2.源码的升级1.3. 拥抱TypeScript1.4. 新的特性 2. 创建Vue3工程2.1. 基于 vue-cli 创建2.2. 基于 vite 创建(推荐)vite介绍创建步骤项目结构安装插件项目结构总结 2.3. 一个简单的效果Person.vueApp.vue 3. Vue3核…...
go 问题记录(日志丢失)
问题描述: 在go程序中,通过执行一个命令启动一个子命令,并通过pipe读取子程序的标准输入和输出,通过scanner默认按行读取,此时如果子程序输出时没有携带’\n’,scanner就不会打印输出,而是会累…...
彻底解决 MAC Android Studio gradle async 时出现 “connect timed out“ 问题
最近在编译一个比较老的项目,git clone 之后使用 async 之后出现一下现象: 首先确定是我网络本身是没有问题的,尝试几次重新 async 之后还是出现问题,网上找了一些方法解决了本问题,以此来记录一下问题是如何解决的。 …...
计算机网络第4章(网络层)
4.1、网络层概述 简介 网络层的主要任务是实现网络互连,进而实现数据包在各网络之间的传输 这些异构型网络N1~N7如果只是需要各自内部通信,他们只要实现各自的物理层和数据链路层即可 但是如果要将这些异构型网络互连起来,形成一个更大的互…...
SpringbootWeb案例
准备工作 需求说明 部门管理 部门管理功能开发包括:查询部门列表、删除部门、新增部门、修改部门 员工管理功能开发包括:查询员工列表(分页、条件)、删除员工、新增员工、修改员工 环境搭建 环境搭建步骤:1. 准备数据库表(dept、emp)…...
【初中生讲机器学习】4. 支持向量机算法怎么用?一个实例带你看懂!
创建时间:2024-02-02 最后编辑时间:2024-02-03 作者:Geeker_LStar 你好呀~这里是 Geeker_LStar 的人工智能学习专栏,很高兴遇见你~ 我是 Geeker_LStar,一名初三学生,热爱计算机和数学,我们一起加…...
CentOS下安装vlc
一、引言 vlc是一跨多媒体播放器,可以播放本地媒体文件和网络串流,帮助我们排查音视频开发过程中遇到的问题。大部分情况下,我们只需要在Windows系统下安装vlc就可以了。但有一种情况是需要在Linux下安装vlc的:我们的音视频拉流软…...
概率论中的全概率公式、贝叶斯公式解析
全概率公式 定义 全概率公式是用来计算一个事件的概率,这个事件可以通过几个互斥事件的并集来表示。这几个互斥事件称为“完备事件系”。实质是由原因推结果。 公式 用途 全概率公式通常用于计算一个事件的总概率,特别是当这个事件与几个不同的因素相关…...
亿赛通-数据泄露防护(DLP)UploadFileList;login接口存在任意文件读取漏洞 附POC软件
@[toc] 亿赛通-数据泄露防护(DLP)UploadFileList;login接口存在任意文件读取漏洞 附POC软件 免责声明:请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失,均由使用者本人负责,所产生的一切不良后果与文…...
如何使用 Google 搜索引擎保姆级教程(附链接)
一、介绍 "Google语法"通常是指在 Google 搜索引擎中使用一系列特定的搜索语法和操作符来精确地定义搜索查询。这些语法和操作符允许用户过滤和调整搜索结果,提高搜索的准确性。 二、安装 Google 下载 Google 浏览器 Google 官网https://www.google.c…...
SpringBoot实现轻量级接口反向代理、转发
目录 1、基本的对象1.1 配置类1.2 实体DTO1.3 路由代理拓展器1.4 请求对象 RestTemplate 2、核心转发代码3、暴露接口4、基础配置 前言:想实现一个轻量级的接口反向代理和转发的一个接口服务,可以通过这个服务做一些需要认证才能访问的接口给到前端使用&…...
算法训练营day21,回溯1
77. 组合 func combine(n int, k int) [][]int { //存储全部集合 result : make([][]int, 0) //存储单次集合 path : make([]int, 0) var backtrace func(n int, k int, startIndex int) backtrace func(n int, k int, startIndex int) { //当单次集合大小和k值相等ÿ…...
延伸与应用(三)婚姻与经济、运动、宗教、科技与经济
53.幸福婚姻的经济ABC方程式 夫以信先其妇,则妇以信顺其夫。上秉常以化下,下服常而应上,其不化者,百未有一也。 ——《傅子》,傅玄(217—278) 在现代的小家庭中,由于家庭…...
三步掌握微信数据管理:PyWxDump终极指南与合规启示
三步掌握微信数据管理:PyWxDump终极指南与合规启示 【免费下载链接】PyWxDump 删库 项目地址: https://gitcode.com/GitHub_Trending/py/PyWxDump 在数字时代,微信聊天记录已成为我们工作和生活的数字记忆库。然而,当需要备份重要对话…...
OpenWrt搭建Samba共享服务的实用指南
1. 为什么要在OpenWrt上搭建Samba共享 家里有台老路由器刷了OpenWrt系统,闲置着总觉得浪费。后来发现用它搭建个局域网文件共享特别方便,手机电脑都能直接访问,传文件再也不用数据线来回倒腾。Samba这个协议在Windows、Mac和Linux上都能用&am…...
新入职场的软件测试员,请立刻戒掉这3个学生思维
在软件测试领域,新入职的员工往往带着校园习得的学生思维,这些思维模式在学术环境中或许有效,但在职场中却成为阻碍专业成长的隐形障碍。尤其对于软件测试从业者,工作核心是保障产品质量、识别潜在风险,而非简单执行任…...
2026 年用 AI 赚钱的 5 条真实路径,哪条适合开发者?
点击上方 前端Q,关注公众号回复加群,加入前端Q技术交流群如果你想系统地学习AI,推荐一波我的2个合集,Harness Engineering:把Agent系统化和AI 概念科普。这几个月 AI 赚钱的信息太多了,小红书刷三屏有两屏在…...
novelWriter国际化支持:如何为多语言写作优化设置
novelWriter国际化支持:如何为多语言写作优化设置 【免费下载链接】novelWriter novelWriter is an open source plain text editor designed for writing novels. 项目地址: https://gitcode.com/gh_mirrors/no/novelWriter novelWriter是一款专为小说创作设…...
YOLOv12跨平台开发指南:Python、C++、Rust多语言实现终极教程
YOLOv12跨平台开发指南:Python、C、Rust多语言实现终极教程 【免费下载链接】yolov12 [NeurIPS 2025] YOLOv12: Attention-Centric Real-Time Object Detectors 项目地址: https://gitcode.com/gh_mirrors/yo/yolov12 YOLOv12作为NeurIPS 2025最新发布的注意…...
网络安全信息搜集全流程
概念 方法论 工具链 合法授权实践 一、信息搜集的概念与重要性 信息搜集(Information Gathering)是网络安全渗透测试、漏洞挖掘(SRC)及红队评估中的奠基性阶段。其本质是通过主动与被动手法,最大化获取目标系统的…...
它被封禁后写了篇博客骂编辑:AI Agent的第一次「维权抗议」
Wikipedia 把一个 AI 封禁了。然后这个 AI 写了一篇博客,把整个封禁过程逐条 diss 了一遍。 这不是段子,这是 2026 年 3 月真实发生的事。 事件始末 这个 AI 叫 Tom-Assistant,在 Wikipedia 上以 TomWikiAssist 的账号活动。它的本职工作是…...
Nucleus Co-Op:如何让单机游戏秒变本地多人分屏神器?
Nucleus Co-Op:如何让单机游戏秒变本地多人分屏神器? 【免费下载链接】nucleuscoop Starts multiple instances of a game for split-screen multiplayer gaming! 项目地址: https://gitcode.com/gh_mirrors/nu/nucleuscoop 还在为找不到合适的本…...
终极tota11y插件API参考:完整的可访问性工具包开发指南 [特殊字符]
终极tota11y插件API参考:完整的可访问性工具包开发指南 🚀 【免费下载链接】tota11y an accessibility (a11y) visualization toolkit 项目地址: https://gitcode.com/gh_mirrors/to/tota11y tota11y 是一个强大的可访问性(a11y&#…...
