原创 【原创】ZigBee学习之25——InitBoard

2010-2-11 10:21 3697 4 4 分类: MCU/ 嵌入式

//初始化板上的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)


//前提条件是定义了闪烁LEDLED硬件驱动服务使能;


// 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而已。关于按键的初始化,稍后再做说明

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
4
关闭 站长推荐上一条 /3 下一条