openwrt的GPIO控制

摘要:
为什么有些GPIO可以在/sys/class/gpio中控制,而有些不行呢?/*EnableGPIO15andGPIO16andpossiblyGPIO26andGPIO27*/ath79_gpio_function_disable;现象:当屏蔽掉上面两行之后,我的使用了GPIO15的程序就出错了!所以这个函数是使能某GPIO口的意思。而上面我们的函数是ath79_gpio_function_disable,意思就是不把这两个GPIO作为以太网交换机的LED使用,因而后面它可以被用作普通的GPIO口了!上面这个寄存器的名字叫做GPIO_FUNCTION_1,其地址是0x18040028,reset值为0x00,因而开机的时候它都是GPIO口功能的。

为什么有些GPIO可以在/sys/class/gpio中控制,而有些不行呢?

先来看一看普通不需要C程序而是使用脚本的控制方法(Linux普遍适用):

First step is making GPIO available inLinux:

echo "29" > /sys/class/gpio/export

then you need to decide ifit will be input or output, as we will use it as a switch so we need output

echo "out" > /sys/class/gpio/gpio29/direction

and last line turns GPIO on or off with 1 or 0:

echo "1" > /sys/class/gpio/gpio29/value

ath79_gpio_function_disable这个函数的作用是?

/*Enable GPIO15 and GPIO16 and possibly GPIO26 and GPIO27 */ath79_gpio_function_disable(AR933X_GPIO_FUNC_ETH_SWITCH_LED2_EN |AR933X_GPIO_FUNC_ETH_SWITCH_LED3_EN);

现象:当屏蔽掉上面两行之后,我的使用了GPIO15的程序就出错了!所以这个函数是使能某GPIO口的意思。

ath79_gpio_function_xxx在哪里定义?

ath79/gpio.c:159:void ath79_gpio_function_setup(u32 set, u32 clear)
ath79/gpio.c:173:void ath79_gpio_function_enable(u32 mask)
ath79/gpio.c:175:    ath79_gpio_function_setup(mask, 0);
ath79/gpio.c:178:void ath79_gpio_function_disable(u32 mask)
ath79/gpio.c:180:    ath79_gpio_function_setup(0, mask);

我们先看一下AR9331的数据手册,关于GPIO15和GPIO16:

openwrt的GPIO控制第1张

当BIT(5),也就是AR933X_GPIO_FUNC_ETH_SWITCH_LED2_EN为1时,GPIO_15会作为以太网交换机的LED使用。而上面我们的函数是ath79_gpio_function_disable,意思就是不把这两个GPIO作为以太网交换机的LED使用,因而后面它可以被用作普通的GPIO口了!

上面这个寄存器的名字叫做GPIO_FUNCTION_1,其地址是0x18040028,reset值为0x00,因而开机的时候它都是GPIO口功能的。

这个寄存器的一小部分定义在openwrt1407/target/linux/ar71xx/image/lzma-loader/src/ar71xx_regs.h,摘抄其中相关的一些宏定义:

#define AR933X_GPIO_FUNC_SPDIF2TCK        BIT(31)
#define AR933X_GPIO_FUNC_SPDIF_EN        BIT(30)
#define AR933X_GPIO_FUNC_I2SO_22_18_EN        BIT(29)
#define AR933X_GPIO_FUNC_I2S_MCK_EN        BIT(27)
#define AR933X_GPIO_FUNC_I2SO_EN        BIT(26)
#define AR933X_GPIO_FUNC_ETH_SWITCH_LED_DUPL    BIT(25)
#define AR933X_GPIO_FUNC_ETH_SWITCH_LED_COLL    BIT(24)
#define AR933X_GPIO_FUNC_ETH_SWITCH_LED_ACT    BIT(23)
#define AR933X_GPIO_FUNC_SPI_EN            BIT(18)
#define AR933X_GPIO_FUNC_SPI_CS_EN2        BIT(14)
#define AR933X_GPIO_FUNC_SPI_CS_EN1        BIT(13)
#define AR933X_GPIO_FUNC_ETH_SWITCH_LED4_EN    BIT(7)
#define AR933X_GPIO_FUNC_ETH_SWITCH_LED3_EN    BIT(6)
#define AR933X_GPIO_FUNC_ETH_SWITCH_LED2_EN    BIT(5)
#define AR933X_GPIO_FUNC_ETH_SWITCH_LED1_EN    BIT(4)
#define AR933X_GPIO_FUNC_ETH_SWITCH_LED0_EN    BIT(3)
#define AR933X_GPIO_FUNC_UART_RTS_CTS_EN    BIT(2)
#define AR933X_GPIO_FUNC_UART_EN        BIT(1)
#define AR933X_GPIO_FUNC_JTAG_DISABLE        BIT(0)

经查找,在~../linux-3-10-49/arch/mips/dev-common.c中有一个对UART的IO口配置工作:

void __init ath79_register_uart(void)
{
    struct clk *clk;

    clk = clk_get(NULL, "uart");
    if(IS_ERR(clk))
        panic("unable to get UART clock, err=%ld", PTR_ERR(clk));

    if(soc_is_ar71xx())
        ath79_gpio_function_enable(AR71XX_GPIO_FUNC_UART_EN);
    else if(soc_is_ar724x())
        ath79_gpio_function_enable(AR724X_GPIO_FUNC_UART_EN);
    else if(soc_is_ar913x())
        ath79_gpio_function_enable(AR913X_GPIO_FUNC_UART_EN);
    else if(soc_is_ar933x())
        ath79_gpio_function_enable(AR933X_GPIO_FUNC_UART_EN);

    if (soc_is_ar71xx() ||soc_is_ar724x() ||soc_is_ar913x() ||soc_is_ar934x() ||soc_is_qca953x() ||soc_is_qca955x()) {
        ath79_uart_data[0].uartclk =clk_get_rate(clk);
        platform_device_register(&ath79_uart_device);
    } else if(soc_is_ar933x()) {
        ar933x_uart_data.uartclk =clk_get_rate(clk);
        platform_device_register(&ar933x_uart_device);
    } else{
        BUG();
    }
}

免责声明:文章转载自《openwrt的GPIO控制》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇创建telegram 机器人 并发送消息Yaffs2根文件系统制作下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

PCI规范学习笔记

以前看过一段时间Cyclone FPGA控制PEX8111的程序,没看懂,最近又结合PCI规范重新看了一下。 PCI Speci rev2.3    FRAME# is driven by the master to indicate the beginning and end of a transaction.   IRDY# is driven by...

openwrt 18.06 支持 qmi和AT

参考链接:  https://openwrt.org/docs/guide-user/network/wan/wwan/ltedongle 在/etc/config/network下进行配置加上 config interface 'wan' option device '/dev/cdc-wdm0' option proto 'qmi' option if...

Linux设备树语法详解

Linux内核从3.x开始引入设备树的概念,用于实现驱动代码与设备信息相分离。在设备树出现以前,所有关于设备的具体信息都要写在驱动里,一旦外围设备变化,驱动代码就要重写。引入了设备树之后,驱动代码只负责处理驱动的逻辑,而关于设备的具体信息存放到设备树文件中,这样,如果只是硬件接口信息的变化而没有驱动逻辑的变化,驱动开发者只需要修改设备树文件信息,不需要改写...

Micro:bit第一集——打造一颗闪烁的心

一. 如何登陆 Micro:bit : 登录Micro:bit网站makecode.microbit.org,显示如下:   二. 打造一颗闪烁的心: 1.拖入无限循环 2.显示图标(爱心) 3.等待100毫秒 4.拖入小爱心 5. 起名为“Smile”,保存文件。完成!  三.AB键图标 1.当A键按下时,显示爱心   2.当B键按下时,显...

【资料】2021年最网红的FPGA开发板之一——DE10-Nano (SOC FPGA入门推荐!)

DE10-Nano开发板可谓2021年最网红的FPGA开发板之一,除了广泛用于物联网,边缘计算,硬件加速,AI 和 EDA教育课程外,还有不少发烧友将其用于网络上日渐风靡的开源复古游戏项目——Mister。可谓是跨越了学术界,工业界,科研界,无所不及。 友晶科技对板子提供的技术支持也是十分给力,不仅24小时官方邮件答复, 论坛值守,还不断不断的开发出配套...

μC/OS-III---I笔记8---事件标志

   当任务需要同步时可以使用信号量。A任务给B任务发送消息后B任务才能继续运行。如果需要A任务给任务B传递数据的时候就可以采用消息队列。但对于繁杂任务的同步,比如多个时间发生以后执行一个事件,或者是C任务需要任务A和任务B都完成对应的处理任务后才能执行C任务的处理工作,这是用信号量就是等待多个内核对象,有没有一种更好的办法呢,操作系统的大神就创造出了时间...