一,开发环境
WINCE6.0下编写串口驱动,使用S3C2440A的UART0和PC进行通信,UART1、UART2和AVR Atemga162单片机进行通信。
二,串口流驱动流程
主要完成 XXX_Init,XXX_Open,XXX_Read,XXX_Write,XXX_Seek,XXX_PowerUp,XXX_PowerDown,XXX_Close,XXX_Deinit,XXX_IOControl函数。下面介绍自己在驱动中用到的函数。
1,XXX_Init()
在XXX_Init()函数中完成驱动中相关变量和资源等的初始化工作。如S3C2440A相关寄存器的初始化,为其分配地址空间。例如串口0控制寄存器的初始化
/*Uart0 Controller Register*/
v_pUART0regs = (volatile S3C2440A_UART_REG *)VirtualAlloc(0,sizeof(S3C2440A_UART_REG),MEM_RESERVE, PAGE_NOACCESS);
if (v_pUART0regs == NULL)
{
RETAILMSG(1,(TEXT("v_pUART0regs: VirtualAlloc failed!rn")));
goto MAP_ERROR;
}
if (!VirtualCopy((PVOID)v_pUART0regs,(PVOID)(S3C2440A_BASE_REG_PA_UART0>>8),sizeof(S3C2440A_UART_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCAC HE ))
{
RETAILMSG(1,(TEXT("v_pUART0regs: VirtualCopy failed!rn")));
goto MAP_ERROR;
}
RETAILMSG(1,(TEXT("[SRM] v_pUART0regs is mapped to %xnr"), v_pUART0regs));
XXX_Init()中,重要的还有为串口的物理中断申请WINCE系统的逻辑中断。完成映射的方式包括动态映射和静态映射,静态映射可以在SrcCommonIntrintr.c中系统初始化时为物理中断分配系统默认的一些逻辑中断 ,如
OALIntrStaticTranslate(SYSINTR_ETH, IRQ_EINT7);
也可以用动态的方式,通过调用函数KernelIoControl申请逻辑中断号,如以下代码,为串口0中断申请逻辑中断号
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &g_Uart0Irq, sizeof(UINT32), &g_Uart0SysIntr, sizeof(UINT32), NULL))
{
RETAILMSG(1, (TEXT("ERROR: UART0_INIT: Failed to request sysintr value for UART0_INIT interrupt.rn")));
return FALSE;
}
RETAILMSG(1,(TEXT("INFO: UART0: Mapped IRQ_UART0 to SysIntr 0x%x.rn"), g_Uart0SysIntr));
当然我们需要配置串口的寄存器和串口中断服务线程。关于S3C2440A串口中断寄存器相关配置在下一篇文章再详细介绍,在移植WINCE5.0到WINCE6.0串口驱动时,发现和串口的FIFO控制寄存器有很大关系。串口接受 中断线程的初始化代码如下
BOOL UART0_InitInterruptThread()
{
BOOL bSuccess = FALSE;
RETAILMSG(DEBUGMODE,(TEXT("+++UART0_InitInterruptThreadn")));
m_hUART0InterruptEvent = CreateEvent( NULL, FALSE, FALSE, NULL);
if (!m_hUART0InterruptEvent)
{
RETAILMSG(1,(TEXT("+++Create m_hUART0Interrupt Faile n")));
return FALSE;
}
bSuccess = InterruptInitialize(g_Uart0SysIntr, m_hUART0InterruptEvent, NULL, 0);
if(!bSuccess)
{
RETAILMSG(1,(TEXT("+++InterruptInitialize Faile n")));
return FALSE;
}
m_hUART0InterruptThread = CreateThread((LPSECURITY_ATTRIBUTES)NULL,
0,
(LPTHREAD_START_ROUTINE)CallUART0InterruptThread,
0,
0,
NULL);
if (!m_hUART0InterruptThread)
{
RETAILMSG(1,(TEXT("----UART0_InitInterruptThread failn")));
return FALSE;
}
// Bump up the priority since the interrupt must be serviced immediately.
CeSetThreadPriority(m_hUART0InterruptThread,30); //change 3
RETAILMSG(DEBUGMODE,(TEXT("----UART0_InitInterruptThreadn")));
return TRUE;
}
首先通过CreateEvent()函数创建一个事件,然后把该事件和前面通过KernelIoControl()申请的逻辑中断号绑定,最后用CreateThread()函数创建接收线程,CeSetThreadPriority()函数设置线程的优先级,优先级的范围如下
0 through 96 Reserved for real-time above drivers.
97 through 152 Used by the default Windows Embedded CE-based device drivers.
153 through 247 Reserved for real-time below drivers.
248 through 255 Maps to non-real-time priorities.
可以根据通信的实时性要求进行不同等级的设置。
串口发送线程的初始化函数如下
BOOL UART0_InitTransmitThread(){
RETAILMSG(DEBUGMODE,(TEXT("+++UART0_InitTransmitThreadn")));
m_hUART0TransmitThread = CreateThread((LPSECURITY_ATTRIBUTES)NULL,0,(LPTHREAD_START_ROUTINE)CallUART0TransmitThread,0,0,NULL);
if (!m_hUART0TransmitThread)
{
RETAILMSG(1,(TEXT("----CallUART0TransmitThread Failn")));
return FALSE;
}
CeSetThreadPriority(m_hUART0TransmitThread,30); //change 2
RETAILMSG(DEBUGMODE,(TEXT("----UART0_InitTransmitThreadn")));
return TRUE;
}
2,XXX_IOControl
XXX_IOControl()函数主要用于接受应用程序调用驱动程序时发送的命令,根据命令的不同执行不同操作。函数原型如下
BOOL DMA_IOControl(DWORD hOpenContext,DWORD dwCode,PBYTE pBufIn,DWORD dwLenIn,
PBYTE pBufOut,DWORD dwLenOut,PDWORD pdwActualOut)
其中dwCode为命令控制码,pBufIn为应用程序传送的参数。
上一篇:内核(2.6.14) + 根文件系统 +Qtopia Core 4移植 for S3C2410
下一篇:S3C2440A串口驱动-WINCE6.0下通过串口和外设进行数据通信(二)