用到的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);
}
//中断处理函数
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);
}
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