📄 i2c.c
字号:
/****************************************Copyright (c)**************************************************
** gec electronics Co.,LTD.
**
**
**
**--------------File Info-------------------------------------------------------------------------------
** File Name: I2C.c
** Last modified Date: 2007-10-25
** Last Version: V1.0
** Description: S3C2410 I2C主机 驱动
**
**------------------------------------------------------------------------------------------------------
** Created By: sam 黄利森
** Created date: 2007-10-25
** Version: V1.0
** Descriptions: The original version
**
**------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Description:
**
********************************************************************************************************/
#include <windows.h>
#include <types.h>
#include <excpt.h>
#include <tchar.h>
#include <cardserv.h>
#include <cardapi.h>
#include <tuple.h>
#include <devload.h>
#include <diskio.h>
#include <nkintr.h>
#include <windev.h>
#include <Pkfuncs.h>
#include "s2410.h"
#include "I2C.h"
#define PRIVATE static
#define PUBLIC
#define S3C2410X_IOPORT_REG IOPreg
#define S3C2410X_BASE_REG_PA_IOPORT IOP_BASE
#define S3C2410X_IICBUS_REG IICreg
#define S3C2410X_BASE_REG_PA_IICBUS IIS_BASE
/* 中断事件 */
PRIVATE HANDLE gI2CIntrEvent;
/* 是否退出中断服务线程 */
PRIVATE UINT32 g_bKillIST = FALSE;
/* 读I2C事件*/
PRIVATE HANDLE gI2CEvent;
/* 中断处理线程 */
PRIVATE HANDLE gI2CIntrThread;
/* I2C 的物理中断号及逻辑中断号 */
UINT32 g_I2CIrq = INTSRC_IIC;
UINT32 g_I2CSysIntr = SYSINTR_UNDEFINED;
/* GPIO 寄存器对应的虚拟地址 */
PRIVATE volatile IOPreg * v_pIOPregs;
PRIVATE volatile IICreg * v_pIICPregs;
// I2C总线设置宏定义: 使能 ACK 位, 使能发送/接收中断, IICCLK = PCLK/512 = 132161
#define IICCON_DEFAULT ((1 << 7) | (1 << 6) | (1 << 5) | (0 << 0))
#define IICCON_DACK(IICCON) IICCON = IICCON & (~(1 << 4)) | (1 << 7); /* 使能 ACK 位 */
#define IICCON_DNACK(IICCON) IICCON &= ~((1 << 4) | (1 << 7)); /* 禁止 ACK 位 */
#define IICCON_CLEAR_PENDING(IICCON) IICCON &= ~(1 << 4); /* 使能 ACK 位 */
/* */
#define I2C_READ 0x01
#define I2C_WRITE 0x00
/* 定义 I2C 总线的各种状态, 中断服务线程根据该状态运行 */
#define I2C_STATUS_SETADDR 0x01 /* 设置地址状态 */
#define I2C_STATUS_RECEIVE 0x02 /* 接收状态 */
#define I2C_STATUS_SEND 0x03 /* 发送状态 */
#define I2C_ERROR_NO_ERR 0x0
#define I2C_ERROR_SETADDR 0x1
#define I2C_ERROR_RECEIVE 0x2
#define I2C_ERROR_SEND 0x3
#define I2C_RW_TIMEOUT 2000
PRIVATE BYTE volatile I2cStatus;
PRIVATE BYTE volatile I2cCurSla; /* I2C从机,当前地址 */
PRIVATE BYTE volatile I2cSla = 0xA0; /* I2C从机地址 */
PRIVATE BYTE IICError = 0;
PRIVATE DWORD g_OpenCount = 0;
/*******************************************************************************************
函数名称: I2C_InitHareware
描 述: 初始化I2C主控器寄存器
输入参数: 无
输出参数: 无
返 回: 无
********************************************************************************************/
PRIVATE void I2C_InitHareware(void)
{
// 设置相关引脚为I2C引脚
v_pIOPregs->rGPECON = (v_pIOPregs->rGPECON & 0x0FFFFFFF) | 0xA0000000;
// 禁止内部上拉电阻
v_pIOPregs->rGPEUP = v_pIOPregs->rGPEUP | 0xC000;
// 设置I2C控制寄存器 (使能ACK位时才能接收从机的应答位)
v_pIICPregs->rIICCON = IICCON_DEFAULT;
// 设置I2C为主机模式
v_pIICPregs->rIICSTAT = (3 << 6) | (1 << 4);
// 从机地址 (作主机时没有用)
v_pIICPregs->rIICADD = 0x10;
}
/*******************************************************************************************
函数名称: I2C_ConfigPinDefault
描 述: 配置I2C引脚恢复为输入引脚
输入参数: 无
输出参数: 无
返 回: 无
********************************************************************************************/
PRIVATE VOID I2C_ConfigPinDefault(VOID)
{
// Set GPE14, GPE15 is Input
v_pIOPregs->rGPFCON &= ~((0x3 << 28) + (0x3 << 30));
}
/*******************************************************************************************
函数名称: I2C_InitializeAddresses
描 述: 取得I2C主控器相关寄存器的虚拟地址
输入参数: 无
输出参数: 无
返 回: > 0 分配到的虚拟地址; FALSE: 失败
********************************************************************************************/
PRIVATE BOOL I2C_InitializeAddresses(void)
{
BOOL RetValue = TRUE;
RETAILMSG(1, (TEXT(">>> IIC_initalization address..set..\r\n")));
v_pIOPregs = (IOPreg *)IOP_BASE;
v_pIICPregs= (IICreg *)IIC_BASE;
// IO Register Allocation
/*
v_pIOPregs = (volatile S3C2410X_IOPORT_REG *)VirtualAlloc(0, sizeof(S3C2410X_IOPORT_REG), MEM_RESERVE, PAGE_NOACCESS);
if (v_pIOPregs == NULL)
{
ERRORMSG(1,(TEXT("For IOPregs : VirtualAlloc failed!\r\n")));
RetValue = FALSE;
}
else
{
if (!VirtualCopy((PVOID)v_pIOPregs, (PVOID)(S3C2410X_BASE_REG_PA_IOPORT), sizeof(S3C2410X_IOPORT_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE))
{
ERRORMSG(1,(TEXT("For IOPregs: VirtualCopy failed!\r\n")));
RetValue = FALSE;
}
}
if (!RetValue)
{
RETAILMSG (1, (TEXT("::: I2C_InitializeAddresses - Fail!!\r\n") ));
if (v_pIOPregs)
VirtualFree((PVOID) v_pIOPregs, 0, MEM_RELEASE);
v_pIOPregs = NULL;
RetValue = FALSE;
return RetValue;
}
// IIC Register Allocation
v_pIICPregs = (volatile S3C2410X_IICBUS_REG *)VirtualAlloc(0, sizeof(S3C2410X_IICBUS_REG), MEM_RESERVE, PAGE_NOACCESS);
if (v_pIICPregs == NULL)
{
ERRORMSG(1,(TEXT("For IICPregs : VirtualAlloc failed!\r\n")));
RetValue = FALSE;
}
else
{
if (!VirtualCopy((PVOID)v_pIICPregs, (PVOID)(S3C2410X_BASE_REG_PA_IICBUS), sizeof(S3C2410X_IICBUS_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE))
{
ERRORMSG(1,(TEXT("For IICPregs: VirtualCopy failed!\r\n")));
RetValue = FALSE;
}
}
if (!RetValue)
{
RETAILMSG (1, (TEXT("::: I2C_InitializeAddresses - Fail!!\r\n") ));
if (v_pIICPregs)
VirtualFree((PVOID) v_pIICPregs, 0, MEM_RELEASE);
v_pIICPregs = NULL;
}
*/
RETAILMSG(1,(TEXT("return(RetValue);\r\n")));
return(RetValue);
}
#define DEFAULT_S3C2410X_PCLK (203000000 / 4)
/*******************************************************************************************
函数名称: I2C_GetSpeed
描 述: 取得 I2C 的传输速度
输入参数: 无
输出参数: 无
返 回: I2C 总线的传输速度, 单位为 Hz
********************************************************************************************/
PRIVATE DWORD I2C_GetSpeed(void)
{
PROCESSOR_INFO procInfo;
DWORD dwBytesReturned;
DWORD pclk, i2cspeed;
/* get the information of the device */
if (!KernelIoControl(IOCTL_PROCESSOR_INFORMATION, NULL, 0, &procInfo, sizeof(PROCESSOR_INFO), &dwBytesReturned))
{
pclk = DEFAULT_S3C2410X_PCLK;
RETAILMSG(TRUE, (TEXT("WARNING: I2C_GetSpeed:: failed to obtain processor frequency - using default value (%d).\r\n"), pclk));
}
else
{
pclk = procInfo.dwClockSpeed;
}
/* calculate the clock of IIC transmit speed */
i2cspeed = pclk / 512 / ((v_pIICPregs->rIICCON & 0x0F) + 1);
return i2cspeed;
}
/*******************************************************************************************
函数名称: StartI2C
描 述: 启动总线,发送从机地址,并发送从机地址
输入参数: BYTE sla: 从机地址
输出参数: 无
返 回: 无
********************************************************************************************/
void StartI2C(BYTE sla)
{
v_pIICPregs->rIICDS = sla; // 设置从机地址
if(sla & 0x01)
{
v_pIICPregs->rIICSTAT = (2 << 6) | (1 << 5) | (1 << 4); // 主接收模式,发送使能,启动总线
IICCON_DACK(v_pIICPregs->rIICCON); // 若是重启总线, 则需要有此操作
}
else
{
v_pIICPregs->rIICSTAT = (3 << 6) | (1 << 5) | (1 << 4); // 主发送模式,发送使能,启动总线
}
}
/*******************************************************************************************
函数名称: StopI2C
描 述: 结束总线
输入参数: BYTE send: I2C当前模模式.主发送模式时为1,否则为0(主接收模式)
输出参数: 无
返 回: 无
********************************************************************************************/
void StopI2C(BYTE send)
{
if(send)
{
v_pIICPregs->rIICSTAT = (3 << 6) | (0 << 5) | (1 << 4); // 发送结束信号
}
else
{
v_pIICPregs->rIICSTAT = (2 << 6) | (0 << 5) | (1 << 4); // 发送结束信号
}
IICCON_DACK(v_pIICPregs->rIICCON);
Sleep(1); // 等待结束信号产生完毕
}
/*******************************************************************************************
函数名称: SendByteI2C
描 述: 发送一个字节的数据
输入参数: BYTE data: 要发送的字节
输出参数: 无
返 回: 无
********************************************************************************************/
void IIC_SendByte(BYTE data)
{
// 将数据写入I2C数据寄存器
v_pIICPregs->rIICDS = data;
// 清除中断标志,允许发送数据操作
IICCON_DACK(v_pIICPregs->rIICCON);
}
/*******************************************************************************************
函数名称: IIC_StartRecByteA
描 述: 开始接收 IIC 总线上的数据, 接收该数据时需要发送一个应答
输入参数: 无
输出参数: 无
返 回: 无
********************************************************************************************/
void IIC_StartRecByteA(void)
{
IICCON_DACK(v_pIICPregs->rIICCON);
}
/*******************************************************************************************
函数名称: IIC_StartRecByteNA
描 述: 开始接收 IIC 总线上的数据, 接收该数据时,不需要发送一个应答
输入参数: 无
输出参数: 无
返 回: 无
********************************************************************************************/
void IIC_StartRecByteNA(void)
{
IICCON_DNACK(v_pIICPregs->rIICCON);
}
/*******************************************************************************************
函数名称: IIC_RecByte
描 述: 从 IIC 总线上接收一个字节
输入参数: 无
输出参数: 无
返 回: 无
********************************************************************************************/
BYTE IIC_RecByte(void)
{
return (v_pIICPregs->rIICDS);
}
/*******************************************************************************************
函数名称: I2C_IntrThread
描 述: I2C 中断服务线程
输入参数: PVOID pArg: 线程输入参数
输出参数: 无
返 回: 1 或 0
********************************************************************************************/
DWORD I2C_IntrThread(PVOID pArg)
{
DWORD ret;
// 创建I2C中断中断事件
gI2CIntrEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
// 初始化 I2C 中断: 注册中断事件, 允许 I2C 中断
if (!(InterruptInitialize(g_I2CSysIntr, gI2CIntrEvent, 0, 0)))
{
CloseHandle(gI2CIntrEvent);
RETAILMSG(1, (TEXT("ERROR: I2C Bus: Interrupt initialize failed.\r\n")));
return 0;
}
// IIC 中断线程开始运行
while (1)
{
ret = WaitForSingleObject(gI2CIntrEvent, INFINITE);
if ((ret != WAIT_OBJECT_0) || (g_bKillIST == TRUE)) /* 驱动卸载或错误发生 */
{
CloseHandle(gI2CIntrEvent);
RETAILMSG(1, (TEXT("INFO: I2C Bus Driver DeInit or Error Occur. \r\n")));
return 0; /* 线程退出 */
}
switch(I2cStatus)
{
// Start IIC Status
case I2C_STATUS_SETADDR:
if((v_pIICPregs->rIICSTAT & 0x09) == 0) // 发送地址成功
{
SetEvent(gI2CEvent);
IICError = I2C_ERROR_NO_ERR;
}
else
{
if (I2cCurSla & I2C_READ)
v_pIICPregs->rIICSTAT = (2 << 6) | (0<<5) | (1<<4); // 读终止
else
v_pIICPregs->rIICSTAT = (3 << 6) | (0<<5) | (1<<4); // 写终止
IICCON_DACK(v_pIICPregs->rIICCON);
Sleep(1); // 等待结束信号产生完毕
SetEvent(gI2CEvent);
IICError = I2C_ERROR_SETADDR;
}
break;
// Send Bytes Status
case I2C_STATUS_SEND:
if((v_pIICPregs->rIICSTAT & 0x09) == 0) // 数据成功发送
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -