驱动间的协调和管理
最新推荐文章于 2020-03-24 19:03:13 发布
在一个嵌入式系统中,各个驱动之间是如何进行协调的呢?如何管理的呢?当要抢占硬件资源时,如何处理呢?下面提供两种方法,该方法是我们在实际系统中使用最广的,也是经过验证可行的。
1 使用虚拟驱动的方法,如我们的一个GPS平台就用到了一个虚拟驱动(该驱动不针对任何硬件),其作用就是一开机就加载了,各个驱动可以打开它,然后用DeviIoControl来实现访问,如在里面设一个USB的标志位,当某一驱动或应用要用到该接口,就要先访问该驱动,设得有关USB的状态信息,如果没别的驱动占用,就可以使用,并要把标志位赋值。
2 使用KernelIoControl的方法,把标志位放到内核中去,这个方法简单快捷,但是只能在驱动之间使用,应用无法直接访问。
例子:
① /src/inc à
Ioctl_cfg.h à
// driver-->kernel
#define IOCTL_HAL_SETPLUGNOTIFYMSGID /
CTL_CODE(FILE_DEVICE_HAL, (HAL_FLAG_FID+11), METHOD_BUFFERED, FILE_ANY_ACCESS)
// driver<--kernel
#define IOCTL_HAL_GETPLUGNOTIFYMSGID /
CTL_CODE(FILE_DEVICE_HAL, (HAL_FLAG_FID+12), METHOD_BUFFERED, FILE_ANY_ACCESS)
②/src/inc à
Ioctl_tab.h à
{IOCTL_HAL_SETPLUGNOTIFYMSGID, 0, OALIoCtlSetPlugNotifyMsgId},
{IOCTL_HAL_GETPLUGNOTIFYMSGID, 0, OALIoCtlGetPlugNotifyMsgId},
对应相应的实现函数
③/src/kernel/oal à
Ioctl.c à
static DWORD s_dwOalPlugNotifyMsgId = 0;
static BOOL OALIoCtlSetPlugNotifyMsgId(
UINT32 code, VOID *lpInBuf, UINT32 nInBufSize, VOID *lpOutBuf,
UINT32 nOutBufSize, UINT32 *pOutSize)
{
if((NULL != lpInBuf) && (sizeof(DWORD)<=nInBufSize))
{
DWORD dwNewNotifyMsgId = *(DWORD *)lpInBuf;
// this msg id is get from RegisterWindowsMessage() which range from 0xc000 to 0xffff.
if((0xC000 <= dwNewNotifyMsgId) && (0xFFFF > dwNewNotifyMsgId))
{ s_dwOalPlugNotifyMsgId = dwNewNotifyMsgId;
return TRUE;
}
}//end if NULL != lpInBuf
return FALSE;
}
static BOOL OALIoCtlGetPlugNotifyMsgId(
UINT32 code, VOID *lpInBuf, UINT32 nInBufSize, VOID *lpOutBuf,
UINT32 nOutBufSize, UINT32 *pOutSize)
{
if((NULL != lpOutBuf) && (sizeof(DWORD)<=nOutBufSize))
{
*(DWORD *)lpOutBuf = s_dwOalPlugNotifyMsgId;
*pOutSize = sizeof(DWORD);
return TRUE;
}//end if NULL != lpInBuf
return FALSE;
}
然后在驱动中就可以通过KernelIoControl函数来写入和读出有关的信息了
如下:
DWORD dwUDiskStates = 0;
DWORD dwReturnBytes = 0;
// get msg id.
if(!KernelIoControl( IOCTL_HAL_GETKERNELUDISKSTATE, NULL, 0, &dwUDiskStates, sizeof(DWORD), &dwReturnBytes))
{
RETAILMSG(TRUE, (TEXT("<psys>Fail to get u-disk states!/r/n")));
}
else{
// set default return value
*(DWORD *)pBufOut = dwUDiskStates;
bRetVal = TRUE;
RETAILMSG(TRUE, (TEXT("<psys>u-disk states=%d!/r/n"), dwUDiskStates));
}