@whycanservice 那引脚速度有多少
L
LilaZhou 发布的帖子
-
回复: D1s 通过内存映射方式,直接操作GPIO寄存器,输出速度很慢,如何提高?
这是操作GPIO的方法, 主要就用
gpio_set_value
方法来设置GPIO端口值。#include <unistd.h> #include <stdint.h> #include <stdio.h> #include <fcntl.h> #include <sys/mman.h> // 一个端口的数据结构 typedef struct { // 工作方式寄存器 / Configure Register uint32_t cfg[4]; // 数据寄存器 / Data Register uint32_t dat; // Multi_Driving Register uint32_t drv[4]; // Pull Register uint32_t pull[3]; } port_t; #define GPIO_MAX_PORT_COUNT 7 // 基地址 #define BASE_ADDR 0x02000000 // 要映射的内存大小 #define MEM_AREA_SIZE (GPIO_MAX_PORT_COUNT * sizeof(port_t)) // port_t数组指针 static port_t *ports = 0; int gpio_init() { // 避免重复初始化 if (ports != 0) { printf("inited already\n"); return 1; } // 打开/dev/mem int fd = open("/dev/mem", O_RDWR); if (fd == -1) { perror("open '/dev/mem' failed\n"); return 1; } // 获取页大小 uint32_t page_size = sysconf(_SC_PAGESIZE); // 计算基址相对于页大小的余数,也就是mmap结果之上的偏移量 uint32_t offset = BASE_ADDR % page_size; // 映射到物理地址 void *map_addr = mmap(0, MEM_AREA_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, BASE_ADDR - offset); // 映射失败 if (map_addr == MAP_FAILED) { perror("mmap failed!\n"); close(fd); return 1; } // 可以关闭/dev/mem,对映射关系没有影响 close(fd); // 把数组首地址指过去,此时就指向了第一个端口的第一个寄存器 ports = (port_t *)(map_addr + offset); return 0; } // 辅助函数,检查参数,如果合法就找到对应的端口 static port_t *check_and_get_gpio(char port, int pin) { // 避免未初始化 if (ports == 0) { printf("not inited yet!\n"); return 0; } // 得到端口编号 int port_index = port - 'A'; // 检查端口编号 if (port_index < 0 || port_index >= GPIO_MAX_PORT_COUNT) { printf("no such port '%c'!\n", port); return 0; } // 检查引脚编号 if (pin < 0 || pin >= 32) { printf("no such pin '%d'!\n", pin); return 0; } // 返回对应编号的端口 return ports + port_index; } void gpio_set_mode(char port, int pin, int mode) { // 获取端口 port_t *pport = check_and_get_gpio(port, pin); if (pport == 0) { return; } // 指向对应的cfg寄存器;因为每个cfg寄存器可以控制8个引脚,所以是第pin/8个cfg寄存器 uint32_t *cfg = &(pport->cfg[pin / 8]); // 掩码的左移位数 int shift = (pin % 8) * 4; // 把cfg寄存器对应的4位清空 *cfg &= ~(((uint32_t)0x0f) << shift); // 把cfg寄存器对应的4位清空设置为mode的低4位 *cfg |= ((uint32_t)(mode & 0x0f)) << shift; } void gpio_set_value(char port, int pin, int value) { // 获取端口 port_t *pport = check_and_get_gpio(port, pin); if (pport == 0) { return; } // 如果为1,就把那一位置位,否则清0 if (value == 1) { pport->dat |= ((uint32_t)1) << pin; } else { pport->dat &= ~(((uint32_t)1) << pin); } }
-
D1s 通过内存映射方式,直接操作GPIO寄存器,输出速度很慢,如何提高?
D1s, tina linux 系统,通过内存映射方式,直接操作GPIO寄存器,循环写入多个GPIO端口,共计操作671232次,需要225秒时间,平均1秒2983次,速度较慢,有什么解决办法可提高速度?