Beaglebone am335x通过mmap访问GPIO,设置并清除引脚

时间:2013-07-24 10:27:20

标签: linux embedded mmap gpio

我正在编写一个简单的程序来设置和清除引脚(目的是将该引脚用作自定义spi_CS)。 我能够导出该引脚(gpio1_17,端口9引脚23 bb白色)并通过文件系统使用它但我必须更快地驱动它。

这是代码:

uint32_t *gpio;

int fd = open("/dev/mem", O_RDWR|O_SYNC);
if (fd < 0){
    fprintf(stderr, "Unable to open port\n\r");
    exit(fd);
}

gpio =(uint32_t *) mmap(NULL, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO1_offset); // start of GPIOA

if(gpio == (void *) -1) {
    printf("Memory map failed.\n");
    exit(0);
} else {
    printf("Memory mapped at address %p.\n", gpio);
}

printf("\nGPIO_OE:%X\n",gpio[GPIO_OE/4]);
gpio[GPIO_OE/4]=USR1;
printf("\nGPIO_OE:%X\n",gpio[GPIO_OE/4]);

printf("\nGPIO_CLEARDATAOUT:%X\n",gpio[GPIO_CLEARDATAOUT/4]);
gpio[GPIO_CLEARDATAOUT/4]=USR1;
printf("\nGPIO_CLEARDATAOUT:%X\n",gpio[GPIO_CLEARDATAOUT/4]);


sleep(1);

printf("\nGPIO_SETDATAOUT%X\n",gpio[GPIO_SETDATAOUT/4]);
gpio[GPIO_DATAOUT/4]=USR1;
printf("\nGPIO_SETDATAOUT%X\n",gpio[GPIO_SETDATAOUT/4]);

#define GPIO1_offset  0x4804c000
#define GPIO1_size  0x4804cfff-GPIO1_offset
#define GPIO_OE  0x134
#define GPIO_SETDATAOUT  0x194
#define GPIO_CLEARDATAOUT  0x190
#define GPIO_DATAOUT 0x13C
#define USR1  1<<17

我能够输出那个引脚,如果我在运行程序之前将其置为高电平,那么ping就会变低。但我无法设置和重置它。有什么想法吗?

1 个答案:

答案 0 :(得分:-1)

为什么要直接修改寄存器?将它用作Linux GPIO更容易:

#define GPIO_1_17                  "49"                        

int gpio;
status_codes stat = STATUS_SUCCESS;

//Export our GPIOs for use
if((gpio = open("/sys/class/gpio/export", O_WRONLY)) >= 0) {
    write(gpio, GPIO_1_17, strlen(GPIO_1_17));
    close(gpio);
} else {
    stat = STATUS_GPIO_ACCESS_FAILURE;
    break;
}

//Set the direction and pull low
if((gpio = open("/sys/class/gpio/gpio" GPIO_1_17 "/direction", O_WRONLY)) >= 0) {
    write(gpio, "out", 3);  // Set out direction
    close(gpio);
} else {
    stat = STATUS_GPIO_ACCESS_FAILURE;
    break;
}
if((gpio = open("/sys/class/gpio/gpio" GPIO_1_17 "/value", O_WRONLY)) >= 0) {
    write(gpio, "0", 1);    // Pull low
    close(gpio);
} else {
    stat = STATUS_GPIO_ACCESS_FAILURE;
    break;
}

然后确保它在你的内容中被复制为gpio。

就你上面的mmap方法而言,你的寻址看起来是正确的。参考手册中的地址是字节地址,你使用的是32位指针,所以你所拥有的是正确的。但是,这一行:gpio [GPIO_OE / 4] = USR1使GPIO1上的每个引脚都是一个输出,除了它输入的17(0 =输出和1 =输入)。你可能的意思是:gpio [GPIO_OE / 4]&amp; = ~USR1

另外我相信你的意思是gpio [GPIO_SETDATAOUT / 4] = USR1;代替gpio [GPIO_DATAOUT / 4] = USR1;它们都会导致GPIO1_17被设置;但是,使用你所拥有的东西也会将GPIO1上的所有其他引脚设置为0。

我肯定会建议使用设计的内核接口,因为内核控制的mmap内容可能会有问题。

祝你好运! :)

编辑:我的不好意识到你说你为什么不直接通过文件系统驱动它,因为你需要更快地开它!您可能还需要考虑编写/修改SPI驱动程序,以便在速度与之后相同的情况下在内核中完成这些操作。 omap gpio接口也很容易在那里使用,只需请求和设置:)。