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) 在现代的小家庭中,由于家庭…...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...
iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
