Zigbee系列 学习笔记三(初始化程序解析)

 

 

 1 int main( void )
 2 {
 3   // Turn off interrupts
 4   osal_int_disable( INTS_ALL );
 5 
 6   // Initialization for board related stuff such as LEDs
 7   HAL_BOARD_INIT();
 8 
 9   // Make sure supply voltage is high enough to run
10   zmain_vdd_check();
11 
12   // Initialize board I/O
13   InitBoard( OB_COLD );
14 
15   // Initialze HAL drivers
16   HalDriverInit();
17 
18   // Initialize NV System
19   osal_nv_init( NULL );
20 
21   // Initialize the MAC
22   ZMacInit();
23 
24   // Determine the extended address
25   zmain_ext_addr();
26 
27 #if defined ZCL_KEY_ESTABLISH
28   // Initialize the Certicom certificate information.
29   zmain_cert_init();
30 #endif
31 
32   // Initialize basic NV items
33   zgInit();
34 
35 #ifndef NONWK
36   // Since the AF isn't a task, call it's initialization routine
37   afInit();
38 #endif
39 
40   // Initialize the operating system
41   osal_init_system();
42 
43   // Allow interrupts
44   osal_int_enable( INTS_ALL );
45 
46   // Final board initialization
47   InitBoard( OB_READY );
48 
49   // Display information about this device
50   zmain_dev_info();
51 
52   /* Display the device info on the LCD */
53 #ifdef LCD_SUPPORTED
54   zmain_lcd_init();
55 #endif
56 
57 #ifdef WDT_IN_PM1
58   /* If WDT is used, this is a good place to enable it. */
59   WatchDogEnable( WDTIMX );
60 #endif
61 
62   osal_start_system(); // No Return from here
63 
64   return 0;  // Shouldn't get here.
65 } // main()
HAL_BOARD_INIT()关于LED灯的板级初始化
 1 #define HAL_BOARD_INIT()                                         \
 2 {                                                                \
 3   uint16 i;                                                      \
 4                                                                  \
 5   SLEEPCMD &= ~OSC_PD;                       /* turn on 16MHz RC and 32MHz XOSC */                \
 6   while (!(SLEEPSTA & XOSC_STB));            /* wait for 32MHz XOSC stable */                     \
 7   asm("NOP");                                /* chip bug workaround */                            \
 8   for (i=0; i<504; i++) asm("NOP");          /* Require 63us delay for all revs */                \
 9   CLKCONCMD = (CLKCONCMD_32MHZ | OSC_32KHZ); /* Select 32MHz XOSC and the source for 32K clock */ \
10   while (CLKCONSTA != (CLKCONCMD_32MHZ | OSC_32KHZ)); /* Wait for the change to be effective */   \
11   SLEEPCMD |= OSC_PD;                        /* turn off 16MHz RC */                              \
12                                                                  \
13   /* Turn on cache prefetch mode */                              \
14   PREFETCH_ENABLE();                                             \
15                                                                  \
16   HAL_TURN_OFF_LED1();                                           \
17   LED1_DDR |= LED1_BV;                                           \
18   HAL_TURN_OFF_LED2();                                           \
19   LED2_DDR |= LED2_BV;                                           \
20   HAL_TURN_OFF_LED3();                                           \
21   LED3_DDR |= LED3_BV;                                           \
22                                                                  \
23   /* configure tristates */                                      \
24   P0INP |= PUSH2_BV;                                             \
25 }

程序解读:16~21行代码,定义了三个LED灯的IO口,分别为P1_0、P1_1、P1_4。第24行代码,定义P0_0为三态

HalDriverInit()初始化硬件层各驱动
 1 void HalDriverInit (void)
 2 {
 3   /* TIMER */
 4 #if (defined HAL_TIMER) && (HAL_TIMER == TRUE)
 5   #error "The hal timer driver module is removed."
 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   /* AES */
20 #if (defined HAL_AES) && (HAL_AES == TRUE)
21   HalAesInit();
22 #endif
23 
24   /* LCD */
25 #if (defined HAL_LCD) && (HAL_LCD == TRUE)
26   HalLcdInit();
27 #endif
28 
29   /* LED */
30 #if (defined HAL_LED) && (HAL_LED == TRUE)
31   HalLedInit();
32 #endif
33 
34   /* UART */
35 #if (defined HAL_UART) && (HAL_UART == TRUE)
36   HalUARTInit();
37 #endif
38 
39   /* KEY */
40 #if (defined HAL_KEY) && (HAL_KEY == TRUE)
41   HalKeyInit();
42 #endif
43 
44   /* SPI */
45 #if (defined HAL_SPI) && (HAL_SPI == TRUE)
46   HalSpiInit();
47 #endif
48 
49   /* HID */
50 #if (defined HAL_HID) && (HAL_HID == TRUE)
51   usbHidInit();
52 #endif
53 }

程序解析:以上程序分别进行了,定时器,ADC,UART等接口初始化

  1 /* ------------------------------------------------------------------------------------------------
  2  *                                     Driver Configuration
  3  * ------------------------------------------------------------------------------------------------
  4  */
  5 
  6 /* Set to TRUE enable H/W TIMER usage, FALSE disable it */
  7 #ifndef HAL_TIMER
  8 #define HAL_TIMER FALSE
  9 #endif
 10 
 11 /* Set to TRUE enable ADC usage, FALSE disable it */
 12 #ifndef HAL_ADC
 13 #define HAL_ADC TRUE
 14 #endif
 15 
 16 /* Set to TRUE enable DMA usage, FALSE disable it */
 17 #ifndef HAL_DMA
 18 #define HAL_DMA TRUE
 19 #endif
 20 
 21 /* Set to TRUE enable Flash access, FALSE disable it */
 22 #ifndef HAL_FLASH
 23 #define HAL_FLASH TRUE
 24 #endif
 25 
 26 /* Set to TRUE enable AES usage, FALSE disable it */
 27 #ifndef HAL_AES
 28 #define HAL_AES TRUE
 29 #endif
 30 
 31 #ifndef HAL_AES_DMA
 32 #define HAL_AES_DMA TRUE
 33 #endif
 34 
 35 /* Set to TRUE enable LCD usage, FALSE disable it */
 36 #ifndef HAL_LCD
 37 #define HAL_LCD TRUE
 38 #endif
 39 
 40 /* Set to TRUE enable LED usage, FALSE disable it */
 41 #ifndef HAL_LED
 42 #define HAL_LED TRUE
 43 #endif
 44 #if (!defined BLINK_LEDS) && (HAL_LED == TRUE)
 45 #define BLINK_LEDS
 46 #endif
 47 
 48 /* Set to TRUE enable KEY usage, FALSE disable it */
 49 #ifndef HAL_KEY
 50 #define HAL_KEY TRUE
 51 #endif
 52 
 53 /* Set to TRUE enable UART usage, FALSE disable it */
 54 #ifndef HAL_UART
 55 #if (defined ZAPP_P1) || (defined ZAPP_P2) || (defined ZTOOL_P1) || (defined ZTOOL_P2)
 56 #define HAL_UART TRUE
 57 #else
 58 #define HAL_UART FALSE
 59 #endif
 60 #endif
 61 
 62 #if HAL_UART
 63 #ifndef HAL_UART_DMA
 64 #if HAL_DMA
 65 #if (defined ZAPP_P2) || (defined ZTOOL_P2)
 66 #define HAL_UART_DMA  2
 67 #else
 68 #define HAL_UART_DMA  1
 69 #endif
 70 #else
 71 #define HAL_UART_DMA  0
 72 #endif
 73 #endif
 74 
 75 #ifndef HAL_UART_ISR
 76 #if HAL_UART_DMA           // Default preference for DMA over ISR.
 77 #define HAL_UART_ISR  0
 78 #elif (defined ZAPP_P2) || (defined ZTOOL_P2)
 79 #define HAL_UART_ISR  2
 80 #else
 81 #define HAL_UART_ISR  1
 82 #endif
 83 #endif
 84 
 85 #if (HAL_UART_DMA && (HAL_UART_DMA == HAL_UART_ISR))
 86 #error HAL_UART_DMA & HAL_UART_ISR must be different.
 87 #endif
 88 
 89 // Used to set P2 priority - USART0 over USART1 if both are defined.
 90 #if ((HAL_UART_DMA == 1) || (HAL_UART_ISR == 1))
 91 #define HAL_UART_PRIPO             0x00
 92 #else
 93 #define HAL_UART_PRIPO             0x40
 94 #endif
 95 
 96 #else
 97 #define HAL_UART_DMA  0
 98 #define HAL_UART_ISR  0
 99 #endif
100 
101 /* USB is not used for CC2530 configuration */
102 #define HAL_UART_USB  0
103 #endif
104 /*******************************************************************************************************
105 */

以上代码在hal_board_cfg.h中,定义了相应硬件接口。在HalDriverInit()函数中可以看到对应的硬件初始化。

针对ADC初始化:

1 void HalAdcInit (void)
2 {
3 #if (HAL_ADC == TRUE)
4   adcRef = HAL_ADC_REF_VOLT;
5 #endif
6 }

定义了ADC的参考电压源。

针对UART的初始化:

 1 void HalUARTInit(void)
 2 {
 3 #if HAL_UART_DMA
 4   HalUARTInitDMA();
 5 #endif
 6 #if HAL_UART_ISR
 7   HalUARTInitISR();
 8 #endif
 9 #if HAL_UART_USB
10   HalUARTInitUSB();
11 #endif
12 }

有三种初始化方式,可以通过hal_board_cfg.h文件中的定义进行选择初始化。

按键初始化:

 1 void HalKeyInit( void )
 2 {
 3   /* Initialize previous key to 0 */
 4   halKeySavedKeys = 0;
 5 
 6   HAL_KEY_SW_6_SEL &= ~(HAL_KEY_SW_6_BIT);    /* Set pin function to GPIO */
 7   HAL_KEY_SW_6_DIR &= ~(HAL_KEY_SW_6_BIT);    /* Set pin direction to Input */
 8 
 9   HAL_KEY_JOY_MOVE_SEL &= ~(HAL_KEY_JOY_MOVE_BIT); /* Set pin function to GPIO */
10   HAL_KEY_JOY_MOVE_DIR &= ~(HAL_KEY_JOY_MOVE_BIT); /* Set pin direction to Input */
11 
12 
13   /* Initialize callback function */
14   pHalKeyProcessFunction  = NULL;
15 
16   /* Start with key is not configured */
17   HalKeyConfigured = FALSE;
18 }

初始化中定义了P0_1和P2_0为按键控制接口

关于DMA的配置过程:

 1 /*用于配置DMA的结构体
 2 -------------------------------------------------------*/
 3 #pragma bitfields=reversed
 4 typedef struct
 5 {
 6   unsigned char SRCADDRH;           //源地址高8位
 7   unsigned char SRCADDRL;           //源地址低8位
 8   unsigned char DESTADDRH;          //目的地址高8位
 9   unsigned char DESTADDRL;          //目的地址低8位
10   unsigned char VLEN        :3;     //长度域模式选择
11   unsigned char LENH        :5;     //传输长度高字节
12   unsigned char LENL        :8;     //传输长度低字节
13   unsigned char WORDSIZE    :1;     //字节(byte)或字(word)传输
14   unsigned char TMODE       :2;     //传输模式选择
15   unsigned char TRIG        :5;     //触发事件选择
16   unsigned char SRCINC      :2;     //源地址增量:-1/0/1/2
17   unsigned char DESTINC     :2;     //目的地址增量:-1/0/1/2
18   unsigned char IRQMASK     :1;     //中断屏蔽
19   unsigned char M8          :1;     //7或8bit传输长度,仅在字节传输模式下适用
20   unsigned char PRIORITY    :2;     //优先级
21 }DMA_CFG;

 使用DMA的基本流程是:配置DMA → 启用配置 → 启动DMA传输 → 等待DMA传输完毕。下面分别介绍:

(1)配置DMA:首先必须配置DMA,但DMA的配置比较特殊:不是直接对某些SFR赋值,而是在外部定义一个结构体,对其赋值,然后再将此结构体的首地址的高8位赋给 DMA0CFGH,将其低8位赋给DMA0CFGL

关于上面源码中对配置结构体的定义,需做两点说明:

1)位域

  在定义此结构体时,用到了很多冒号(:),后面还跟着一个数字,这种语法叫“位域”:

  位域是指信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,C语言提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几个不同的区域, 并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字节的二进制位域来表示。

2)抽象出常用函数

  细心的读者会发现,在对结构体赋值时,经常会涉及到将一个16位unsigned int 类型值分别赋予两个8位的unsigned char类型值,处理方法如下:

  dmaConfig.SRCADDRH=(unsigned char)((unsigned int)&sourceString>> 8);     //源地址
  dmaConfig.SRCADDRL=(unsigned char)((unsignedint)&sourceString);

  对于这类经常会用到的函数,我们不妨抽象出来作为一个通用函数,如下:  

  #define SET_WORD(destH,destL,word)
    do{
       destH=(unsigned char)((unsigned int)word >> 8);     
       destL=(unsigned char)((unsigned int)word);
    }while(0)

  以后每当你需要进行类似的分割操作时,直接调用即可,如下所示:

  SET_WORD(dmaConfig.SRCADDRH, dmaConfig.SRCADDRL,&sourceString);

(2)启用配置:首先将结构体的首地址 &dmaConfig 的高/低8位分别赋给SFR DMA0CFGH 和DMA0CFGL(其中的0表示对通道0配置,CC2530包含5个DMA通道,此处使用通道0)。然对DMAARM.0 赋值1,启用通道0的配置,使通道0处于工作模式。

(3)开启DMA传输:对 DMAREQ.0 赋值1,启动通道0的DMA传输。

(4)等待DMA传输完毕:通道0的DMA传输完毕后,就会触发中断,通道0的中断标志 DMAIRQ.0会被自动置1。然后对两个字符串的每一个字符进行比较,将校验结果发送至PC。

posted on 2015-09-18 14:53  humbird  阅读(2864)  评论(0编辑  收藏  举报

导航