? Zigbee的HAL層提供了開發(fā)板所有硬件設(shè)備(例如LED、LCD、KEY、UART等)的驅(qū)動函數(shù)和接口。HAL文件夾為硬件平臺的抽象層,包含common、include和target三個文件夾。
1 Common文件夾? common文件夾下包含有hal_assert.c和hal_drivers.c兩個文件。其中hal_assert.c是聲明文件,用于調(diào)試,hal_drivers.c是驅(qū)動文件
1.1 hal_assert.c? 在hal_assert.c文件中包含兩個重要的函數(shù):halAssertHandler()和halAssertHazardLights()。
1.1.1 halAssertHandle()函數(shù)? halAssertHandler()函數(shù)為硬件系統(tǒng)檢測函數(shù)。如果定義了ASSERT_RESET宏,系統(tǒng)將調(diào)用HAL_SYSTEM_RESET復(fù)位,否則將調(diào)用halAssertHazardLights()執(zhí)行閃爍LED命令。
void halAssertHandler(void)
{
/* execute code that handles asserts */
//如果定義了ASSERT_RESET宏定義
#ifdef ASSERT_RESET
//系統(tǒng)復(fù)位
HAL_SYSTEM_RESET();
#elif !defined ASSERT_WHILE
//當檢測到錯誤,LED燈閃爍命令函數(shù)
halAssertHazardLights();
#else
while(1);
#endif
}
1.1.2 halAssertHazardLights()函數(shù)
? halAssertHazardLights()函數(shù)控制LED燈閃爍,根據(jù)不同的硬件平臺定義的LED的個數(shù)來決定閃爍的LED的不同。其控制LED燈閃爍代碼如下:
//如果硬件平臺定義的LED燈的個數(shù)是1
#if (HAL_NUM_LEDS >= 1)
//LED1閃爍
HAL_TOGGLE_LED1();
#if (HAL_NUM_LEDS >= 2)
HAL_TOGGLE_LED2();
#if (HAL_NUM_LEDS >= 3)
HAL_TOGGLE_LED3();
#if (HAL_NUM_LEDS >= 4)
HAL_TOGGLE_LED4();
#endif
#endif
#endif
#endif
其完整定義可自行查看。
1.2 hal_drivers.c
? hal_drivers.c文件中包含了與硬件相關(guān)的初始化和事件處理函數(shù)。此文件中有4個比較重要的函數(shù):硬件初始化函數(shù)Hal_Init()、硬件驅(qū)動初始化函數(shù)HalDriverInit()、硬件事件處理函數(shù)Hal_ProcessEvent()和詢檢函數(shù)Hal_ProcessPoll()。
1.2.1Hal_Init()函數(shù)? Hal_Init()函數(shù)是硬件初始化函數(shù),其功能是通過“注冊任務(wù)ID號”以實現(xiàn)在OSAL層注冊,從而允許硬件驅(qū)動的消息和事件由OSAL處理。其函數(shù)內(nèi)容為:
void Hal_Init( uint8 task_id )
{
/* Register task ID */
Hal_TaskID = task_id;
#ifdef CC2591_COMPRESSION_WORKAROUND
osal_start_reload_timer( Hal_TaskID, PERIOD_RSSI_RESET_EVT, PERIOD_RSSI_RESET_TIMEOUT );
#endif
}
1.2.2 HalDriverInit()函數(shù)
? HalDriverInit()函數(shù)被main()函數(shù)調(diào)用,用于初始化與硬件設(shè)備有關(guān)的驅(qū)動。HalDriverInit()函數(shù)的具體功能如下:
void HalDriverInit (void)
{
/* TIMER */
//如果定義了定時器則初始化定時器
#if (defined HAL_TIMER) && (HAL_TIMER == TRUE)
//在Zstack-CC2530-2.5.1a版本中移除了定時器的初始化,但不影響Zstack的運行。
#error "The hal timer driver module is removed."
#endif
/* ADC */
//如果定義了ADC,初始化ADC
#if (defined HAL_ADC) && (HAL_ADC == TRUE)
HalAdcInit();
#endif
/* DMA */
//如果定義了DMA,初始化DMA
#if (defined HAL_DMA) && (HAL_DMA == TRUE)
// Must be called before the init call to any module that uses DMA.
HalDmaInit();
#endif
/* AES */
//如果定義了AES,初始化AES
#if (defined HAL_AES) && (HAL_AES == TRUE)
HalAesInit();
#endif
/* LCD */
//如果定義了LCD,初始化LCD
#if (defined HAL_LCD) && (HAL_LCD == TRUE)
HalLcdInit();
#endif
/* LED */
//如果定義了LED,初始化LED
#if (defined HAL_LED) && (HAL_LED == TRUE)
HalLedInit();
#endif
/* UART */
//如果定義了UART,初始化UART
#if (defined HAL_UART) && (HAL_UART == TRUE)
HalUARTInit();
#endif
/* KEY */
//如果定義了按鍵,初始化KEY
#if (defined HAL_KEY) && (HAL_KEY == TRUE)
HalKeyInit();
#endif
/* SPI */
//如果定義了SPI,初始化SPI
#if (defined HAL_SPI) && (HAL_SPI == TRUE)
HalSpiInit();
#endif
/* HID */
//如果定義了USB,初始化USB,只限CC2531
#if (defined HAL_HID) && (HAL_HID == TRUE)
usbHidInit();
#endif
}
1.2.3 Hal_ProcessEvent()函數(shù)
? Hal_ProcessEvent()函數(shù)在APP層中的任務(wù)事件處理中被調(diào)用,用于對相應(yīng)的硬件事件作出處理,具體包括系統(tǒng)消息事件、LED閃爍事件、按鍵處理事件和睡眠模式等。
uint16 Hal_ProcessEvent( uint8 task_id, uint16 events )
{
uint8 *msgPtr;
(void)task_id; // Intentionally unreferenced parameter
//系統(tǒng)消息事件
if ( events & SYS_EVENT_MSG )
{
msgPtr = osal_msg_receive(Hal_TaskID);
while (msgPtr)
{
/* Do something here - for now, just deallocate the msg and move on */
/* De-allocate */
osal_msg_deallocate( msgPtr );
/* Next */
msgPtr = osal_msg_receive( Hal_TaskID );
}
return events ^ SYS_EVENT_MSG;
}
//LED閃爍事件
if ( events & HAL_LED_BLINK_EVENT )
{
#if (defined (BLINK_LEDS)) && (HAL_LED == TRUE)
HalLedUpdate();
#endif /* BLINK_LEDS && HAL_LED */
return events ^ HAL_LED_BLINK_EVENT;
}
//按鍵處理事件
if (events & HAL_KEY_EVENT)
{
#if (defined HAL_KEY) && (HAL_KEY == TRUE)
/* Check for keys */
HalKeyPoll();
/* if interrupt disabled, do next polling */
if (!Hal_KeyIntEnable)
{
osal_start_timerEx( Hal_TaskID, HAL_KEY_EVENT, 100);
}
#endif // HAL_KEY
return events ^ HAL_KEY_EVENT;
}
//睡眠模式
#ifdef POWER_SAVING
if ( events & HAL_SLEEP_TIMER_EVENT )
{
halRestoreSleepLevel();
return events ^ HAL_SLEEP_TIMER_EVENT;
}
#endif
#ifdef CC2591_COMPRESSION_WORKAROUND
if ( events & PERIOD_RSSI_RESET_EVT )
{
macRxResetRssi();
return (events ^ PERIOD_RSSI_RESET_EVT);
}
#endif
/* Nothing interested, discard the message */
return 0;
}
1.2.4 Hal_ProcessPoll()函數(shù)
? Hal_ProcessPoll()函數(shù)在main()函數(shù)中被osal_start_system()調(diào)用,用來對可能產(chǎn)生的硬件事件進行詢檢。函數(shù)原型為:
void Hal_ProcessPoll ()
{
/* Timer Poll */
//定時器詢檢
#if (defined HAL_TIMER) && (HAL_TIMER == TRUE)
#error "The hal timer driver module is removed."
#endif
/* UART Poll */
//UART詢檢,即串口詢檢
#if (defined HAL_UART) && (HAL_UART == TRUE)
HalUARTPoll();
#endif
/* SPI Poll */
#if (defined HAL_SPI) && (HAL_SPI == TRUE)
HalSpiPoll();
#endif
/* HID poll */
//USB詢檢(僅限CC2530)
#if (defined HAL_HID) && (HAL_HID == TRUE)
usbHidProcessEvents();
#endif
//如果定義了休眠模式
#if defined( POWER_SAVING )
/* Allow sleep before the next OSAL event loop */
//允許在下一個事件到來之前進入休眠模式
ALLOW_SLEEP_MODE();
#endif
}
? 硬件驅(qū)動初始化函數(shù)HalDriverInit()和硬件事件處理函數(shù)Hal_ProcessEvent()是Zigbee協(xié)議棧固有的,一般不需要作出較大范圍的修改,只需直接使用即可。 2. Include文件夾
3. Target文件夾
? Target目錄下包含了某個設(shè)備類型下的硬件驅(qū)動文件、硬件開發(fā)板上的配置文件、MCU信息和數(shù)據(jù)類型。
? CC2530EB中的字符EB是TI公司的Zstack在某個硬件上實現(xiàn)的版本號。例如:BB是電池版(Battery Board);DB是開發(fā)版(Development Board),EB是評估版(Evaluate Board)
? 在CC2530EB文件夾下包含了三個子文件夾,分別是Config、Derive、Includes
3.1 Config文件夾? Config文件夾中包含了hal_board_cfg.h,在hal_board_cfg.h中定義了硬件CC2530硬件資源的配置,比如GPIO、DMA、ADC等。
? 在hal_board_cfg.h文件中可以定義開發(fā)版的硬件資源。以LED為例,TI官方的CC2530EB版本定義了兩個LED:LED1和LED2,其在hal_board_cfg.h中定義如下:
/* 1 - Green */
//有關(guān)LED1的宏定義
#define LED1_BV BV(0)
#define LED1_SBIT P1_0
#define LED1_DDR P1DIR
#define LED1_POLARITY ACTIVE_HIGH
//如果定義了HAL_BOARD_CC2530EB_REC17,則定了LED2和LED3
#if defined (HAL_BOARD_CC2530EB_REV17)
/* 2 - Red */
//有關(guān)LED2的宏定義
#define LED2_BV BV(1)
#define LED2_SBIT P1_1
#define LED2_DDR P1DIR
#define LED2_POLARITY ACTIVE_HIGH
/* 3 - Yellow */
//有關(guān)LED3的宏定義
#define LED3_BV BV(4)
#define LED3_SBIT P1_4
#define LED3_DDR P1DIR
#define LED3_POLARITY ACTIVE_HIGH
#endif
? LED宏定義完成之后,設(shè)置LED的打開和關(guān)閉,其代碼在hal_board_cfg.h文件中,代碼如下:
#if defined (HAL_BOARD_CC2530EB_REV17) && !defined (HAL_PA_LNA) && !defined (HAL_PA_LNA_CC2590)
#define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0); )
#define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0); )
#define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0); )
#define HAL_TURN_OFF_LED4() HAL_TURN_OFF_LED1()
#define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1); )
#define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1); )
#define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1); )
#define HAL_TURN_ON_LED4() HAL_TURN_ON_LED1()
#define HAL_TOGGLE_LED1() st( if (LED1_SBIT) { LED1_SBIT = 0; } else { LED1_SBIT = 1;} )
#define HAL_TOGGLE_LED2() st( if (LED2_SBIT) { LED2_SBIT = 0; } else { LED2_SBIT = 1;} )
#define HAL_TOGGLE_LED3() st( if (LED3_SBIT) { LED3_SBIT = 0; } else { LED3_SBIT = 1;} )
#define HAL_TOGGLE_LED4() HAL_TOGGLE_LED1()
#define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT))
#define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT))
#define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT))
#define HAL_STATE_LED4() HAL_STATE_LED1()
3.2 Derivers文件夾
? 以最常用的LED為例,在hal_led.c文件中提供了兩個封裝好的函數(shù),在應(yīng)用層可以直接調(diào)用,以控制LED。這兩個函數(shù)是:
uint8 HalLedSet (uint8 leds, uint8 mode);
void HalLedBlink (uint8 leds, uint8 numBlinks, uint8 percent, uint16 period);
3.2.1 HalLedSet()函數(shù)
? HalLedSet()函數(shù)控制LED的亮滅:
3.2.2 HalLedBlink()函數(shù)參數(shù)leds,指LED的名稱,取值可以是:HAL_LED_1、HAL_LED_2、HAL_LED_3和HAL_LED_4;
參數(shù)mode,指LED的狀態(tài),取值可以是:HAL_LED_MODE_ON、HAL_LED_MODE_OFF和HAL_LED_MODE_TOGGLE。
? HalLedBlink()函數(shù)控制LED燈閃爍:
???????????? 參數(shù)numBlinks:閃爍次數(shù)。
???????????? 參數(shù)percent:LED亮和滅的所用時間占空比。
???????????? 參數(shù)period:LED閃爍一個周期所需要的時間,以毫秒為單位。