首页 > 其他分享 >ICM20948 DMP代码详解(23)

ICM20948 DMP代码详解(23)

时间:2024-09-16 09:20:19浏览次数:12  
标签:ICM20948 icm20948 set 23 inv DMP result BIT mode

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

 

上一回解析完了inv_icm20948_wakeup_mems函数,本回回到inv_icm20948_initialize_lower_driver函数中,继续往下解析。为了便于理解和回顾,再次贴出inv_icm20948_initialize_lower_driver函数源码,在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948DataBaseDriver.c中,如下:

/** Should be called once on power up. Loads DMP3, initializes internal variables needed 
*   for other lower driver functions.
*/
int inv_icm20948_initialize_lower_driver(struct inv_icm20948 * s, enum SMARTSENSOR_SERIAL_INTERFACE type, 
	const uint8_t *dmp3_image, uint32_t dmp3_image_size)
{
	int result = 0;
	static unsigned char data;
	// set static variable
	s->sAllowLpEn = 1;
	s->s_compass_available = 0;
	// ICM20948 do not support the proximity sensor for the moment.
	// s_proximity_available variable is nerver changes
	s->s_proximity_available = 0;

	// Set varialbes to default values
	memset(&s->base_state, 0, sizeof(s->base_state));
	s->base_state.pwr_mgmt_1 = BIT_CLK_PLL;
	s->base_state.pwr_mgmt_2 = BIT_PWR_ACCEL_STBY | BIT_PWR_GYRO_STBY | BIT_PWR_PRESSURE_STBY;
	s->base_state.serial_interface = type;
	result |= inv_icm20948_read_mems_reg(s, REG_USER_CTRL, 1, &s->base_state.user_ctrl);

	result |= inv_icm20948_wakeup_mems(s);

	result |= inv_icm20948_read_mems_reg(s, REG_WHO_AM_I, 1, &data);

	/* secondary cycle mode should be set all the time */
	data = BIT_I2C_MST_CYCLE|BIT_ACCEL_CYCLE|BIT_GYRO_CYCLE;

	// Set default mode to low power mode
	result |= inv_icm20948_set_lowpower_or_highperformance(s, 0);
	
	// Disable Ivory DMP.
	if(s->base_state.serial_interface == SERIAL_INTERFACE_SPI)   
		s->base_state.user_ctrl = BIT_I2C_IF_DIS;
	else
		s->base_state.user_ctrl = 0;

	result |= inv_icm20948_write_single_mems_reg(s, REG_USER_CTRL, s->base_state.user_ctrl);

	//Setup Ivory DMP.
	result |= inv_icm20948_load_firmware(s, dmp3_image, dmp3_image_size);
	if(result)
		return result;
	else
		s->base_state.firmware_loaded = 1;
	result |= inv_icm20948_set_dmp_address(s);
	// Turn off all sensors on DMP by default.
	//result |= dmp_set_data_output_control1(0);   // FIXME in DMP, these should be off by default.
	result |= dmp_icm20948_reset_control_registers(s);
	
	// set FIFO watermark to 80% of actual FIFO size
	result |= dmp_icm20948_set_FIFO_watermark(s, 800);

	// Enable Interrupts.
	data = 0x2;
	result |= inv_icm20948_write_mems_reg(s, REG_INT_ENABLE, 1, &data); // Enable DMP Interrupt
	data = 0x1;
	result |= inv_icm20948_write_mems_reg(s, REG_INT_ENABLE_2, 1, &data); // Enable FIFO Overflow Interrupt

	// TRACKING : To have accelerometers datas and the interrupt without gyro enables.
	data = 0XE4;
	result |= inv_icm20948_write_mems_reg(s, REG_SINGLE_FIFO_PRIORITY_SEL, 1, &data);

	// Disable HW temp fix
	inv_icm20948_read_mems_reg(s, REG_HW_FIX_DISABLE,1,&data);
	data |= 0x08;
	inv_icm20948_write_mems_reg(s, REG_HW_FIX_DISABLE,1,&data);

	// Setup MEMs properties.
	s->base_state.accel_averaging = 1; //Change this value if higher sensor sample avergaing is required.
	s->base_state.gyro_averaging = 1;  //Change this value if higher sensor sample avergaing is required.
	inv_icm20948_set_gyro_divider(s, FIFO_DIVIDER);       //Initial sampling rate 1125Hz/19+1 = 56Hz.
	inv_icm20948_set_accel_divider(s, FIFO_DIVIDER);      //Initial sampling rate 1125Hz/19+1 = 56Hz.

	// Init the sample rate to 56 Hz for BAC,STEPC and B2S
	dmp_icm20948_set_bac_rate(s, DMP_ALGO_FREQ_56);
	dmp_icm20948_set_b2s_rate(s, DMP_ALGO_FREQ_56);

	// FIFO Setup.
	result |= inv_icm20948_write_single_mems_reg(s, REG_FIFO_CFG, BIT_SINGLE_FIFO_CFG); // FIFO Config. fixme do once? burst write?
	result |= inv_icm20948_write_single_mems_reg(s, REG_FIFO_RST, 0x1f); // Reset all FIFOs.
	result |= inv_icm20948_write_single_mems_reg(s, REG_FIFO_RST, 0x1e); // Keep all but Gyro FIFO in reset.
	result |= inv_icm20948_write_single_mems_reg(s, REG_FIFO_EN, 0x0); // Slave FIFO turned off.
	result |= inv_icm20948_write_single_mems_reg(s, REG_FIFO_EN_2, 0x0); // Hardware FIFO turned off.
    
	s->base_state.lp_en_support = 1;
	
	if(s->base_state.lp_en_support == 1)
		inv_icm20948_set_chip_power_state(s, CHIP_LP_ENABLE, 1);

	result |= inv_icm20948_sleep_mems(s);   
        
	return result;
}

当前来到以下一行:

	result |= inv_icm20948_read_mems_reg(s, REG_WHO_AM_I, 1, &data);

再次读一下WHO_AM_I寄存器。这一句代码似乎没有什么作用。

接下来是:

	/* secondary cycle mode should be set all the time */
	data = BIT_I2C_MST_CYCLE|BIT_ACCEL_CYCLE|BIT_GYRO_CYCLE;

BIT_I2S_MST_CYCLE、BIT_ACCEL_CYCLE、BIT_GYRO_CYCLE三个宏都是在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948Defs.h中定义,如下:

#define REG_LP_CONFIG           (BANK_0 | 0x05)
#define BIT_I2C_MST_CYCLE               0x40
#define BIT_ACCEL_CYCLE                 0x20
#define BIT_GYRO_CYCLE                  0x10

对应芯片手册中的内容如下:

6b24cf4e68b84ff4b1c2f3b4f05cbcab.png

09f0185e41264ee3a472347a90eca30b.png

这段代码的意思是设置LP_CONFIG寄存器中的I2C_MST_CYCLE、ACCEL_CYCLE、GYRO_CYCLE位,也即设置i2C master、加速度计、陀螺仪为占空比模式。当然,这里还没有实际设置到寄存器中,只是先进行了变量赋值。

接下来是:

	// Set default mode to low power mode
	result |= inv_icm20948_set_lowpower_or_highperformance(s, 0);

inv_icm20948_set_lowpower_or_highperformance函数在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948Setup.c中,代码如下:

int inv_icm20948_set_lowpower_or_highperformance(struct inv_icm20948 *s, uint8_t lowpower_or_highperformance)
{
	s->go_back_lp_when_odr_low = 0;
	if(lowpower_or_highperformance)
		return inv_icm20948_enter_low_noise_mode(s);
	else
		return inv_icm20948_enter_duty_cycle_mode(s);
}

inv_icm20948_set_lowpower_or_highperformance函数一上来先将s->go_back_lp_when_odr_low设置为0。go_back_lp_when_odr_low是struct inv_icm20948中的成员,定义如下:

typedef struct inv_icm20948 {
    ……

	uint8_t go_back_lp_when_odr_low; // set to 1 when we forced a switch from LP to LN mode to be able to reach 1kHz ODR, so we will need to go back to LP mode ASAP
    ……
} inv_icm20948_t;

接下来根据第2个参数uint8_t lowpower_or_highperformance,选择不同分支。

1)非0分支 —— inv_icm20948_enter_low_noise_mode函数

inv_icm20948_enter_low_noise_mode函数也在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948DataBaseDriver.c中,代码如下:

int inv_icm20948_enter_low_noise_mode(struct inv_icm20948 *s)
{
	/* secondary cycle mode should be set all the time */
	unsigned char data  = BIT_I2C_MST_CYCLE;

	s->base_state.chip_lp_ln_mode = CHIP_LOW_NOISE_ICM20948;
	return inv_icm20948_write_mems_reg(s, REG_LP_CONFIG, 1, &data);
}

上边提到了BIT_I2C_MST_CYCLE,这里是实际将值BIT_I2C_MST_CYCLE设置到了LP_CONFIG寄存器,也即设置i2C master为占空比模式。同时将s->base_state.chip_lp_ln_mode设置为CHIP_LOW_NOISE_ICM20948。

CHIP_LOW_NOISE_ICM20948为枚举值,在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948.h中,定义如下:

typedef enum {
	CHIP_LOW_NOISE_ICM20948,
	CHIP_LOW_POWER_ICM20948,
} chip_lp_ln_mode_icm20948_t;

2)0分支 —— inv_icm20948_enter_duty_cycle_mode函数

inv_icm20948_enter_duty_cycle_mode函数也在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948DataBaseDriver.c中,代码如下:

int inv_icm20948_enter_duty_cycle_mode(struct inv_icm20948 * s)
{
	/* secondary cycle mode should be set all the time */
	unsigned char data  = BIT_I2C_MST_CYCLE|BIT_ACCEL_CYCLE|BIT_GYRO_CYCLE;

	s->base_state.chip_lp_ln_mode = CHIP_LOW_POWER_ICM20948;
	return inv_icm20948_write_mems_reg(s, REG_LP_CONFIG, 1, &data);
}

这个函数其实就是上边那段代码加上实际写入寄存器。

	/* secondary cycle mode should be set all the time */
	data = BIT_I2C_MST_CYCLE|BIT_ACCEL_CYCLE|BIT_GYRO_CYCLE;

估计是老版本中直接是在inv_icm20948_initialize_lower_driver函数中设置的,后来多了个Low Noise(LN)模式,就单独封了inv_icm20948_set_lowpower_or_highperformance函数,但是忘记把上边这一段代码删掉了。从这里以及整体工程代码的混乱格式就能感觉出来,要么这个DMP库代码赶时间,对于代码规范做得不够细致;要么这个项目是Invensense找的外包做的,实现了功能就得,对于其它不大要求。总之,以Linux内核代码规范标准来评判,整个工程代码在格式上“一门都没有”。

书归正题,此处由于传给inv_icm20948_set_lowpower_or_highperformance函数的实参是0,因此走的是0分支。

	// Set default mode to low power mode
	result |= inv_icm20948_set_lowpower_or_highperformance(s, 0);

至此,inv_icm20948_set_lowpower_or_highperformance函数就解析完了。下一回继续解析inv_icm20948_initialize_lower_driver函数中的其余部分。

 

标签:ICM20948,icm20948,set,23,inv,DMP,result,BIT,mode
From: https://blog.csdn.net/phmatthaus/article/details/142181077

相关文章

  • 文心一言 VS 讯飞星火 VS chatgpt (347)-- 算法导论23.2 6题
    六、假定一个图中所有的边权重均匀分布在半开区间[0,1)内。Prim算法和Kruskal算法哪一个可以运行得更快?如果要写代码,请用go语言。文心一言:在比较Prim算法和Kruskal算法在特定条件下的性能时,我们需要考虑几个因素,主要是图的表示方式、边的数量、顶点的数量以及边的权重分布。由于在......
  • 信息学奥赛初赛天天练-90-CSP-S2023基础题2-离散数学、染色、完全三叉树、平面图、边
    PDF文档公众号回复关键字:202409152023CSP-S选择题1单项选择题(共15题,每题2分,共计30分:每题有且仅有一个正确选项)6以下连通无向图中,()一定可以用不超过两种颜色进行染色A完全三叉树B平面图C边双连通图D欧拉图7最长公共子序列长度常常用来衡量两个序列的相......
  • SP17123 解题报告
    题目传送门扫描线是一种求矩形面积并或周长并的好方法。假设在一个平面上有几个矩形,要求它们共覆盖了多大的面积。由于矩形可能会有重叠的地方,所以最后要求的图形就是一个不规则的图形。要求它的面积十分复杂,特别是在矩形数量很大时。为了解决这个问题,扫描线法应运而生。想......
  • 二分图 by LFRED2023
    本文由LFRED2023撰写,由本人帮忙代发二分图二分图的定义二分图又叫二部图,是图论的一种特殊模型假设$S=(V,E)$是一个无向图。如果顶点$V$可分割为两个互不相交的子集$(A,B)$,并且图中的每条边$(i,j)$所关联的两个顶点$i$和$j$分别属于这两个不同的顶点......
  • 国产RAID卡2230-10i windows&Linux操作系统安装指导
    环境准备:1.准备2个U盘。一个刻录系统,一个装载驱动2.需保持CSM为UEFI状态和PCIEDEVICESLIST 下2230-10i的卡为UEFI状态,如图:环境排查:由于......
  • 23. 几何体顶点位置数据和点模型
    本节课主要目的是给大家讲解几何体geometry的顶点概念,相对偏底层一些,不过掌握以后,你更容易深入理解Threejs的几何体和模型对象。缓冲类型几何体BufferGeometrythreejs的长方体BoxGeometry、球体SphereGeometry等几何体都是基于BufferGeometry (opensnewwindow)类构建的,Bu......
  • 2023年全国高中数学联合竞赛A卷加试P3:组合极值、染色
    题目求具有下述性质的最小正整数$k$:若将$1,2,\cdots,k$中的每个数任意染为红色或者蓝色,则或者存在$9$个不同的红色的数$x_1,x_2,\cdots,x_9$满足$x_1+x_2+\cdots+x_8<x_9,$或者存在$10$个互不相同的蓝色的数$y_1,y_2,\cdots,y_{10}$满足$y_1+y_2+\cdots+y_9<y_{10}.$解......
  • 基于django+vue电脑DIY微信小程序演示录像22023【开题报告+程序+论文】-计算机毕设
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着科技的飞速发展,个人电脑(PC)已成为人们日常生活与工作中不可或缺的一部分。然而,在市场上琳琅满目的电脑配件和复杂多变的配置选项中,许多......
  • 信息学奥赛初赛天天练-89-CSP-S2023基础题1-linux常用命令、完全平方数、稀疏图、队列
    PDF文档公众号回复关键字:202409142023CSP-S选择题单项选择题(共15题,每题2分,共计30分:每题有且仅有一个正确选项)1在Linux系统终端中,以下哪个命令用于创建一个新的目录?()AnewdirBmkdirCcreateDmkfold2从0,1,2,3,4中选取4个数字,能组成(......
  • LeetCode238. 除自身以外数组的乘积(2024秋季每日一题 17)
    给你一个整数数组nums,返回数组answer,其中answer[i]等于nums中除nums[i]之外其余各元素的乘积。题目数据保证数组nums之中任意元素的全部前缀元素和后缀的乘积都在32位整数范围内。请不要使用除法,且在示例1:输入:nums=[1,2,3,4]输出:[24,12,8,6]示例2:输......