1. gzyueqian
      13352868059
      首頁 > 新聞中心 > > 正文

      S3C2410的WINCE BSP添加串口支持

      更新時間: 2008-08-25 08:54:57來源: 粵嵌教育瀏覽量:1929

        近在調優龍ST2410的板子,總體來說,優龍的板子做的不錯,技術支持也還可以~
        
        不過呢,優龍提供的WinCE BSP也只是在三星的公版BSP上少量修改而成的,雖然三星S3C2410能夠提供3個UART支持,也就是說每個UART控制器都可以工作在Interrupt(中斷)模式或DMA(直接內存訪問)模式,但是三星提供的公版BSP上只添加了UART0(COM1)和UART2(紅外)的支持,所以優龍提供的BSP也就只有一個串口能用,另外一個紅外我也不知道怎么用(沒有紅外設備測試)。
        
        這樣的話,我買的板子上面的兩個串口豈不是浪費了一個,這可不行,因為COM1是默認作為調試串口了,系統的啟動信息都是靠這個串口輸出的,總不能調試和使用共用一個吧!
        
        在優龍官方論壇尋覓未果,他們好像就沒做UART1的BSP支持,這樣,只好自己動手,豐衣足食了。
        
        我的平臺是WinCE 5.0和Platform Builder 5.0,雖然手頭的資料都是WinCE 4.2的,但根據修改比較,好像沒有區別,不知道WinCE 5.0到底升級了什么?

        首先列舉一下要修改文件的清單:
      SMDK2410FILESplatform.reg
      SMDK2410INCoalintr.h
      SMDK2410DRIVERSSERIALser2410_hw.c
      SMDK2410DRIVERSSERIALser2410_ser.c
      SMDK2410KERNELHALcfw.c
      SMDK2410KERNELHALARMarmint.c
      SMDK2410smdk2410.cec

        好了,Let's gooooooooo~

        1、打開platform.reg文件,這個是WinCE注冊表文件,在這里,我們要修改并添加串口。

        搜索:[HKEY_LOCAL_MACHINEDriversBuiltInSER2410],這就是串口1。
      將其下面的鍵值改為:

      [HKEY_LOCAL_MACHINEDriversBuiltInSER2410]
      "DeviceArrayIndex"=dword:0
      "Irq"=dword:13
      "IoBase"=dword:50000000
      "IoLen"=dword:2C
      "Prefix"="COM"
      "Dll"="SER2410.Dll"
      "Order"=dword:0
      "Priority"=dword:0
      "Port"="COM1:"
      "DeviceType"=dword:0
      "FriendlyName"="Serial Cable on COM1:"
      "Tsp"="Unimodem.dll"
      "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

      再在其后面添加串口2:

      [HKEY_LOCAL_MACHINEDriversBuiltInSER2410_2]
      "DeviceArrayIndex"=dword:1
      "Irq"=dword:23
      "IoBase"=dword:50004000
      "IoLen"=dword:2C
      "Prefix"="COM"
      "Dll"="SER2410.Dll"
      "Order"=dword:1
      "Priority"=dword:0
      "Port"="COM2:"
      "DeviceType"=dword:0
      "FriendlyName"="Serial Cable on COM2:"
      "Tsp"="Unimodem.dll"
      "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

      [HKEY_LOCAL_MACHINEDriversBuiltInSER2410_2Unimodem]
      "Tsp"="Unimodem.dll"
      "DeviceType"=dword:0
      "FriendlyName"="SER2410_2 UNIMODEM"
      "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

      再搜索:[HKEY_LOCAL_MACHINEDriversBuiltInIRDA2410],這個是紅外,也要修改下:

      [HKEY_LOCAL_MACHINEDriversBuiltInIRDA2410]
      "DeviceArrayIndex"=dword:2
      "Irq"=dword:19
      "IoBase"=dword:50008000
      "IoLen"=dword:2C
      "Prefix"="COM"
      "Dll"="IRDA2410.Dll"
      "Order"=dword:0
      "Priority"=dword:0
      "Port"="COM3:"
      "DeviceType"=dword:0 ; IRDA modem, 0 -> null modem
      "FriendlyName"="S2410 IRDA2410"
      "Index"=dword:2
      "IClass"="{A32942B7-920C-486b-B0E6-92A702A99B35}"

      好了,注冊表就改到這里,以上要特別注意Irq的值,要和oalintr.h里面的中斷定義對應,并且注意Order的順序,DeviceArrayIndex的值以及IoBase,后面串口源代碼中要用到該值作判斷。

      2、打開oalintr.h文件,我們添加一個新的串口,并定義中斷號。
      添加:

      #define SYSINTR_SERIAL1 (SYSINTR_FIRMWARE+19)

      這里,我們可以看到SYSINTR_SERIAL1定義到16+19=35=0x23,與注冊表中一致。


      然后修改下這個地方:

      MapIrq2SysIntr(DWORD _Irq)
      {
      if( _Irq<=19 )
      return ( SYSINTR_FIRMWARE + _Irq );
      else
      return (0xffffffff);
      }

      3、打開串口源文件中ser2410_hw.c文件。
      搜索:
      S2410_SetSerialIOP(
      PVOID pHead // @parm points to device head
      )
      將其函數改為:

      {
      PS2410_UART_INFO pHWHead = (PS2410_UART_INFO)pHead;
      PSER_INFO pHWHead1 = (PSER_INFO)pHead;

      RETAILMSG(DEBUGMODE, (TEXT("S2410_SetSerialIOP ")));
      if(pHWHead1->dwIOBase == 0x50004000)
      {
      #if USEVIRTUAL
      EnterCriticalSection(&(pHWHead->RegCritSec));
      v_pIOPregs->rGPHCON &= ~(0x3<<8 | 0x3<<10 /*| 0x3<<12 | 0x3<<14*/); // clear uart 1 - rx, tx
      v_pIOPregs->rGPHCON |= (0x2<<8 | 0x2<<10 /*| 0x1<<12 | 0x0<<14*/);
      v_pIOPregs->rGPHCON |= (0x2<<0 | 0x2<<2 );
      v_pIOPregs->rGPHUP |= 0x03;
      pHWHead->rDTRport = (volatile unsigned int *)&(v_pIOPregs->rGPHDAT);
      pHWHead->rDSRport = (volatile unsigned int *)&(v_pIOPregs->rGPHDAT);
      pHWHead->DtrPortNum = 0;
      pHWHead->DsrPortNum = 1;
      #else
      volatile IOPreg *s2410IOP;
      s2410IOP = (volatile IOPreg *)IOP_BASE;

      EnterCriticalSection(&(pHWHead->RegCritSec));
      s2410IOP->rGPHCON &= ~(0x3<<8 | 0x3<<10/* | 0x3<<12 | 0x3<<14*/); // clear uart 1 - rx, tx
      s2410IOP->rGPHCON |= (0x2<<8 | 0x2<<10 /*| 0x1<<12 | 0x0<<14*/);
      s2410IOP->rGPHCON |= (0x2<<0 | 0x2<<2 );
      s2410IOP->rGPHUP |= 0x03;
      pHWHead->rDTRport = (volatile unsigned int *)(IOP_BASE+0x74); //s2410IOP->rGPHDAT
      pHWHead->rDSRport = (volatile unsigned int *)(IOP_BASE+0x74);
      pHWHead->DtrPortNum = 0;
      pHWHead->DsrPortNum = 1;
      #endif
      }
      else if(pHWHead1->dwIOBase == 0x50008000)
      {
      #if USEVIRTUAL
      EnterCriticalSection(&(pHWHead->RegCritSec));
      v_pIOPregs->rGPHCON &= ~( 0x3<<12 | 0x3<<14); // clear uart 2 - rx, tx
      v_pIOPregs->rGPHCON |= ( 0x2<<12 | 0x2<<14);
      v_pIOPregs->rGPHCON |= (0x2<<0 | 0x2<<2 );
      v_pIOPregs->rGPHUP &= ~0xc0;
      pHWHead->rDTRport = (volatile unsigned int *)&(v_pIOPregs->rGPHDAT);
      pHWHead->rDSRport = (volatile unsigned int *)&(v_pIOPregs->rGPHDAT);
      pHWHead->DtrPortNum = 0;
      pHWHead->DsrPortNum = 1;
      #else
      volatile IOPreg *s2410IOP;
      s2410IOP = (volatile IOPreg *)IOP_BASE;

      EnterCriticalSection(&(pHWHead->RegCritSec));
      s2410IOP->rGPHCON &= ~(0x3<<12 | 0x3<<14); // clear uart 2 - rx, tx
      s2410IOP->rGPHCON |= ( 0x02<<12 | 0x02<<14);
      s2410IOP->rGPHCON |= (0x2<<0 | 0x2<<2 );
      s2410IOP->rGPHUP &= ~0xc0;
      pHWHead->rDTRport = (volatile unsigned int *)(IOP_BASE+0x74); //s2410IOP->rGPHDAT
      pHWHead->rDSRport = (volatile unsigned int *)(IOP_BASE+0x74);
      pHWHead->DtrPortNum = 0;
      pHWHead->DsrPortNum = 1;
      #endif
      }
      else
      {
      #if USEVIRTUAL
      EnterCriticalSection(&(pHWHead->RegCritSec));
      v_pIOPregs->rGPHCON &= ~(0x3<<0 | 0x3<<2 | 0x3<<4 | 0x3<<6/* | 0x3<<12 | 0x3<<14*/); // clear uart 0 - rx, tx
      v_pIOPregs->rGPHCON |= (0x2<<4 | 0x2<<6/* | 0x1<<12 | 0x0<<14*/);
      v_pIOPregs->rGPHCON |= (0x2<<0 | 0x2<<2 );
      v_pIOPregs->rGPHUP |= 0x03;
      pHWHead->rDTRport = (volatile unsigned int *)&(v_pIOPregs->rGPHDAT);
      pHWHead->rDSRport = (volatile unsigned int *)&(v_pIOPregs->rGPHDAT);
      pHWHead->DtrPortNum = 0;
      pHWHead->DsrPortNum = 1;
      #else
      volatile IOPreg *s2410IOP;
      s2410IOP = (volatile IOPreg *)IOP_BASE;

      EnterCriticalSection(&(pHWHead->RegCritSec));
      s2410IOP->rGPHCON &= ~(0x3<<0 | 0x3<<2 | 0x3<<4 | 0x3<<6 /*| 0x3<<12 | 0x3<<14*/); // clear uart 0 - rx, tx
      s2410IOP->rGPHCON |= (0x2<<4 | 0x2<<6 /*| 0x1<<12 | 0x0<<14*/);
      s2410IOP->rGPHCON |= (0x2<<0 | 0x2<<2 );
      s2410IOP->rGPHUP |= 0x03;
      pHWHead->rDTRport = (volatile unsigned int *)(IOP_BASE+0x74); //s2410IOP->rGPHDAT
      pHWHead->rDSRport = (volatile unsigned int *)(IOP_BASE+0x74);
      pHWHead->DtrPortNum = 0;
      pHWHead->DsrPortNum =1;
      #endif
      }
      LeaveCriticalSection(&(pHWHead->RegCritSec));
      }

      接著搜索:
      SL_Init(
      PVOID pHead, // @parm points to device head
      PUCHAR pRegBase, // Pointer to 16550 register base
      UINT8 RegStride, // Stride amongst the 16550 registers
      EVENT_FUNC EventCallback, // This callback exists in MDD
      PVOID pMddHead, // This is the first parm to callback
      PLOOKUP_TBL pBaudTable // BaudRate Table
      )
      在PS2410_UART_INFO pHWHead = (PS2410_UART_INFO)pHead;這一句后面添加:

      PSER_INFO pHWHead1 = (PSER_INFO)pHead;

      再搜索:
      if ( pHWHead->UseIrDA )
      {
      pHWHead->bINT = BIT_UART2;
      pHWHead->bTxINT = INTSUB_TXD2;
      pHWHead->bRxINT = INTSUB_RXD2;
      pHWHead->bErrINT = INTSUB_ERR2;
      #if USEVIRTUAL
      pHWHead->s2410SerReg = (S2410_UART_REG *)v_pUART2regs;
      pRegBase = (PUCHAR)pHWHead->s2410SerReg;
      #else
      pRegBase = (PUCHAR)UART2_BASE;
      pHWHead->s2410SerReg = (S2410_UART_REG *)pRegBase;
      #endif
      }
      else
      {
      把這其中的代碼修改為以下代碼
      }

      if(pHWHead1->dwIOBase == 0x50004000)
      {
      pHWHead->bINT = BIT_UART1;
      pHWHead->bTxINT = INTSUB_TXD1;
      pHWHead->bRxINT = INTSUB_RXD1;
      pHWHead->bErrINT = INTSUB_ERR1;
      #if USEVIRTUAL
      pHWHead->s2410SerReg = (S2410_UART_REG *)v_pUART1regs;
      pRegBase = (PUCHAR)pHWHead->s2410SerReg;
      #else
      pRegBase = (PUCHAR)UART1_BASE;
      pHWHead->s2410SerReg = (S2410_UART_REG *)pRegBase;
      #endif

      }
      else if(pHWHead1->dwIOBase == 0x50008000)
      {
      pHWHead->bINT = BIT_UART2;
      pHWHead->bTxINT = INTSUB_TXD2;
      pHWHead->bRxINT = INTSUB_RXD2;
      pHWHead->bErrINT = INTSUB_ERR2;
      #if USEVIRTUAL
      pHWHead->s2410SerReg = (S2410_UART_REG *)v_pUART2regs;
      pRegBase = (PUCHAR)pHWHead->s2410SerReg;
      #else
      pRegBase = (PUCHAR)UART2_BASE;
      pHWHead->s2410SerReg = (S2410_UART_REG *)pRegBase;
      #endif
      }
      else
      {

      pHWHead->bINT = BIT_UART0;
      pHWHead->bTxINT = INTSUB_TXD0;
      pHWHead->bRxINT = INTSUB_RXD0;
      pHWHead->bErrINT = INTSUB_ERR0;
      #if USEVIRTUAL
      pHWHead->s2410SerReg = (S2410_UART_REG *)v_pUART0regs;
      pRegBase = (PUCHAR)pHWHead->s2410SerReg;
      #else
      pRegBase = (PUCHAR)UART0_BASE;
      pHWHead->s2410SerReg = (S2410_UART_REG *)pRegBase;
      #endif
      }

      再搜索:
      if ( pHWHead->UseIrDA )
      {
      pHWHead->pUFTXH = (volatile unsigned char *)&(v_pUART2regs->rUTXH);
      pHWHead->pUFRXH = (volatile unsigned char *)&(v_pUART2regs->rURXH);
      }
      else
      {
      把這其中的代碼修改為以下代碼
      }

      if(pHWHead1->dwIOBase == 0x50004000)
      {
      pHWHead->pUFTXH = (volatile unsigned char *)&(v_pUART1regs->rUTXH);
      pHWHead->pUFRXH = (volatile unsigned char *)&(v_pUART1regs->rURXH);
      }
      else if(pHWHead1->dwIOBase == 0x50008000)
      {
      pHWHead->pUFTXH = (volatile unsigned char *)&(v_pUART2regs->rUTXH);
      pHWHead->pUFRXH = (volatile unsigned char *)&(v_pUART2regs->rURXH);
      }
      else
      {
      pHWHead->pUFTXH = (volatile unsigned char *)&(v_pUART0regs->rUTXH);
      pHWHead->pUFRXH = (volatile unsigned char *)&(v_pUART0regs->rURXH);
      }

      4、打開ser2410_ser.c文件。
      搜索:
      const HWOBJ IoObj = {
      THREAD_AT_INIT,
      SYSINTR_SERIAL,
      (PHW_VTBL) &IoVTbl
      };
      在其后面添加:

      const HWOBJ Io1Obj = {
      THREAD_AT_INIT,
      SYSINTR_SERIAL1,
      (PHW_VTBL) &IoVTbl
      };

      const HWOBJ Io2Obj = {
      THREAD_AT_INIT,
      SYSINTR_IR,
      (PHW_VTBL) &IoVTbl
      };

      接著搜索:
      const PCHWOBJ HWObjects[] = {
      &IoObj,
      &IrObj
      };
      將其修改為:

      const PCHWOBJ HWObjects[] = {
      &IoObj,
      &Io1Obj,
      &Io2Obj
      };

      再搜索:
      GetSerialObject(
      DWORD DeviceArrayIndex
      )
      將其函數改為:

      {
      PHWOBJ pSerObj;

      DEBUGMSG(DEBUGMODE,(TEXT("GetSerialObject : DeviceArrayIndex = %d "), DeviceArrayIndex));

      // Now return this structure to the MDD.
      if ( DeviceArrayIndex == 2 )
      {
      RETAILMSG(1,(TEXT("GetSerialObject Io2Obj ")));
      pSerObj = (PHWOBJ)(&Io2Obj);
      }
      else if(DeviceArrayIndex == 1)
      pSerObj = (PHWOBJ)(&Io1Obj);
      else
      pSerObj = (PHWOBJ)(&IoObj);

      return (pSerObj);
      }

      5、打開cfw.c文件,這就是中斷處理。
      搜索:
      BOOL
      OEMInterruptEnable(DWORD idInt, // @parm Interrupt ID to be enabled. See <l Interrupt ID's.Interrupt ID's> for a list of possble values.
      LPVOID pvData, // @parm ptr to data passed in in the <f InterruptInitialize> call
      DWORD cbData) // @parm Size of data pointed to be <p pvData>
      找到這一句:case SYSINTR_SERIAL:
      在其后面添加:

      case SYSINTR_SERIAL1: // Serial port1.
      s2410INT->rSUBSRCPND = (INTSUB_RXD1 | INTSUB_TXD1 | INTSUB_ERR1);
      s2410INT->rINTSUBMSK &= ~INTSUB_RXD1;
      s2410INT->rINTSUBMSK &= ~INTSUB_TXD1;
      s2410INT->rINTSUBMSK &= ~INTSUB_ERR1;
      s2410INT->rSRCPND = BIT_UART1;
      // S3C2410X Developer Notice (page 4) warns against writing a 1 to a 0 bit in the INTPND register.
      if (s2410INT->rINTPND & BIT_UART1) s2410INT->rINTPND = BIT_UART1;
      s2410INT->rINTMSK &= ~BIT_UART1;
      break;

      搜索:
      void
      OEMInterruptDisable(DWORD idInt) // @parm Interrupt ID to be disabled. See <t Interrupt ID's>
      還是這一句:case SYSINTR_SERIAL:
      在其后面添加:

      case SYSINTR_SERIAL1:
      s2410INT->rINTMSK |= BIT_UART1;
      s2410INT->rINTSUBMSK |= INTSUB_RXD1;
      s2410INT->rINTSUBMSK |= INTSUB_TXD1;
      s2410INT->rINTSUBMSK |= INTSUB_ERR1;
      break;

      搜索:
      void
      OEMInterruptDone(DWORD idInt) // @parm Interrupt ID. See <t Interrupt ID's>
      依舊找到case SYSINTR_SERIAL:
      在其后面添加:

      case SYSINTR_SERIAL1:
      s2410INT->rINTMSK &= ~BIT_UART1;
      s2410INT->rINTSUBMSK &= ~INTSUB_RXD1;
      break;

      6、打開armint.c文件。


      搜索:else if(IntPendVal == INTSRC_UART0)
      在其后面添加:

      else if(IntPendVal == INTSRC_UART1)
      {
      SubIntPendVal = s2410INT->rSUBSRCPND;

      // Note that we only mask the sub source interrupt - the serial driver will clear the
      // sub source pending register.
      //
      if(SubIntPendVal & INTSUB_ERR1)
      {
      s2410INT->rINTSUBMSK |= INTSUB_ERR1;
      }
      else if(SubIntPendVal & INTSUB_RXD1)
      {
      s2410INT->rINTSUBMSK |= INTSUB_RXD1;
      }
      else if(SubIntPendVal & INTSUB_TXD1)
      {
      s2410INT->rINTSUBMSK |= INTSUB_TXD1;
      }
      else
      {
      return(SYSINTR_NOP);
      }

      // NOTE: Don't clear INTSRC:UART1 here - serial driver does that.
      //
      s2410INT->rINTMSK |= BIT_UART1;
      if (s2410INT->rINTPND & BIT_UART1) s2410INT->rINTPND = BIT_UART1;

      return(SYSINTR_SERIAL1);

      }

      7、打開smdk2410.cec文件,添加UART1這個feature。
      搜索
      ComponentType
      (
      Name ( "Serial" )
      GUID ( {6563AD6C-E71C-11D4-B892-0050FC049781} )
      MaxResolvedImpsAllowed( 999 )
      Implementations
      (
      Implementation
      (
      Name ( "S32410 Serial UART" )
      在其后面添加:

      Implementation
      (
      Name ( "S32410 Serial UART1" )
      GUID ( {7C4427A5-286C-4C7A-B687-4E3B364D079B} )
      Description ( "Samsung S32410 serial UART controller." )
      BSPPlatformDir ( "smdk2410" )
      Version ( "5.0.0.0" )
      Locale ( 0409 )
      Vendor ( "Microsoft" )
      Date ( "2003-1-13" )
      SizeIsCPUDependent( 1 )
      BuildMethods
      (
      BuildMethod
      (
      GUID ( {07DA2083-6261-4ED6-B5BB-70CF4D930D68} )
      Step ( BSP )
      CPU ( "ARMV4" )
      CPU ( "ARMV4I" )
      Action ( '#BUILD(SOURCES,"$(_WINCEROOT)PLATFORMSMDK2410driversserial")')
      )
      )
      )

      我感覺這個改不改沒什么關系,反正網上有人這樣改了,我也就改了,但是實際內核定制時中并沒有添加上這個feature。

      到這里,整個過程就結束了,耗費了我整整!其實改動量并不大,但是調試一次光編譯就要15分鐘,還要下載,燒寫,啟動~唉,沒有仿真器就是麻煩。調了好多次沒有成功,就是在注冊表的中斷號那兒出了問題!

      免費預約試聽課

      亚洲另类欧美综合久久图片区_亚洲中文字幕日产无码2020_欧美日本一区二区三区桃色视频_亚洲AⅤ天堂一区二区三区

      
      

      1. 亚洲女同国产一区二区 | 亚洲精品国产自在久久 | 视频一区二区三区四区在线综合网 | 午夜福利麻豆国产精品午夜福利 | 日韩精品肥臀蜜桃一区二区自在线拍 | 日本人成视频免费观看看 |