S3C2440A串口驱动-----WINCE6.0下通过串口和外设进行数据通信(一)

一,开发环境

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!\r\n")));
		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!\r\n")));
		goto MAP_ERROR;
	}
	RETAILMSG(1,(TEXT("[SRM] v_pUART0regs is mapped to %x\n\r"), v_pUART0regs));
XXX_Init()中,重要的还有为串口的物理中断申请WINCE系统的逻辑中断。完成映射的方式包括动态映射和静态映射,静态映射可以在\Src\Common\Intr\intr.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.\r\n")));
		return FALSE;
	}
	RETAILMSG(1,(TEXT("INFO: UART0: Mapped IRQ_UART0 to SysIntr 0x%x.\r\n"), g_Uart0SysIntr));
当然我们需要配置串口的寄存器和串口中断服务线程。关于S3C2440A串口中断寄存器相关配置在下一篇文章再详细介绍,在移植WINCE5.0到WINCE6.0串口驱动时,发现和串口的FIFO控制寄存器有很大关系。串口接受 中断线程的初始化代码如下
BOOL UART0_InitInterruptThread()
{
	BOOL bSuccess = FALSE;
	RETAILMSG(DEBUGMODE,(TEXT("+++UART0_InitInterruptThread\n")));

	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 fail\n")));
		return FALSE;
	}

	// Bump up the priority since the interrupt must be serviced immediately.
	CeSetThreadPriority(m_hUART0InterruptThread,30);   //change 3
	RETAILMSG(DEBUGMODE,(TEXT("----UART0_InitInterruptThread\n")));
	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_InitTransmitThread\n")));
	m_hUART0TransmitThread  = CreateThread((LPSECURITY_ATTRIBUTES)NULL,0,(LPTHREAD_START_ROUTINE)CallUART0TransmitThread,0,0,NULL);
	if (!m_hUART0TransmitThread)
	{
		RETAILMSG(1,(TEXT("----CallUART0TransmitThread Fail\n")));
		return FALSE;
	}
	CeSetThreadPriority(m_hUART0TransmitThread,30);   //change 2
	RETAILMSG(DEBUGMODE,(TEXT("----UART0_InitTransmitThread\n")));
	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为应用程序传送的参数。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值