WinCE6.0+ S3C6410 IIC驱动源码学习

news/2024/9/23 1:35:23/
今天总结一下IIC驱动的源码学习。IIC驱动也是Wince下的流接口驱动,所以配置文件的设置和其他流接口都一样,本人在以前已经对该问题做了介绍,这里就不重复了。
IIC驱动较为简单,主要的源文件有iic.hiic_pdd.hiic_mdd.hiic_mdd.cpps3c6410_icc_lib.cpp五个文件,三个h文件都是关于相关数据结构和宏的定义,cpp文件是所有功能的实现。
下面主要从流接口的几个接口函数来分析驱动源码,包括DllEntryIIC_InitIIC_DeinitIIC_OpenIIC_CloseIIC_IOControlIIC_PowerUpIIC_PowerDown
        一、在 Device.exe 加载 IIC 驱动时,首先执行的是 DllEntry IIC_Init 函数, DllEntry 函数没有任何实际的操作,这里跳过,直接看 IIC_Init 函数。
       入口参数是关于IIC驱动在注册表中的路径。
       144行是为PHW_INIT_INFO结构体在堆上分配空间,pInitContext存储在IIC_Init函数中获得的相关信息,并作为参数传递给IIC_Open函数。PHW_INIT_INFO结构体的定义在文件iic_mdd.h中,这里不再给出。
       174204行读取注册表中的相关信息,并将数据填充到pInitContext中。
       208行在后面的IIC中断处理函数中使用,用来判断是否驱动卸载。
       212行进行IIC硬件的相关初始化工作,后面分析。
       222行返回pInitContext,将在后面作为IIC_Open函数的参数。
       HW_Init函数在文件s3c6410_icc_lib.cpp中,下面分析一下该函数。
94 MapVirtualAddress 函数实现在本文件 s3c6410_icc_lib.cpp 中, 完成相关寄存器的虚拟地址映射。
100 InitializeGPIOPort 函数实现在本文件 s3c6410_icc_lib.cpp 中,完成 GPIO GPB 的相关设置,使 IO SCL SDA 功能。
104 118 行创建了两个事件, g_hTransferEvent 用于记录发送和接收数据的事件, g_hTransferDone 用于记录发送结束或者接收结束的事件。
122 139 行首先向内核注册中断逻辑号( IRQ_I2C ),然后通过 InterruptInitialize 将中断号与相应的事件进行映射。当内核触发该中断时,通过查表触发相应的事件。
143 行创建相应的中断处理函数 IIC_IST ,该函数也在本文件中,下面进行分析。
677 行和 682 行用来判断 IIC 运行状态,前面初始化时已经设置成了 IIC_RUN 的状态,当退出 IIC 驱动的时候,修改状态为 IIC_FINISH ,从而退出中断处理线程。这是中断处理线程中经常使用的方法。
680 行用来等待 IIC 收发数据事件的发生,超时时间设置为无限等待。
685 709 行是对 IIC 四种状态的判断。 ARBITRATION_FAILED 代表 IIC 总线仲裁失败即在申请对总线的使用权时失败, SLAVE_ADDRESS_MATCHED 代表收到的从设备地址与 ICCADD 寄存器里面的值相等, SLAVE_ADDRESS_ZERO 代表收到的从设备地址为 0 ACK_NOT_RECEIVED 代表收到的最后一个 bit 不是 0 ,即没有收到 ACK 信号。
711 行是用来判断当前设备处于何种状态,由于 CPU 总是作为主设备存在,所以只能是主设备接收和主设备发送两种状态。
719 739 行是主设备接收状态的情况,在本人的另一篇博文中座了较详细的分析 http://jazka.blog.51cto.com/809003/702584
741 756 行是主设备发送状态的情况, if (g_uIIC_PT<g_uIIC_DATALEN) 判断数据是否发送完毕,没有则继续从 Buffer 中读取一个字节到 IICDS 寄存器中,如果发送完了,就置结束标志 bDone ,同时设置 IICSTAT 寄存器发送 STOP 信号, g_pIICReg->IICCON &= ~(1<<4) 用来清除中断标志,没发送一个字节都需要清除中断标志。
       761 765 行用来在接收或者发送结束的情况下,设置结束事件,以保证在程序的其他地方检测到结束事件后进行相应的处理。
        二、上面操作完成之后, IIC 驱动就已经成功加载了,当用户调用 CreateFile 函数是调用 IIC_Open 函数,下面分析该函数,只列出比较重要的内容。
       PHW_INIT_INFO是初始化函数IIC_Init返回的信息结构体,而PHW_OPEN_INFO是将该函数中收集的相关信息结构体,用于返回给IIC_IOControl的参数。
       pInitContext->OpenCnt用来记录IIC打开的次数。
       372378行用于初次打开IIC设备时的处理,HW_OpenFirst函数主要完成从设备地址设置和使能中断。如下:
// slave address setting 
pInitContext-PDDCommonVal.SlaveAddress = DEFAULT_SLAVE_ADDRESS; 
pInitContext->PDDCommonVal.InterruptEnable = DEFAULT_INTERRUPT_ENABLE;
       HW_PowerUp函数用来打开IIC设备Power,如下:
g_pSYSCONReg->PCLK_GATE |= IIC_POWER_ON;
       381行完成打开IIC设备的大部分操作,HW_Open函数后面介绍。
       387行用来增加IIC设备的开启数量。
       HW_Open函数的绝大部分操作如下:
       401404行主要完成时钟、主从收发模式、过滤使能以及延时的设置。时钟要根据从设备的情况而设置,否则收发会出现问题,此处为了3000Hz。模式默认选择为主设备发送模式。
       CalculateClockSet函数用来设置时钟分频以达到想要的时钟频率。S3C6410有两种模式,通过IICCON寄存器进行设置。
408 行的 DirtyBit 用来标记寄存器设置是否发生变化,每次设置寄存器时都需要判断该标志。
       410 行的 HW_SetRegister 函数用来设置 IIC 的寄存器,包括 IICADD IICSTAT IICLC IICCON 四种寄存器,如下:
if(g_OwnerContext != pOpenContext || pOpenContext->DirtyBit == TRUE) 

        DEBUGMSG (ZONE_FUNCTION, 
                            (TEXT("+HW_SetRegister(0x%X)\r\n"), 
                             pOpenContext)); 
        g_pIICReg->IICADD = pOpenContext->pInitContext->PDDCommonVal.SlaveAddress; 
        g_pIICReg->IICSTAT = (g_pIICReg->IICSTAT & ~(0x3<<6)) | (1<<4) | (pOpenContext->PDDContextVal.ModeSel<<6); 
        g_pIICReg->IICLC = (pOpenContext->PDDContextVal.FilterEnable<<2) | (pOpenContext->PDDContextVal.Delay); 
        g_pIICReg->IICCON = (pOpenContext->PDDContextVal.ClockSel << 6) | (pInitContext->PDDCommonVal.InterruptEnable << 5) | 
                                                        (pOpenContext->PDDContextVal.ClockDiv & 0xf); 

        g_OwnerContext = pOpenContext; 
        pOpenContext->DirtyBit = FALSE; 

三、最后在打开IIC设备之后,便是通过IIC_IOControl接口对IIC设备进行各种操作。IOControl控制码主要包括一下几种:
IOCTL_POWER_CAPABILITIES IOCTL_IIC_WRITE IOCTL_IIC_READ IOCTL_IIC_SET_CLOCK IOCTL_IIC_GET_CLOCK IOCTL_IIC_SET_MODE IOCTL_IIC_GET_MODE IOCTL_IIC_SET_FILTER
IOCTL_IIC_GET_FILTER IOCTL_IIC_SET_DELAY IOCTL_IIC_GET_DELAY 等。
          在这些控制码中,比较常用的是读写请求 IOCTL_IIC_WRITE IOCTL_IIC_READ 时钟设置 IOCTL_IIC_GET_CLOCK 延时设置 IOCTL_IIC_SET_DELAY
时钟设置的请求,实际调用的函数依然上面提到的CalculateClockSet函数。
延时设置调用pOpenContext->PDDContextVal.Delay = (IIC_DELAY)*(UINT32*)pBufIn;
        写请求主要调用 HW_Write 函数,大部分情况用来设置从设备的初始化等,位于 s3c6410_iic_lib.cpp 文件中,如下:
578 行根据写请求之前的各项设置重新设置相关寄存器。
580 行重置 g_hTransferDone 事件,在每次的读写操作之前都需要该操作。
582 行是通过 IICSTAT 寄存器的状态判断 IIC 总线是否空闲,如果有其他设备正在使用则需要等待其释放。
588 行到 598 行首先记录要发送数据的 buffer 以及长度,然后设置接收 ACK 信号和收发模式、从设备的写地址,最后发送 START 信号,此时 IICDS 上的数据变随着 CLK 发送到了从设备,并且每次发送完一个字节都会触发收发数据的中断处理线程函数中,前面已经介绍了。
600 行用于等待所有的数据都发送完成,包括 STOP 信号的发送。
读请求主要调用 HW_Read 函数,主要用来读取从设备的状态及有效数据等,位于 s3c6410_iic_lib.cpp 文件中,如下:
529 行到 539 行的内容基本都喝 HW_Write 函数的一样,唯一不同的是多了一个函数 HW_Write ,在读取从设备数据之前,首先需要发送从设备的写地址,其次需要告诉从设备你要读取哪些数据 ( 大多数是要读取数据的地址 ) ,所以此处会包含该函数。
540 行到 548 行首先设置接收数据的 buffer 和长度,然后设置接收 ACK 信号和设备模式、从设备的读地址等,最好发送 START 信号。
       600 行用于等待所有的数据都接收完成。

本文转自jazka 51CTO博客,原文链接:http://blog.51cto.com/jazka/707401,如需转载请自行联系原作者

http://www.ppmy.cn/news/110696.html

相关文章

区块链 fisco bcos 2.72 在多机器上部署多个docker节点 ubuntu

一、安装 1. 安装依赖 安装curl、openssl: sudo apt-get update sudo apt install -y curl openssl 2. 安装docker: (1)安装docker # 更新包索引 sudo apt-get update # 安装基础依赖库 sudo apt-get install \apt-transport-https \ca-certificates \curl \gnupg-agent \…

Linux驱动程序调试方法

驱动程序开发的一个重大难点就是不易调试。本文目的就是介绍驱动开发中常用的几种直接和间接的调试手段&#xff0c;它们是&#xff1a; 利用printk查看OOP消息利用strace利用内核内置的hacking选项利用ioctl方法利用/proc 文件系统使用kgdb 一、利用printk 这是驱动开发中最…

基于决策树模型的金融保险用户分类综合项目【数据可视化相关性分析填充缺失值转码建模商业应用】

大家早上好&#xff0c;本人姓吴&#xff0c;如果觉得文章写得还行的话也可以叫我吴老师。欢迎大家跟我一起走进数据分析的世界&#xff0c;一起学习&#xff01; 感兴趣的朋友可以关注我或者我的数据分析专栏&#xff0c;里面有许多优质的文章跟大家分享哦。 目录 必看前言1 行…

error C2440: “static_cast”: 无法从“void (__thiscall CChatDlg::* )(WPARAM,LPARAM)”转换为“LRESULT

error C2440: “static_cast”: 无法从“void (__thiscall CChatDlg::* )(WPARAM,LPARAM)”转换为“LRESULT (__thiscall CWnd::* )(WPARAM,LPARAM)” 1> 从基类型到派生类型的强制转换需要 dynamic_cast 或 static_cast 搜索发现为开发平台迁移问题。 由vc6.0升级至…

unrecognized selector sent to instance 0x10b34e810

报错&#xff1a; *** Terminating app due to uncaught exception NSInvalidArgumentException, reason: -[NSURLError isEqualToString:]: unrecognized selector sent to instance 0x10b34e810 *** First throw call stack: (lldb) po 0x10b34e810 Error DomainNSURLErrorD…

CISCO服务器配置RAID步骤

CISCO服务器配置RAID步骤 ILO为DHCP&#xff08;不建议设成固定&#xff09;&#xff0c;打开页面&#xff08;如&#xff1a;https://10.0.1.240&#xff09;&#xff0c;用户名&#xff1a;admin&#xff0c;密码&#xff1a;password&#xff0c;首次登陆会让该密码&#xf…

hashcat(爆破工具,支持GPU,精)

目录 简介 分类 参数 -m hash的类型 -a 攻击方式 掩码 使用方法 字典破解 hash表

redis-sentinel主从切换

上篇我们搭建了redis主从&#xff0c;那么如果redis的master宕掉之后&#xff0c;sentinel可以切换一台slave为master 上篇我们搭建redis主从是一主二从在一台机器上&#xff0c;所以现在需要3个sentinel服务来监控三个redis节点 主&#xff1a;127.0.0.1:6379从&#xff1a;…