分类: LINUX
2009-11-12 11:13:53
经过上面的介绍,大家应该对HAL层有所了解了,现在我们开始以一个具体的实例来使用它。
在这里我是以5*5键盘为例来说明如何添加键盘的HAL层及以后硬件改变时该怎样修改HAL层。
我们首先要知道键盘需要五根GPIO口和五个外部中断,所以在这里两种资源的使用我们都需要申请,在sep4020_hal.h中我们需要添加的内容如下
/* --------------------------------------------------------------------
* key board interface
键盘原理图示意图,具体请参考各类板的原理图
Col5(PA4) Col4(PA3) Col3(PA2) Col2(PA1) Col1(PA0)
| | | | |
Row5(PD4)-----|------------|-----------|-----------|-----------|---
| | | | |
Row4(PD3) ----|------------|-----------|-----------|-----------|---
| | | | |
Row3(PD2)-----|------------|-----------|-----------|-----------|---
| | | | |
Row2(PD1) ----|------------|-----------|-----------|-----------|---
| | | | |
Row1(PD0) ----|------------|-----------|-----------|-----------|---
* -------------------------------------------------------------------- */
/*---key interrupt define键盘中断的申请----------*/
#define COL1_INT INTSRC_EXTINT0
#define COL2_INT INTSRC_EXTINT1
#define COL3_INT INTSRC_EXTINT2
#define COL4_INT INTSRC_EXTINT3
#define COL5_INT INTSRC_EXTINT4
#define COL_INT_TYPE LOW_LEVEL_TRIG //定义键盘的中断触发类型是低电平触发
/*--------键盘列port端口的申请-----------------------------*/
#define COL_MASK (0x
#define COL_SEL_PORT GPIO_PORTA_SEL_V
#define COL_DIR_PORT GPIO_PORTA_DIR_V
#define COL_DATA_PORT GPIO_PORTA_DATA_V
/*--------键盘列五个bits的申请-----------------------------*/
#define COL1_BIT 0
#define COL1_SEL_PORT GPIO_PORTA_SEL_V
#define COL1_DIR_PORT GPIO_PORTA_DIR_V
#define COL1_DATA_PORT GPIO_PORTA_DATA_V
#define COL2_BIT 1
#define COL2_SEL_PORT GPIO_PORTA_SEL_V
#define COL2_DIR_PORT GPIO_PORTA_DIR_V
#define COL2_DATA_PORT GPIO_PORTA_DATA_V
#define COL3_BIT 2
#define COL3_SEL_PORT GPIO_PORTA_SEL_V
#define COL3_DIR_PORT GPIO_PORTA_DIR_V
#define COL3_DATA_PORT GPIO_PORTA_DATA_V
#define COL4_BIT 3
#define COL4_SEL_PORT GPIO_PORTA_SEL_V
#define COL4_DIR_PORT GPIO_PORTA_DIR_V
#define COL4_DATA_PORT GPIO_PORTA_DATA_V
#define COL5_BIT 4
#define COL5_SEL_PORT GPIO_PORTA_SEL_V
#define COL5_DIR_PORT GPIO_PORTA_DIR_V
#define COL5_DATA_PORT GPIO_PORTA_DATA_V
/*--------------键盘行port的申请-----------------------------*/
#define ROW_MASK ( 0x
#define ROW_SEL_PORT GPIO_PORTD_SEL_V
#define ROW_DIR_PORT GPIO_PORTD_DIR_V
#define ROW_DATA_PORT GPIO_PORTD_DATA_V
/*--------键盘行五个bits的申请-----------------------------*/
#define ROW1_BIT 0
#define ROW1_SEL_PORT GPIO_PORTD_SEL_V
#define ROW1_DIR_PORT GPIO_PORTD_DIR_V
#define ROW1_DATA_PORT GPIO_PORTD_DATA_V
#define ROW2_BIT 1
#define ROW2_SEL_PORT GPIO_PORTD_SEL_V
#define ROW2_DIR_PORT GPIO_PORTD_DIR_V
#define ROW2_DATA_PORT GPIO_PORTD_DATA_V
#define ROW3_BIT 2
#define ROW3_SEL_PORT GPIO_PORTD_SEL_V
#define ROW3_DIR_PORT GPIO_PORTD_DIR_V
#define ROW3_DATA_PORT GPIO_PORTD_DATA_V
#define ROW4_BIT 3
#define ROW4_SEL_PORT GPIO_PORTD_SEL_V
#define ROW4_DIR_PORT GPIO_PORTD_DIR_V
#define ROW4_DATA_PORT GPIO_PORTD_DATA_V
#define ROW5_BIT 4
#define ROW5_SEL_PORT GPIO_PORTD_SEL_V
#define ROW5_DIR_PORT GPIO_PORTD_DIR_V
#define ROW5_DATA_PORT GPIO_PORTD_DATA_V
我们在sep4020_hal.h中定义了键盘相应的资源,在驱动里我们就只能用HAL层的键盘资源,而不能直接去操作4020的IO口寄存器了,也就是说我们要把以前操作GPIO和中断的语句全部换成现在的HAL层的操作宏。这里面我仅举几个例子说明:
(1) 键盘硬件setup函数
static void sep4020_key_setup(void)
{
//关闭键盘中断
maskkey();
SET_PORT_MASK(ROW_SEL_PORT,ROW_MASK);
CLR_PORT_MASK(ROW_DATA_PORT,ROW_MASK);
CLR_PORT_MASK(ROW_DIR_PORT,ROW_MASK);
CONFIG_INT(COL1_INT,COL_INT_TYPE); //FP
CONFIG_INT(COL2_INT,COL_INT_TYPE);
CONFIG_INT(COL3_INT,COL_INT_TYPE);
CONFIG_INT(COL4_INT,COL_INT_TYPE);
CONFIG_INT(COL5_INT,COL_INT_TYPE);
/*
*(volatile unsigned long*)GPIO_PORTD_SEL_V |= 0x
*(volatile unsigned long*)GPIO_PORTD_DIR_V &= (~0x
*(volatile unsigned long*)GPIO_PORTD_DATA_V &= (~0x
*(volatile unsigned long*)GPIO_PORTA_SEL_V |= 0x
*(volatile unsigned long*)GPIO_PORTA_DIR_V |= 0x
*(volatile unsigned long*)GPIO_PORTA_INTRCTL_V |= 0x03ff; //低电平触发
*(volatile unsigned long*)GPIO_PORTA_INCTL_V |= 0x
*(volatile unsigned long*)GPIO_PORTA_INTRCLR_V |= 0x
*(volatile unsigned long*)GPIO_PORTA_INTRCLR_V = 0x0000; //清除中断
*/
//开启键盘中断
unmaskkey();
}
其中蓝色部分是我们以前对GPIO端口寄存器直接操作的,现在全部换成前面黑色的语句来替换。
(2)在键盘中断函数中清中断
static irqreturn_t sep4020_key_irqhandler(int irq, void *dev_id, struct pt_regs *reg)
{
//关闭键盘中断
maskkey();
CLR_INT(irq); //清除相应的外部中断
key_dev->keystatus = KEY_UNSURE;
key_timer.expires = jiffies + KEY_TIMER_DELAY_JUDGE;
add_timer(&key_timer); //启动定时器
//we will turn on the irq in the timer_handler
return IRQ_HANDLED;
}
(3)在行反转时的置位操作
static void write_row(int index, int HighLow) //FP
{
switch (index)
{
case 0:
if (HighLow)
{
SET_BIT(ROW1_DATA_PORT,ROW1_BIT);
}
else
{
CLR_BIT(ROW1_DATA_PORT,ROW1_BIT);
}
break;
case 1:
if (HighLow)
{
SET_BIT(ROW2_DATA_PORT,ROW2_BIT);
}
else
{
CLR_BIT(ROW2_DATA_PORT,ROW2_BIT);
}
break;
case 2:
if (HighLow)
{
SET_BIT(ROW3_DATA_PORT,ROW3_BIT);
}
else
{
CLR_BIT(ROW3_DATA_PORT,ROW3_BIT);
}
break;
case 3:
if (HighLow)
{
SET_BIT(ROW4_DATA_PORT,ROW4_BIT);
}
else
{
CLR_BIT(ROW4_DATA_PORT,ROW4_BIT);
}
break;
case 4:
if (HighLow)
{
SET_BIT(ROW5_DATA_PORT,ROW5_BIT);
}
else
{
CLR_BIT(ROW5_DATA_PORT,ROW5_BIT);
}
break;
default:
break;
}
}
可以看出这个中间没有对硬件寄存器的直接操作,全部是通过HAL层的宏来操作的
其他的实例就不一一讲述了,大家现在可以根据自己的需要将驱动中涉及到这两种资源的操作全部替换下。
前面讲述了HAL层的建立了,现在若硬件平台发生了改变现在就能很方便通过更改HAL层的相关硬件定义就鞥完成整个驱动的移植了,再也用不着把所有的驱动统统修改一遍了。
比如键盘的口线现在改变了,我们需要更改的东西只有sep4020_hal.h文件下面这么多内容
/* --------------------------------------------------------------------
* key board interface
键盘原理图示意图,具体请参考各类板的原理图
Col5(PA4) Col4(PA3) Col3(PA2) Col2(PA1) Col1(PA0)
| | | | |
Row5(PD4)-----|------------|-----------|-----------|-----------|---
| | | | |
Row4(PD3) ----|------------|-----------|-----------|-----------|---
| | | | |
Row3(PD2)-----|------------|-----------|-----------|-----------|---
| | | | |
Row2(PD1) ----|------------|-----------|-----------|-----------|---
| | | | |
Row1(PD0) ----|------------|-----------|-----------|-----------|---
* -------------------------------------------------------------------- */
/*---key interrupt define键盘中断的申请----------*/
#define COL1_INT INTSRC_EXTINT0
#define COL2_INT INTSRC_EXTINT1
#define COL3_INT INTSRC_EXTINT2
#define COL4_INT INTSRC_EXTINT3
#define COL5_INT INTSRC_EXTINT4
#define COL_INT_TYPE LOW_LEVEL_TRIG //定义键盘的中断触发类型是低电平触发
/*--------键盘列port端口的申请-----------------------------*/
#define COL_MASK (0x
#define COL_SEL_PORT GPIO_PORTA_SEL_V
#define COL_DIR_PORT GPIO_PORTA_DIR_V
#define COL_DATA_PORT GPIO_PORTA_DATA_V
/*--------键盘列五个bits的申请-----------------------------*/
#define COL1_BIT 0
#define COL1_SEL_PORT GPIO_PORTA_SEL_V
#define COL1_DIR_PORT GPIO_PORTA_DIR_V
#define COL1_DATA_PORT GPIO_PORTA_DATA_V
#define COL2_BIT 1
#define COL2_SEL_PORT GPIO_PORTA_SEL_V
#define COL2_DIR_PORT GPIO_PORTA_DIR_V
#define COL2_DATA_PORT GPIO_PORTA_DATA_V
#define COL3_BIT 2
#define COL3_SEL_PORT GPIO_PORTA_SEL_V
#define COL3_DIR_PORT GPIO_PORTA_DIR_V
#define COL3_DATA_PORT GPIO_PORTA_DATA_V
#define COL4_BIT 3
#define COL4_SEL_PORT GPIO_PORTA_SEL_V
#define COL4_DIR_PORT GPIO_PORTA_DIR_V
#define COL4_DATA_PORT GPIO_PORTA_DATA_V
#define COL5_BIT 4
#define COL5_SEL_PORT GPIO_PORTA_SEL_V
#define COL5_DIR_PORT GPIO_PORTA_DIR_V
#define COL5_DATA_PORT GPIO_PORTA_DATA_V
/*--------------键盘行port的申请-----------------------------*/
#define ROW_MASK ( 0x
#define ROW_SEL_PORT GPIO_PORTD_SEL_V
#define ROW_DIR_PORT GPIO_PORTD_DIR_V
#define ROW_DATA_PORT GPIO_PORTD_DATA_V
/*--------键盘行五个bits的申请-----------------------------*/
#define ROW1_BIT 0
#define ROW1_SEL_PORT GPIO_PORTD_SEL_V
#define ROW1_DIR_PORT GPIO_PORTD_DIR_V
#define ROW1_DATA_PORT GPIO_PORTD_DATA_V
#define ROW2_BIT 1
#define ROW2_SEL_PORT GPIO_PORTD_SEL_V
#define ROW2_DIR_PORT GPIO_PORTD_DIR_V
#define ROW2_DATA_PORT GPIO_PORTD_DATA_V
#define ROW3_BIT 2
#define ROW3_SEL_PORT GPIO_PORTD_SEL_V
#define ROW3_DIR_PORT GPIO_PORTD_DIR_V
#define ROW3_DATA_PORT GPIO_PORTD_DATA_V
#define ROW4_BIT 3
#define ROW4_SEL_PORT GPIO_PORTD_SEL_V
#define ROW4_DIR_PORT GPIO_PORTD_DIR_V
#define ROW4_DATA_PORT GPIO_PORTD_DATA_V
#define ROW5_BIT 4
#define ROW5_SEL_PORT GPIO_PORTD_SEL_V
#define ROW5_DIR_PORT GPIO_PORTD_DIR_V
#define ROW5_DATA_PORT GPIO_PORTD_DATA_V
通过改变上面的内容我们就能将键盘移植到了新的平台上了。