当前位置:首页 > 编程开发

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

webgou15年前 (2011-04-28)编程开发413

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

扫描二维码推送至手机访问。

版权声明:本文由知了博客发布,如需转载请注明出处。

本文链接:https://www.webgou.info/?id=458

标签: wince
分享给朋友:

“Windows CE下操作GPIO的方法(以ARM9 S3C2410为例)” 的相关文章

static_cast、dynamic_cast、reinterpret_cast、和const_cast

关于强制类型转换的问题,很多书都讨论过,写的最详细的是C++ 之父的《C++ 的设计和演化》。最好的解决方法就是不要使用C风格的强制类型转换,而是使用标准C++的类型转换符:static_cast, dynamic_cast。标准C++中有四个类型转换符:static_cast dynamic_ca…

Android 修改Bitmap 图片像素的信息 R G B 颜色值 详解

要想修改Bitmap图片的 R G B信息 首先 得先拿到这张图片每个点的Color值 然后根据这个Color值 就可以算出对应的R G B 值 我们都知道在计算机语言中在内存中加载一张图片实际上是把图片的每个点的RGB信息写入内存 如果动态的修改了这些颜色信息 那绘制出来的图片就会改变。修…

Android核心模块内容概述

Android作为一个移动设备的平台,其软件层次结构包括了一个操作系统(OS),中间件(MiddleWare)和应用程序(Application)。根据Android的软件框图,其Android核心模块结构自下而上分为以下几个层次:第一、操作系统层(OS)第二、各种库(Libraries)和Andr…

Android文件系统深入剖析

用过Linux的朋友可能对开源的系统有一个非常好的印象。那么在日益成熟的手机操作系统中,有没有一款像Linux一样的开源系统呢?谷歌公司就退出了一款基于Linux平台的Android 操作系统来满足人们的需求。在这里大家可以先来了解一下Android文件系统的相关内容。1、Android文件系统的结…

Mac电脑安装OpenClaw教程

 自2026年1月起,一款名为OpenClaw(网友俗称“小龙虾”)的开源AI智能体在国内外社交媒体爆火,并衍生出收费安装服务。北京、上海、深圳等地的不少企业放出了“OpenClaw开发工程师”等岗位,其要求不限于“熟悉OpenC…

工程源码目录

严谨用于商业行为,请下载后于24小时之内删除。 …

发表评论

访客

看不清,换一张

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