ICM20948 DMP代码详解(25)

接前一篇文章:ICM20948 DMP代码详解(24)

 

上一回讲到了inv_icm20948_load_firmware函数,对于大体功能进行了介绍,本回深入其具体实现代码细节。为了便于理解和回顾,再次贴出相关代码:

	//Setup Ivory DMP.result |= inv_icm20948_load_firmware(s, dmp3_image, dmp3_image_size);if(result)return result;elses->base_state.firmware_loaded = 1;
/** Loads the dmp firmware for the icm20948 part.
* @param[in] dmp_image_sram Load DMP3 image from SRAM.
*/
int inv_icm20948_load_firmware(struct inv_icm20948 *s, const unsigned char *dmp3_image, unsigned int dmp3_image_size)
{return inv_icm20948_firmware_load(s, dmp3_image, dmp3_image_size, DMP_LOAD_START);
}
int inv_icm20948_firmware_load(struct inv_icm20948 *s, const unsigned char *data_start, unsigned short size_start, unsigned short load_addr)
{ int write_size;int result;unsigned short memaddr;const unsigned char *data;unsigned short size;unsigned char data_cmp[INV_MAX_SERIAL_READ];int flag = 0;if(s->base_state.firmware_loaded)return 0;// Write DMP memorydata = data_start;size = size_start;memaddr = load_addr;while (size > 0) {write_size = min(size, INV_MAX_SERIAL_WRITE);if ((memaddr & 0xff) + write_size > 0x100) {// Moved across a bankwrite_size = (memaddr & 0xff) + write_size - 0x100;}result = inv_icm20948_write_mems(s, memaddr, write_size, (unsigned char *)data);if (result)  return result;data += write_size;size -= write_size;memaddr += write_size;}// Verify DMP memorydata = data_start;size = size_start;memaddr = load_addr;while (size > 0) {write_size = min(size, INV_MAX_SERIAL_READ);if ((memaddr & 0xff) + write_size > 0x100) {// Moved across a bankwrite_size = (memaddr & 0xff) + write_size - 0x100;}result = inv_icm20948_read_mems(s, memaddr, write_size, data_cmp);if (result)flag++; // Error, DMP not written correctlyif (memcmp(data_cmp, data, write_size))return -1;data += write_size;size -= write_size;memaddr += write_size;}#if defined(WIN32)   //if(!flag)// inv_log("DMP Firmware was updated successfully..\r\n");
#endifreturn 0;
}

先看以下代码片段:

    // Write DMP memorydata = data_start;size = size_start;memaddr = load_addr;while (size > 0) {write_size = min(size, INV_MAX_SERIAL_WRITE);if ((memaddr & 0xff) + write_size > 0x100) {// Moved across a bankwrite_size = (memaddr & 0xff) + write_size - 0x100;}result = inv_icm20948_write_mems(s, memaddr, write_size, (unsigned char *)data);if (result)  return result;data += write_size;size -= write_size;memaddr += write_size;}

data = data_start,对应的实际是dmp3_image数组的地址;size = size_start,对应的实际是dmp3_image数组的长度;memaddr = load_addr,对应的实际是DMP_LOAD_START。DMP_LOAD_START宏在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948Dmp3Driver.c和EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948Defs.h中都有定义,不过值都是一样的。

#define DMP_LOAD_START      0x90

接下来进入while循环。

一上来先确定write_size即本次写入的数据长度。

        write_size = min(size, INV_MAX_SERIAL_WRITE);

write_size取size和INV_MAX_SERIAL_WRITE的较小者。一开始的时候,size为size_start,也就是sizeof(dmp3_image),非常大(#define DMP_CODE_SIZE 14301);而INV_MAX_SERIAL_WRITE前文书提到过,只有16,因此write_size为16。

这里实际上就能知道,这个写入是每次最多写入16个字节,最后一次写入的很有可能小于16个字节。

接下来要做的是调整write_size:

        if ((memaddr & 0xff) + write_size > 0x100) {// Moved across a bankwrite_size = (memaddr & 0xff) + write_size - 0x100;}

memaddr当前是0x90,write_size当前是0,两者加在一起为0x90,小于0x100即256,因此不会进入判断体,无需调整。

那么什么时候需要调整呢?每次写16个字节,当某一次memaddr加上write_size大于0x100(256)的时候,就不再写write_size字节了,而是写(memaddr & 0xff) + write_size - 0x100个字节。这样实际上就保证了memaddr按照以bank为模进行写入,也就是注释中的“Moved across a bank”。

为何要这样做?笔者理解是因为dmp3_image数组中是以bank为单位的,一个bank是256个字节。

d1f4f3cb121545a78120d6f2bdca9cb3.png

96867e13ebf647839362401705ecccd8.png

bank0的长度为0x100-0x90=256-144=112(0x70),正好是7行。从bank1开始,就是16行了。

接下来来到以下代码片段:

        result = inv_icm20948_write_mems(s, memaddr, write_size, (unsigned char *)data);if (result)  return result;data += write_size;size -= write_size;memaddr += write_size;

从memaddr开始写入write_size个字节的数据。memaddr一开始是0x90,第一次写入16个字节后,变为0x90+0x10=0xA0(160),size减小16,data即dmp3_image数组的指针也向后移16个字节。第二次重复这一过程……这样依次循环,直到size<=0(实际上只能是==0)为止。

写完之后就来到以下代码片段:

    // Verify DMP memorydata = data_start;size = size_start;memaddr = load_addr;while (size > 0) {write_size = min(size, INV_MAX_SERIAL_READ);if ((memaddr & 0xff) + write_size > 0x100) {// Moved across a bankwrite_size = (memaddr & 0xff) + write_size - 0x100;}result = inv_icm20948_read_mems(s, memaddr, write_size, data_cmp);if (result)flag++; // Error, DMP not written correctlyif (memcmp(data_cmp, data, write_size))return -1;data += write_size;size -= write_size;memaddr += write_size;}

这段很好理解。就是写入之后,再从DMP_LOAD_START(0x90)开始读取sizeof(dmp3_image)大小的数据(当然,还是每次最多16个字节的机制),并与dmp3_image原始数据进行比较,最终完全一致,则证明写入正确,返回0;中间有任何一次不正确,则返回-1,表示DMP固件加载失败。

这里提一下DMP_LOAD_START(0x90)这个寄存器,也可以说是内存。你如果在芯片手册中找,是找不到的。感觉这个DMP像个后门似的,在手册中不体现,一般不让用户知道。

至此,inv_icm20948_firmware_load函数就解析完了,inv_icm20948_load_firmware函数也就解析完了。回到inv_icm20948_initialize_lower_driver函数中的代码片段:

​	//Setup Ivory DMP.result |= inv_icm20948_load_firmware(s, dmp3_image, dmp3_image_size);if(result)return result;elses->base_state.firmware_loaded = 1;

如果正常没有问题即返回了0,则走else分支,将s->base_state.firmware_loaded设置为1。

下一回继续解析inv_icm20948_initialize_lower_driver函数中的后续代码。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1537401.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

甲骨文创始人埃里森:人工智能终有一天会追踪你的一举一动

9月17日消息&#xff0c;据外电报道&#xff0c;甲骨文创始人拉里埃里森在甲骨文财务分析师会议上表示&#xff0c;他预计人工智能有一天将为大规模执法监控网络提供动力。“我们将进行监督。”他说。“每一位警察都将随时受到监督&#xff0c;如果有问题&#xff0c;人工智能会…

从0到一个漏洞几千块,走了这么久,走了这么远,当然还要继续走下去。

从0到一个漏洞几千块&#xff0c;走了这么久&#xff0c;走了这么远&#xff0c;当然还要继续走下去。

odb使用

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、创建学生类和班级类1.学生类2.班级类3.生成数据库支持代码 二、创建数据库对象&#xff0c;对数据库进行操作1.构建连接池工厂配置对象2.构造数据库操作对象…

概率分布深度解析:PMF、PDF和CDF的技术指南

本文将深入探讨概率分布&#xff0c;详细阐述概率质量函数&#xff08;PMF&#xff09;、概率密度函数&#xff08;PDF&#xff09;和累积分布函数&#xff08;CDF&#xff09;这些核心概念&#xff0c;并通过实际示例进行说明。 在深入探讨PMF、PDF和CDF之前&#xff0c;有必…

JavaSE - 面向对象编程03

01 多态 01_01 认识多态 01_02 多态的好处和缺点 【1】好处&#xff1a;① 可以解耦合&#xff0c;扩展性更强&#xff0c;父类引用指向的子类对象可以随时切换&#xff0c;而后面的逻辑 代码并不需要更改。 ② 使用父类引用可以作为方法的形参或返…

java138-异常处理_java 138错误

//异常 public class test79 { //定义方法声明定义异常&#xff0c;在满足条件时抛出异常对象&#xff0c;程序转向异常处理 public double count(double n,double m)throws Exception { if (m 0) {//如果除数等于0.则抛出异常实例 throw new Ex…

C/C++:优选算法(持续更新~~)

一、双指针 1.1移动零 链接&#xff1a;283. 移动零 - 力扣&#xff08;LeetCode&#xff09; 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操…

近期值得关注的扩散模型Diffusion与时间序列结合的文章

扩散模型 扩散模型&#xff08;diffusion model&#xff09;是一类生成模型&#xff0c;运用了物理热力学扩散思想&#xff0c;主要用于对复杂数据分布进行建模和采样。以图片生成举例简要介绍下扩散模型运作方法。给定目标分布q(x)中的一些观测数据x&#xff0c;生成模型的目…

常见算法——自相关的含义及Python、C实现

常见算法——自相关的含义及C实现 一、概念1. 自相关概念2. 滞后期示例说明&#xff1a; 二、自相关的计算步骤&#xff1a;1. 确定滞后期 (Lag)&#xff1a;2. 计算平均值&#xff1a;3. 计算自相关&#xff1a; 三、示例 Python自相关计算1. 代码2. 运行结果 四、C语言实现自…

剖解杨辉三角

杨辉三角 思路&#xff1a; 我们将上述转换为一个二维数组&#xff0c;即可实现效果 另外在实现代码之前我们要了解Java中是如何实现二维数组的&#xff1a; 实现代码如下&#xff1a; public List<List<Integer>> generate(int numRows){List<List<Integ…

【linux-Day3】linux的基本指令<中>

【linux-Day3】linux的基本指令<中> linux下的基本指令&#x1f4e2;man&#xff1a;访问linux手册页&#x1f4e2;echo&#xff1a;把字符串写入指定文件中&#x1f4e2;cat&#xff1a;查看目标文件的内容&#x1f4e2;cp&#xff1a;复制文件或目录&#x1f4e2;mv&am…

【Go】Go语言中延迟函数、函数数据的类型、匿名函数、闭包等高阶函数用法与应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

通信工程学习:什么是EPON以太网无源光网络

EPON&#xff1a;以太网无源光网络 EPON&#xff08;Ethernet Passive Optical Network&#xff0c;以太网无源光网络&#xff09;是一种结合了以太网技术和无源光网络&#xff08;PON&#xff09;优势的高速、大容量宽带接入技术。以下是关于EPON的详细解释&#xff1a; 一、…

springboot Controller层返回的结果,日志添加traceId ,方便对日志的追踪查询

要解决的问题&#xff1f; 接口报错&#xff0c;如何快速定位问题&#xff1f;这个需要日志的辅助&#xff0c;一般错误日志中有详细的堆栈信息&#xff0c;具体是哪行代码报错&#xff0c;都可以看到。 要想快速定位问题&#xff0c;前提是要能够快速定位日志。 海量日志&am…

GPU加速生物信息分析的尝试

GPU工具分类 实话实说&#xff0c;暂时只有英伟达的GPU才能实现比较方便的基因组分析集成化解决方案&#xff0c;其他卡还需要努力呀&#xff0c;或者需要商业公司或学术团体的努力开发呀&#xff01;FPGA等这种专用卡的解决方案也是有的&#xff0c;比如某测序仪厂家&#xf…

Leetcode—815. 公交路线【困难】(unordered_map+queue)

2024每日刷题&#xff08;163&#xff09; Leetcode—815. 公交路线 bfs实现代码 class Solution { public:int numBusesToDestination(vector<vector<int>>& routes, int source, int target) {if(source target) {return 0;}unordered_map<int, vector…

ROS组合导航笔记1:融合传感器数据

使用机器人定位包&#xff08;robot_localization package&#xff09;来合并来自不同传感器的数据&#xff0c;以改进机器人定位时的姿态估计。 基本概念 在现实生活中操作机器人时&#xff0c;有时我们需要处理不够准确的传感器数据。如果我们想要实现机器人的高精度定位&am…

Jemter项目实战(黑马程序员)

视频网址&#xff1a;02测试数据准备_哔哩哔哩_bilibili 自动化脚本架构搭建 新增和修改 新增 删除和查询 弱压力、高并发、高频率 弱压力测试 高并发 高频率 生成图形化报告

记忆化搜索算法专题——算法简介力扣实战应用

目录 1、记忆化搜索算法简介 1.1 什么是记忆化搜索 1.2 如何实现记忆化搜索 1.3 记忆化搜索与动态规划的区别 2、算法应用【leetcode】 2.1 题一&#xff1a;斐波那契数 2.1.1 递归暴搜解法代码 2.1.2 记忆化搜索解法代码 2.1.3 动态规划解法代码 2.2 题二&#xff1…

JavaScript高级——闭包的作用

1、使用函数内部的变量在函数执行完后&#xff0c;仍然存活在内存中&#xff08;延长了局部变量的生命周期&#xff09; 2、让函数外部可以操作&#xff08;读写&#xff09;到函数内部的数据&#xff08;变量/函数&#xff09; 3、函数执行完后&#xff0c;函数内部声明的局…