ST IKS01A1 驱动程序分析
1.问题出现
我想把st官方的IKS01A1 板子的驱动程序移植到另一个板子上(stm32F767ZI NUCLEO),他原本的程序都是比较难懂,并且耦合度高,挺难移植的,但是我还是移植成功了,这里要对这个驱动代码进行分析。虽然我本来都比较喜欢正点原子那种简单易懂的程序,但是这种代码看了对自己的提高还是挺大的。
2.驱动代码
我以一个初始化函数为例。
首先主函数定义一个 static void *LSM6DS0_X_0_handle = NULL;
BSP_ACCELERO_Init(LSM6DS0_X_0, &LSM6DS0_X_0_handle); //初始化函数
函数原型: 这里就对 BSP_LSM6DS0_ACCELERO_Init(handle) 进行分析。
这里 &LSM6DS0_X_0_handle 赋值给 **handle ,传入的handle即LSM6DS0_X_0_handle 。
DrvStatusTypeDef BSP_ACCELERO_Init( ACCELERO_ID_t id, void **handle ) {*handle = NULL;switch(id){case ACCELERO_SENSORS_AUTO:default:{/* Try to init the LSM6DS3 before */if( BSP_LSM6DS3_ACCELERO_Init(handle) == COMPONENT_ERROR ){/* Try to init the LSM6DS0 if we do not use the LSM6DS3 */if( BSP_LSM6DS0_ACCELERO_Init(handle) == COMPONENT_ERROR ){return COMPONENT_ERROR;}}break;}case LSM6DS0_X_0:{if( BSP_LSM6DS0_ACCELERO_Init(handle) == COMPONENT_ERROR )//我的板子执行这个 {return COMPONENT_ERROR;}break;}case LSM6DS3_X_0:{if( BSP_LSM6DS3_ACCELERO_Init(handle) == COMPONENT_ERROR ){return COMPONENT_ERROR;}break;}}return COMPONENT_OK; }
接下来是对static DrvStatusTypeDef BSP_LSM6DS0_ACCELERO_Init( void **handle )分析
源代码为
static DrvStatusTypeDef BSP_LSM6DS0_ACCELERO_Init( void **handle ) {ACCELERO_Drv_t *driver = NULL;if(ACCELERO_SensorHandle[ LSM6DS0_X_0 ].isInitialized == 1){/* We have reached the max num of instance for this component */return COMPONENT_ERROR;}if ( Sensor_IO_Init() == COMPONENT_ERROR ){return COMPONENT_ERROR;}/* Setup sensor handle. */ACCELERO_SensorHandle[ LSM6DS0_X_0 ].who_am_i = LSM6DS0_ACC_GYRO_WHO_AM_I;ACCELERO_SensorHandle[ LSM6DS0_X_0 ].ifType = 0; /* I2C interface */ACCELERO_SensorHandle[ LSM6DS0_X_0 ].address = LSM6DS0_ACC_GYRO_I2C_ADDRESS_HIGH;ACCELERO_SensorHandle[ LSM6DS0_X_0 ].instance = LSM6DS0_X_0;ACCELERO_SensorHandle[ LSM6DS0_X_0 ].isInitialized = 0;ACCELERO_SensorHandle[ LSM6DS0_X_0 ].isEnabled = 0;ACCELERO_SensorHandle[ LSM6DS0_X_0 ].isCombo = 1;ACCELERO_SensorHandle[ LSM6DS0_X_0 ].pData = ( void * )&ACCELERO_Data[ LSM6DS0_X_0 ];ACCELERO_SensorHandle[ LSM6DS0_X_0 ].pVTable = ( void * )&LSM6DS0_X_Drv;ACCELERO_SensorHandle[ LSM6DS0_X_0 ].pExtVTable = 0;LSM6DS0_X_0_Data.comboData = &LSM6DS0_Combo_Data[0];ACCELERO_Data[ LSM6DS0_X_0 ].pComponentData = ( void * )&LSM6DS0_X_0_Data;ACCELERO_Data[ LSM6DS0_X_0 ].pExtData = 0;*handle = (void *)&ACCELERO_SensorHandle[ LSM6DS0_X_0 ];driver = ( ACCELERO_Drv_t * )((DrvContextTypeDef *)(*handle))->pVTable;if ( driver->Init == NULL ){memset((*handle), 0, sizeof(DrvContextTypeDef));*handle = NULL;return COMPONENT_ERROR;}if ( driver->Init( (DrvContextTypeDef *)(*handle) ) == COMPONENT_ERROR ){memset((*handle), 0, sizeof(DrvContextTypeDef));*handle = NULL;return COMPONENT_ERROR;}/* Configure interrupt lines for LSM6DS0 */LSM6DS0_Sensor_IO_ITConfig();return COMPONENT_OK; }
重点对我画红圈的地方进行分析。
1.ACCELERO_SensorHandle[ LSM6DS0_X_0 ]
这其实是一个全局的设备参数结构体定义
原定义
typedef struct {/* Identity */uint8_t who_am_i;/* Configuration */uint8_t ifType; /* 0 means I2C, 1 means SPI, etc. */uint8_t address; /* Sensor I2C address (NOTE: Not a unique sensor ID). */uint8_t spiDevice; /* Sensor Chip Select for SPI Bus */uint8_t instance; /* Sensor instance (NOTE: Sensor ID unique only within its class). */uint8_t isInitialized; /* Sensor setup done. */uint8_t isEnabled; /* Sensor ON. */uint8_t isCombo; /* Combo sensor (component consists of more sensors). *//* Pointer to the Data */ void *pData;/* Pointer to the Virtual Table */ void *pVTable;/* Pointer to the Extended Virtual Table */ void *pExtVTable; } DrvContextTypeDef;
最后的三个还可以关联到这个设备的数据、驱动函数、扩展驱动函数
2.LSM6DS0_X_Drv
这是一个全局的驱动函数结构体,保存了这个设备的所有驱动。将所有的函数指针赋值到结构体。
定义:
typedef struct {DrvStatusTypeDef ( *Init ) ( DrvContextTypeDef* );DrvStatusTypeDef ( *DeInit ) ( DrvContextTypeDef* );DrvStatusTypeDef ( *Sensor_Enable ) ( DrvContextTypeDef* );DrvStatusTypeDef ( *Sensor_Disable ) ( DrvContextTypeDef* );DrvStatusTypeDef ( *Get_WhoAmI ) ( DrvContextTypeDef*, uint8_t* );DrvStatusTypeDef ( *Check_WhoAmI ) ( DrvContextTypeDef* );DrvStatusTypeDef ( *Get_Axes ) ( DrvContextTypeDef*, SensorAxes_t* );DrvStatusTypeDef ( *Get_AxesRaw ) ( DrvContextTypeDef*, SensorAxesRaw_t* );DrvStatusTypeDef ( *Get_Sensitivity ) ( DrvContextTypeDef*, float* );DrvStatusTypeDef ( *Get_ODR ) ( DrvContextTypeDef*, float* );DrvStatusTypeDef ( *Set_ODR ) ( DrvContextTypeDef*, SensorOdr_t );DrvStatusTypeDef ( *Set_ODR_Value ) ( DrvContextTypeDef*, float );DrvStatusTypeDef ( *Get_FS ) ( DrvContextTypeDef*, float* );DrvStatusTypeDef ( *Set_FS ) ( DrvContextTypeDef*, SensorFs_t );DrvStatusTypeDef ( *Set_FS_Value ) ( DrvContextTypeDef*, float );DrvStatusTypeDef ( *Get_Axes_Status ) ( DrvContextTypeDef*, uint8_t* );DrvStatusTypeDef ( *Set_Axes_Status ) ( DrvContextTypeDef*, uint8_t* );DrvStatusTypeDef ( *Read_Reg ) ( DrvContextTypeDef*, uint8_t, uint8_t* );DrvStatusTypeDef ( *Write_Reg ) ( DrvContextTypeDef*, uint8_t, uint8_t );DrvStatusTypeDef ( *Get_DRDY_Status ) ( DrvContextTypeDef*, uint8_t* ); } ACCELERO_Drv_t;ACCELERO_Drv_t LSM6DS0_X_Drv = {LSM6DS0_X_Init,LSM6DS0_X_DeInit,LSM6DS0_X_Sensor_Enable,LSM6DS0_X_Sensor_Disable,LSM6DS0_X_Get_WhoAmI,LSM6DS0_X_Check_WhoAmI,LSM6DS0_X_Get_Axes,LSM6DS0_X_Get_AxesRaw,LSM6DS0_X_Get_Sensitivity,LSM6DS0_X_Get_ODR,LSM6DS0_X_Set_ODR,LSM6DS0_X_Set_ODR_Value,LSM6DS0_X_Get_FS,LSM6DS0_X_Set_FS,LSM6DS0_X_Set_FS_Value,LSM6DS0_X_Get_Axes_Status,LSM6DS0_X_Set_Axes_Status,LSM6DS0_X_Read_Reg,LSM6DS0_X_Write_Reg,LSM6DS0_X_Get_DRDY_Status };
3.*handle = (void *)&ACCELERO_SensorHandle[ LSM6DS0_X_0 ];
这个的意思就是把赋值好的 全局设备参数结构体地址 传给 自己定义的LSM6DS0_X_0_handle。
并且转换成(void *);
4.driver = ( ACCELERO_Drv_t * )((DrvContextTypeDef *)(*handle))->pVTable;
首先把(*handle)强制转换 (DrvContextTypeDef *)。也就是这个时候相当于原来的ACCELERO_SensorHandle[LSM6DS0_X_0 ]。再把这个结构体的 void * pVTable,强制转换成ACCELERO_Drv_t *,相当于又变成了LSM6DS0_X_Drv。 现在把这个 LSM6DS0_X_Drv结构体的地址赋值给driver。
5.driver->Init( (DrvContextTypeDef *)(*handle)
driver->Init( (DrvContextTypeDef *)(*handle);现在就可以通过driver调用init来使用
![](/assets/blank.gif)
4.简单例子
#include <stdio.h> #include "func.h"static void *LSM6DS0_X_0_handle = NULL;void Init_acc(void **handle);int main(int argc, char *argv[]) {Init_acc(&LSM6DS0_X_0_handle);return 0; }void Init_acc(void **handle) {//临时--初始化----设备结构体 DrvContextTypeDef ACCELERO_SensorHandle;//设备驱动结构体初始化ACCELERO_Drv_t *driver=NULL ;//初始化一些信息ACCELERO_SensorHandle.who_am_i=110;//将驱动函数连接到设备的驱动ACCELERO_SensorHandle.pVTable=( void * )&LSM6DS0_X_Drv;//将刚刚初始化的信息传给handle,这样传进来的handle就会被赋值*handle =(void *)&ACCELERO_SensorHandle;// driver=(ACCELERO_Drv_t *)((DrvContextTypeDef *)(*handle))->pVTable;if(driver->Init == NULL){printf("error\r\n");}else {driver->Init( (DrvContextTypeDef *)(*handle));}}
fun.c
#include "func.h" #include "stdio.h" #include "stdint.h" void ACC_Init(DrvContextTypeDef *handle) { // printf("Init LSM6DS0 %d\r\n",cnt);printf("Init Handle->who am i : %d\r\n",handle->who_am_i); } void ACC_DeInit(DrvContextTypeDef *handle) { // printf("DeInit LSM6DS0 %d\r\n",cnt); }//驱动结构体赋值,将函数关联到结构体中 ACCELERO_Drv_t LSM6DS0_X_Drv = {ACC_Init,ACC_DeInit, };
fun.h
#ifndef FUNC_H #define FUNC_H #include "stdint.h"//定义设备内容结构体 typedef struct {/* Identity */uint8_t who_am_i;/* Configuration */uint8_t ifType; /* 0 means I2C, 1 means SPI, etc. */uint8_t address; /* Sensor I2C address (NOTE: Not a unique sensor ID). */uint8_t spiDevice; /* Sensor Chip Select for SPI Bus */uint8_t instance; /* Sensor instance (NOTE: Sensor ID unique only within its class). */uint8_t isInitialized; /* Sensor setup done. */uint8_t isEnabled; /* Sensor ON. */uint8_t isCombo; /* Combo sensor (component consists of more sensors). *//* Pointer to the Data */void *pData;/* Pointer to the Virtual Table */void *pVTable;/* Pointer to the Extended Virtual Table */void *pExtVTable;} DrvContextTypeDef;//定义驱动结构体 typedef struct {void ( *Init ) (DrvContextTypeDef *handle);void ( *DeInit ) (DrvContextTypeDef *handle); } ACCELERO_Drv_t;extern ACCELERO_Drv_t LSM6DS0_X_Drv;#endif // FUNC_H
转载于:https://www.cnblogs.com/ZQQH/p/8870122.html
ST IKS01A1 驱动程序分析相关推荐
- STM32-I2C总线驱动程序分析
文章目录 I2C硬件电路原理图 I2C 简介 添加相应的文件并添加进工程文件 I2C驱动程序结构 I2C驱动程序分析 LM75A温度传感器电路原理图 LM75A温度传感器驱动程序分析 杨桃32学习笔记 ...
- android 电容屏(三):驱动调试之驱动程序分析篇
平台信息: 内核:linux3.4.39 系统:android4.4 平台:S5P4418(cortex a9) 作者:瘋耔(欢迎转载,请注明作者) 欢迎指正错误,共同学习.共同进步!! 关注博主新 ...
- Microsoft宣布为Power BI提供AI模型构建器,关键驱动程序分析和Azure机器学习集成...
微软的Power BI现在是一种正在大量结合人工智能(AI)的商业分析服务,它使用户无需编码经验或深厚的技术专长就能够创建报告,仪表板等.近日西雅图公司宣布推出几款新的AI功能,包括图像识别和文本分析 ...
- Linux NAND FLASH驱动程序分析(mini2440)
Linux NAND FLASH驱动程序分析(mini2440) 一.Linux-MTD Subsystem介绍 FLASH在嵌入式系统中是必不可少的,它是bootloader.linux内核和文件系 ...
- linux网卡驱动程序分析
linux网卡驱动程序分析 学习应该是一个先把问题简单化,在把问题复杂化的过程.一开始就着手处理复杂的问题,难免让人 有心惊胆颤,捉襟见肘的感觉.读Linux网卡驱动也是一样.那长长的源码夹杂着那些我 ...
- linux3.4.0 按键驱动程序分析(pandaboard omap4460)
linux3.4.0 按键驱动程序分析(pandaboard omap4460) 在内核中,按键的驱动程序已经设计好了,要使自己板上的按键工作起来,需要做的是在相应的文件中添加硬件信息,然后对内核进行 ...
- Linux系统GIC驱动程序分析
百问网技术交流群,百万嵌入式工程师聚集地: https://www.100ask.net/page/2248041 资料下载 coding无法使用浏览器打开,必须用git工具下载: git clone ...
- MTD 设备驱动 和 NAND Flash 驱动程序分析。
硬件环境: 飞凌OK6410,256MB DDR,2GB NAND Flash. NAND Flash 型号:K9G8G08U9A . 分析源码:Linux 2.6.36.2 内核源码 ...
- RT-Thread下的串口驱动程序分析
编写本文稿的目的,在于通过分析stm32平台上的串口中断源码,学习 RTT中如何编写中断处理程序 如何编写RTT设备驱动接口代码 了解串行设备的常见处理机制 先以RTT官方源码中的STM32 BSP包 ...
最新文章
- Uncaught SyntaxError: Unexpected token
- 【Java 网络编程】TCP 数据传输示例 ( 客户端参数设置 | 服务器端参数设置 | ByteBuffer 存放读取数据类型 )
- Linux如何显示文件数目的技巧比较两个文件夹是否相同
- SignalR ——Android实践
- React-引领未来的用户界面开发框架-读书笔记(二)
- java文本框背景_用Java编写小程序(包含组合框下拉和文本框)变换背景颜色
- SAP License:AM手工折旧计算外折旧
- linux db2在线备份,DB2 pureScale在线备份恢复实例
- 你凭什么被叫做程序员?
- html5的video怎么把里面的控制器移出来_6个月宝宝米粉怎么冲,一次吃多少?一天吃几次?关于宝宝米粉的难题,答案都在这了!...
- Asp.net Core 2.1新功能Generic Host(通用主机),了解一下
- POJ- 1751 Highways
- 深入理解C语言指针的奥秘
- 菜鸟教程的Linux命令大全
- python | 秦九昭算法详细介绍
- xio you c语言 程序设计入门——函数的定义
- android保存url图片到相册简书,Android保存图片到系统相册
- 0.1uf 电容浅析
- 网易我的世界能安装java模组吗_网易的我的世界能不能自己制作模组?怎么制作?...
- 我们不一样!告诉你百度是如何做智能流量异常检测的
热门文章
- Python自学笔记-列表生成式(来自廖雪峰的官网Python3)
- Hibernate 具体用法(自整理)
- Linux学习之CentOS(三十四)--配置域主DNS服务器
- 润乾转html居中,[分享]润乾报表内置的jsp编辑器
- Git中的工作区(Working Directory)、暂存区(stage)和历史记录区(history)
- java soa例子_哪位大牛能举个实例讲下SOA与传统架构的区别?
- python HTTP后台响应服务
- 三安光电圈钱凶猛 两年三轮再融资逾百亿
- OSPF虚拟链路实验
- DDoS攻击走向应用层