知了博客

集天地之精华,吸日月之灵气

« 关于性格内向者的10个误解,献给奋战在一线的程序员存储与地址映射技术 »

Windows CE下操作GPIO的方法(以ARM9 S3C2410为例)

GPIO 是ARM芯片最基本的输入输出通道,在ADS下操作就是一个单片机工作,直接读写其寄存器。在ARM9平台上,Windows CE系统将GPIO的实地址(例如2410的GPIO的基地址为0x56000000)映射到虚拟地址空间(GPIO对应为0xB1600000),这 样,通过对这段虚拟地址空间的操作,就能够完成对GPIO或者其他片内资源的控制、输入输出工作。
要操作一个平台的GPIO,在其对应BSP中按照基地址,找到虚拟地址,并且找到方便操作这个地址的数据结构就可以了,关键函数就是 VirtualAlloc和VirtualCopy。并且CE的方便之处就是用户态的应用程序仍然可以使用这两个函数来访问所有这些虚拟空间,对于不太复 杂的程序,甚至可以省略写驱动直接在应用程序中操作,其实在CE6之前,这些驱动也是工作在用户态的。
下面以操作Samsung S3C2410的GPIO为例,讲述这个步骤:
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 ")));
  return TRUE;
 }
 if (!VirtualCopy((PVOID)v_pIOPRegs, (PVOID)IOP_BASE, sizeof(IOPreg), PAGE_READWRITE|PAGE_NOCACHE)) {
  DEBUGMSG (1,(TEXT("v_pIOPRegs is not mapped ")));
  return TRUE;
 }
 DEBUGMSG (1,(TEXT("v_pIOPRegs is mapped to %x "), v_pIOPRegs));
这3个步骤之后,对v_pIOPRegs的操作将直接和GPIO的寄存器关联
例如:设置GPB的控制寄存器为全部Output
v_pIOPRegs->rGPBCON=0x155555;
设置GPB的数据寄存器输出高电平
v_pIOPRegs->rGPBDAT=0x3FF;

更多的操作,需要查阅ARM的datasheet以及WINCE的BSP源码完成。

对于非ARM的平台,在CE下操作,也可以参考这个思路。

 

////////////////////////////////////////////////////////////////////////////////////////////////////////

Telechip 参考:http://blog.csdn.net/norains/archive/2010/11/09/5997230.aspx
操作LCD Register 代码:

#ifndef _VIRTUAL_H_
#define _VIRTUAL_H_

#include <windows.h>

#ifdef __TCC89XX_WINCE__

    #define __HDMI_INCLUDE__
    //#define __ROTATE_INCLUDE__
        //#define __2DACCELATE_CHECK__                // After BSP v2664
    //#define    __SCALER1_INCLUDE__                    // this define used at TCMovieManager CM2MScaler Class
    //#define    __WITH_PHOTOPLAY__

    #ifdef __HDMI_INCLUDE__
        #define __HDMI_SUBTITLE__
    #endif

    #ifdef __HDMI_INCLUDE__
    #define SCALER_YSIZE    0x00200000
    #else
    #define SCALER_YSIZE    0x00100000   
    #endif

    #define UV_FACTOR  1            // M2M Scaler Output UV data Size factor. YUV422->1, YUV420 -> 2
                                    // YUV422[2]->(Y[1]+U[1/2]+V[1/2]) -> Y[1] + UV[1]
                                    // YUV420[1+1/2]->(Y[1]+U[1/4]+V[1/4] -> Y[1] + UV[1/2]

    #define SCALER_UVSIZE        SCALER_YSIZE/UV_FACTOR   
    #define SCALER_BUFF_SIZE    (SCALER_YSIZE + SCALER_UVSIZE)

    #ifdef __ROTATE_INCLUDE__
    #define ROTATE_BUFF_SIZE    SCALER_BUFF_SIZE
    #else
    #define ROTATE_BUFF_SIZE    0
    #endif   
   
    #ifdef __HDMI_SUBTITLE__
    #define HDMI_SUBTITLE_BUFF_SIZE 0x00100000
    #else
    #define HDMI_SUBTITLE_BUFF_SIZE 0
    #endif

    #ifdef __SCALER1_INCLUDE__
    #define SCALER1_BUFF_SIZE    SCALER_BUFF_SIZE
    #define JPEG_ENC_BUFF_SIZE    0x00080000
    #else
    #define SCALER1_BUFF_SIZE    0
    #define JPEG_ENC_BUFF_SIZE    0
    #endif

    #ifdef __WITH_PHOTOPLAY__
    #define PHOTODEC_BUFF_SIZE 0x01A00000
    #else
    #define PHOTODEC_BUFF_SIZE    0
    #endif
   
    // Current Offset = Previous Offset + Previous Region Size(Not Current Region Size)
    ///////////////////////////////////////////////////////////////////////////
    #define SCALER0_MEM0_OFFSET        PHOTODEC_BUFF_SIZE //0
    #define SCALER0_MEM1_OFFSET        SCALER0_MEM0_OFFSET + SCALER_BUFF_SIZE

    #define SCALER1_MEM0_OFFSET        SCALER0_MEM1_OFFSET + SCALER_BUFF_SIZE
    #define ROTATE1_MEM_OFFSET        SCALER1_MEM0_OFFSET + SCALER1_BUFF_SIZE    // *2
       
    #define ROTATE2_MEM_OFFSET        ROTATE1_MEM_OFFSET + ROTATE_BUFF_SIZE
   
    #define JPEG_ENC_MEM_OFFSET         (ROTATE2_MEM_OFFSET+ROTATE_BUFF_SIZE)

    #define HDMI_SUBTITLE_MEM_OFFSET JPEG_ENC_MEM_OFFSET+JPEG_ENC_BUFF_SIZE

    #define VIDEO_DEC_MEM_OFFSET        (HDMI_SUBTITLE_MEM_OFFSET + HDMI_SUBTITLE_BUFF_SIZE)

    #define CAMERA_MEM_OFFSET            VIDEO_DEC_MEM_OFFSET
    #define CAMERA_MEM_SIZE            0x900000    // preview 3 frame(max 1280x729 YUV422) + capture 1 frame(max 1600x1200)
    #define VIDEO_ENC_MEM_OFFSET        CAMERA_MEM_OFFSET + CAMERA_MEM_SIZE


typedef struct _UID_MEM {
    DWORD dwHwBaseAddress;
    DWORD dwAllocBaseAddress;
    DWORD dwSize;
}UID_MEM;

extern volatile LPVOID SetVirtual(unsigned int HwBaseAddress, unsigned int nSize);
extern void FreeVirtual(LPVOID pVirtualAddress, unsigned int nSize);

#else

#include "Pkfuncs.h"

#define SHARED_MEM_PHYSADDR        0xA0000000

//#define RAM128
#ifdef RAM128
#define HW_MEM_BASE            0x27C00000
#else
#define HW_MEM_BASE            0x23C00000
#endif

#define HW_MEM_LIMIT            0x00400000

#define OUTBUFFER_BASE            HW_MEM_BASE
#define OUTBUFFER_LIMIT            0x00300000
#define INBUFFER_BASE            (HW_MEM_BASE + OUTBUFFER_LIMIT)
#define INBUFFER_LIMIT            0x00040000
#define DATABUFFER_BASE            (HW_MEM_BASE + OUTBUFFER_LIMIT + INBUFFER_LIMIT)
#define DATABUFFER_LIMIT        0x00040000
#define SCALER_OUT1            (HW_MEM_BASE + OUTBUFFER_LIMIT + INBUFFER_LIMIT + DATABUFFER_LIMIT)
#define SCALER_OUT2            (HW_MEM_BASE + OUTBUFFER_LIMIT + INBUFFER_LIMIT + DATABUFFER_LIMIT + SCALER_LIMIT)
#define SCALER_LIMIT            0x00040000

#define HW_MEM_BASE_TCC79X        0x20100000 // for TCC79x (defaul value)
#define SCALER_TCC79X_OUT1        0x20480000 // for TCC79x (default value)
#define SCALER_TCC79X_OUT2        0x204C0000 // for TCC79x (default value)

#define DFLT_BASE_WMV9_ROBASE            0x10004000
#define DFLT_BASE_MPEG2_ROBASE            0x10008000
#define DFLT_BASE_MPEG2_HTBASE            0x10016000
#define DFLT_BASE_MPEG4SP_ROBASE        0x10004000
#define DFLT_BASE_MPEG4SP_HTBASE        0x10016000

#define MBMEM0BASE                0x10010000
#define MBMEM0BASE_SIZE                6144

#define DFLT_BASE_JPEGDEC_ROBASE        0x10008000
#define DFLT_BASE_JPEGDEC_ROBASE_LIBV033 0x10004000

#define    DFLT_BASE_JPEGENC_ROBASE        0x10008000
#define PHY_ADDR_R_PINGPONG_1            0x10014000
#define PHY_ADDR_R_PINGPONG_2            0x10016000

extern volatile LPVOID SetVirtual(unsigned int physical_addr, unsigned int mem_size);
extern volatile LPVOID SetVirtualCache(unsigned int physical_addr, unsigned int mem_size);
extern void FreeVirtual(LPVOID virtual_ptr, unsigned int mem_size);

#endif    // __TCC89XX_WINCE__

#endif    // _VIRTUAL_H_
#include "StdAfx.h"
#include "Virtual.h"

#ifndef __TCC89XX_WINCE__
#include <ceddk.h>

volatile LPVOID SetVirtual(unsigned int physical_addr, unsigned int mem_size)
{
    LPVOID pVirtual;

    PHYSICAL_ADDRESS PA;
    PA.LowPart = (DWORD)(physical_addr);

    pVirtual = (DWORD*)MmMapIoSpace(PA,mem_size, FALSE);
    if(!pVirtual){
        printf("MmMapIoSpace GetLastError() : %d\n",GetLastError());
        return NULL;
    }
    return pVirtual;
}
volatile LPVOID SetVirtualCache(unsigned int physical_addr, unsigned int mem_size)
{
    LPVOID pVirtual;

    PHYSICAL_ADDRESS PA;
    PA.LowPart = (DWORD)(physical_addr);

    pVirtual = (DWORD*)MmMapIoSpace(PA,mem_size, TRUE);
    if(!pVirtual){
        printf("MmMapIoSpace GetLastError() : %d\n",GetLastError());
        return NULL;
    }
    return pVirtual;
}
void FreeVirtual(LPVOID virtual_ptr, unsigned int mem_size)
{
    MmUnmapIoSpace(virtual_ptr, mem_size);
}
#else

#include "ioctl_code.h"
#include "Pkfuncs.h"
volatile LPVOID SetVirtual(unsigned int HwBaseAddress, unsigned int nSize)
{
    volatile LPVOID pVirtual;
    UID_MEM uid_mem;
    if(HwBaseAddress&0xFFF)
    {
        RETAILMSG(1,(TEXT("Need to Align Baseaddress.. (%x) \n"),HwBaseAddress&0xFFF));
        return NULL;
    }
    //need align 8bit
    uid_mem.dwHwBaseAddress = (DWORD)(HwBaseAddress>>8);
    //alloc virtual space
    pVirtual = VirtualAlloc(0,
        nSize,
        MEM_RESERVE,
        PAGE_EXECUTE_READWRITE);
    uid_mem.dwAllocBaseAddress =(DWORD)pVirtual;
    //define alloc size
    uid_mem.dwSize = nSize;
    DWORD nhRet =KernelIoControl(IOCTL_HAL_VIRTUALCOPY,&uid_mem, sizeof(UID_MEM), NULL, NULL, NULL);
    return pVirtual;
}

void FreeVirtual(LPVOID pVirtualAddress, unsigned int nSize)
{
    if(VirtualFree(pVirtualAddress, 0, MEM_RELEASE) == 0)
    {
        RETAILMSG(1,(TEXT("(VirtualFree Fail.. (%d) \n"),GetLastError()));
    }
}
#endif

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

日历

最新评论及回复

最近发表

Powered By Z-Blog 1.8 Arwen Build 90619 Code detection by Codefense  theme by BokeZhuti

Copyright know blog. Some Rights Reserved.站长(msn):webmaster#webgou.info(#换成@) 粤ICP备09183716号