看名字是初始化一些硬件驱动,里面全都是调用一些子函数来实现,包括TIMER、ADC、DMA、FLASH等等,如下
void HalDriverInit (void) { /* TIMER */ #if (defined HAL_TIMER) && (HAL_TIMER == TRUE) HalTimerInit(); #endif /* ADC */ #if (defined HAL_ADC) && (HAL_ADC == TRUE) HalAdcInit(); #endif /* DMA */ #if (defined HAL_DMA) && (HAL_DMA == TRUE) // Must be called before the init call to any module that uses DMA. HalDmaInit(); #endif /* Flash */ #if (defined HAL_FLASH) && (HAL_FLASH == TRUE) // Must be called before the init call to any module that uses Flash access or NV. HalFlashInit(); #endif /* AES */ #if (defined HAL_AES) && (HAL_AES == TRUE) HalAesInit(); #endif /* LED */ #if (defined HAL_LED) && (HAL_LED == TRUE) HalLedInit(); #endif /* UART */ #if (defined HAL_UART) && (HAL_UART == TRUE) HalUARTInit(); #endif /* KEY */ #if (defined HAL_KEY) && (HAL_KEY == TRUE) HalKeyInit(); #endif /* SPI */ #if (defined HAL_SPI) && (HAL_SPI == TRUE) HalSpiInit(); #endif /* LCD */ #if (defined HAL_LCD) && (HAL_LCD == TRUE) HalLcdInit(); #endif }
/* Set to TRUE enable H/W TIMER usage, FALSE disable it */ #ifndef HAL_TIMER #define HAL_TIMER FALSE #endif /* Set to TRUE enable ADC usage, FALSE disable it */ #ifndef HAL_ADC #define HAL_ADC TRUE #endif /* Set to TRUE enable DMA usage, FALSE disable it */ #ifndef HAL_DMA #define HAL_DMA TRUE #endif /* Set to TRUE enable Flash access, FALSE disable it */ #ifndef HAL_FLASH #define HAL_FLASH TRUE #endif /* Set to TRUE enable AES usage, FALSE disable it */ #ifndef HAL_AES #define HAL_AES TRUE #endif #ifndef HAL_AES_DMA #define HAL_AES_DMA TRUE #endif /* Set to TRUE enable LCD usage, FALSE disable it */ #ifndef HAL_LCD #define HAL_LCD TRUE #endif /* Set to TRUE enable LED usage, FALSE disable it */ #ifndef HAL_LED #define HAL_LED TRUE #endif #if (!defined BLINK_LEDS) && (HAL_LED == TRUE) #define BLINK_LEDS #endif /* Set to TRUE enable KEY usage, FALSE disable it */ #ifndef HAL_KEY #define HAL_KEY TRUE #endif /* Set to TRUE enable UART usage, FALSE disable it */ #ifndef HAL_UART #if (defined ZAPP_P1) || (defined ZAPP_P2) || (defined ZTOOL_P1) || (defined ZTOOL_P2) #define HAL_UART TRUE #else #define HAL_UART FALSE #endif #endif
void HalTimerInit (void) { T1CCTL0 = 0; /* Make sure interrupts are disabled */ T1CCTL1 = 0; /* Make sure interrupts are disabled */ T1CCTL2 = 0; /* Make sure interrupts are disabled */ T3CCTL0 = 0; /* Make sure interrupts are disabled */ T3CCTL1 = 0; /* Make sure interrupts are disabled */ T4CCTL0 = 0; /* Make sure interrupts are disabled */ T4CCTL1 = 0; /* Make sure interrupts are disabled */ /* Setup prescale & clock for timer0 */ halTimerRecord[HW_TIMER_1].prescale = HAL_TIMER1_16_PRESCALE; halTimerRecord[HW_TIMER_1].clock = HAL_TIMER_32MHZ; halTimerRecord[HW_TIMER_1].prescaleVal = HAL_TIMER1_16_PRESCALE_VAL; /* Setup prescale & clock for timer2 */ halTimerRecord[HW_TIMER_3].prescale = HAL_TIMER3_8_PRESCALE; halTimerRecord[HW_TIMER_3].clock = HAL_TIMER_32MHZ; halTimerRecord[HW_TIMER_3].prescaleVal = HAL_TIMER3_8_PRESCALE_VAL; /* Setup prescale & clock for timer3 */ halTimerRecord[HW_TIMER_4].prescale = HAL_TIMER4_8_PRESCALE; halTimerRecord[HW_TIMER_4].clock = HAL_TIMER_32MHZ; halTimerRecord[HW_TIMER_4].prescaleVal = HAL_TIMER4_8_PRESCALE_VAL; /* Setup Timer1 Channel structure */ halTimerChannel[HW_TIMER_1].TxCCTL = TCHN_T1CCTL; halTimerChannel[HW_TIMER_1].TxCCL = TCHN_T1CCL; halTimerChannel[HW_TIMER_1].TxCCH = TCHN_T1CCH; halTimerChannel[HW_TIMER_1].TxOVF = TCNH_T1OVF; halTimerChannel[HW_TIMER_1].ovfbit = TCHN_T1OVFBIT; halTimerChannel[HW_TIMER_1].intbit = TCHN_T1INTBIT; …… }
#define HW_TIMER_1 0x00 #define HW_TIMER_3 0x01 #define HW_TIMER_4 0x02 #define HW_TIMER_INVALID 0x03 #define HW_TIMER_MAX 0x03 #define HAL_TIMER1_16_PRESCALE HAL_TIMER1_16_TC_DIV128 #define HAL_TIMER1_16_PRESCALE_VAL 128 #define HAL_TIMER3_8_PRESCALE HAL_TIMER34_8_TC_DIV128 #define HAL_TIMER3_8_PRESCALE_VAL 128 #define HAL_TIMER4_8_PRESCALE HAL_TIMER34_8_TC_DIV128 #define HAL_TIMER4_8_PRESCALE_VAL 128 #define HAL_TIMER1_16_TC_DIV128 0x0c /* Clock pre-scaled by 128 */ #define HAL_TIMER34_8_TC_DIV128 0xE0 /* Clock pre-scaled by 128 */ /* Clock settings */ #define HAL_TIMER_16MHZ 16 #define HAL_TIMER_32MHZ 32 /* Default all timers to use channel 0 */ #define TCHN_T1CCTL &(X_T1CCTL0) #define TCHN_T1CCL &(X_T1CC0L) #define TCHN_T1CCH &(X_T1CC0H) #define TCNH_T1OVF &(X_TIMIF) #define TCHN_T1OVFBIT TIMIF_T1OVFIM #define TCHN_T1INTBIT IEN1_T1IE
typedef struct { bool configured; bool intEnable; uint8 opMode; uint8 channel; uint8 channelMode; uint8 prescale; uint8 prescaleVal; uint8 clock; halTimerCBack_t callBackFunc; } halTimerSettings_t; typedef struct { uint8 volatile XDATA *TxCCTL; uint8 volatile XDATA *TxCCH; uint8 volatile XDATA *TxCCL; uint8 volatile XDATA *TxOVF; uint8 ovfbit; uint8 intbit; } halTimerChannel_t; /********************************************************************* * GLOBAL VARIABLES */ static halTimerSettings_t halTimerRecord[HW_TIMER_MAX]; static halTimerChannel_t halTimerChannel[HW_TIMER_MAX];
T1CNTH和T1CNTL没啥可说的,保存16位计数值,T1CCnH和T1CCnL是保存通道的捕获/比较16位数值,T1CTL是定时器1的控制寄存器,T1STAT是定时器1的状态寄存器如下
T1CTL管理定时器的分频以及工作模式,T1STAT是一些中断标志位,T1CCTLn是各个通道的捕获/比较控制器,在这里是一个重要的寄存器,T3CTL分频占了3位略微有点区别。
该寄存器配置通道的使能、模式选择(比较模式还是捕获模式),模式的控制(两个模式的配置),寄存器一目了然,看代码才是王道,首先是屏蔽通道中断,然后配置时钟分频器,对于定时器1来说取得值是0x0c,对比与T1CTL来说就是128分频,而后设置适中源32MHz,对于prescaleVal目前还不清楚是做啥子的,赋值为128,定时器3和定时器4也是128分频,时钟源是32MHz,但这只是为这个结构体赋值了,并没有对具体的寄存器赋值还。接着是设置定时器通道结构体,默认都是通道0,这里用到了两个寄存器如下
都是一些中断标志位,这段代码里就将结构体与寄存器联系在一起了,他的定义用的是寄存器。HalTimerInit()函数只是一些定时器的配置,也没有啥是性质东西,不过那两个结构体要搞清楚方便管理定时器。
接下来看一哈HalAdcInit()这个函数,同样只是一些简单的配置
void HalAdcInit (void) { #if (HAL_ADC == TRUE) volatile uint8 tmp; ADCCON1 = HAL_ADC_STSEL | HAL_ADC_RAND_GEN | 0x03; ADCCON2 = HAL_ADC_REF_VOLT | HAL_ADC_DEC_RATE | HAL_ADC_SCHN; /* * After reset, the first ADC reading of the extra conversion always reads GND level. * We will do a few dummy conversions to bypass this bug. */ tmp = ADCL; /* read ADCL,ADCH to clear EOC */ tmp = ADCH; ADCCON3 = HAL_ADC_REF_VOLT | HAL_ADC_DEC_RATE | HAL_ADC_ECHN; while ((ADCCON1 & HAL_ADC_EOC) != HAL_ADC_EOC); /* Wait for conversion */ tmp = ADCL; /* read ADCL,ADCH to clear EOC */ tmp = ADCH; ADCCON3 = HAL_ADC_REF_VOLT | HAL_ADC_DEC_RATE | HAL_ADC_ECHN; while ((ADCCON1 & HAL_ADC_EOC) != HAL_ADC_EOC); /* Wait for conversion */ tmp = ADCL; /* read ADCL,ADCH to clear EOC */ tmp = ADCH; #endif }
ADCCON1主要用于控制,启动ADC转换,ADCCON2主要是配置,
#define HAL_ADC_STSEL HAL_ADC_STSEL_ST #define HAL_ADC_RAND_GEN HAL_ADC_RAND_STOP #define HAL_ADC_REF_VOLT HAL_ADC_REF_AVDD #define HAL_ADC_DEC_RATE HAL_ADC_DEC_064 #define HAL_ADC_SCHN HAL_ADC_CHN_VDD3 #define HAL_ADC_ECHN HAL_ADC_CHN_GND #define HAL_ADC_STSEL_ST 0x30 /* ADCCON1.ST =1 Trigger */ #define HAL_ADC_RAND_STOP 0x0c /* Stop Random Generator */ #define HAL_ADC_REF_AVDD 0x80 /* AVDD_SOC Pin Reference */ #define HAL_ADC_DEC_064 0x00 /* Decimate by 64 : 8-bit resolution */ #define HAL_ADC_CHN_VDD3 0x0f /* VDD/3 */ #define HAL_ADC_CHN_GND 0x0c /* GND */ #define HAL_ADC_EOC 0x80 /* End of Conversion bit */
进入该函数首先是一个判断,第一条语句是设置利用ADCCON1的ST位启动一个新的转换序列,关闭16位随机数发生器,最后两位保留写1。第二条语句设置序列转换的参考电压为AVDD5引脚(他给的注释是与CC2430相符合的,貌似注释都是沿用CC2430的,)唉!64抽取率,序列通道为VDD/3(也就是单个ADC转换了),读取ADCL、ADCH。设置ADCCON3选择用于额外转换的参考电压为AVDD5,64抽取率,通道为GND,当转换完成时,读取转换结果,后面又进行了一次转换,看其注释说道,重启之后,首先对ADC的外部转换都是GND level,所以在这里做了几次转换来避过这个bug。
下面看一下DMA的初始化,这个代码更简短
void HalDmaInit( void ) { HAL_DMA_SET_ADDR_DESC0( &dmaCh0 ); HAL_DMA_SET_ADDR_DESC1234( dmaCh1234 ); #if (HAL_UART_DMA || \ ((defined HAL_SPI) && (HAL_SPI == TRUE)) || \ ((defined HAL_IRGEN) && (HAL_IRGEN == TRUE))) DMAIE = 1; #endif }
用户需要为每一个通道配置以下几个参数:源地址、目标地址、传送长度,可变长度(VLEN)、优先级别、触发事件、源地址和目标地址增量、传送模式、字节传送或字传送、中断屏蔽以及M8,参数有点多貌似。
#define HAL_DMA_SET_ADDR_DESC0( a ) \ st( \ DMA0CFGH = (uint8)( (uint16)(a) >> 8 ); \ DMA0CFGL = (uint8)( (uint16)(a) ); \ ) #define HAL_DMA_SET_ADDR_DESC1234( a ) \ st( \ DMA1CFGH = (uint8)( (uint16)(a) >> 8 ); \ DMA1CFGL = (uint8)( (uint16)(a) ); \ )
typedef struct { uint8 srcAddrH; uint8 srcAddrL; uint8 dstAddrH; uint8 dstAddrL; uint8 xferLenV; uint8 xferLenL; uint8 ctrlA; uint8 ctrlB; } halDMADesc_t;