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。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM