Windows CE6.0 S3C2440A IIC驱动编码解析

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: S3C2440A RISC微处理器可以支持多主设备IIC总线串行接口。专用串行总线(SDA)和串行时钟线(SCL)承载总线主机设备和连接IIC总线的外围设备之间的信息。

S3C2440A RISC微处理器可以支持多主设备IIC总线串行接口。专用串行总线(SDA)和串行时钟线(SCL)承载总线主机设备和连接IIC总线的外围设备之间的信息。SDASCL线都是双向的。本章采用TQ2440开发板进行分析,我们先来看看其硬件电路图;

从这里可以看的出 TQ2440 采用的是AT24C02A IIC器件,其中I2CSCLI2CSDA分别表示时钟线和数据线。接下来看看IIC寄存器的相关结构体;

typedef struct _I2C_CONTEXT {

    DWORD   Sig;    // Signature

    volatile S3C2440A_IICBUS_REG *pI2CReg; // I2C Registers

    volatile S3C2440A_IOPORT_REG *pIOPReg;   // GPIO Ports

    volatile S3C2440A_CLKPWR_REG *pCLKPWRReg; // Clock / Power

    CRITICAL_SECTION RegCS; // Register CS

    I2C_MODE    Mode; // State

    I2C_STATE   State;

    int         Status;

    FLAGS       Flags;

    // Data

    PUCHAR      Data;           // pointer to R/W data buffer

    int         DataCount;      // nBytes to R/W to/from data buffer

    UCHAR       WordAddr;       // slave word address

    UCHAR       RxRetAddr;      // returned slave address on Rx

    DWORD       SlaveAddress;   // Our I2C Slave Address

    HANDLE      DoneEvent;      // I/O Done Event

    HANDLE      ISTEvent;       // IST Event

    HANDLE      IST;            // IST Thread

    DWORD       OpenCount;

    DWORD       LastError;

    HANDLE      hProc;

    CEDEVICE_POWER_STATE    Dx;

} I2C_CONTEXT, *PI2C_CONTEXT;

在这个结构体中pI2CRegpIOPRegpCLKPWRReg都扮演着非常重要的角色,如下来看看如何实现这上个寄存器初始化工作,后面将介绍IIC驱动的几个关键部分代码;

bMapReturn = VirtualCopy( pVMem,(LPVOID)(S3C2440A_BASE_REG_PA_IICBUS>>8),        PAGE_SIZE,PAGE_READWRITE | PAGE_NOCACHE |PAGE_PHYSICAL);

       pI2C->pI2CReg = (volatile S3C2440A_IICBUS_REG*)(pVMem);

        pVMem += PAGE_SIZE;

VirtualCopy(pVMem,(LPVOID)(S3C2440A_BASE_REG_PA_IOPORT>>8),

     PAGE_SIZE,PAGE_READWRITE | PAGE_NOCACHE |PAGE_PHYSICAL);

pI2C->pIOPReg = (volatile S3C2440A_IOPORT_REG*)(pVMem);

pVMem += PAGE_SIZE;

VirtualCopy(pVMem,(LPVOID)(S3C2440A_BASE_REG_PA_CLOCK_POWER>>8),

PAGE_SIZE,PAGE_READWRITE | PAGE_NOCACHE |PAGE_PHYSICAL);

pI2C->pCLKPWRReg = (volatile S3C2440A_CLKPWR_REG*)(pVMem);

中断模式处理

   Windows CE当中中断处理的常用的几个函数有KernelIoControlInterruptInitializeInterruptDisableInterruptDone函数,如下所示是其处理过程。

Irq = IRQ_IIC;

KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &Irq, sizeof(UINT32), &gIntrIIC, sizeof(UINT32), NULL))      

// initialize the interrupt

InterruptInitialize(gIntrIIC, pI2C->ISTEvent, NULL, 0) ) ;

InterruptDone(gIntrIIC);

// create the IST

pI2C->IST = CreateThread(NULL, 0, I2C_IST, (LPVOID)pI2C, 0, NULL));

CeSetThreadPriority(pI2C->IST, I2C_THREAD_PRIORITY));

IST函数

    PI2C_CONTEXT pI2C = (PI2C_CONTEXT)Context;

    DWORD i2cSt;

    BOOL bDone = FALSE;

    do  {

        if (pI2C->Mode == INTERRUPT) {

            DWORD we;

            bDone = FALSE;

            we = WaitForSingleObject(pI2C->ISTEvent, INFINITE);

            // clear the interrupt here because we re-arm another below

            InterruptDone(gIntrIIC);

            switch(pI2C->State)

            {

                case OFF:

                    DEBUGMSG(ZONE_IST|ZONE_TRACE,(TEXT("I2C_IST: ExitThread /r/n")));

                    ExitThread(ERROR_SUCCESS);

                    break;

                case IDLE:

                    DEBUGMSG(ZONE_IST|ZONE_TRACE,(TEXT("I2C_IST: IDLE /r/n")));

                    continue;

                    break;

                default:

                    if (pI2C->State != WRITE_ACK &&

                        pI2C->State != RESUME &&

                        pI2C->DataCount == INVALID_DATA_COUNT) {

                        continue;

                    }

                    break;

            }

        }

//        EnterCriticalSection(&pI2C->RegCS);

        __try {

            switch(pI2C->State)

            {

                case IDLE:

                case SUSPEND:

                    continue;

                    break;

                case RESUME:

                    InitRegs(pI2C);

                    pI2C->LastError = ERROR_OPERATION_ABORTED;

                    SetEvent(pI2C->DoneEvent);

                    break;

                case SET_READ_ADDR:

                    if ( (pI2C->DataCount--) == 0 )

                    {

                        bDone = TRUE;

                        break;

                    }      

                    // write word address

                    // For setup time of SDA before SCL rising edge, rIICDS must be written

                    // before clearing the interrupt pending bit.

                    if (pI2C->Flags.WordAddr) {

                        rIICDS = pI2C->WordAddr;

                        // clear interrupt pending bit (resume)

                        rIICCON = RESUME_IIC_CON;

                        pI2C->Flags.WordAddr = FALSE;

                    }

                    break;

                case READ_DATA:                   

                    ASSERT(pI2C->Data);

                    if ( (pI2C->DataCount--) == 0 )

                    {

                        bDone = TRUE;

                   

                        *pI2C->Data = (UCHAR)rIICDS;

                        pI2C->Data++;

                        rIICSTAT = MRX_STOP;   

                        rIICCON  = RESUME_IIC_CON;  // resume operation.                   

break;   

                    }

                    // Drop the returned Slave WordAddr?

                    if ( pI2C->Flags.DropRxAddr )

                    {

                        pI2C->RxRetAddr = (UCHAR)rIICDS;

                        pI2C->Flags.DropRxAddr = FALSE;                       

                    } else {

                        *pI2C->Data = (UCHAR)rIICDS;

                        pI2C->Data++;

                    }

                    // The last data is read with no ack.

                    if ( pI2C->DataCount == 0 ) {

                        rIICCON = RESUME_NO_ACK;    // resume operation with NOACK. 

                        DEBUGMSG(ZONE_READ|ZONE_TRACE,(TEXT("R1:0x%X /r/n"), r));

                    } else {

                        rIICCON = RESUME_IIC_CON;       // resume operation with ACK

                        DEBUGMSG(ZONE_READ|ZONE_TRACE,(TEXT("R2:0x%X /r/n"), r));

                    }

                    break;

                case WRITE_DATA:                       

                    ASSERT(pI2C->Data);

                    if ( (pI2C->DataCount--) == 0 )

                    {

                        bDone = TRUE;

                        rIICSTAT = MTX_STOP;   

                        rIICCON  = RESUME_IIC_CON;  // resume operation.

                        //The pending bit will not be set after issuing stop condition.

                        break;   

                    }

                        rIICDS = (UCHAR)*pI2C->Data;

                        pI2C->Data++;

                    }

                    rIICCON = RESUME_IIC_CON;   // resume operation.

                    break;

            }

       

        } _except(EXCEPTION_EXECUTE_HANDLER) {

            rIICSTAT = (pI2C->State == READ_DATA) ? MRX_STOP : MTX_STOP;

            rIICCON  = RESUME_IIC_CON;

 

            pI2C->DataCount = INVALID_DATA_COUNT;

            pI2C->LastError = GetExceptionCode();

        }

        if (bDone) {

            DEBUGMSG(ZONE_IST, (TEXT("SetEvent DONE/r/n")));

            SetEvent(pI2C->DoneEvent);

        }           

} while (pI2C->Mode == INTERRUPT);   

return ERROR_SUCCESS;

}

读取数据操作

驱动采用的是中断方式读取数据,其中数据指针保存在pI2C->pData当中,其中为了保证用户区缓冲和驱动内核区缓冲一致,还必须调用GetCallerProcess() MapPtrToProcess()GetCurrentProcessID()函数,这几个函数的具体用法可以查询MSDN帮助即可,这部分代码如下;

pI2C->State     = WRITE_DATA;

pI2C->DataCount = 1 + Count; // slave word address + data

pI2C->WordAddr  = WordAddr;

pI2C->Flags.WordAddr = TRUE;   

pI2C->Data = pData;

// write slave address

rIICDS   = (UCHAR)SlaveAddr;

rIICSTAT = MTX_START;

// IST writes the slave word address & data

if (WAIT_OBJECT_0 != SyncIst(pI2C, TX_TIMEOUT)) {

goto _done;

}

写数据操作

写操作和读操作方法很类似,是其反过程,代码很简单,这里就不多讲了,具体在S3C2440A BSP中可以看到。

这个IIC驱动是一个典型的Windows CE流接口驱动程序,是一个很好的学习范例,特写至此,希望对来客有写帮助。

目录
相关文章
|
2月前
|
自然语言处理 Linux Windows
Cmder - 想让你的windows下 cmd 和 SecureCRT 操作 Linux 一样帅吗 附字符集编码 chcp 936、chcp 65001
Cmder - 想让你的windows下 cmd 和 SecureCRT 操作 Linux 一样帅吗 附字符集编码 chcp 936、chcp 65001
22 1
|
2月前
|
开发者 C# Windows
WPF与游戏开发:当桌面应用遇见游戏梦想——利用Windows Presentation Foundation打造属于你的2D游戏世界,从环境搭建到代码实践全面解析新兴开发路径
【8月更文挑战第31天】随着游戏开发技术的进步,WPF作为.NET Framework的一部分,凭借其图形渲染能力和灵活的UI设计,成为桌面游戏开发的新选择。本文通过技术综述和示例代码,介绍如何利用WPF进行游戏开发。首先确保安装最新版Visual Studio并创建WPF项目。接着,通过XAML设计游戏界面,并在C#中实现游戏逻辑,如玩家控制和障碍物碰撞检测。示例展示了创建基本2D游戏的过程,包括角色移动和碰撞处理。通过本文,WPF开发者可更好地理解并应用游戏开发技术,创造吸引人的桌面游戏。
94 0
|
2月前
|
存储 开发者 C#
WPF与邮件发送:教你如何在Windows Presentation Foundation应用中无缝集成电子邮件功能——从界面设计到代码实现,全面解析邮件发送的每一个细节密武器!
【8月更文挑战第31天】本文探讨了如何在Windows Presentation Foundation(WPF)应用中集成电子邮件发送功能,详细介绍了从创建WPF项目到设计用户界面的全过程,并通过具体示例代码展示了如何使用`System.Net.Mail`命名空间中的`SmtpClient`和`MailMessage`类来实现邮件发送逻辑。文章还强调了安全性和错误处理的重要性,提供了实用的异常捕获代码片段,旨在帮助WPF开发者更好地掌握邮件发送技术,提升应用程序的功能性与用户体验。
36 0
|
2月前
|
API C# Shell
WPF与Windows Shell完美融合:深入解析文件系统操作技巧——从基本文件管理到高级Shell功能调用,全面掌握WPF中的文件处理艺术
【8月更文挑战第31天】Windows Presentation Foundation (WPF) 是 .NET Framework 的关键组件,用于构建 Windows 桌面应用程序。WPF 提供了丰富的功能来创建美观且功能强大的用户界面。本文通过问题解答的形式,探讨了如何在 WPF 应用中集成 Windows Shell 功能,并通过具体示例代码展示了文件系统的操作方法,包括列出目录下的所有文件、创建和删除文件、移动和复制文件以及打开文件夹或文件等。
45 0
|
2月前
|
数据库 Windows
超详细步骤解析:从零开始,手把手教你使用 Visual Studio 打造你的第一个 Windows Forms 应用程序,菜鸟也能轻松上手的编程入门指南来了!
【8月更文挑战第31天】创建你的第一个Windows Forms (WinForms) 应用程序是一个激动人心的过程,尤其适合编程新手。本指南将带你逐步完成一个简单WinForms 应用的开发。首先,在Visual Studio 中创建一个“Windows Forms App (.NET)”项目,命名为“我的第一个WinForms 应用”。接着,在空白窗体中添加一个按钮和一个标签控件,并设置按钮文本为“点击我”。然后,为按钮添加点击事件处理程序`button1_Click`,实现点击按钮后更新标签文本为“你好,你刚刚点击了按钮!”。
103 0
|
2月前
|
消息中间件 Java RocketMQ
微服务架构师的福音:深度解析Spring Cloud RocketMQ,打造高可靠消息驱动系统的不二之选!
【8月更文挑战第29天】Spring Cloud RocketMQ结合了Spring Cloud生态与RocketMQ消息中间件的优势,简化了RocketMQ在微服务中的集成,使开发者能更专注业务逻辑。通过配置依赖和连接信息,可轻松搭建消息生产和消费流程,支持消息过滤、转换及分布式事务等功能,确保微服务间解耦的同时,提升了系统的稳定性和效率。掌握其应用,有助于构建复杂分布式系统。
38 0
|
2月前
【Azure 应用服务】App Service 配置 Application Settings 访问Storage Account得到 could not be resolved: '*.file.core.windows.net'的报错。没有解析成对应中国区 Storage Account地址 *.file.core.chinacloudapi.cn
【Azure 应用服务】App Service 配置 Application Settings 访问Storage Account得到 could not be resolved: '*.file.core.windows.net'的报错。没有解析成对应中国区 Storage Account地址 *.file.core.chinacloudapi.cn
|
2月前
|
Windows
Windows 映射网络驱动器及删除-此网格连接不存在
Windows 映射网络驱动器及删除-此网格连接不存在
101 0
|
3月前
|
监控 安全 网络安全
Windows系统安全深度解析:挑战、策略与全面防护
对敏感数据进行加密是保护数据机密性的重要手段。使用强加密算法对敏感数据进行加密存储和传输,即使数据被窃取也无法被轻易解密。此外,还可以考虑使用全磁盘加密技术来保护整个系统的数据安全性。
|
关系型数据库 MySQL 数据库
MySQL:Windows环境下的编码问题和解决
MySQL:Windows环境下的编码问题和解决
107 0

热门文章

最新文章

推荐镜像

更多
下一篇
无影云桌面