13367|42

79

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

com16550驱动请教!!!!请做过此驱动的大哥帮忙!!!谢谢!!! [复制链接]

现在BSP中用的是在public下移植过来的com16550驱动,可是一直没看懂是怎么用的外部中断

看了网上 xunjingzhpu 的博客中:
3 需要增加串口芯片对应的gpio口中断,在中断处理线程DWORD CPdd16550::ThreadRun()中记得重新使能中断,在中断触发上如果采用单边沿触发模式可能会漏中断,漏中断是致命的bug,一旦漏了就没有清除16550的中断寄存器将不再产生接收中断。

我发现我现在的这个驱动好象就没有用到外部中断

这个外部中断是通过注册表写进去的:
[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\Serial4]
   "IRQ"=dword:12        这个地方应该是系统中断号SysIntr还是物理中断号,
                                如果是物理中断号我的板子上应该是3(EINT3)

   "IoBase"=dword:20000000
   "IoLen"=dword:8
   "DeviceArrayIndex"=dword:4
   "Prefix"="COM"
   "Dll"="com16550.dll"
   "Order"=dword:1
   "FriendlyName"="COM4:"
   "Index"=dword:4
我看这个驱动中在ThreadRun()中 InterruptDone(m_dwSysIntr);

而m_dwSysIntr在整个驱动中要么m_dwSysIntr = MAXDWORD;要么 m_dwSysIntr = ddi.dwSysintr;

这个ddi.dwSysintr我没找到定义处,不知道这个驱动是怎么用我注册表中定义的外部中断的,
或者需要我怎么在这个驱动中添加上这个中断,

另外,驱动的MDD层,刚开始就读注册表,读取到  "DeviceArrayIndex"=dword:4 这个值 ,后来
又把pSerObj->dwIntID = DeviceArrayIndex ,以后在整个驱动中用到很多InterruptDone(pSerialHead->pHWObj->dwIntID);
是拿这个ID当中断吗??

最新回复

呵呵,正遇到此问题。呵呵。  详情 回复 发表于 2010-3-30 16:59
点赞 关注

回复
举报

72

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
也在看串口这块的东西,觉得16550其实跟6410/2440是一个道理,分MDD+PDD层,PDD层实现MDD要调用的接口函数.获取成功(其实就是HW_VTBL函数表)MDD就可以通过这个PDD接口访问PDD层的底层硬件了(也就是些SFR操作),对于6410/2440就是那些UART的SFR了,对于你说的16550估计在整个系统内存空间也占有(或者映射)了一片地址,16550内部的SFR也可以通过访问这片内存地址来访问,觉得道理是一样的.不过MDD跟PDD层的几个有继承关系的类应该好好把握,因为很多很多接口都是虚函数实现而虚函数带来了灵活但给我们的理解带来了困难.子类重载了父类的虚函数调用的时候具体应该调那一个.

觉得理顺层次关系很重要!!!

1>class CPdd6410Uart: public CSerialPDD, public CMiniThread

2>class CPdd16550 : public CSerialPDD, public CMiniThread

class CPdd6410Uart跟class CPdd16550 的角色跟地位是一个样!!!


下面的代码应该就是事件跟中断号的绑定代码!!!!




  1. BOOL CPdd6410Uart::Init()
  2. {
  3.     if ( CSerialPDD::Init() && IsKeyOpened() && m_XmitFlushDone!=NULL)
  4.     {
  5.         // IST Setup .
  6.         DDKISRINFO ddi;
  7.         if (GetIsrInfo(&ddi)!=ERROR_SUCCESS)
  8.         {
  9.             return FALSE;
  10.         }
  11.         m_dwSysIntr = ddi.dwSysintr;
  12.         if (m_dwSysIntr !=  MAXDWORD && m_dwSysIntr!=0 )
  13.         {
  14.             m_hISTEvent= CreateEvent(0,FALSE,FALSE,NULL);
  15.         }

  16.         if (m_hISTEvent!=NULL)
  17.         {
  18.             InterruptInitialize(m_dwSysIntr,m_hISTEvent,0,0);
  19.         }
  20.         else
  21.         {
  22.             return FALSE;
  23.         }

  24.         // Get Device Index.
  25.         if (!GetRegValue(PC_REG_DEVINDEX_VAL_NAME, (PBYTE)&m_dwDevIndex, PC_REG_DEVINDEX_VAL_LEN))
  26.         {
  27.             m_dwDevIndex = 0;
  28.         }
  29.         if (!GetRegValue(PC_REG_SERIALWATERMARK_VAL_NAME,(PBYTE)&m_dwWaterMark,PC_REG_SERIALWATERMARKER_VAL_LEN))
  30.         {
  31.             m_dwWaterMark = 8;
  32.         }
  33.         if (!GetRegValue(PC_REG_6410UART_IST_TIMEOUTS_VAL_NAME,(PBYTE)&m_dwISTTimeout, PC_REG_6410UART_IST_TIMEOUTS_VAL_LEN))
  34.         {
  35.             m_dwISTTimeout = INFINITE;
  36.         }
  37.         if (!GetRegValue(PC_REG_6410UART_MEM_LENGTH_VAL_NAME, (PBYTE)&m_dwMemLen, PC_REG_6410UART_MEM_LENGTH_VAL_LEN))
  38.         {
  39.             m_dwMemLen = 0x40;
  40.         }
  41.         if (!MapHardware()  || !CreateHardwareAccess())
  42.         {
  43.             return FALSE;
  44.         }

  45.         return TRUE;        
  46.     }
  47.     return FALSE;
  48. }


复制代码










  1. BOOL CPdd16550::Init()
  2. {
  3.     if ( CSerialPDD::Init() && IsKeyOpened() && m_XmitFlushDone!=NULL) {
  4.         // IST Setup .
  5.         DDKISRINFO ddi;
  6.         if (GetIsrInfo(&ddi)!=ERROR_SUCCESS) {
  7.             return FALSE;
  8.         }
  9.         m_dwSysIntr = ddi.dwSysintr;
  10.         if (m_dwSysIntr !=  SYSINTR_UNDEFINED && m_dwSysIntr!=0 )
  11.             m_hISTEvent= CreateEvent(0,FALSE,FALSE,NULL);
  12.         
  13.         if (m_hISTEvent!=NULL) {
  14.             if (!InterruptInitialize(m_dwSysIntr,m_hISTEvent,0,0)) {
  15.                 m_dwSysIntr = SYSINTR_UNDEFINED ;
  16.                 return FALSE;
  17.             }
  18.         }
  19.         else
  20.             return FALSE;
  21.         
  22.         // Get Device Index.
  23.         if (!GetRegValue(PC_REG_DEVINDEX_VAL_NAME, (PBYTE)&m_dwDevIndex, PC_REG_DEVINDEX_VAL_LEN)) {
  24.             m_dwDevIndex = 0;
  25.         }
  26.         if (!GetRegValue(PC_REG_SERIALWATERMARK_VAL_NAME,(PBYTE)&m_dwWaterMark,sizeof(DWORD))) {
  27.             m_dwWaterMark = 8;
  28.         }
  29.         if (!MapHardware() || !CreateHardwareAccess()) {
  30.             return FALSE;
  31.         }
  32.         
  33.         return TRUE;        
  34.     }
  35.     return FALSE;
  36. }

复制代码



 
 

回复

75

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
thank u!
还是有些疑问:
这里跟事件关联InterruptInitialize(m_dwSysIntr,m_hISTEvent,0,0);
的中断是m_dwSysIntr,而m_dwSysIntr = ddi.dwSysintr;
ddi.dwSysintr这个系统中断号是哪个中断?
对应到注册表中哪个中断?是16550的外部中断吗??
怎么查到(在哪里)的注册表中的中断值?

代码下面这几个GetRegValue读取的都不是这个外部中断号!
 
 
 

回复

70

帖子

0

TA的资源

一粒金砂(初级)

4
 
请问xqhrs232兄:
是通过GetIsrInfo得到的吗??
请问您注册表信息是怎么写的?
是否跟可安装ISR有关????

 
 
 

回复

66

帖子

0

TA的资源

一粒金砂(初级)

5
 
下面是我的注册表内容,有可以是通过GetIsrInfo,这个函数会操作注册表的,你把DDI打印出来看看是那个中断在修改对应的注册表项,看再次读取的中断号会不会跟着变化.
IF BSP_NOUART0 !
IF BSP_KITL != SERIAL_UART0
IF BSP_DEBUGPORT != SERIAL_UART0
;--------------- UART0 (Physical COM1 Port) ----------------------------------
[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\Serial0]
        "DeviceArrayIndex"=dword:0
        "Irq"=dword:3D                                ; UART0 Virtual IRQ = 61 (0x3D), Physical IRQ = 37
        "MemBase"=dword:7F005000
        "MemLen"=dword:40
;        "ISTTimeouts"=dword:200                ; every 512 ticks checking Modem status.
        "Prefix"="COM"
        "Index"=dword:1
        "Dll"="smdk6410_serial.dll"
        "Order"=dword:30
        "Port"="COM1:"
        "DeviceType"=dword:0
        "FriendlyName"=LOC_DISPLAYNAME_COM1
        "Tsp"="unimodem.dll"
        "IClass"="{CC5195AC-BA49-48a0-BE17-DF6D1B0173DD}"
        "DevConfig"=hex: 10,00, 00,00, 05,00,00,00, 10,01,00,00, 00,4B,00,00, 00,00, 08, 00, 00, 00,00,00,00
;--------------------------------------------------------------------------
ENDIF
ENDIF
ENDIF
 
 
 

回复

69

帖子

0

TA的资源

一粒金砂(初级)

6
 


  1. DWORD   GetIsrInfo( DDKISRINFO* pddi )
  2.     {
  3.         if( pddi && m_hDevKey )
  4.         {
  5.             pddi->cbSize = sizeof( DDKISRINFO );
  6.             DWORD status = DDKReg_GetIsrInfo( m_hDevKey, pddi );
  7.             return status;
  8.         }
  9.         else
  10.         {
  11.             return ERROR_INVALID_FUNCTION;
  12.         }
  13.     }

复制代码


DWORD WINAPI DDKReg_GetIsrInfo(
  HKEY hk,
  PDDKISRINFO pii
);

This function populates a DDKISRINFO structure with information from the registry. If you specify an interrupt service routine (ISR) DLL, you must also specify a handler entry point and an interrupt request (IRQ).
When the DDKReg_GetIsrInfo function reads the registry, it does the following:

If an IsrDll entry is configured, it ensures that there is an IsrHandler entry configured.


If there is no IsrDll entry nor an IsrHandler entry, the function returns ERROR_SUCCESS.


If there is an IsrHandler entry, but no IsrDll entry, the function returns ERROR_INVALID_DATA.


If there are both IsrDll and IsrHandler entries, the function checks that there must be a valid Irq entry configured.

对应的数据结构typedef struct _DDKISRINFO_tag {
  DWORD cbSize;
  DWORD dwIrq;
  DWORD dwSysintr;
  WCHAR szIsrDll[DEVDLL_LEN];
  WCHAR szIsrHandler[DEVENTRY_LEN];
} DDKISRINFO, *PDDKISRINFO;




 
 
 

回复

71

帖子

0

TA的资源

一粒金砂(初级)

7
 
下面是我的6410里面头文件的虚拟中断号定义.
//define in s3c6410_vintr.h

/*
#define IRQ_UART0            61    // 37
#define IRQ_UART1            62    // 38
#define IRQ_UART2            63    // 39
#define IRQ_UART3            64    // 40
*/

应该是你准备把那个虚拟中断映射到16550对应的硬件中断,在注册表里面"Irq"=dword:3D ; UART0 Virtual IRQ = 61 (0x3D), Physical IRQ = 37
这一项就对应填上那个虚拟中断号.
 
 
 

回复

80

帖子

0

TA的资源

一粒金砂(初级)

8
 
哦??您的BSP是WINCE6下的吧??
好象跟我现在的不太一样
我的是在REG中:
"IRQ"=dword:3   表示物理中断号      
"SysIntr"=dword:12    ;(SYSINTR_FIRMWARE+2)   表示系统中断号

具体中断处理:
1、在SMDK2416\Src\Inc\bsp_cfg.h(204)中:
    #define SYSINTR_UART4           (SYSINTR_FIRMWARE+2)  该值为12,系统中断号
2、在SMDK2416\Src\Kernel\Oal\intr.c(55):   
    OALIntrStaticTranslate(SYSINTR_UART4, IRQ_EINT3);(IRQ_EINT3为外部中断3,物理中断号该值为3)
3、在SMDK2416\Src\Inc\s3c2450_intr.h(81):
   #define IRQ_EINT3           3
4、在ISR处理中处理这个物理中断号IRQ_EINT3

---------------------------------------------------------------
下面还是有些疑问:
1、注册表项中,我看网上有用"IRQ" 还有 "SysIntr"
   我理解,如果用“IRQ”应该是读到的物理中断号(比如我的BSP下应该是3),
   而用"SysIntr”应该是系统中断号(比如我的BSP下应该是12)
   那么,当前GetIsrInfo,它需要读取的是哪个中断号呢??("IRQ" or "SysIntr"?)
   看原程序:m_dwSysIntr = ddi.dwSysintr; 这段应该是用注册表下这个键值SysIntr吧?
2、同样,RegBase、IoBase、MemBase这三个键值名称网上也都有用到的
   这个注册表信息应该是GetWindowInfo这个函数读取的吧?
   那么这三个键值名称怎么区分?应该用哪一个呢???
 
 
 

回复

101

帖子

0

TA的资源

一粒金砂(中级)

9
 
12应该是16进制形式,实际应该是18这个中断号.
 
 
 

回复

62

帖子

0

TA的资源

一粒金砂(初级)

10
 
哦!对
我看BSP的SMDK2416\Src\Inc\bsp_cfg.h中
#define SYSINTR_OHCI            (SYSINTR_FIRMWARE+1)
我在这个后面加上:
#define SYSINTR_UART4           (SYSINTR_FIRMWARE+2)
而OHCI在注册表中的注释是"SysIntr"=dword:11          ; (SYSINTR_FIRMWARE+1)
我的这个应该是"SysIntr"=dword:12    ;(SYSINTR_FIRMWARE+2)  吧???
 
 
 

回复

78

帖子

0

TA的资源

一粒金砂(初级)

11
 
下面还是有些疑问:
1、注册表项中,我看网上有用"IRQ" 还有 "SysIntr"
  我理解,如果用“IRQ”应该是读到的物理中断号(比如我的BSP下应该是3),
  而用"SysIntr”应该是系统中断号(比如我的BSP下应该是12)
  那么,当前GetIsrInfo,它需要读取的是哪个中断号呢??("IRQ" or "SysIntr"?)
  看原程序:m_dwSysIntr = ddi.dwSysintr; 这段应该是用注册表下这个键值SysIntr吧?
2、同样,RegBase、IoBase、MemBase这三个键值名称网上也都有用到的
  这个注册表信息应该是GetWindowInfo这个函数读取的吧?
  那么这三个键值名称怎么区分?应该用哪一个呢???
 
 
 

回复

64

帖子

0

TA的资源

一粒金砂(初级)

12
 
"SysIntr"=dword:11   ;--------这个表示的应该是17号这个中断吧!
 
 
 

回复

72

帖子

0

TA的资源

一粒金砂(初级)

13
 
这个我没试过,你可以追踪那几个GETISRINFO/GETWINDOWINFO函数,你修改一下你的注册表.

1>IRQ跟SYSINTR不同
2>RegBase、IoBase、MemBase这三个分别不同,把GETISRINFO/GETWINDOWINFO读取的结果向串口打印出来,就可以知道他们到底用的是那一项


这样的方法估计是最笨的方法了.
 
 
 

回复

71

帖子

0

TA的资源

一粒金砂(初级)

14
 
引用 9 楼 wangxin_801115 的回复:
哦!对
我看BSP的SMDK2416\Src\Inc\bsp_cfg.h中
#define SYSINTR_OHCI? ? ? ? ? ? (SYSINTR_FIRMWARE+1)
我在这个后面加上:
#define SYSINTR_UART4? ? ? ? ? (SYSINTR_FIRMWARE+2)
而OHCI在注册表中的注释是"SysIntr"=dword:11 ? ; (SYSINTR_FIRMWARE+1)
我的这个应该是"SysIntr"=dword:12? ? ;(SYSINTR_FIRMWARE+2)? 吧???


这个应该没有问题.关键是你绑定过去没有,有没什么方法验证一下,不如直接用个I/O线测试一下,先不接16550.
 
 
 

回复

70

帖子

0

TA的资源

一粒金砂(初级)

15
 
引用 11 楼 xqhrs232 的回复:
"SysIntr"=dword:11? ;--------这个表示的应该是17号这个中断吧!

不是,
看我的BSP中对USB的中断定义来跑一圈:
1、SMDK2416\Src\Inc\bsp_cfg.h(202):
    #define SYSINTR_OHCI         (SYSINTR_FIRMWARE+1) 定义了一个系统中断号
2、SMDK2416\Src\Kernel\Oal\intr.c(52):   
   OALIntrStaticTranslate(SYSINTR_OHCI, IRQ_USBH); 把物理中断号跟系统中断号关联
3、SMDK2416\Src\Inc\s3c2450_intr.h(107):
    #define IRQ_USBH            26   传说中的物理中断号
4、注册表中:
[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\OHCI]
   "Irq"=dword:1a                ; 26    物理中断号IRQ
   "SysIntr"=dword:11                ; (SYSINTR_FIRMWARE+1)   系统中断号 SysIntr

所以11不管是十进制还是16进制他都只是通过SYSINTR_FIRMWARE+1 得到的系统中断号(虚拟中断号)
对应的物理中断号(也是自己定义的)应该是IRQ_USBH = 26
------------------------------------------------------------------
同样我看SD卡的驱动和注册表发现
SD卡驱动也用到了GetIsrInfo 和 GetWindowInfo 来获得注册表中的中断
SD卡的注册表信息是:
    "MemBase"=dword:4AC00000     用的这个键值名称
    "MemLen"=dword:100          这个怎么这么大??您的"MemLen"=dword:40 是怎么定义的?
    "Irq"=dword:15                ; 21   
                              这个在SMDK2416\Src\Inc\bsp_cfg.h下查,也是物理中断号
                                   #define IRQ_SDI_0           21  对应 0x15
                                   
 
 
 

回复

77

帖子

0

TA的资源

一粒金砂(初级)

16
 
您的16550通了吗?
我看注册表项:
"Irq"=dword:3D ; UART0 Virtual IRQ = 61 (0x3D), Physical IRQ = 37
直接用的虚拟中断号
并没有用物理中断号?
这个地方有没有问题?
我的理解如果是读取IRQ,应该是需要一个物理中断号
但是这里你传了一个系统中断号(虚拟中断号)进去
不知道你的BSP中对中断是否需要  物理----系统 关联? 如果都用一个号,那可能就
无所谓了!
 
 
 

回复

80

帖子

0

TA的资源

一粒金砂(初级)

17
 


  1. extern "C" PHWOBJ
  2. GetSerialObject(
  3.                DWORD DeviceArrayIndex
  4.                )
  5. {
  6.     PHWOBJ pSerObj;

  7.     // Unlike many other serial samples, we do not have a statically allocated
  8.     // array of HWObjs.  Instead, we allocate a new HWObj for each instance
  9.     // of the driver.  The MDD will always call GetSerialObj/HWInit/HWDeinit in
  10.     // that order, so we can do the alloc here and do any subsequent free in
  11.     // HWDeInit.
  12.     // Allocate space for the HWOBJ.
  13.     pSerObj=(PHWOBJ)LocalAlloc( LPTR ,sizeof(HWOBJ) );
  14.     if ( !pSerObj )
  15.         return (NULL);

  16.     // Fill in the HWObj structure that we just allocated.

  17.     pSerObj->BindFlags = THREAD_IN_PDD;     // PDD create thread when device is first attached.
  18.     pSerObj->dwIntID = DeviceArrayIndex;   // Only it is useful when set set THREAD_AT_MDD. We use this to transfer DeviceArrayIndex
  19.     pSerObj->pFuncTbl = (HW_VTBL *) &IoVTbl; // Return pointer to appropriate functions




  20.     // Now return this structure to the MDD.
  21.     return (pSerObj);
  22. }

  23. [color=#FF0000]pSerObj->dwIntID = DeviceArrayIndex;   // Only it is useful when set set THREAD_AT_MDD. We use this to transfer DeviceArrayIndex[/color]


  24. [color=#FF0000]上面这句代码不知道什么意思,pSerialHead->pHWObj->BindFlags有三种模式!!!

  25. 1>THREAD_AT_INIT
  26. 2>THREAD_IN_PDD
  27. 3>THREAD_AT_MDD

  28. 看来还有很多不清楚的地方!!![/color]


复制代码
 
 
 

回复

76

帖子

0

TA的资源

一粒金砂(初级)

18
 
我的BSP有一个对照表,物理号跟虚拟号是对应的,其实只要知道一个就可以的.知道其中一个用数组访问一个就可以知道另外的一个.


1>static const UINT32 g_VirIrq2PhyIrq[IRQ_MAX_S3C6410]
2>static const UINT32 g_PhyIrq2VirIrq[PHYIRQ_MAX_S3C6410]
 
 
 

回复

59

帖子

0

TA的资源

一粒金砂(初级)

19
 
pSerObj->dwIntID = DeviceArrayIndex
不知道后面为什么很多地方用到这个ID作为一个中断号用

昨天有位高手给我解释了一下,大概是说从MDD起的时候需要用真正的外部中断
从PDD起的时候就用这个ID(也就是DeviceArrayIndex )来判断用的哪个串口

不知道记没记反,具体没理解上去!

想先把中断这个问题搞定

昨天编译了一个内核进去,到com16550的驱动后就死机了
今天换个驱动试试!
 
 
 

回复

75

帖子

0

TA的资源

一粒金砂(初级)

20
 
引用 15 楼 wangxin_801115 的回复:
您的16550通了吗?
我看注册表项:
"Irq"=dword:3D ; UART0 Virtual IRQ = 61 (0x3D), Physical IRQ = 37
直接用的虚拟中断号
并没有用物理中断号?
这个地方有没有问题?
我的理解如果是读取IRQ,应该是需要一个物理中断号,
但是这里你传了一个系统中断号(虚拟中断号)进去
不知道你的BSP中对中断是否需要?物理----系统 关联? 如果都用一个号,那可能就
无所谓了!




我没弄什么16550,我只是在弄虚拟串口驱动程序顺带把串口驱动看了看.你弄过虚拟串口没?
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表