友善之臂 mini2440 linux led 驱动代码,友善之臂mini2440的LEDdriver驱动分析及测试程序...

一,前言:因为友善尚未公布mini2440开发板上的测试程序,所以我自己就写了一个。还好不是太难。

(WINCE6.0+mini2440)

二,首先来分析一下LEDDriver。

2.1,入口函数:(Sources文件里指明了DLLENTRY=DllEntry)

BOOL WINAPI

DllEntry(HANDLEhinstDLL,

DWORD dwReason,

LPVOID /* lpvReserved */)

{

switch(dwReason)

{

case DLL_PROCESS_ATTACH:

DEBUGREGISTER((HINSTANCE)hinstDLL);

return TRUE;

case DLL_THREAD_ATTACH:

break;

case DLL_THREAD_DETACH:

break;

case DLL_PROCESS_DETACH:

break;

#ifdef UNDER_CE

case DLL_PROCESS_EXITING:

break;

case DLL_SYSTEM_STARTED:

break;

#endif

}

return TRUE;

}

这里要对dwReason作一些说明,一个程序要调用Dll里的函数,首先要先把DLL文件映射到进程的地址空间。要把一个DLL文件映射到进程的地址空间,有两种方法:静态链接和动态链接的LoadLibrary。当一个DLL文件被映射到进程的地址空间时,传递的dwReason参数为DLL_PROCESS_ATTACH。这种调用只会发生在第一次映射时。如果同一个进程后来为已经映射进来的DLL再次调用LoadLibrary,操作系统只会增加DLL的使用次数,它不会再用DLL_PROCESS_ATTACH调用DLL的DllMain函数。但如果是不同进程用LoadLibrary同一个DLL时,则每个进程的第一次映射都会调用DllMain函数,并传递DLL_PROCESS_ATTACH。(驱动一般会在这个case下或XXX_Init()里作些初始化的工作)。

相反地,当进程结束或者使用FreeLibrary解除DLL的映射时,系统再次调用DLL的DllMain(),此时传递的dwReason就是DLL_PROCESS_DETACH。

当进程创建一个线程时,系统调用DLL的DllMain(),此时传递的dwReason是DLL_THREAD_ATTACH。

当线程结束时,系统调用DLL的DllMain(),此时传递的dwReason是DLL_THREAD_DETACH。

2.2:

DWORD LED_Init(DWORD dwContext)

{

RETAILMSG(1,(TEXT("LED_Init----\r\n")));

// 1. Virtual Alloc

Virtual_Alloc();

LEDGpioInit();

mInitialized = TRUE;

return TRUE;

}

先看一看

void Virtual_Alloc()

{

// GPIO Virtual alloc

s2440IOP = (volatile IOPreg *) VirtualAlloc(0,sizeof(IOPreg),MEM_RESERVE, PAGE_NOACCESS);

if(s2440IOP == NULL) {

RETAILMSG(1,(TEXT("For s2440IOP: VirtualAlloc faiLED!\r\n")));

}

else {

if(!VirtualCopy((PVOID)s2440IOP,(PVOID)(IOP_BASE),sizeof(IOPreg),PAGE_READWRITE | PAGE_NOCACHE )) {

RETAILMSG(1,(TEXT("For s2440IOP: VirtualCopy faiLED!\r\n")));

}

}

}

先是用VirtualAlloc()来预留一块内存,如果成功则用VirtualCopy()映射IOP_BASE到刚申请的一块内存里。

2.3:

BOOL LEDGpioInit()

{

RETAILMSG(1,(TEXT("LED_Gpio_Setting----\r\n")));

s2440IOP->rGPBCON= (s2440IOP->rGPBCON&~(3 << 10)) | (1<< 10);// GPB5 == OUTPUT.

s2440IOP->rGPBCON= (s2440IOP->rGPBCON&~(3 << 12)) | (1<< 12);// GPB6 == OUTPUT.

s2440IOP->rGPBCON= (s2440IOP->rGPBCON&~(3 << 14)) | (1<< 14);// GPB7 == OUTPUT.

s2440IOP->rGPBCON= (s2440IOP->rGPBCON&~(3 << 16)) | (1<< 16);// GPB8 == OUTPUT.

return TRUE;

}

配置跟LED阴级连接的四个IO管脚为输出方向。这里有意思的是,wince对寄存器的访问方式,s2440IOP是一个指向IOPreg结构体的指针,可以看到该结构体的成员排列顺序和datasheet里的寄存器顺序里一样的,并且IOP_BASE的值是0xB1600000(寄存器rGPACON首地址0x56000000映射到内核中的虚拟地址),所以s2440IOP->rGPBCON就是对应寄存器的值了。这跟linux的(首地址+位移)的访问方式有点不一样。

2.4:

BOOL LED_IOControl(DWORD hOpenContext,

DWORD dwCode,

PBYTE pBufIn,

DWORD dwLenIn,

PBYTE pBufOut,

DWORD dwLenOut,

PDWORD pdwActualOut)

{

LEDGpioInit();

switch(dwCode)

{

case IO_CTL_LED_1_ON:

s2440IOP->rGPBDAT=s2440IOP->rGPBDAT&~(0x1<<5);

break;

case IO_CTL_LED_2_ON:

s2440IOP->rGPBDAT=s2440IOP->rGPBDAT&~(0x1<<6);

break;

case IO_CTL_LED_3_ON:

s2440IOP->rGPBDAT=s2440IOP->rGPBDAT&~(0x1<<7);

break;

case IO_CTL_LED_4_ON:

s2440IOP->rGPBDAT=s2440IOP->rGPBDAT&~(0x1<<8);

break;

case IO_CTL_LED_ALL_ON:

s2440IOP->rGPBDAT=s2440IOP->rGPBDAT&~(0xF<<5);

break;

case IO_CTL_LED_1_OFF:

s2440IOP->rGPBDAT=s2440IOP->rGPBDAT|(0x1<<5);

break;

case IO_CTL_LED_2_OFF:

s2440IOP->rGPBDAT=s2440IOP->rGPBDAT|(0x1<<6);

break;

case IO_CTL_LED_3_OFF:

s2440IOP->rGPBDAT=s2440IOP->rGPBDAT|(0x1<<7);

break;

case IO_CTL_LED_4_OFF:

s2440IOP->rGPBDAT=s2440IOP->rGPBDAT|(0x1<<8);

break;

case IO_CTL_LED_ALL_OFF:

s2440IOP->rGPBDAT=s2440IOP->rGPBDAT|(0xF<<5);

break;

default:

break;

}

RETAILMSG(1,(TEXT("LED:Ioctl code = 0x%x\r\n"), dwCode));

return TRUE;

}

这个就是控制LED亮与灭的接口了,其实就是把相应管脚置低或置高。

三,测试程序分别用了win32 API函数和MFC两种方式来实现。见后面的附件。

Win32 API方式:采用了Boling D.的编程风格,这种方式可以自己掌控窗口的创建,窗口过程,对话框的创建,对话框过程。

MFC:相对来说就简单多了,只要动动鼠标,VS就会帮你生成很多代码。------------------------------------------

本文乃原创!

转载请注明出处:http://sparklecliz.cublog.cn/

------------------------------------------

rar.gif

文件:

ledtest.rar

大小:

57KB

下载:rar.gif

文件:

LedControl.rar

大小:

160KB

下载:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值