调试MT7688的GPIO:输出、输入(中断)

用到的GPIO如下:

GPIO#11,名称为GPIO0,连接beep用于输出。

GPIO#36,名称为PERST_N,连接到开发板的reset button,用于输入(irq模式)

1、BEEP控制(GPIO#11)

参考手册可知应该进行如下操作:

a.首先要把GPIO_CTRL_0(0x600)寄存器的bit11设置为1,即代表把GPIO#11设置为GPIO output mode.

b.然后通过GPIO_DSET_0(0x630)和GPIO_DCLR_0(0x640)来控制输出高电平或低电平:

  对GPIO_DSET_0的bit11写1,数据输出寄存器置高,输出高电平,beep off

  对GPIO_DCLR_0的bit11写1,数据输出寄存器清零,输出低电平,beep on


2、通过按键触发外部中断(GPIO#36)

a.首先把GPIO#36设置为输入模式:GPIO_CTRL_1(0x604)的bit4设置为0,GPIO input mode;

b.使能falling edge interrupt:GINT_FEDGE_1(0x664)的bit4设置为1,Enable falling edge triggered;

c.注意:在中断服务器程序中,应当清除中断标志位,并需要重新使能下降沿中断,具体操作如下:

  i.清除中断标志位:GINT_STAT_1(0x694)的bit4写入1(手册中写了W1C,即write 1 to clear)

  ii.重新使能下降沿中断:GINT_FEDGE_1(0x664)的bit4设置为1


部分代码如下:

头文件包含:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 
#include 
#include 
#include 

#include 
#include 

#include 
#include   
#include		/* for gpio_to_irq */
设置GPIO#11的方向寄存器:

// gpio#11
static void my_gpio_set_direction(u32 dir)
{
	u32 mode;
	u32 reg;
	
	if(dir)
	{
		reg = 0x600;		
		mode = rt_sysc_r32(reg);
		mode = mode & 0xFFFFF7FF;
		mode = mode | 0x00000800;

		// 1:output
		rt_sysc_w32(mode, reg);
	}
	else
	{
		reg = 0x600;		
		mode = rt_sysc_r32(reg);
		mode = mode & 0xFFFFF7FF;
		// 0:input
		rt_sysc_w32(mode, reg);
	}
}
设置GPIO#11的数据寄存器:

static void my_gpio_set_value(u32 val)
{
	u32 mode;
	u32 reg;

	if(val)
	{
			
		reg = 0x630;	//DSET	
		mode = rt_sysc_r32(reg);
		mode = mode & 0xFFFFF7FF;
		mode = mode | 0x00000800;

		// 1 --> set	
		rt_sysc_w32(mode, reg);
	}
	else
	{
		reg = 0x640;	//DCLR	
		mode = rt_sysc_r32(reg);
		mode = mode & 0xFFFFF7FF;
		mode = mode | 0x00000800;
		// 1 --> clear	
		rt_sysc_w32(mode, reg);
	}
}
GPIO#36中断初始化:

static void my_irq_init(void)
{
	int irq_no;	
	int iRet;

	irq_no  = gpio_to_irq(GPIO_PIN_RST);//GPIO_PIN_RST=36
	//申请中断并设置中断处理函数	
	iRet = request_irq(irq_no, buttons_irq, IRQF_DISABLED, "gpio_int", NULL);	
	if (iRet != 0)
	{		
		printk("request irq failed!! ret: %d  irq:%d gpio:%d  \n", iRet, irq_no, GPIO_PIN_RST);	
		return -EBUSY;	
	}
	else
	{
		//input
		my_gpio_set_direction_RST(0);
		//set pin to high
		my_gpio_set_value_RST(1);

		//enable interrupt
		my_enable_rst_button_interrupt();
	}
}

GPIO#36,中断使能,中断关闭,清除中断标志位等操作:

static void my_enable_rst_button_interrupt(void)
{
	u32 mode;
	
	//Falling Edge Interrupt
	mode = rt_sysc_r32(0x664);
	mode = mode | 0x00000010;
	// 1 --> enabled
	rt_sysc_w32(mode, 0x664);
}

static void my_disable_rst_button_interrupt(void)
{
	u32 mode;
	
	//Falling Edge Interrupt
	mode = rt_sysc_r32(0x664);
	mode = mode & 0xFFFFFFF7;
	// 0 --> disable
	rt_sysc_w32(mode, 0x664);
}


static void my_clear_rst_button_interrupt(void)
{
	u32 mode;
	mode = rt_sysc_r32(0x694);	//interrupt status reg
	mode = mode | 0x00000010;	// write 1 to clear;		
	rt_sysc_w32(mode, 0x694);
}

GPIO#36中断服务程序:

//中断处理函数
static irqreturn_t buttons_irq(int irq, void *dev_id)
{	
	my_clear_rst_button_interrupt();
	printk("rst button irq triggered, irq=%d\n",irq);

	//must re-enable interrupt.
	my_enable_rst_button_interrupt();
	return IRQ_RETVAL(IRQ_HANDLED);
}

最后,Makefile:

KERNELDIR=/work/openwrt/build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/linux-ramips_mt7688/linux-3.18.45
PWD:=$(shell pwd)
INSTALLDIR=/work/dev/drivers
TOOLCHAIN="/work/openwrt/staging_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mipsel-openwrt-linux-"
obj-m:=hello.o
.PHONY:modules modules_install clean
modules:
	#$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
	make -C $(KERNELDIR) ARCH=mips CROSS_COMPILE=$(TOOLCHAIN) M=$(PWD) modules
modules_install:
	cp hello.ko $(INSTALLDIR)
clean:
	rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

备注,dts文件位于:

/work/openwrt/target/linux/ramips/dts






你可能感兴趣的:(Linux)