2007年2月27日 星期二

操作 GPIO 的方式(ARM)

下面提到的範例平台為Samsung S3C2410 實際操作還是需要要查閱ARMdatasheet以及使用中的BSP代碼 要操作一個平臺的GPIO,在其對應BSP中按照基底位址,找到虛擬位址,並且找到方便操作這個位址的資料結構就可以了,關鍵函數就是VirtualAllocVirtualCopy。並且CE的方便之處就是user mode的應用程式仍然可以使用這兩個函數來訪問所有這些虛擬空間,對於不太複雜的程式,甚至可以省略寫驅動直接在應用程式中操作 下面以操作Samsung S3C2410GPIO為例,講述這個步驟: 1.首先在BSP中的s2410.h檔,找到虛擬位址映射以及操作GPIO的寄存器結構體(這個在自己製作一些特殊設備的BSP時,會依據需而不同) // // Registers : I/O port // #define IOP_BASE 0xB1600000 // 0x56000000 typedef struct { unsigned int rGPACON; // 00 unsigned int rGPADAT; unsigned int rPAD1[2]; unsigned int rGPBCON; // 10 unsigned int rGPBDAT; unsigned int rGPBUP; unsigned int rPAD2; unsigned int rGPCCON; // 20 unsigned int rGPCDAT; unsigned int rGPCUP; unsigned int rPAD3; unsigned int rGPDCON; // 30 unsigned int rGPDDAT; unsigned int rGPDUP; unsigned int rPAD4; unsigned int rGPECON; // 40 unsigned int rGPEDAT; unsigned int rGPEUP; unsigned int rPAD5; unsigned int rGPFCON; // 50 unsigned int rGPFDAT; unsigned int rGPFUP; unsigned int rPAD6; unsigned int rGPGCON; // 60 unsigned int rGPGDAT; unsigned int rGPGUP; unsigned int rPAD7; unsigned int rGPHCON; // 70 unsigned int rGPHDAT; unsigned int rGPHUP; unsigned int rPAD8; unsigned int rMISCCR; // 80 unsigned int rDCKCON; unsigned int rEXTINT0; unsigned int rEXTINT1; unsigned int rEXTINT2; // 90 unsigned int rEINTFLT0; unsigned int rEINTFLT1; unsigned int rEINTFLT2; unsigned int rEINTFLT3; // A0 unsigned int rEINTMASK; unsigned int rEINTPEND; unsigned int rGSTATUS0; // AC unsigned int rGSTATUS1; // B0 unsigned int rGSTATUS2; // B4 unsigned int rGSTATUS3; // B8 unsigned int rGSTATUS4; // BC }IOPreg; //將這些複製備用。 2.EVC中建立一個應用程式工程,由於VirtualCopy函數沒有在頭檔中定義,但是在coredll.lib裏面提供了符號連接,所以我們這裏直接添加一個函數定義就OK了。 #ifdef __cplusplus extern "C" { #endif BOOL VirtualCopy( LPVOID, LPVOID, DWORD, DWORD ); #ifdef __cplusplus } #endif 同時將步驟1裏面的定義複製到這裏。 3.按照驅動程式裏面操作的方法在應用程式中寫GPIO操作函數 (1)定義一個寄存器結構體變數 volatile IOPreg *v_pIOPRegs; (2)給這個變數分配空間並且映射到寄存器的空間上 v_pIOPRegs = (volatile IOPreg*)VirtualAlloc(0, sizeof(IOPreg), MEM_RESERVE, PAGE_NOACCESS); if (v_pIOPRegs == NULL) { DEBUGMSG (1,(TEXT("v_pIOPRegs is not allocated\n\r"))); return TRUE; } if (!VirtualCopy((PVOID)v_pIOPRegs, (PVOID)IOP_BASE, sizeof(IOPreg), PAGE_READWRITEPAGE_NOCACHE)) { DEBUGMSG (1,(TEXT("v_pIOPRegs is not mapped\n\r"))); return TRUE; } DEBUGMSG (1,(TEXT("v_pIOPRegs is mapped to %x\n\r"), v_pIOPRegs)); 3個步驟之後,對v_pIOPRegs的操作將直接和GPIO的寄存器關聯 例如:設置GPB的控制寄存器為全部Output v_pIOPRegs->rGPBCON=0x155555; 設置GPB的資料寄存器輸出高電平 v_pIOPRegs->rGPBDAT=0x3FF;