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) 在现代的小家庭中,由于家庭…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...

中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...

20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...

MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
NPOI Excel用OLE对象的形式插入文件附件以及插入图片
static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...

(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...
如何配置一个sql server使得其它用户可以通过excel odbc获取数据
要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据,你需要完成以下配置步骤: ✅ 一、在 SQL Server 端配置(服务器设置) 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到:SQL Server 网络配…...

若依登录用户名和密码加密
/*** 获取公钥:前端用来密码加密* return*/GetMapping("/getPublicKey")public RSAUtil.RSAKeyPair getPublicKey() {return RSAUtil.rsaKeyPair();}新建RSAUti.Java package com.ruoyi.common.utils;import org.apache.commons.codec.binary.Base64; im…...

如何在Windows本机安装Python并确保与Python.NET兼容
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...

【QT控件】显示类控件
目录 一、Label 二、LCD Number 三、ProgressBar 四、Calendar Widget QT专栏:QT_uyeonashi的博客-CSDN博客 一、Label QLabel 可以用来显示文本和图片. 核心属性如下 代码示例: 显示不同格式的文本 1) 在界面上创建三个 QLabel 尺寸放大一些. objectName 分别…...