Jetson Nano 系列之:C通过内存映射操作GPIO

目标

NVIDIA提供了python版本的GPIO库,但没有提供C版,并且python版本是通过文件句柄实现的,性能不行,需要C版本内存映射来操作GPIO。

寄存器地址映射规则

根据官方文档 Tegra_X1_TRM_DP07225001_v1.3p.pdf 第9章表32,A~Z、AA、BB、CC、DD、EE、FF共有32个port,每4个port为一个controller,每个port控制8个GPIO针(pin)。寄存器地址范围000~FFF共4096个字节,每4个port的地址是交错的,如下表中A、B、C、D所示。

 

步骤一:打开GPIO口

代码来自jetsonGPIO,gpio参数传入GPIO的设备地址,例如BCM=20/BOARD=38对应的设备地址是77,详见下表。

// Export the given gpio to userspace;
// Return: Success = 0 ; otherwise open file error
int gpioExport(unsigned int gpio)
{
    int fileDescriptor, length;
    char commandBuffer[MAX_BUF];

    fileDescriptor = open(SYSFS_GPIO_DIR "/export", O_WRONLY);
    if (fileDescriptor < 0)
    {
        char errorBuffer[128];
        snprintf(errorBuffer, sizeof(errorBuffer), "gpioExport unable to open gpio%d", gpio);
        perror(errorBuffer);
        return fileDescriptor;
    }

    length = snprintf(commandBuffer, sizeof(commandBuffer), "%d", gpio);
    if (write(fileDescriptor, commandBuffer, length) != length)
    {
        perror("gpioExport");
        return fileDescriptor;
    }
    close(fileDescriptor);

    return 0;
}

步骤二:设置GPIO口的读/写

代码来自jetsonGPIO,gpio参数传入GPIO的设备地址,详见下表。

// Set the direction of the GPIO pin
// Return: Success = 0 ; otherwise open file error
int gpioSetDirection(unsigned int gpio, unsigned int out_flag)
{
    int fileDescriptor;
    char commandBuffer[MAX_BUF];

    snprintf(commandBuffer, sizeof(commandBuffer), SYSFS_GPIO_DIR "/gpio%d/direction", gpio);

    fileDescriptor = open(commandBuffer, O_WRONLY);
    if (fileDescriptor < 0)
    {
        char errorBuffer[128];
        snprintf(errorBuffer, sizeof(errorBuffer), "gpioSetDirection unable to open gpio%d", gpio);
        perror(errorBuffer);
        return fileDescriptor;
    }

    if (out_flag)
    {
        if (write(fileDescriptor, "out", 4) != 4)
        {
            perror("gpioSetDirection");
            return fileDescriptor;
        }
    }
    else
    {
        if (write(fileDescriptor, "in", 3) != 3)
        {
            perror("gpioSetDirection");
            return fileDescriptor;
        }
    }
    close(fileDescriptor);
    return 0;
}

步骤三:建立mmap

代码来自jetson-nano-gpio-example。其中,GPIO_ADDRESS 见下表中的内存映射地址。

    //  read physical memory (needs root)
    int fd = open("/dev/mem", O_RDWR | O_SYNC);
    if (fd < 0) {
        fprintf(stderr, "usage : $ sudo %s (with root privilege)\n", argv[0]);
        exit(1);
    }

    //  map a particular physical address into our address space
    int pagesize = getpagesize();
    int pagemask = pagesize-1;

    //  This page will actually contain all the GPIO controllers, because they are co-located
    void *base = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (GPIO_ADDRESS & ~pagemask));
    if (base == NULL) {
        perror("mmap()");
        exit(1);
    }

内存映射表

该表是我根据jetson的地址规则计算的内存映射地址和设备地址。

BCMJETSONGPIO内存映射地址设备地址
47GPIO3_PBB.000x6000d60C216
2637GPIO3_PB.040x6000d00412
2522GPIO3_PB.050x6000d00413
2713GPIO3_PB.060x6000d00414
2418GPIO3_PB.070x6000d00415
2316GPIO3_PDD.000x6000d704232
1333GPIO3_PE.060x6000d10038
529GPIO3_PS.050x6000d408149
2215GPIO3_PY.020x6000d600194
1232GPIO3_PV.000x6000d504168
631GPIO3_PZ.000x6000d604200
2038GPIO3_PJ.050x6000d20477
2140GPIO3_PJ.060x6000d20478
1935GPIO3_PJ.040x6000d20476
1812GPIO3_PJ.070x6000d20479
128GPIO3_PJ.010x6000d20473
027GPIO3_PJ.000x6000d20472
35GPIO3_PJ.020x6000d20474
23GPIO3_PJ.030x6000d20475
148GPIO3_PG.000x6000d10848
1510GPIO3_PG.010x6000d10849
1711GPIO3_PG.020x6000d10850
1636GPIO3_PG.030x6000d10851
1019GPIO3_PC.000x6000d00816
921GPIO3_PC.010x6000d00817
1123GPIO3_PC.020x6000d00818
824GPIO3_PC.030x6000d00819
726GPIO3_PC.040x6000d00820
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值