关于ar9331 gpio调试遇到的问题

小白今天又踩坑,又有一个填坑的经验

源码:

首先介绍一下关键源码的说明,加红色说明是需要注意的地方

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include " gpio_control_app.h"
#include "errno.h"
//static unsigned char gpio_pin;//define GPIOs to be use
static int gpio_dev_fd = -1;;

int mcu_gpio_pin = 12;
int work_gpio_pin = 18;

void mcu_gpio_release(int signal_no)
{

     ioctl(gpio_dev_fd, GPIO_CONTROL_SET_IN, GPIO_IOCTL_PRAM(mcu_gpio_pin, 0));
    //信号量响应,将相应的IO口设置输入
     ioctl(gpio_dev_fd, GPIO_CONTROL_FREE_GPIO, GPIO_IOCTL_PRAM(mcu_gpio_pin, 0));
    //信号量响应,释放相应的IO口资源

      exit(0);
}

void bsp_gpio_init(void)
{
    gpio_dev_fd = open(GPIO_CONTROL_DEVICE_PATH, O_RDWR);//open gpio device
    if (gpio_dev_fd < 0)
    {

        printf("###open %s ERROR###\n", GPIO_CONTROL_DEVICE_PATH);

    }
    else
    {
         printf("***open %s success***\n", GPIO_CONTROL_DEVICE_PATH);
    }

}

int set_work_gpio(void)
{
    int ret = 0;
    if(gpio_dev_fd == -1)
    {
        return -1;
    }
    printf("work_gpio_pin:%d\n", work_gpio_pin);
    ret =ioctl(gpio_dev_fd, GPIO_CONTROL_REQUEST_GPIO, GPIO_IOCTL_PRAM(work_gpio_pin, 0));
    printf("%s\n",strerror(errno));
    printf("set_gpio ret = %d\n",ret);
    if (ret < 0)
    {
       printf("###request GPIO %d error###", work_gpio_pin);
       return -1;
    }
    ret = ioctl(gpio_dev_fd, GPIO_CONTROL_SET_OUT, GPIO_IOCTL_PRAM(work_gpio_pin, 0));
    if (ret < 0)
    {
        printf("###set GPIO %d output error###", work_gpio_pin);
        return -1;   
    }
    return 1;
}

int bsp_work_gpio_ctrl(int gpio_state)
{
    if(gpio_dev_fd == -1)
    {
       return -1;
    }
    if(gpio_state == 0)
    {

      ioctl(gpio_dev_fd, GPIO_CONTROL_SET_VALUE, GPIO_IOCTL_PRAM(work_gpio_pin, 0));
      printf("###set work_gpio low ###\r\n");
    }
    else
    {
       ioctl(gpio_dev_fd, GPIO_CONTROL_SET_VALUE, GPIO_IOCTL_PRAM(work_gpio_pin, 1));
       printf("###set work_gpio high ###\r\n");
    }
    return 0;
}
int set_mcu_gpio(void)
{

    int ret;
    if(gpio_dev_fd == -1)
    {
       return -1;
    }
    printf("mcu_gpio_pin:%d\n", mcu_gpio_pin);
    ret = ioctl(gpio_dev_fd, GPIO_CONTROL_REQUEST_GPIO, GPIO_IOCTL_PRAM(mcu_gpio_pin, 0));
    printf("bsp_mcu_gpio_ctrl ret = %d\n",ret);
    if (ret < 0)
    {
      printf("###request GPIO %d error###\n", mcu_gpio_pin);
      return -1;
    }
    ret = ioctl(gpio_dev_fd, GPIO_CONTROL_SET_OUT, GPIO_IOCTL_PRAM(mcu_gpio_pin, 0));
    if (ret < 0)
    {
      printf("###set GPIO %d output error###", mcu_gpio_pin);
      return -1;   
    }
    return 1;
}

int bsp_mcu_gpio_ctrl(void)
{

    signal(SIGINT, mcu_gpio_release);//register terminal signa    注册相应的信号量
    ioctl(gpio_dev_fd, GPIO_CONTROL_SET_VALUE, GPIO_IOCTL_PRAM(mcu_gpio_pin, 0));
    printf("### mcu_gpio_pin high###\r\n");
    return 0;

}

int main(int argc, char *argv[])
{
    bsp_gpio_init();
    set_work_gpio();
    set_mcu_gpio();
    bsp_mcu_gpio_ctrl();
    while(1)
    {
      bsp_work_gpio_ctrl(1);
      sleep(1);
      bsp_work_gpio_ctrl(0);
      sleep(1);
    }
 return 1;

}

 

代码中先通过GPIO_CONTROL_REQUEST_GPIO取得了相应的gpio的资源,

在终端输入ctrl+c 释放相应的gpio的资源:

遇到的问题:

下次代码运行的时候,无法重新设置相应的IO

 

调试方法:

在虚拟机中

步骤一

修改gpio_control_driver.c

进入相应的驱动目录:

~/lede_AR9331_zhuotk_source_32bit/package/kernel/gpio_control_driver/src$

打开gpio_control_driver.c

GPIO_CONTROL_REQUEST_GPIO下的打印信息打开

 

 make menuconfig 进行选择

重新进行make V=s编译

找到生成的.ko文件

~/lede_AR9331_zhuotk_source_32bit/build_dir/target-mips_24kc_musl/linux-ar71xx_generic/gpio_control_driver$

gpio_control_driver.ko为新生成的驱动

步骤二

在开发板中

进入开发板的命令行终端:

首先卸载掉以前的驱动

原有的驱动程序加载模块在目录

root@AOTUO:/lib/modules/4.4.79#

输入命令行:rmmod  gpio_control_driver.ko

 

将新生成的驱动传输到当前目录

 

输入命令行:insmod gpio_control_driver.ko

 

重新加入驱动模块

 

步骤三

在命令行终端运行相应的app程序,

 

 

发现错误信息打印,request GPIO 18 error

 

进入内核日志,查看打印信息

 

 

发现驱动中的打印GPIO_CONTROL_REQUEST_GPIO 返回值为-16

 

解决问题:

Linux中调用gpio_request申请一个GPIO时返回错误码-16,原因是前面已经用gpio_request对同一个GPIO做了申请操作。可以把前面的GPIO用gpio_free先释放再改作它用。

这是因为ctrl+c信号量那边只释放了一个IO口的资源,另一个没有进行释放。下次调用的时候会出现调用失败的情况

一般来说,一个GPIO只是分配给一个设备的,所以这个设备的驱动会请求这个GPIO。这样,在其他的设备也想请求这个GPIO的时候会返回失败。事实上,gpio_request只是给这个GPIO做一个标示,并没有什么实质的作用。操作GPIO是通过gpio_set_value、gpio_direction_output之类的函数去做的,即便没有request,一样可以设置GPIO的电平。

 

结束进程的时候,将相应的io口资源进行释放

后记:

一个实用的命令

   find –iname  文件名                   //查找

实用的快捷键

在命令行终端

Ctrl+shirt+n                             //多窗口

下面这一篇是关于led驱动的开发应用流程,可以作为参考

https://www.jianshu.com/p/e5ffb5ecbf39

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值