问题描述
我正在尝试访问Atmel的Arm9 9g20上的GPIO引脚.我下面的代码不断在
上失败gpio = mmap(0,getpagesize(),PROT_READ | PROT_WRITE,MAP_SHARED,fd,0xFFFFF400);//GPIOA的开始
I'm trying access the GPIO pins on Atmel's Arm9 9g20. My code below keeps getting failing at
gpio = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0xFFFFF400); // start of GPIOA
有人可以帮助我处理我的代码,并提供一些I/O示例代码来帮助我度过这个难关吗?谢谢.
Could someone help me with my code and offer a bit of I/O example code to get me past this hump? Thanks.
// gpio.c
// compile arm-linux-gcc -o button button.c
//
#include<unistd.h>
#include<sys/types.h>
#include<sys/mman.h>
#include<stdio.h>
#include<fcntl.h>
#include<string.h>
// GPIO Registers
//http://www.atmel.com/dyn/resources/prod_documents/doc6384.pdf - page 374
#define PIO_PER 0x0000 // PIO Enable Register Write-only –
#define PIO_PDR 0x0004 // PIO Disable Register Write-only –
#define PIO_PSR 0x0008 // PIO Status Register Read-only
#define PIO_OER 0x0010 // Output Enable Register Write-only –
#define PIO_ODR 0x0014 // Output Disable Register Write-only –
#define PIO_OSR 0x0018 // Output Status Register Read-only. reset 0x0000 0000
//0x001C Reserved
#define PIO_IFER 0x0020 // Glitch Input Filter Enable Register Write-only –
#define PIO_IFDR 0x0024 // Glitch Input Filter Disable Register Write-only –
#define PIO_IFSR 0x0028 // Glitch Input Filter Status Register Read-only. Reset 0x0000 0000
//0x002C Reserved
#define PIO_SODR 0x0030 // Set Output Data Register Write-only –
#define PIO_CODR 0x0034 // Clear Output Data Register Write-only
#define PIO_ODSR 0x0038 // Output Data Status Register Read-only or Read-write
#define PIO_PDSR 0x003C // Pin Data Status Register Read-only
#define PIO_IER 0x0040 // Interrupt Enable Register Write-only –
#define PIO_IDR 0x0044 // Interrupt Disable Register Write-only –
#define PIO_IMR 0x0048 // Interrupt Mask Register Read-only. Reset 0x00000000
#define PIO_ISR 0x004C // Interrupt Status Register Read-only. Reset 0x00000000
#define PIO_MDER 0x0050 // Multi-driver Enable Register Write-only –
#define PIO_MDDR 0x0054 // Multi-driver Disable Register Write-only –
#define PIO_MDSR 0x0058 // Multi-driver Status Register Read-only. Reset 0x00000000
//0x005C Reserved
#define PIO_PUDR 0x0060 // Pull-up Disable Register Write-only –
#define PIO_PUER 0x0064 // Pull-up Enable Register Write-only –
#define PIO_PUSR 0x0068 // Pad Pull-up Status Register
#define PIO_ASR 0x0070 // Peripheral A Select Register Write-only –
#define PIO_BSR 0x0074 // Peripheral B Select Register Write-only –
#define PIO_ABSR 0x0078 // AB Status Register Read-only 0x00000000
//0x007C to 0x009C Reserved
#define PIO_OWER 0x00A0 // Output Write Enable Write-only –
#define PIO_OWDR 0x00A4 // Output Write Disable Write-only –
#define PIO_OWSR 0x00A8 // Output Write Status Register Read-only 0x00000000
/*******************************************************************************************************
* MAIN
*******************************************************************************************************/
int main(int argc, char **argv) {
volatile unsigned int *PADR, *PADDR, *PBDR, *PBDDR, *PCDR, *PCDDR;
unsigned long *gpio;
int fd = open("/dev/mem", O_RDWR|O_SYNC);
if (fd < 0){
fprintf(stderr, "Unable to open port\n\r");
exit(fd);
}
gpio = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0xFFFFF400); // start of GPIOA
if(gpio == (void *) -1) {
printf("Memory map failed.\n");
exit(0);
} else {
printf("Memory mapped at address %p.\n", gpio);
}
PADR = (unsigned int *)(gpio + 0x00); // port a
PADDR = (unsigned int *)(gpio + PIO_OER); // port a output enable
*PADDR = 0xff; // make all output
*PADR = 0xffff; // turn All of A Off
close(fd);
return 0;
}
推荐答案
不确定所遇到的故障类型(未描述),但使用GPIO端口和注释的操作不正确.首先,寄存器 PIO_PER 是IO使能寄存器,设置位不是使它们输出,而是使能.另一方面,PIO_OER实际上是用于使它们输出,而不是全部关闭.因此,您应该遵循以下顺序:
Not sure what type of failings you are experiencing (they are not described) but operations with GPIO port and comments are not correct. First of all, register PIO_PER is IO enable register, setting bits is not making them output but enabling. On the other hand, PIO_OER is indeed for making them output and not turning all off. So, you should stick to the following sequence:
// initializing
*(unsigned int *) (gpio + PIO_PER) = 0xff; // enable
*(unsigned int *) (gpio + PIO_OER) = 0xff; // set output
// working
...
*(unsigned int *) (gpio + PIO_SODR) = 0xff; // set 1's
...
*(unsigned int *) (gpio + PIO_CODR) = 0xff; // set 0's
更新
由于只能映射整个页面,因此应考虑到这一点:
Since only whole pages can be mapped, you should take that into consideration:
#define MAP_SIZE 4096UL
#define MAP_MASK (MAP_SIZE - 1)
#define GPIOA_BASE 0xFFFFF400
...
/* Map one page */
map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIOA_BASE & & ~MAP_MASK);
...
gpio = map_base + (GPIOA_BASE & MAP_MASK);
...
检查著名的devmem工具的来源:此处
Check the sources of well-known devmem tool: here
这篇关于使用mmap读取ARM 9g20 GPIO无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!