//初始化板上的IO
InitBoard( OB_COLD );<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
//参数【OnBoard.h】
#define OB_COLD 0
#define OB_WARM 1
#define OB_READY 2
//【OnBoard.c】
void InitBoard( byte level )
{
if ( level == OB_COLD )
{
//关中断,最初的时候已经见过了
osal_int_disable( INTS_ALL );
// 关闭所有的LED,调用了LED设置函数
HalLedSet( HAL_LED_ALL, HAL_LED_MODE_OFF );
//【hal_led.h】
// #define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4),我这里呢只有两个LED,所以可以屏蔽掉LED3,LED4,或者将后两个LED也映射到前面两个LED(其实就是宏定义啦)
// #define HAL_LED_MODE_OFF 0x00
//#define HAL_LED_MODE_ON 0x01
//#define HAL_LED_MODE_BLINK 0x02
//#define HAL_LED_MODE_FLASH 0x04
//#define HAL_LED_MODE_TOGGLE 0x08
//LED设置函数【hal_led.c】
uint8 HalLedSet (uint8 leds, uint8 mode)
{
#if (defined (BLINK_LEDS)) && (HAL_LED == TRUE)
//前提条件是定义了闪烁LED和LED硬件驱动服务使能;
// HAL_LED定义在【hal_board_cfg.h】
#ifndef HAL_LED
#define HAL_LED TRUE
//当设为FALSE时就不使用LED
#endif
#if (!defined BLINK_LEDS) && (HAL_LED == TRUE)
#define BLINK_LEDS
#endif
uint8 led;
HalLedControl_t *sts;
// LED控制结构体
typedef struct {
uint8 mode; /* 操作模式 */
uint8 todo; /* 剩余的闪烁周期数 */
uint8 onPct; /* 周期中所占的比例 */
uint16 time; /* 开关周期时间(msec) */
uint32 next; /* 下次改变的时间 */
} HalLedControl_t;
switch (mode)
{
case HAL_LED_MODE_BLINK:
HalLedBlink (leds, 1, HAL_LED_DEFAULT_DUTY_CYCLE, HAL_LED_DEFAULT_FLASH_TIME);
//LED设置的一些默认参数【hal_led.h】
#define HAL_LED_DEFAULT_MAX_LEDS 4
#define HAL_LED_DEFAULT_DUTY_CYCLE 5
#define HAL_LED_DEFAULT_FLASH_COUNT 50
#define HAL_LED_DEFAULT_FLASH_TIME 1000
//LED闪烁函数【hal_led.c】
void HalLedBlink (uint8 leds, uint8 numBlinks, uint8 percent, uint16 period)
{
#if (defined (BLINK_LEDS)) && (HAL_LED == TRUE)
//同样先判断是否启用了LED并且使用LED闪烁功能
uint8 led;
HalLedControl_t *sts;
if (leds && percent && period)
//判断参数的有效性,percent参数指明一个周期中LED将开启的时间
{
if (percent < 100)
//如果一个周期中开启时间小于100%
{
led = HAL_LED_1;
leds &= HAL_LED_ALL;
//屏蔽掉不想要操作的LED
sts = HalLedStatusControl.HalLedControlTable;
//HalLedStatusControl是事先定义好的一个结构体
typedef struct
{
HalLedControl_t HalLedControlTable[HAL_LED_DEFAULT_MAX_LEDS];
uint8 sleepActive;
} HalLedStatus_t;
#define HAL_LED_DEFAULT_MAX_LEDS 4
#ifdef BLINK_LEDS
static HalLedStatus_t HalLedStatusControl;
#endif
while (leds)
//这个循环主要是对传进来的每一个LED进行独立的设置,比如传进来的是需要设置LED1和LED2,那么此循环会先设置LED1然后再设置LED2
{
if (leds & led)
//检测当前LED是否是需要设置的
{
preBlinkState |= (led & HalLedState);
//储存目前的额LED状态
//static uint8 preBlinkState;
sts->mode = HAL_LED_MODE_OFF; /*关闭先前的模式 */
sts->time = period; /* Time for one on/off cycle */
sts->onPct = percent; /* % of cycle LED is on */
sts->todo = numBlinks; /* Number of blink cycles */
if (!numBlinks) sts->mode |= HAL_LED_MODE_FLASH;
//如果规定的次数未达到则继续闪烁
sts->next = osal_GetSystemClock(); /* Start now */
//读取当前系统时钟【OSAL_Timers.c】
uint32 osal_GetSystemClock( void )
{
return ( osal_systemClock );
}
//static uint32 osal_systemClock;
//这样看来第一次运行的时候osal_systemClock=0,系统中应该启动了定时器,用来记录系统运行时间。
sts->mode |= HAL_LED_MODE_BLINK; /* Enable blinking */
leds ^= led;
//屏蔽掉已设置好的这个LED
}
led <<= 1;
//检测下一个LED
sts++;
}//真的是高手才能写出的函数啊!自叹,C语言编程能力还差的远啊
osal_set_event (Hal_TaskID, HAL_LED_BLINK_EVENT);
//【hal_drivers.h】
//#define HAL_LED_BLINK_EVENT 0x0002
//extern uint8 Hal_TaskID;
//此函数为用户设置任务标志【OSAL.c】
//第一个参数是任务ID,第二个参数是要设置的事件
byte osal_set_event( byte task_id, UINT16 event_flag )
{
if ( task_id < tasksCnt )
//【sapi.c】
const pTaskEventHandlerFn tasksArr[] = {
macEventLoop,
nwk_event_loop,
Hal_ProcessEvent,
#if defined( MT_TASK )
MT_ProcessEvent,
#endif
APS_event_loop,
ZDApp_event_loop,
SAPI_ProcessEvent
};
//【OSAL_Tasks.h】
//事件处理函数原型:typedef unsigned short (*pTaskEventHandlerFn)( unsigned char task_id, unsigned short event );
//定义事件处理函数的函数指针类型
//tasksArr中任务事件循环中的顺序必须和osalInitTask中任务的初始化顺序一致
const uint8 tasksCnt = sizeof( tasksArr ) / sizeof( tasksArr[0] );
//得到任务数
//只有当任务ID小于总任务数时才继续执行,也就是说只有当此为有效任务才执行。
{
halIntState_t intState;
//【hal_mcu.h】其实就是一个无符号字符类型
//typedef unsigned char halIntState_t;
HAL_ENTER_CRITICAL_SECTION(intState); // 维持全局中断状态
//【hal_mcu.h】
#define HAL_ENTER_CRITICAL_SECTION(x) st( x = EA; HAL_DISABLE_INTERRUPTS(); )
//保存当前全局中断状态,然后关闭全局中断
#define HAL_EXIT_CRITICAL_SECTION(x) st( EA = x; )
#define HAL_CRITICAL_STATEMENT(x) st( halIntState_t s; HAL_ENTER_CRITICAL_SECTION(s); x; HAL_EXIT_CRITICAL_SECTION(s); )
tasksEvents[task_id] |= event_flag; // Stuff the event bit(s)
//【sapi.c】
//uint16 *tasksEvents;
HAL_EXIT_CRITICAL_SECTION(intState); // Release interrupts
}
else
return ( INVALID_TASK );
//如果任务ID超出返回则返回任务无效
//返回值类型定义在【ZComDef.h】
//#define INVALID_TASK 1
return ( ZSUCCESS );
}
}
Else
//如果点亮时间百分比超过100%也就相当于常亮了,就执行LED常亮的设置
{
HalLedSet (leds, HAL_LED_MODE_ON);
//【hal_led.c】
uint8 HalLedSet (uint8 leds, uint8 mode)
{
#if (defined (BLINK_LEDS)) && (HAL_LED == TRUE)
//一样的前提是开始了LED硬件驱动服务
uint8 led;
HalLedControl_t *sts;
switch (mode)
//检测要切换的LED模式
{
case HAL_LED_MODE_BLINK:
HalLedBlink (leds, 1, HAL_LED_DEFAULT_DUTY_CYCLE, HAL_LED_DEFAULT_FLASH_TIME);
break;
//如果是闪烁模式,则将指定的LED闪烁一次,点亮时间默认为5%,闪烁周期是1S
//【hal_led.h】
#define HAL_LED_DEFAULT_MAX_LEDS 4
#define HAL_LED_DEFAULT_DUTY_CYCLE 5
#define HAL_LED_DEFAULT_FLASH_COUNT 50
#define HAL_LED_DEFAULT_FLASH_TIME 1000
case HAL_LED_MODE_FLASH:
/* Default flash, N times, D% duty cycle */
HalLedBlink (leds, HAL_LED_DEFAULT_FLASH_COUNT, HAL_LED_DEFAULT_DUTY_CYCLE, HAL_LED_DEFAULT_FLASH_TIME);
break;
//如果是连闪模式,则将指定的LED闪烁50次,点亮时间默认为5%,闪烁周期是1S
case HAL_LED_MODE_ON:
case HAL_LED_MODE_OFF:
case HAL_LED_MODE_TOGGLE:
//如果是开、关、切换模式,则分别一个个的操作指定的LED
led = HAL_LED_1;
leds &= HAL_LED_ALL;
sts = HalLedStatusControl.HalLedControlTable;
while (leds)
{
if (leds & led)
{
if (mode != HAL_LED_MODE_TOGGLE)
{
sts->mode = mode; /* ON or OFF */
}
else
{
sts->mode ^= HAL_LED_MODE_ON; /* Toggle */
//开关的切换,利用了和1相异或为取反的特性。到这里为止还只是设置了LED的模式,并没有真正的对LED进行开关的操作,也就是说LED并没有演示出效果。
}
HalLedOnOff (led, sts->mode);
//这个函数是对LED进行开关操作的真正的函数了,这个函数执行完后应该能看到LED状态的变化。列举程序中部分段落(因为其他段落都差不多呵呵)【hal_led.c】
if (leds & HAL_LED_1)
//检测是否是LED1
{
if (mode == HAL_LED_MODE_ON)
//检测开关模式
{
HAL_TURN_ON_LED1();
//点亮LED1
}
else
{
HAL_TURN_OFF_LED1();
}
}
…………
if (mode)
{
HalLedState |= leds;
}
else
{
HalLedState &= ~leds;
}
//此用来记住当前操作的LED的状态,如果是点亮的就把HalLedState中相应的位置位,否则清零
leds ^= led;
}
led <<= 1;
sts++;
}
break;
default:
break;
}
#elif (HAL_LED == TRUE)
LedOnOff(leds, mode);
#endif /* BLINK_LEDS && HAL_LED */
return ( HalLedState );
//返回的是操作了的LED的状态,每个LED在此状态中用1位来表示
}
}
}
Else
//如果没有开始LED驱动服务,或者没有开启LED闪烁,就直接关闭LED
{
HalLedSet (leds, HAL_LED_MODE_OFF); /* No on time, turn off */
}
#elif (HAL_LED == TRUE)
//如果没有定义闪烁,则只对LED进行单次的一次转换状态操作
percent = (leds & HalLedState) ? HAL_LED_MODE_OFF : HAL_LED_MODE_ON;
HalLedOnOff (leds, percent); /* Toggle */
#endif /* BLINK_LEDS && HAL_LED */
}
break;
case HAL_LED_MODE_FLASH:
/* Default flash, N times, D% duty cycle */
HalLedBlink (leds, HAL_LED_DEFAULT_FLASH_COUNT, HAL_LED_DEFAULT_DUTY_CYCLE, HAL_LED_DEFAULT_FLASH_TIME);
break;
case HAL_LED_MODE_ON:
case HAL_LED_MODE_OFF:
case HAL_LED_MODE_TOGGLE:
led = HAL_LED_1;
leds &= HAL_LED_ALL;
sts = HalLedStatusControl.HalLedControlTable;
while (leds)
{
if (leds & led)
{
if (mode != HAL_LED_MODE_TOGGLE)
{
sts->mode = mode; /* ON or OFF */
}
else
{
sts->mode ^= HAL_LED_MODE_ON; /* Toggle */
}
HalLedOnOff (led, sts->mode);
leds ^= led;
}
led <<= 1;
sts++;
}
break;
default:
break;
}
#elif (HAL_LED == TRUE)
LedOnOff(leds, mode);
#endif /* BLINK_LEDS && HAL_LED */
return ( HalLedState );
}
//通过上面程序的解读我发现,到目前为止对LED的操作真正实现的只有开、关、切换,所谓的闪烁只是调用了一个系统事件设置函数osal_set_event (Hal_TaskID, HAL_LED_BLINK_EVENT);难道这都是通过系统事件来实现的?因为闪烁涉及到了时间占空比,估计还调用了定时器,那有可能还用到了中断,嗯,有可能。先接着分析下面的函数
// Check for Brown-Out reset
ChkReset();
//检测重启原因【OnBoard.c】
void ChkReset( void )
{
uint8 led;
uint8 rib;
// Isolate reset indicator bits
rib = SLEEP & LRESET;
//得到SLEEP中的RST状态【hal_mcu.h】
//#define LRESET 0x18
if ( rib == RESETPO )
//重启的原因【OnBoard.h】
#define RESETPO 0x00 // 上电重启
#define RESETEX 0x08 //外部重启
#define RESETWD 0x10 //看门狗重启
{
// Put code here to handle Power-On reset
}
else if ( rib == RESETEX )
{
// Put code here to handle External reset
}
else if ( rib == RESETWD )
{
// Put code here to handle WatchDog reset
}
Else
//未知的重启原因,闪烁LED指示
{
HAL_DISABLE_INTERRUPTS();
led = HAL_LED_4;
while ( 1 ) {
HalLedSet( led, HAL_LED_MODE_ON );
MicroWait( 62500 );
MicroWait( 62500 );
HalLedSet( led, HAL_LED_MODE_OFF );
MicroWait( 37500 );
MicroWait( 37500 );
if ( !(led >>= 1) )
led = HAL_LED_4;
}
}
}
/* Timer2 for Osal timer*/
//设置OSAL的时钟
OnboardTimerIntEnable = FALSE;
HalTimerConfig (OSAL_TIMER, // 8bit timer2
HAL_TIMER_MODE_CTC, // Clear Timer on Compare
HAL_TIMER_CHANNEL_SINGLE, // Channel 1 - default
HAL_TIMER_CH_MODE_OUTPUT_COMPARE, // Output Compare mode
OnboardTimerIntEnable, // Use interrupt
Onboard_TimerCallBack); // Channel Mode
//【OnBoard.h】
// 使用指定的定时器#define OSAL_TIMER HAL_TIMER_2
//【hal_timer.h】
//#define HAL_TIMER_0 0x00 // 8bit timer
//fine HAL_TIMER_1 0x01 // 16bit Mac timer
//fine HAL_TIMER_2 0x02 // 8bit timer
//fine HAL_TIMER_3 0x03 // 16bit timer
//efine HAL_TIMER_MAX 4 // Max number of timer
//定时器的操作模式
//#define HAL_TIMER_MODE_NORMAL 0x01 // Normal Mode
//#define HAL_TIMER_MODE_CTC 0x02 // Clear Timer On Compare
//#define HAL_TIMER_MODE_MASK (HAL_TIMER_MODE_NORMAL | HAL_TIMER_MODE_CTC)
//定时器通道定义
//#define HAL_TIMER_CHANNEL_SINGLE 0x01 // Single Channel - default
//#define HAL_TIMER_CHANNEL_A 0x02 // Channel A
//#define HAL_TIMER_CHANNEL_B 0x04 // Channel B
//#define HAL_TIMER_CHANNEL_C 0x08 // Channel C
//#define HAL_TIMER_CHANNEL_MASK (HAL_TIMER_CHANNEL_SINGLE | \
HAL_TIMER_CHANNEL_A | \
HAL_TIMER_CHANNEL_B | \
HAL_TIMER_CHANNEL_C)
//通道模式
//#define HAL_TIMER_CH_MODE_INPUT_CAPTURE 0x01 // Channel Mode Input-Capture
//#define HAL_TIMER_CH_MODE_OUTPUT_COMPARE 0x02 // Channel Mode Output_Compare
//#define HAL_TIMER_CH_MODE_OVERFLOW 0x04 // Channel Mode Overflow
//#define HAL_TIMER_CH_MODE_MASK (HAL_TIMER_CH_MODE_INPUT_CAPTURE | \
HAL_TIMER_CH_MODE_OUTPUT_COMPARE | \
HAL_TIMER_CH_MODE_OVERFLOW)
//更新定时器的函数【OnBoard.c】
void Onboard_TimerCallBack ( uint8 timerId, uint8 channel, uint8 channelMode)
{
if ((timerId == OSAL_TIMER) && (channelMode == HAL_TIMER_CH_MODE_OUTPUT_COMPARE))
{
osal_update_timers();
//【OSAL_Timers.c】
//每一个时钟滴答跟新时钟结构体
void osal_update_timers( void )
{
osalTimerUpdate( tmr_decr_time );
//【OSAL_Timers.c】
static void osalTimerUpdate( uint16 updateTime )
{
halIntState_t intState;
osalTimerRec_t *srchTimer;
osalTimerRec_t *prevTimer;
osalTimerRec_t *saveTimer;
//typedef struct
//{
//void *next;
//UINT16 timeout;
//UINT16 event_flag;
//byte task_id;
//} osalTimerRec_t;
HAL_ENTER_CRITICAL_SECTION( intState ); //保存中断状态
// Update the system time
osal_systemClock += updateTime;
//就目前的程序流程来看updateTime=0
// Look for open timer slot
if ( timerHead != NULL )
//osalTimerRec_t *timerHead;
{
// Add it to the end of the timer list
srchTimer = timerHead;
prevTimer = (void *)NULL;
// Look for open timer slot
while ( srchTimer )
{
// Decrease the correct amount of time
if (srchTimer->timeout <= updateTime)
srchTimer->timeout = 0;
else
srchTimer->timeout = srchTimer->timeout - updateTime;
// When timeout, execute the task
if ( srchTimer->timeout == 0 )
{
osal_set_event( srchTimer->task_id, srchTimer->event_flag );
// Take out of list
if ( prevTimer == NULL )
timerHead = srchTimer->next;
else
prevTimer->next = srchTimer->next;
// Next
saveTimer = srchTimer->next;
// Free memory
osal_mem_free( srchTimer );
srchTimer = saveTimer;
}
else
{
// Get next
prevTimer = srchTimer;
srchTimer = srchTimer->next;
}
}
#ifdef POWER_SAVING
osal_retune_timers();
//osal_retune_timers调整CPU睡眠时间到最低的超时值,如果超时值大于RETUNE_THRESHOLD,则睡眠时间将被设置为RETUNE_THRESHOLD
// osal_timer_activate()启动或者停止系统时钟,参数为FALSE或者TRUE
#endif
}
HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts.
}
//所有的定时器都以链表的形式储存着。这段关于系统时钟的程序也没有看懂,真的看的是不明所以,不晓得到底要干什么,请知道的通知说明一下啊,谢谢了
}
#ifdef POWER_SAVING
}
}
//配置时钟服务【hal_timer.c】
uint8 HalTimerConfig (uint8 timerId, uint8 opMode, uint8 channel, uint8 channelMode,
bool intEnable, halTimerCBack_t cBack)
{
uint8 hwtimerid;
hwtimerid = halTimerRemap (timerId);
//API硬件定时器ID与硬件定时器ID的转换,为什么要做这个转换?搞不懂【hal_timer.c】
#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
uint8 halTimerRemap (uint8 timerId)
{
switch (timerId)
{
case HAL_TIMER_0:
return HW_TIMER_3;
case HAL_TIMER_2:
return HW_TIMER_4;
case HAL_TIMER_3:
return HW_TIMER_1;
default:
return HW_TIMER_INVALID;
}
}
if ((opMode & HAL_TIMER_MODE_MASK) && (timerId < HAL_TIMER_MAX) &&
(channelMode & HAL_TIMER_CHANNEL_MASK) && (channel & HAL_TIMER_CHANNEL_MASK))
//检测参数的正确性
{
halTimerRecord[hwtimerid].configured = TRUE;
halTimerRecord[hwtimerid].opMode = opMode;
halTimerRecord[hwtimerid].channel = channel;
halTimerRecord[hwtimerid].channelMode = channelMode;
halTimerRecord[hwtimerid].intEnable = intEnable;
halTimerRecord[hwtimerid].callBackFunc = cBack;
//【hal_timer.c】
// static halTimerSettings_t halTimerRecord[HW_TIMER_MAX];
//typedef struct
//{
// bool configured;
// bool intEnable;
// uint8 opMode;
// uint8 channel;
// uint8 channelMode;
// uint8 prescale;
// uint8 prescaleVal;
// uint8 clock;
// halTimerCBack_t callBackFunc;
//} halTimerSettings_t;
//typedef void (*halTimerCBack_t) (uint8 timerId, uint8 channel, uint8 channelMode);定时器的回调函数
}
else
{
return HAL_TIMER_PARAMS_ERROR;
}
return HAL_TIMER_OK;
}
}
else // !OB_COLD
{
#ifdef ZTOOL_PORT
MT_IndReset();
#endif
/* Initialize Key stuff */
OnboardKeyIntEnable = HAL_KEY_INTERRUPT_DISABLE;
HalKeyConfig( OnboardKeyIntEnable, OnBoard_KeyCallback);
//初始化Key配置,这里是跟安全有关的东西,暂时不讨论
}
}
//可见系统启动参数的作用了冷启动(OB_COLD)中有系统时钟及LED的初始化,而热启动只是重置了一下KEY而已。关于按键的初始化,稍后再做说明
文章评论(0条评论)
登录后参与讨论