现在我要写串口的驱动,我看了串口驱动的相关资料,发现COM_IOControl、COM_Open、COM_Close,等函数都在MDD层里定义了,那我现在还要写什么函数呢?是不是配置GPIO口为串口,时钟设置,判断那个串口然后调用MDD里的相关函数呢?
引用: 引用楼主 andylao62 的帖子:
现在我要写串口的驱动,我看了串口驱动的相关资料,发现COM_IOControl、COM_Open、COM_Close,等函数都在MDD层里定义了,那我现在还要写什么函数呢?是不是配置GPIO口为串口,时钟设置,判断那个串口然后调用MDD里的相关函数呢?
你自己写?我看你还是先放弃,据我所知,串口驱动比较麻烦。这个串口对于刚学的人来说,看都要花点吃奶的力气。MDD+PDD的确比较难看懂。现在这些驱动大把啊,何必自己重头写呢?
问题的难点应该在CS片选信号跟中断的选择上,只要能解决这个问题,应该就简单多了
class CPdd2410Serial1 : public CPdd2410Uart {
public:
CPdd2410Serial1(LPTSTR lpActivePath, PVOID pMdd, PHWOBJ pHwObj)
: CPdd2410Uart(lpActivePath, pMdd, pHwObj)
{
m_pIOPregs = NULL;
m_fIsDSRSet = FALSE;
}
~CPdd2410Serial1() {
if (m_pIOPregs!=NULL)
MmUnmapIoSpace((PVOID)m_pIOPregs,0);
}
virtual BOOL Init() {
PHYSICAL_ADDRESS ioPhysicalBase = { S3C2410X_BASE_REG_PA_IOPORT, 0};
ULONG inIoSpace = 0;
if (TranslateBusAddr(m_hParent,Internal,0, ioPhysicalBase,&inIoSpace,&ioPhysicalBase)) {
// Map it if it is Memeory Mapped IO.
m_pIOPregs = (S3C2410X_IOPORT_REG *)MmMapIoSpace(ioPhysicalBase, sizeof(S3C2410X_IOPORT_REG),FALSE);
}
if (m_pIOPregs) {
DDKISRINFO ddi;
if (GetIsrInfo(&ddi)== ERROR_SUCCESS &&
KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &ddi.dwIrq, sizeof(UINT32), &ddi.dwSysintr, sizeof(UINT32), NULL))
{
RegSetValueEx(DEVLOAD_SYSINTR_VALNAME,REG_DWORD,(PBYTE)&ddi.dwSysintr, sizeof(UINT32));
}
else
return FALSE;
m_pDTRPort = (volatile ULONG *)&(m_pIOPregs->GPHDAT);
m_pDSRPort = (volatile ULONG *)&(m_pIOPregs->GPHDAT);
m_dwDTRPortNum = 6;
m_dwDSRPortNum = 7;
return CPdd2410Uart::Init();
}
return FALSE;
};
virtual void SetDefaultConfiguration() {
m_pIOPregs->GPHCON &= ~(0x3<<0 | 0x3<<2 | 0x3<<4 | 0x3<<6 | 0x3<<12 | 0x3<<14); // clear uart 0 - rx, tx
m_pIOPregs->GPHCON |= (0x2<<4 | 0x2<<6 | 0x1<<12 | 0x0<<14);
m_pIOPregs->GPHCON |= (0x2<<0 | 0x2<<2 );
m_pIOPregs->GPHUP |= 0xc3;
CPdd2410Uart::SetDefaultConfiguration();
}
virtual BOOL InitModem(BOOL bInit) {
SetDTR(bInit);
return CPdd2410Uart::InitModem(bInit);
}
virtual ULONG GetModemStatus() {
ULONG ulReturn = CPdd2410Uart::GetModemStatus();
ULONG ulEvent = 0;
m_HardwareLock.Lock();
BOOL fIsDSRSet = (((*m_pDSRPort) & (1<
if (fIsDSRSet != m_fIsDSRSet) {
ulEvent |= EV_DSR | EV_RLSD;
}
ulReturn |= (fIsDSRSet?(MS_DSR_ON|MS_RLSD_ON):0);
m_fIsDSRSet = fIsDSRSet;
m_HardwareLock.Unlock();
if (ulEvent!=0)
EventCallback(ulEvent,ulReturn);
return ulReturn;
}
virtual void SetDTR(BOOL bSet) {
if (bSet)
*m_pDTRPort &= ~(1<
else
*m_pDTRPort |= (1<
};
private:
volatile S3C2410X_IOPORT_REG * m_pIOPregs;
volatile ULONG * m_pDTRPort;
DWORD m_dwDTRPortNum;
volatile ULONG * m_pDSRPort;
DWORD m_dwDSRPortNum;
BOOL m_fIsDSRSet;
};
class CPdd2410Serial2 : public CPdd2410Uart {
..............................................
class CPdd2410Serial3 : public CPdd2410Uart {
..............................................
CSerialPDD * CreateSerialObject(LPTSTR lpActivePath, PVOID pMdd,PHWOBJ pHwObj, DWORD DeviceArrayIndex)
{
CSerialPDD * pSerialPDD = NULL;
switch (DeviceArrayIndex)
{
#if UART0_DEBUG_EN /* UART0 is debug output */
case 1:
pSerialPDD = new CPdd2410Serial2(lpActivePath,pMdd, pHwObj); /* UART1 is Serial */
break;
case 2:
pSerialPDD = new CPdd2410Serial3(lpActivePath,pMdd, pHwObj); /* UART2 is Serial */
break;
#else /* UART1 is debug output */
case 0:
pSerialPDD = new CPdd2410Serial1(lpActivePath,pMdd, pHwObj); /* UART0 is modem */
break;
#endif
default:
pSerialPDD = NULL;
break;
}
if (pSerialPDD && !pSerialPDD->Init()) {
delete pSerialPDD;
pSerialPDD = NULL;
}
return pSerialPDD;
}
void DeleteSerialObject(CSerialPDD * pSerialPDD)
{
if (pSerialPDD)
delete pSerialPDD;
}
上边是个别人写的驱动,是不是我按照上边的格式改就好了呢?还有这些函数和MDD里边的COM_IOControl、COM_Open、COM_Close又怎么联系起来呢。。。
我也才开始接触,可能理解不够,我觉得,根据硬件的相关资料,在Init中配置好相关的参数,然后,在其他的函数中定义写相关的操作代码不是就可以了么?
mark , 学习
正常的话主要是配置一下注册表,然后在PDD里面把相应的UART的GPIO配置一下,CLOCK设置一下就OK了
需要别的操作的话可以实现继承类里的OPEN,CLOSE等函数
串口驱动没有这么复杂,MDD层的代码也都是公开的,所以花点时间研究一下就好了,这跟哪个平台没有太大关系
引用: 引用 10 楼 hzdysymbol 的回复:
正常的话主要是配置一下注册表,然后在PDD里面把相应的UART的GPIO配置一下,CLOCK设置一下就OK了
需要别的操作的话可以实现继承类里的OPEN,CLOSE等函数
串口驱动没有这么复杂,MDD层的代码也都是公开的,所以花点时间研究一下就好了,这跟哪个平台没有太大关系
也就是说大概思路就是把相应的UART的GPIO配置一下,CLOCK设置一下就差不多了是吗?
刚才我把MDD.c文件下的流接口函数大概看了一遍,包括初始化设备、打开注册表、优先级判断,接下来调用GetSerialObject来操作底层,最后(void) pSerialHead->pHWObj->pFuncTbl->HWPostInit( pHWHead );
HWPostInit这个又怎么和我要写的驱动函数有联系起来呢?
也就是说MDD里的函数怎么和我的函数对应起来,还有,我要写的驱动应用程序时候,是不是就直接调用MDD里的OPEN,CLOSE流接口函数呢?
MDD里SC_Init这个函数也就是由用户设置的硬件配置,例如线路控制、波特率等等,那我的驱动函数是怎么和这个函数有联系起来呢。。。
不要太指望别人来帮你,再说人家也不太可能有跟你一样平台的代码,即使有也不一定有时间,即使有时间也不一定愿意花时间来研究你的问题,所以说一切还是要靠自己
耐心一点,刚开始的时候都是这样的
也就是说那部分是我们做的,那部分是和硬件有关的,要求写的