惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 聂微东
Y
Y Combinator Blog
WordPress大学
WordPress大学
L
LangChain Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
A
About on SuperTechFans
小众软件
小众软件
有赞技术团队
有赞技术团队
S
SegmentFault 最新的问题
宝玉的分享
宝玉的分享
Recent Announcements
Recent Announcements
GbyAI
GbyAI
I
InfoQ
The GitHub Blog
The GitHub Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
酷 壳 – CoolShell
酷 壳 – CoolShell
罗磊的独立博客
C
Check Point Blog
V
V2EX
Apple Machine Learning Research
Apple Machine Learning Research
月光博客
月光博客
量子位
雷峰网
雷峰网
Hugging Face - Blog
Hugging Face - Blog

博客园 - bitwoods

Linux驱动开发:内核模块堆叠(1) Linux驱动开发:内核模块与普通应用的区别 Linux驱动开发:从一个最简单的模块开始 c++ prepareStatement使用like查询语句的方式 glog编译报错解决 阿里云Ubuntu服务器优化 linux c++程序使用MD5 串口AT与数据的混杂接收处理 蓝牙Mesh简介(一)设备标识:UUID和Mesh地址 adblock plus 您的地区不可用 OpenWRT 修改固件默认显示中文 OpenWRT:插件自启动 OpenWRT编译时修改时区与主机名 SC200L Android10启动和关机修改 ILI9881D驱动 ubuntu20.04 微信和迅雷安装包 开启power management功能有坑,ESP32串口频繁出现UART_BREAK中断 MAC地址与字符串的相互转化 ESP32音频开发板ESP32-Korvo V1.1踩坑
MT7621 openWrt插件操作GPIO(mmap)
bitwoods · 2023-02-11 · via 博客园 - bitwoods

OpenWrt 应用中操作GPIO的方式多数都是:

  1. 修改设备树
  2. 通过shell脚本export出对应的GPIO
  3. 通过shell脚本或操作文件的方式控制GPIO/通过LEDE LED配置控制GPIO

不用这种方式的时候,通常按照Linux方式先写驱动,然后在应用/插件中调用驱动程序接口控制GPIO

以上方式的例程和资料网上很容易找,英文阅读没问题的话,直接看官方资料就可以轻松搞定;

最近项目需要在OpenWrt 插件中根据运行情况和指令直接操作GPIO,不想写驱动;参考了网上的资料,没折腾就成功了
这种方式的好处是不用改设备树和写驱动,减少了代码维护的复杂度;用写寄存器的方式控制GPIO,速度应该快点
坏处是对对寄存器不熟悉的新手不太友好

使用基本只需要根据芯片资料修改一下代码中的寄存器相关的宏定义和mmap函数中的offset地址即可;
如果是MTK相关的芯片,直接根据芯片资料修改mmap函数中的offset地址

原代码针对的是MT7628, GPIO BASE ADDRESS 为0x10000600,故offset设为0x10000000,
而MT7621的 GPIO BASE ADDRESS 为0x1E000600,故offset设为0x1e0000000


详细代码请自行查看下方参考代码对应的github项目链接;

下方的代码非原创,完全抄袭,仅修改了函数名(原函数名前有mt7628_)和增加一条注释,
原作者未使用license,若下方代码涉及侵权, 请站内消息联系删除

static int gpio_mmap(void)
{
    if ((gpio_mmap_fd = open(MMAP_PATH, O_RDWR)) < 0) {
        fprintf(stderr, "unable to open mmap file");
        return -1;
    }

    gpio_mmap_reg = (uint8_t*) mmap(NULL, 1024, PROT_READ | PROT_WRITE,
        MAP_FILE | MAP_SHARED, gpio_mmap_fd, 0x1e000000);//MT7628则offset为0x10000000
    if (gpio_mmap_reg == MAP_FAILED) {
        perror("foo");
        fprintf(stderr, "failed to mmap");
        gpio_mmap_reg = NULL;
        close(gpio_mmap_fd);
        return -1;
    }

    return 0;
}

int gpio_get_pin(int pin)
{
    uint32_t tmp = 0;

    /* MT7621, MT7628 */
    if (pin <= 31) {
        tmp = *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIODATA);
        tmp = (tmp >> pin) & 1u;
    } else if (pin <= 63) {
        tmp = *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO6332DATA);
        tmp = (tmp >> (pin-32)) & 1u;
    } else if (pin <= 95) {
        tmp = *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO9564DATA);
        tmp = (tmp >> (pin-64)) & 1u;
        tmp = (tmp >> (pin-24)) & 1u;
    }
    return tmp;

}

void gpio_set_pin_direction(int pin, int is_output)
{
    uint32_t tmp;

    /* MT7621, MT7628 */
    if (pin <= 31) {
        tmp = *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIODIR);
        if (is_output)
            tmp |=  (1u << pin);
        else
            tmp &= ~(1u << pin);
        *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIODIR) = tmp;
    } else if (pin <= 63) {
        tmp = *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO6332DIR);
        if (is_output)
            tmp |=  (1u << (pin-32));
        else
            tmp &= ~(1u << (pin-32));
        *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO6332DIR) = tmp;
    } else if (pin <= 95) {
        tmp = *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO9564DIR);
        if (is_output)
            tmp |=  (1u << (pin-64));
        else
            tmp &= ~(1u << (pin-64));
        *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO9564DIR) = tmp;
    }
}

void gpio_set_pin_value(int pin, int value)
{
    uint32_t tmp;

    /* MT7621, MT7628 */
    if (pin <= 31) {
        tmp = (1u << pin);
        if (value)
            *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIOSET) = tmp;
        else
            *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIORESET) = tmp;
    } else if (pin <= 63) {
        tmp = (1u << (pin-32));
        if (value)
            *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO6332SET) = tmp;
        else
            *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO6332RESET) = tmp;
    } else if (pin <= 95) {
        tmp = (1u << (pin-64));
        if (value)
            *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO9564SET) = tmp;
        else
            *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO9564RESET) = tmp;
    }
}

参考代码:https://github.com/ForgotFun/mt76x8