分类: LINUX
2009-11-12 11:12:29
HAL层的含义是硬件抽象层,它是位于Linux操作系统内核(包含驱动)与硬件电路之间的接口层,其目的在于将硬件抽象化。它隐藏了特定平台的硬件接口细节,为操作系统提供虚拟硬件平台,使其具有硬件无关性,可在多种平台上进行移植。 从软硬件测试的角度来看,软硬件的测试工作都可分别基于硬件抽象层来完成,使得软硬件测试工作的并行进行成为可能。
我们之所以要提出这个HAL层是由于现在SEP4020的硬件平台类型很多像EVB系列,MBT系列,MINI4020系列,EPOS系列,这些不同类型的硬件如果想应用我们的SEP4020的SDK,那么我们就要为每套平台移植驱动,因为它们的I/O硬件口线都不一样的,所以我们经过讨论认为HAL层可能是解决这个问题的一个比较好的方法。
我们的HAL层是位于驱动层和硬件层的中间,它本身是把SEP4020的硬件资源,主要是GPIO口和中断抽象出来了,驱动想用硬件资源就只能到HAL层去申请了,所以在HAL层我们能够看到所有的硬件资源的使用情况,下面我们看下HAL在整个linux中的位置:
我们的HAL层由于主要包含两种资源(中断和GPIO),所以我们必须在这里对这两种资源的使用作一个详细说明。
在这里我们将GPIO的使用分成两种类型:第一种是GPIO口单根线的使用,也即bit的操作;第二种是多个bits或整个port的使用,这里我们提供了两组宏来操作两种不同类型,驱动中间是不能直接使用单个和整个port的,只能通过这些宏来操作GPIO的,这样就将他们与具体的硬件分开了。
#define REG32(addr) (*(volatile unsigned int *)(addr))
/*-------------------------- bit operation------------------------*/
#define SET_BIT(port,bit) REG32(port) |= (1 << bit) //对单个bit置位
#define CLR_BIT(port,bit) REG32(port) &= (~(1 << bit)) //对单个bit清零
#define GET_BIT(port,bit) (REG32(port) & (1 << bit)) //获取单个bit的值
/*-----------port or many bit operation------------------------*/
#define SET_PORT_VALUE(port,value,mask) ({unsigned long res_port = REG32(port); REG32(port) = (res_port & (~mask)) | (value & mask); }) //对没有mask的port位赋值value
#define SET_PORT_MASK(port,mask) REG32(port) |= mask //对没有mask的port位置位
#define CLR_PORT_MASK(port,mask) REG32(port) &= (~mask) //对没有mask的port位清零
#define GET_PORT_MASK(port,mask) (REG32(port) & mask) //获取没有mask的port位的值
对于外部中断我们也是统一接管的,驱动想使用也是需要在HAL层申请的,这里涉及到两种操作:第一种:中断的申请和配置;第二种:中断的清除
/*--------------------------EXTERN INTERRUPT----------------------------------------*/
/*---------中断类型定义------------------------------------------------------*/
#define RISING_EDGE_TRIG 0x0
#define FALLING_EDGE_TRIG 0x1
#define HIGHT_LEVEL_TRIG 0x2
#define LOW_LEVEL_TRIG 0x3
/*----------------------------------中断的申请和配置-------------------------------------------------------*/
#define CONFIG_INT(int_num,int_type) \
do{ \
if(int_num == 11){ \
(*(volatile unsigned long*)GPIO_PORTF_SEL_V) |= 0x0001 ;(*(volatile unsigned long*)GPIO_PORTF_DIR_V) |= 0x0001 ; (*(volatile unsigned long*)GPIO_PORTF_INTRCTL_V) |= int_type;(*(volatile unsigned long*)GPIO_PORTF_INCTL_V) |= 0x0001;(*(volatile unsigned long*)GPIO_PORTF_INTRCLR_V) |= 0x0001;(*(volatile unsigned long*)GPIO_PORTF_INTRCLR_V) = 0x0000;}\
else if(int_num < 11){ \
*(volatile unsigned long*)GPIO_PORTA_SEL_V |= 0x1 << (int_num - 1);*(volatile unsigned long*)GPIO_PORTA_DIR_V |= 0x1 << (int_num - 1);*(volatile unsigned long*)GPIO_PORTA_INTRCTL_V |= int_type << ((int_num - 1)*2);*(volatile unsigned long*)GPIO_PORTA_INCTL_V |= 0x1 << (int_num - 1);*(volatile unsigned long*)GPIO_PORTA_INTRCLR_V |= 0x1 << (int_num - 1);*(volatile unsigned long*)GPIO_PORTA_INTRCLR_V = 0x0000;}\
}while(0)
/*--------------------------------------外部中断的清除------------------------------------------*/
#define CLR_INT(int_num) \
do{ \
if(int_num == 11){ \
*(volatile unsigned long*)GPIO_PORTF_INTRCLR_V |= 0x0001;*(volatile unsigned long*)GPIO_PORTF_INTRCLR_V = 0x0000;} \
else if(int_num < 11){ \
*(volatile unsigned long*)GPIO_PORTA_INTRCLR_V |= 0x1 << (int_num - 1);*(volatile unsigned long*)GPIO_PORTA_INTRCLR_V = 0x0000;} \
}while(0)