首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将NanoPi的GPIO设置为硬件级的输出?

如何将NanoPi的GPIO设置为硬件级的输出?
EN

Stack Overflow用户
提问于 2017-01-06 17:56:10
回答 2查看 769关注 0票数 2

我正在尝试将Pin G11设置在以前配置为输入的NanoPi Neo上,通过将PIO函数寄存器映射到使用mmap的虚拟内存中并设置一个位来在C++中输出。

每个全赢家H3数据表指定以下硬件地址:

基本地址: 0x01C20800 (第316页) 配置寄存器1偏移量: 0xDC (第338页) PG11位: 14:12

类似于Raspberry Pi的函数寄存器,Pin至少知道两种状态:

代码语言:javascript
复制
000: input
001: output

因此,在我的脚本中,我试图设置PG配置寄存器1的第12位。C++代码如下:

代码语言:javascript
复制
struct peripheral {
    unsigned long addr_hardware;
    int map_size;
    int mem_fd;
    void *mem_map;
    volatile unsigned long *addr_virtual;
    
    int map() {
        if ((mem_fd = open("/dev/mem", O_RDWR | O_SYNC)) < 0) return -1;
        // map addr_hardware=0x01C20000 into /dev/mem
        if ((mem_map = mmap(0, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd, addr_hardware)) == MAP_FAILED) return -1;
        // store virtual address with offset of 0x800, which was rounded down before
        addr_virtual = (volatile unsigned long *) mem_map + 0x800;
        return 0;
    };
    void unmap() {
        munmap(mem_map, map_size);
        close(mem_fd);
    };
};

int main() {
    // initialize peripheral at rounded down PIO base address
    peripheral gpio {0x01C20000, 4096 * 10};
    // map PIOs into virtual memory
    if (gpio.map() == -1) return -1;

    // output current value of PG Configure Register 1
    cout << bitset<32>(*(gpio.addr_virtual + 0xDC)) << endl;
    // set 12th bit
    *(gpio.addr_virtual + 0xDC) |= (1 << 12);
    // output value of register after setting the 12th bit
    cout << bitset<32>(*(gpio.addr_virtual + 0xDC)) << endl;

    gpio.unmap();
    return 0;
}

不幸的是,我的代码不起作用。当我再次运行脚本时,PIO配置寄存器的内容已更改为以前的状态。当我将Pin G11配置为输出时(通过WiringNP),显示的值不会改变。我正在用LED检查我的代码的适当功能(当状态从IN更改到OUT时,它应该打开,因为它被设置为高)。

当我修改map_size时,我得到了以下结果(为提高可读性而添加的空格):

代码语言:javascript
复制
> gpio {0x01C20000, 4096 * 2}
< 00000000 00000000 00000000 00000000
< 00000000 00000000 00010000 00000000

> gpio {0x01C20000, 4096 * 10}
< 00000000 00000000 00000000 00110011
< 00000000 00000000 00000000 00110011

我期望得到以下结果:

代码语言:javascript
复制
> gpio {0x01C20000, 4096 * 10}
< 00000000 00000000 00000000 00110011
< 00000000 00000000 00010000 00110011
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-09-11 19:29:48

为了解决我的问题,我必须以以下方式更改用于访问PIO硬件的虚拟地址:

代码语言:javascript
复制
addr_virtual = (volatile unsigned long *) mem_map + (0x800 >> 2);

这等于缩短的语句:

代码语言:javascript
复制
addr_virtual = (volatile unsigned long *) mem_map + 0x200;

但是更易读,因为PIO硬件地址是0x01C20000 + 0x800。我还使用了4096 * 10字节的映射大小。

我使用这些宏进行I/O操作:

代码语言:javascript
复制
#define GPIO_IN(g) *(gpio.addr_virtual + (((((g) / 32) * 36) + ((((g) - ((g) & ~31)) / 8) * 4)) >> 2)) &= ~(7 << ((((g) - (((g) / 32) * 32)) - ((((g) - (((g) / 32) * 32)) / 8) * 8)) * 4))
#define GPIO_OUT(g) GPIO_IN(g); *(gpio.addr_virtual + (((((g) / 32) * 36) + ((((g) - ((g) & ~31)) / 8) * 4)) >> 2)) |= 1 << ((((g) - (((g) / 32) * 32)) - ((((g) - (((g) / 32) * 32)) / 8) * 8)) * 4)

#define GPIO_SET(g) *(gpio.addr_virtual + (((((g) / 32) * 36) + 0x10) >> 2)) |= 1 << ((g) - (((g) / 32) * 32))
#define GPIO_CLR(g) *(gpio.addr_virtual + (((((g) / 32) * 36) + 0x10) >> 2)) &= ~(1 << ((g) - (((g) / 32) * 32)))
票数 1
EN

Stack Overflow用户

发布于 2017-05-19 21:56:58

如果在设备树中定义了pio,内核将控制和覆盖相关寄存器。例如,如果它想通过这个寄存器驱动闪烁的led或其他io。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41511494

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档