[海思] 中断申请和重启问题

背景

  • 海思的硬件复位RSTN复位后无法启动,目前确定不了问题出在哪里

  • 另一方案:通过内核捕获gpio的中断后将整个系统复位,即软复位

基本代码框架

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/fs.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/device.h>
#include <linux/miscdevice.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <asm/irq.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/reboot.h>

struct st_gpio_int {
    int int_irq;//中断号
    int int_pin;//中断寄存器
    int int_num;//中断编号
    char *int_name;//中断名称
};

#define ARRY_SIZE(A) 			(sizeof(A)/sizeof(A[0]))
#define GPIO_INT_READ			_IOR('L', 0x03, char [4])
#define HI3531D_GPIO23_0		93
#define REG_WRITE(addr, value)	((*(volatile unsigned int *)(addr)) = (value))
#define REG_READ(Addr)			(*(volatile unsigned int *)(Addr))

#define GPIO_23_BASE		    0x122C0000
#define GPIO_23_DIR				IO_ADDRESS(GPIO_23_BASE + 0x400)//GPIO 方向控制寄存器
#define GPIO_23_IS				IO_ADDRESS(GPIO_23_BASE + 0x404)//GPIO 中断触发寄存器
#define GPIO_23_IEV				IO_ADDRESS(GPIO_23_BASE + 0x40C)//GPIO 触发中断条件寄存器
#define GPIO_23_IC				IO_ADDRESS(GPIO_23_BASE + 0x41C)//GPIO 中断清除寄存器
#define GPIO_23_IE				IO_ADDRESS(GPIO_23_BASE + 0x410)//GPIO 中断屏蔽寄存器
#define GPIO_23_RIS				IO_ADDRESS(GPIO_23_BASE + 0x414)//GPIO 原始中断状态寄存器

static const struct st_gpio_int gpio_reboot[] = {
        {HI3531D_GPIO23_0, 23, 0,"GPIO23_0_INT"},
};

static void hi3531d_pin_cfg(void)
{
        unsigned char regvalue;

      //GPIO23_0
       /*配置作为普通输入 in=0 out=1 */
	regvalue = REG_READ(GPIO_23_DIR);
	regvalue &= ~(1<<0);
	REG_WRITE(GPIO_23_DIR, regvalue);
	
        /*GPIO4_7 管脚中断配置*/
	regvalue = REG_READ(GPIO_23_IS);/*is=0 边沿触发中断 is=1 电平触发*/
	regvalue |= (1<<0);
	REG_WRITE(GPIO_23_IS, regvalue);

	regvalue = REG_READ(GPIO_23_IEV);/*iev=1 上升沿触发,高电平触发中断 iev=0 下降沿触发,低电平触发中断*/
	regvalue &= ~(1<<0);
	REG_WRITE(GPIO_23_IEV, regvalue);

	regvalue = REG_READ(GPIO_23_IC);/*ic清除中断*/
	regvalue = 0xff;
	REG_WRITE(GPIO_23_IC, regvalue);

	regvalue = REG_READ(GPIO_23_IE);/*ie不屏蔽中断*/
	regvalue |= (1<<0);
	REG_WRITE(GPIO_23_IE, regvalue);
}

/*
 * Describe: gpio23_0 irq function 
 */
static irqreturn_t gpio_reboot_eint(int irq, void *dev_id)
{
        unsigned char regvalue;

        if( HI3531D_GPIO23_0 == irq)
        {
            regvalue = 0xff;
            REG_WRITE(GPIO_23_IC, regvalue);/*ic清除中断*/

            kernel_restart(NULL); //重启
        }
        return IRQ_HANDLED;
}

static int __init irq_init(void)
{
        int ret = -1;
    	
        hi3531d_pin_cfg();


        ret = request_irq(gpio_reboot[0].int_irq, gpio_reboot_eint, IRQF_SHARED ,  //这里为共享中断
                          gpio_reboot[0].int_name, (void *)&gpio_reboot);
        if(ret)
        {
            printk("requtest EINT_%d(%s) failed:%d 
", gpio_reboot[0].int_irq, gpio_reboot[0].int_name, ret);
            goto err_gpio_request;
        }
    	
        printk("success
");
    	
        return 0;

err_gpio_request:

	return ret;
}

static void __exit irq_exit(void) 
{
      free_irq(gpio_reboot[0].int_irq, (void *)&gpio_reboot);
}

module_init(irq_init);
module_exit(irq_exit);

MODULE_LICENSE("GPL");
MODULE_VERSION("v1.0");

问题

  1. 中断申请标志位问题:

    • 申请中断时,使用request_irq,第三个参数为触发的方式,最初用的是IRQF_SHARED | IRQF_TRIGGER_HIGH 的标志位,出现以下问题:

      genirq: Setting trigger mode 8 for irq 93 failed (gic_set_type+0x0/0x90)
      
    • 猜想:应该是同组的其他GPIO也申请中断,并且申请的中断触发情况不同,在海思3531d中,GPIO20 - GPIO23共享一个中断号93

    • 解决方案:中断申请标志改为 IRQF_SHARED

    • 参考链接: https://www.pianshen.com/article/4986305785/

  2. 内核重启指令

    • 应用层直接使用system函数,而内核层没有相关函数,使用的是kernel_restart

      #include <linux/reboot.h>
      kernel_restart(NULL);
      
原文地址:https://www.cnblogs.com/chenj-nry/p/15226007.html