我是靠谱客的博主 执着钻石,最近开发中收集的这篇文章主要介绍Zstack协议栈之HalDriverInit()函数解析,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

看名字是初始化一些硬件驱动,里面全都是调用一些子函数来实现,包括TIMER、ADC、DMA、FLASH等等,如下

[cpp]  view plain  copy
  1. void HalDriverInit (void)  
  2. {  
  3.   /* TIMER */  
  4. #if (defined HAL_TIMER) && (HAL_TIMER == TRUE)  
  5.   HalTimerInit();  
  6. #endif  
  7.   
  8.   /* ADC */  
  9. #if (defined HAL_ADC) && (HAL_ADC == TRUE)  
  10.   HalAdcInit();  
  11. #endif  
  12.   
  13.   /* DMA */  
  14. #if (defined HAL_DMA) && (HAL_DMA == TRUE)  
  15.   // Must be called before the init call to any module that uses DMA.  
  16.   HalDmaInit();  
  17. #endif  
  18.   
  19.   /* Flash */  
  20. #if (defined HAL_FLASH) && (HAL_FLASH == TRUE)  
  21.   // Must be called before the init call to any module that uses Flash access or NV.  
  22.   HalFlashInit();  
  23. #endif  
  24.   
  25.   /* AES */  
  26. #if (defined HAL_AES) && (HAL_AES == TRUE)  
  27.   HalAesInit();  
  28. #endif  
  29.   
  30.    
  31.   /* LED */  
  32. #if (defined HAL_LED) && (HAL_LED == TRUE)  
  33.   HalLedInit();  
  34. #endif  
  35.   
  36.   /* UART */  
  37. #if (defined HAL_UART) && (HAL_UART == TRUE)  
  38.   HalUARTInit();  
  39. #endif  
  40.   
  41.   /* KEY */  
  42. #if (defined HAL_KEY) && (HAL_KEY == TRUE)  
  43.   HalKeyInit();  
  44. #endif  
  45.   
  46.   /* SPI */  
  47. #if (defined HAL_SPI) && (HAL_SPI == TRUE)  
  48.   HalSpiInit();  
  49. #endif  
  50.    /* LCD */  
  51. #if (defined HAL_LCD) && (HAL_LCD == TRUE)  
  52.   HalLcdInit();  
  53. #endif  
  54.   
  55. }  

宏定义如下

[cpp]  view plain  copy
  1. /* Set to TRUE enable H/W TIMER usage, FALSE disable it */  
  2. #ifndef HAL_TIMER  
  3. #define HAL_TIMER FALSE  
  4. #endif  
  5.   
  6. /* Set to TRUE enable ADC usage, FALSE disable it */  
  7. #ifndef HAL_ADC  
  8. #define HAL_ADC TRUE  
  9. #endif  
  10.   
  11. /* Set to TRUE enable DMA usage, FALSE disable it */  
  12. #ifndef HAL_DMA  
  13. #define HAL_DMA TRUE  
  14. #endif  
  15.   
  16. /* Set to TRUE enable Flash access, FALSE disable it */  
  17. #ifndef HAL_FLASH  
  18. #define HAL_FLASH TRUE  
  19. #endif  
  20.   
  21. /* Set to TRUE enable AES usage, FALSE disable it */  
  22. #ifndef HAL_AES  
  23. #define HAL_AES TRUE  
  24. #endif  
  25.   
  26. #ifndef HAL_AES_DMA  
  27. #define HAL_AES_DMA TRUE  
  28. #endif  
  29.   
  30. /* Set to TRUE enable LCD usage, FALSE disable it */  
  31. #ifndef HAL_LCD  
  32. #define HAL_LCD TRUE  
  33. #endif  
  34.   
  35. /* Set to TRUE enable LED usage, FALSE disable it */  
  36. #ifndef HAL_LED  
  37. #define HAL_LED TRUE  
  38. #endif  
  39. #if (!defined BLINK_LEDS) && (HAL_LED == TRUE)  
  40. #define BLINK_LEDS  
  41. #endif  
  42.   
  43. /* Set to TRUE enable KEY usage, FALSE disable it */  
  44. #ifndef HAL_KEY  
  45. #define HAL_KEY TRUE  
  46. #endif  
  47.   
  48. /* Set to TRUE enable UART usage, FALSE disable it */  
  49. #ifndef HAL_UART  
  50. #if (defined ZAPP_P1) || (defined ZAPP_P2) || (defined ZTOOL_P1) || (defined ZTOOL_P2)  
  51. #define HAL_UART  TRUE  
  52. #else  
  53. #define HAL_UART FALSE  
  54. #endif  
  55. #endif  

可以看到除了TIMER和UART以外其他宏定义均是TRUE,在定时器服务的初始化中涉及到的是定时器1、3、4,查看代码

[cpp]  view plain  copy
  1. void HalTimerInit (void)  
  2. {  
  3.   T1CCTL0 = 0;    /* Make sure interrupts are disabled */  
  4.   T1CCTL1 = 0;    /* Make sure interrupts are disabled */  
  5.   T1CCTL2 = 0;    /* Make sure interrupts are disabled */  
  6.   T3CCTL0 = 0;    /* Make sure interrupts are disabled */  
  7.   T3CCTL1 = 0;    /* Make sure interrupts are disabled */  
  8.   T4CCTL0 = 0;    /* Make sure interrupts are disabled */  
  9.   T4CCTL1 = 0;    /* Make sure interrupts are disabled */  
  10.   
  11.   /* Setup prescale & clock for timer0 */  
  12.   halTimerRecord[HW_TIMER_1].prescale    = HAL_TIMER1_16_PRESCALE;  
  13.   halTimerRecord[HW_TIMER_1].clock       = HAL_TIMER_32MHZ;  
  14.   halTimerRecord[HW_TIMER_1].prescaleVal = HAL_TIMER1_16_PRESCALE_VAL;  
  15.   
  16.   /* Setup prescale & clock for timer2 */  
  17.   halTimerRecord[HW_TIMER_3].prescale    = HAL_TIMER3_8_PRESCALE;  
  18.   halTimerRecord[HW_TIMER_3].clock       = HAL_TIMER_32MHZ;  
  19.   halTimerRecord[HW_TIMER_3].prescaleVal = HAL_TIMER3_8_PRESCALE_VAL;  
  20.   
  21.   /* Setup prescale & clock for timer3 */  
  22.   halTimerRecord[HW_TIMER_4].prescale    = HAL_TIMER4_8_PRESCALE;  
  23.   halTimerRecord[HW_TIMER_4].clock       = HAL_TIMER_32MHZ;  
  24.   halTimerRecord[HW_TIMER_4].prescaleVal = HAL_TIMER4_8_PRESCALE_VAL;  
  25.   
  26.   /* Setup Timer1 Channel structure */  
  27.   halTimerChannel[HW_TIMER_1].TxCCTL =  TCHN_T1CCTL;  
  28.   halTimerChannel[HW_TIMER_1].TxCCL =   TCHN_T1CCL;  
  29.   halTimerChannel[HW_TIMER_1].TxCCH =   TCHN_T1CCH;  
  30.   halTimerChannel[HW_TIMER_1].TxOVF =   TCNH_T1OVF;  
  31.   halTimerChannel[HW_TIMER_1].ovfbit =  TCHN_T1OVFBIT;  
  32.   halTimerChannel[HW_TIMER_1].intbit =  TCHN_T1INTBIT;  
  33. ……  
  34. }  


定时器3、4的配置与定时器1相同,节省下空间,都是一些寄存器的配置,先看下宏定义吧

[cpp]  view plain  copy
  1. #define HW_TIMER_1        0x00  
  2. #define HW_TIMER_3        0x01  
  3. #define HW_TIMER_4        0x02  
  4. #define HW_TIMER_INVALID  0x03  
  5. #define HW_TIMER_MAX      0x03  
  6.   
  7. #define HAL_TIMER1_16_PRESCALE      HAL_TIMER1_16_TC_DIV128  
  8. #define HAL_TIMER1_16_PRESCALE_VAL  128  
  9. #define HAL_TIMER3_8_PRESCALE       HAL_TIMER34_8_TC_DIV128  
  10. #define HAL_TIMER3_8_PRESCALE_VAL   128  
  11. #define HAL_TIMER4_8_PRESCALE       HAL_TIMER34_8_TC_DIV128  
  12. #define HAL_TIMER4_8_PRESCALE_VAL   128  
  13.   
  14. #define HAL_TIMER1_16_TC_DIV128   0x0c  /* Clock pre-scaled by 128 */  
  15. #define HAL_TIMER34_8_TC_DIV128   0xE0  /* Clock pre-scaled by 128 */  
  16.   
  17. /* Clock settings */  
  18. #define HAL_TIMER_16MHZ           16  
  19. #define HAL_TIMER_32MHZ           32  
  20.   
  21. /* Default all timers to use channel 0 */  
  22. #define TCHN_T1CCTL   &(X_T1CCTL0)  
  23. #define TCHN_T1CCL    &(X_T1CC0L)  
  24. #define TCHN_T1CCH    &(X_T1CC0H)  
  25. #define TCNH_T1OVF    &(X_TIMIF)  
  26. #define TCHN_T1OVFBIT TIMIF_T1OVFIM  
  27. #define TCHN_T1INTBIT IEN1_T1IE  

貌似有点多看着,而且这里面还用到了一个halTimerRecord数组和一个halTimerChannel数组,查看下其定义

[cpp]  view plain  copy
  1. typedef struct  
  2. {  
  3.   bool configured;  
  4.   bool intEnable;  
  5.   uint8 opMode;  
  6.   uint8 channel;  
  7.   uint8 channelMode;  
  8.   uint8 prescale;  
  9.   uint8 prescaleVal;  
  10.   uint8 clock;  
  11.   halTimerCBack_t callBackFunc;  
  12. } halTimerSettings_t;  
  13.   
  14. typedef struct  
  15. {  
  16.   uint8 volatile XDATA *TxCCTL;  
  17.   uint8 volatile XDATA *TxCCH;  
  18.   uint8 volatile XDATA *TxCCL;  
  19.   uint8 volatile XDATA *TxOVF;  
  20.   uint8 ovfbit;  
  21.   uint8 intbit;  
  22. } halTimerChannel_t;  
  23.   
  24. /********************************************************************* 
  25.  * GLOBAL VARIABLES 
  26.  */  
  27. static halTimerSettings_t halTimerRecord[HW_TIMER_MAX];  
  28. static halTimerChannel_t  halTimerChannel[HW_TIMER_MAX];  

用这两个数组管理者三个定时器,跟定时器1相关的寄存器有以下几个


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()这个函数,同样只是一些简单的配置

[cpp]  view plain  copy
  1. void HalAdcInit (void)  
  2. {  
  3. #if (HAL_ADC == TRUE)  
  4.   volatile uint8  tmp;  
  5.   
  6.   ADCCON1 = HAL_ADC_STSEL | HAL_ADC_RAND_GEN | 0x03;  
  7.   ADCCON2 = HAL_ADC_REF_VOLT | HAL_ADC_DEC_RATE | HAL_ADC_SCHN;  
  8.   /* 
  9.   *  After reset, the first ADC reading of the extra conversion always reads GND level. 
  10.   *  We will do a few dummy conversions to bypass this bug. 
  11.   */  
  12.   tmp = ADCL;     /* read ADCL,ADCH to clear EOC */  
  13.   tmp = ADCH;  
  14.   ADCCON3 = HAL_ADC_REF_VOLT | HAL_ADC_DEC_RATE | HAL_ADC_ECHN;  
  15.   while ((ADCCON1 & HAL_ADC_EOC) != HAL_ADC_EOC);   /* Wait for conversion */  
  16.   tmp = ADCL;     /* read ADCL,ADCH to clear EOC */  
  17.   tmp = ADCH;  
  18.   ADCCON3 = HAL_ADC_REF_VOLT | HAL_ADC_DEC_RATE | HAL_ADC_ECHN;  
  19.   while ((ADCCON1 & HAL_ADC_EOC) != HAL_ADC_EOC);   /* Wait for conversion */  
  20.   tmp = ADCL;     /* read ADCL,ADCH to clear EOC */  
  21.   tmp = ADCH;  
  22. #endif  
  23. }  

ADC一共三个寄存器ADCCON1、ADCCON2以及ADCCON3,其中ADCCON3在供电检测的时候用到过了,



ADCCON1主要用于控制,启动ADC转换,ADCCON2主要是配置,

[cpp]  view plain  copy
  1. #define HAL_ADC_STSEL       HAL_ADC_STSEL_ST  
  2. #define HAL_ADC_RAND_GEN    HAL_ADC_RAND_STOP  
  3. #define HAL_ADC_REF_VOLT    HAL_ADC_REF_AVDD  
  4. #define HAL_ADC_DEC_RATE    HAL_ADC_DEC_064  
  5. #define HAL_ADC_SCHN        HAL_ADC_CHN_VDD3  
  6. #define HAL_ADC_ECHN        HAL_ADC_CHN_GND  
  7.   
  8. #define HAL_ADC_STSEL_ST    0x30    /* ADCCON1.ST =1 Trigger */  
  9. #define HAL_ADC_RAND_STOP   0x0c    /* Stop Random Generator */  
  10. #define HAL_ADC_REF_AVDD    0x80    /* AVDD_SOC Pin Reference */  
  11. #define HAL_ADC_DEC_064     0x00    /* Decimate by 64 : 8-bit resolution */  
  12. #define HAL_ADC_CHN_VDD3    0x0f    /* VDD/3 */  
  13. #define HAL_ADC_CHN_GND     0x0c    /* GND */  
  14. #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的初始化,这个代码更简短

[cpp]  view plain  copy
  1. void HalDmaInit( void )  
  2. {  
  3.   HAL_DMA_SET_ADDR_DESC0( &dmaCh0 );  
  4.   HAL_DMA_SET_ADDR_DESC1234( dmaCh1234 );  
  5. #if (HAL_UART_DMA ||   
  6.    ((defined HAL_SPI) && (HAL_SPI == TRUE))  ||   
  7.    ((defined HAL_IRGEN) && (HAL_IRGEN == TRUE)))  
  8.   DMAIE = 1;  
  9. #endif  
  10. }  

DMA有5个通道,3个可配置的DMA通道优先级,32个可配置的传送触发事件等等,DMA的状态图如下



用户需要为每一个通道配置以下几个参数:源地址、目标地址、传送长度,可变长度(VLEN)、优先级别、触发事件、源地址和目标地址增量、传送模式、字节传送或字传送、中断屏蔽以及M8,参数有点多貌似。

[cpp]  view plain  copy
  1. #define HAL_DMA_SET_ADDR_DESC0( a )   
  2.   st(   
  3.     DMA0CFGH = (uint8)( (uint16)(a) >> 8 );    
  4.     DMA0CFGL = (uint8)( (uint16)(a) );         
  5.   )  
  6.   
  7. #define HAL_DMA_SET_ADDR_DESC1234( a )   
  8.   st(   
  9.     DMA1CFGH = (uint8)( (uint16)(a) >> 8 );    
  10.     DMA1CFGL = (uint8)( (uint16)(a) );         
  11.   )  

这里只是为DMA赋值为通道n的配置数据结构的开始地址,通道0与通道1234是分开的,其结构如下

[cpp]  view plain  copy
  1. typedef struct {  
  2.   uint8 srcAddrH;  
  3.   uint8 srcAddrL;  
  4.   uint8 dstAddrH;  
  5.   uint8 dstAddrL;  
  6.   uint8 xferLenV;  
  7.   uint8 xferLenL;  
  8.   uint8 ctrlA;  
  9.   uint8 ctrlB;  
  10. } halDMADesc_t;  

更细致的DMA操作还是等到后面再学习吧。


最后

以上就是执着钻石为你收集整理的Zstack协议栈之HalDriverInit()函数解析的全部内容,希望文章能够帮你解决Zstack协议栈之HalDriverInit()函数解析所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(57)

评论列表共有 0 条评论

立即
投稿
返回
顶部