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) 在现代的小家庭中,由于家庭…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...

SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...