• 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,详见下表。

    1. // Export the given gpio to userspace;
    2. // Return: Success = 0 ; otherwise open file error
    3. int gpioExport(unsigned int gpio)
    4. {
    5. int fileDescriptor, length;
    6. char commandBuffer[MAX_BUF];
    7. fileDescriptor = open(SYSFS_GPIO_DIR "/export", O_WRONLY);
    8. if (fileDescriptor < 0)
    9. {
    10. char errorBuffer[128];
    11. snprintf(errorBuffer, sizeof(errorBuffer), "gpioExport unable to open gpio%d", gpio);
    12. perror(errorBuffer);
    13. return fileDescriptor;
    14. }
    15. length = snprintf(commandBuffer, sizeof(commandBuffer), "%d", gpio);
    16. if (write(fileDescriptor, commandBuffer, length) != length)
    17. {
    18. perror("gpioExport");
    19. return fileDescriptor;
    20. }
    21. close(fileDescriptor);
    22. return 0;
    23. }

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

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

    1. // Set the direction of the GPIO pin
    2. // Return: Success = 0 ; otherwise open file error
    3. int gpioSetDirection(unsigned int gpio, unsigned int out_flag)
    4. {
    5. int fileDescriptor;
    6. char commandBuffer[MAX_BUF];
    7. snprintf(commandBuffer, sizeof(commandBuffer), SYSFS_GPIO_DIR "/gpio%d/direction", gpio);
    8. fileDescriptor = open(commandBuffer, O_WRONLY);
    9. if (fileDescriptor < 0)
    10. {
    11. char errorBuffer[128];
    12. snprintf(errorBuffer, sizeof(errorBuffer), "gpioSetDirection unable to open gpio%d", gpio);
    13. perror(errorBuffer);
    14. return fileDescriptor;
    15. }
    16. if (out_flag)
    17. {
    18. if (write(fileDescriptor, "out", 4) != 4)
    19. {
    20. perror("gpioSetDirection");
    21. return fileDescriptor;
    22. }
    23. }
    24. else
    25. {
    26. if (write(fileDescriptor, "in", 3) != 3)
    27. {
    28. perror("gpioSetDirection");
    29. return fileDescriptor;
    30. }
    31. }
    32. close(fileDescriptor);
    33. return 0;
    34. }

    步骤三:建立mmap

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

    1. // read physical memory (needs root)
    2. int fd = open("/dev/mem", O_RDWR | O_SYNC);
    3. if (fd < 0) {
    4. fprintf(stderr, "usage : $ sudo %s (with root privilege)\n", argv[0]);
    5. exit(1);
    6. }
    7. // map a particular physical address into our address space
    8. int pagesize = getpagesize();
    9. int pagemask = pagesize-1;
    10. // This page will actually contain all the GPIO controllers, because they are co-located
    11. void *base = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (GPIO_ADDRESS & ~pagemask));
    12. if (base == NULL) {
    13. perror("mmap()");
    14. exit(1);
    15. }

    内存映射表

    该表是我根据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
  • 相关阅读:
    一个由登录接口引发的思考
    ClickHouse部署文档
    Java并发编程: Thread常见方法
    Xcode14.3.1打包报错Command PhaseScriptExecution failed with a nonzero exit code
    【git系列2】关于安装 Git 的时候选择 core.autocrlf 的配置值
    shell 实现对Hive表字段脱敏写入新表
    Springboot初始化自动生成数据库表结构
    基于算术优化算法优化概率神经网络PNN的分类预测 - 附代码
    FastAdmin表格顶部增加toolbar按钮
    罗克韦尔AB PLC Logix5000中如何创建标签并使用标签进行编程?
  • 原文地址:https://blog.csdn.net/xhydongda/article/details/126401225