Serial Port Extension under WinCE

Source: Internet
Author: User
Tags 0xc0 builtin

Reprinted please indicate the source

Author: Pony


The company needs to expand the serial port to use a transplanted project. After a few days, it has finally succeeded.

 

2410 itself supports three UART with the same function, which can be called uart0, uart1, and uart2. how is the connection of the Board Sub-wiring of youlong, have you cited all three uarts. the circuit diagram is clear.

 

 

 

From the two pictures above, I can draw the following conclusion: the fs2410 Board cited uart0 (COM1) and uart1 (com2) serial ports correspond to the above J8 and j7. uart2 respectively and infrared (IRDA) the patch line cap is used for selection, but uart2 (com3) does not bring out the DB9 standard interface of the serial port. You need to use this interface yourself. my task is to add wince support for uart1 and uart2 (uart0 is used for output debugging information under dnw, BSP has added support for uart0 by default)

 

The hardware principle has been clarified. The following is the system-level modification. Based on experience, there should be two parts: one is the modification of registration information, and the other is the modification of driver code.

 

I checked some information on the Internet and sorted out the following process. This is a practice and can be used.

Step 1: Open the platform. reg file (under smdk2410/files) and find the following registry information:

;=============== UART0 (physical COM1 connector P1) (Serial) ===============IF BSP_NOSERIAL ![HKEY_LOCAL_MACHINE/Drivers/BuiltIn/SER2410]   "DeviceArrayIndex"=dword:0   "Irq"=dword:03   "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,00ENDIF BSP_NOSERIAL ! [HKEY_LOCAL_MACHINE/Drivers/BuiltIn/SER2410/Unimodem]   "Tsp"="Unimodem.dll"   "DeviceType"=dword:0   "FriendlyName"="SER2410 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

This is the registration information of uart0 (COM1. therefore, in addition to outputting debugging information when downloading the operating system, uart0 can also be used directly (for example, controlling printers under wince ). briefly explain the meaning of each value

Devicearrayindex is a serial index.

Order indicates the serial port loading sequence.

IRQ is the system interrupt number (hexadecimal) of the device. This value is consistent with that defined by oalintr. h.

The name of the friendlyname serial port displayed in the dialup program.

 

Add the following registration information under the above Code

;=============== UART1 (physical COM2 connector P2) (Serial) ===============IF BSP_NOSERIAL ![HKEY_LOCAL_MACHINE/Drivers/BuiltIn/SER2410_2]   "DeviceArrayIndex"=dword:1   "Irq"=dword:13   "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,00ENDIF BSP_NOSERIAL ! ; S2410 IrDA(UART2)[HKEY_LOCAL_MACHINE/Drivers/BuiltIn/IRDA2410]       "DeviceArrayIndex"=dword:2       "Irq"=dword:09       "IoBase"=dword:50008000       "IoLen"=dword:2C       ;modified by pony here.       ;"Prefix"="COM3"       "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}"

Pay attention to the differences between the two codes. The devicearrayindex item will be determined in the program, and the IRQ item and oalintr. h defines the same, which is equivalent to registering a system interrupt for uart1. the iobase item is the physical access address determined by the 2410 chip. You can find this value in the 2410 chip manual.

 

Step 2: Open the oalintr. h file (under smdk2410/INC) to add a new serial port and define the interrupt number.

#define SYSINTR_SERIAL1 (SYSINTR_FIRMWARE+19) 

Then modify the following function:

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

The interrupt number must meet the range specified in mapirq2sysintr. The maximum number of interrupts supported by wince4.2 is 32, and that supported by wince5.0 is 64.

 

Step 3: Open the ser2410_h1_c file (under smdk2410/Drivers/serial). Here, the parameters of the registers in the UART Controller in arm are directly modified.
Find:

S2410_SetSerialIOP( PVOID pHead // @parm points to device head ) 

Change it:

{ 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 = 6; pHWHead->DsrPortNum = 7; #endif } else { #if USEVIRTUAL EnterCriticalSection(&(pHWHead->RegCritSec)); v_pIOPregs->rGPHCON &= ~(0x3<<0 | 0x3<<2 | 0x3<<4 | 0x3<<6/* | 0x3<<12 | 0x3<<14*/); // 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 = 6; pHWHead->DsrPortNum = 7; #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 = 6; pHWHead->DsrPortNum =7; #endif } LeaveCriticalSection(&(pHWHead->RegCritSec)); } 

Search:

In ps2410 _

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 ) 

Uart_info phwhead = (ps2410_uart_info) phead:

PSER_INFO pHWHead1 = (PSER_INFO)pHead; 

Search again:

If (phwhead-> useirda) {phwhead-> bint = Hangzhou; 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 {// modify the code to the following code} 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) uart#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-> Limit = (Limit *) limit; pregbase = (puchar) phwhead-> s2410serreg; # else pregbase = (puchar) uart2_base; phwhead-> s2410serreg = (optional *) pregbase; # endif} else {phwhead-> bint = bit_uart0; phwhead-> btxint = Beijing; phwhead-> brxint = Beijing; phwhead-> berrint = intsub_err0; # If usevirtual phwhead-> s2410serreg = (Hangzhou *) Shanghai; pregbase = (puchar) phwhead-> s2410serreg; # else pregbase = (puchar) uart0_base; phwhead-> s2410serreg = (s2410_uart_reg *) pregbase; # endif}

Search again:

If (phwhead-> useirda) {phwhead-> puftxh = (volatile unsigned char *) & (v_puart2regs-> rutxh); phwhead-> pufrxh = (volatile unsigned char *) & (v_puart2regs-> rurxh);} else {// modify the code to the following code} If (phwhead1-> dwiobase = 0x50004000) {phwhead-> puftxh = (volatile unsigned char *) & (v_puart1regs-> rutxh); phwhead-> pufrxh = (volatile unsigned char *) & (response-> rurxh );} else if (phhuad1-> 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 );}

Step 4: Open the ser2410_ser.c file (under Drivers/serial). This is the driver's PDD layer. It is mainly responsible for providing calling interfaces for functions on the MDD layer.
Search:

const HWOBJ IoObj = { THREAD_AT_INIT, SYSINTR_SERIAL, (PHW_VTBL) &IoVTbl }; 

Add:

const HWOBJ Io1Obj = { THREAD_AT_INIT, SYSINTR_SERIAL1, (PHW_VTBL) &IoVTbl };const HWOBJ IrObj = {       THREAD_AT_INIT,       SYSINTR_IR,       (PHW_VTBL) &IrVTbl}; const HWOBJ Io2Obj = {       THREAD_AT_INIT,       SYSINTR_IR,       (PHW_VTBL) &IoVTbl};

Search:

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

Modify it:

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

Search again:

GetSerialObject( DWORD DeviceArrayIndex ) 

Change the function:

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

Step 5: Open CFW. the C file (under smdk2410/kernel/hal) defines the interrupt handler function of the kernel. located in the oal layer of the operating system. enable and disable code for custom interrupt
Search:

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> 

Find this sentence: Case sysintr_serial:
Add:

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; 

Search:

void OEMInterruptDisable(DWORD idInt) // @parm Interrupt ID to be disabled. See <t Interrupt ID's> 

Case sysintr_serial:
Add:

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

Search:

void OEMInterruptDone(DWORD idInt) // @parm Interrupt ID. See <t Interrupt ID's> 

Still find case sysintr_serial:
Add:

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

Step 6: Open armint. c file (under smdk2410/kernel/hal/ARM). Here we are looking for ISR, that is, the interrupt processing routine. of course, the interrupted service example program must be used to handle the interruption. it also maps a physical interrupt number into a logical interrupt value. that is, in oalintr. system_xxxx value defined in H.

Search: else if (intpendval = intsrc_uart0)
Add:

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 | = Beijing ;} 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 (Interrupt); // physical interrupt ing is logical interrupt}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.