TI OSAL解析

来源:互联网 发布:知乎评价章泽天长相 编辑:程序博客网 时间:2024/06/06 12:32

SYD8801是一款低功耗高性能蓝牙低功耗SOC,集成了高性能2.4GHz射频收发机、32位ARM Cortex-M0处理器、128kB Flash存储器、以及丰富的数字接口。SYD8801片上集成了Balun无需阻抗匹配网络、高效率DCDC降压转换器,适合用于可穿戴、物联网设备等。具体可咨询:http://www.syd-tek.com/

TI OSAL 解析

    先看看《OSAL操作系统-实验01 OSAL初探》中对osal的main函数的解析解析:

int main(void)

{

  /*Initialize hardware */

 HAL_BOARD_INIT();      //初始化时钟稳定时钟等等

 

  //Initialize board I/O

  //冷启动,关闭了led灯与中断, 一边接下来的各种初始化不受干扰

 InitBoard( OB_COLD );

 

  /*Initialze the HAL driver */

 HalDriverInit();   //各种驱动的初始化、如按键、lcd、adc、usb、uart等

 

  /*Initialize NV system */

 //snv 内部用于保存配对数据或你的用户自定义数据的一段flash,4kB空间

 osal_snv_init();

 

  /*Initialize LL */

 

  /*Initialize the operating system */

 //oasl 操作系统初始化, 包含内存分配、消息队列、定时器、电源管理和任务等

  osal_init_system();

 

  /*Enable interrupts */

 HAL_ENABLE_INTERRUPTS();// 开启全局中断

 

  //Final board initialization

 InitBoard( OB_READY );      //设置标志标示系统初始化完毕

 

  #ifdefined ( POWER_SAVING )

  // 如果你使能了低功耗, 就启动低功耗模式,

   osal_pwrmgr_device( PWRMGR_BATTERY );

 #endif

/*

低功耗部分

1.如何总是在PM1

 osal_pwrmgr_device( PWRMGR_ALWAYS_ON );

2.如何进入PM2

 osal_pwrmgr_device( PWRMGR_BATTERY );在空闲的时候就会进入到PM2模式

3.如何进入PM3

  存在连接就断开连接,存在广播就停掉广播,并确认自己创建的所有定时任务都已关闭,

  则系统应该就会进入PM3模式,只能进行外部中断唤醒

*/

 

  /*Start OSAL */

 osal_start_system(); // No Return from here

/* osal 操作系统启动,实际上是一个大循环,只是检查相对应的标志位,

就指定相对应的任务,看到这里,同学们应该往哪里看呢?其实,这已经是尽头了?那么我们的应用程序是在哪里写的呢

其实是在上面的上面的函数 osal_init_system 里就初始化了,现在回过头去看看

osal_init_system 这个函数内部就知道了

*/   

 return 0;

}


    涉及osal的有三个函数:

  /*Initialize NV system */

 //snv 内部用于保存配对数据或你的用户自定义数据的一段flash,4kB空间

 osal_snv_init();

  /*Initialize the operating system */

 //oasl 操作系统初始化, 包含内存分配、消息队列、定时器、电源管理和任务等

  osal_init_system();

  /*Start OSAL */

 osal_start_system(); // No Return from here

    下面是《OSAL操作系统-实验01 OSAL初探》的主函数:
int main(void)
{
  /* Initialize hardware */
  HAL_BOARD_INIT();

  // Initialize board I/O
  InitBoard( OB_COLD );

  /* Initialze the HAL driver */
  HalDriverInit();

  /* Initialize NV system */
  osal_snv_init();

  /* Initialize LL */

  /* Initialize the operating system */
  osal_init_system();

  /* Enable interrupts */
  HAL_ENABLE_INTERRUPTS();

  // Final board initialization
  InitBoard( OB_READY );

  #if defined ( POWER_SAVING )
    osal_pwrmgr_device( PWRMGR_BATTERY );
  #endif

  /* Start OSAL */
  osal_start_system(); // No Return from here

  return 0;
}

    我们先从 osal_start_system中的osal_run_system函数的任务调度部分开始:

  do {
    if (tasksEvents[idx])  // Task is highest priority that is ready.
    {
      break;
    }
  } while (++idx < tasksCnt);

  if (idx < tasksCnt)
  {
    uint16 events;
    halIntState_t intState;

    HAL_ENTER_CRITICAL_SECTION(intState);
    events = tasksEvents[idx];
    tasksEvents[idx] = 0;  // Clear the Events for this task.
    HAL_EXIT_CRITICAL_SECTION(intState);

    activeTaskID = idx;
    events = (tasksArr[idx])( idx, events );
    activeTaskID = TASK_NO_TASK;

    HAL_ENTER_CRITICAL_SECTION(intState);
    tasksEvents[idx] |= events;  // Add back unprocessed events to the current task.
    HAL_EXIT_CRITICAL_SECTION(intState);
  }

    这里是通过tasksEvents判断任务有没有挂起,我们看看他的定义:

const uint8 tasksCnt = sizeof( tasksArr ) / sizeof( tasksArr[0] );
uint16 *tasksEvents;

void osalInitTasks( void )
{
  uint8 taskID = 0;

  tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
  osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));

  .................

}

    从这里可以看出tasksEvents是一个uint16 *指针数组,tasksArr中每一个任务都分配了一个tasksEvents,也就是16位的标志位。只要相应的tasksEvents标志位非0则认为该任务条件被触发!下面就是设置和清除事件的函数:

/*********************************************************************
 * @fn      osal_set_event
 *
 * @brief
 *
 *    This function is called to set the event flags for a task. The
 *    event passed in is OR'd into the task's event variable.
 *
 * @param   uint8 task_id - receiving tasks ID
 * @param   uint8 event_flag - what event to set
 *
 * @return  SUCCESS, INVALID_TASK
 */
uint8 osal_set_event( uint8 task_id, uint16 event_flag )
{
  if ( task_id < tasksCnt )
  {
    halIntState_t   intState;
    HAL_ENTER_CRITICAL_SECTION(intState);    // Hold off interrupts
    tasksEvents[task_id] |= event_flag;  // Stuff the event bit(s)
    HAL_EXIT_CRITICAL_SECTION(intState);     // Release interrupts
    return ( SUCCESS );
  }
   else
  {
    return ( INVALID_TASK );
  }
}

/*********************************************************************
 * @fn      osal_clear_event
 *
 * @brief
 *
 *    This function is called to clear the event flags for a task. The
 *    event passed in is masked out of the task's event variable.
 *
 * @param   uint8 task_id - receiving tasks ID
 * @param   uint8 event_flag - what event to clear
 *
 * @return  SUCCESS, INVALID_TASK
 */
uint8 osal_clear_event( uint8 task_id, uint16 event_flag )
{
  if ( task_id < tasksCnt )
  {
    halIntState_t   intState;
    HAL_ENTER_CRITICAL_SECTION(intState);    // Hold off interrupts
    tasksEvents[task_id] &= ~(event_flag);   // Clear the event bit(s)
    HAL_EXIT_CRITICAL_SECTION(intState);     // Release interrupts
    return ( SUCCESS );
  }
   else
  {
    return ( INVALID_TASK );
  }
}

    回到osal_run_system函数当发现有任务运行的时候就调用events = (tasksArr[idx])( idx, events );执行指针函数!

    osal_set_event函数的调用流程(例子:Peripheral.c (projects\ble\profiles\roles):        VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT );):

VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT );
           

  -------》


void GAPRole_Init( uint8 task_id )
{
  gapRole_TaskID = task_id;

  gapRole_state = GAPROLE_INIT;
  gapRole_ConnectionHandle = INVALID_CONNHANDLE;

....................

}


--》

void osalInitTasks( void )
{
  uint8 taskID = 0;
...................................

  /* GATT Task */
  GATT_Init( taskID++ );
...............................
}


->>>
const pTaskEventHandlerFn tasksArr[] =
{
.....................................................
  GAPRole_ProcessEvent,                                             // task 8
...........................................
};


->>>

uint16 GAPRole_ProcessEvent( uint8 task_id, uint16 events )
{
  VOID task_id; // OSAL required parameter that isn't used in this function
.................................................
  if ( events & START_ADVERTISING_EVT )
  {
    if ( gapRole_AdvEnabled )
    {
      gapAdvertisingParams_t params;

      // Setup advertisement parameters
      params.eventType = gapRole_AdvEventType;
      params.initiatorAddrType = gapRole_AdvDirectType;
      VOID osal_memcpy( params.initiatorAddr, gapRole_AdvDirectAddr, B_ADDR_LEN );
      params.channelMap = gapRole_AdvChanMap;
      params.filterPolicy = gapRole_AdvFilterPolicy;

      if ( GAP_MakeDiscoverable( gapRole_TaskID, &params ) != SUCCESS )
      {
        gapRole_state = GAPROLE_ERROR;
        
        // Notify the application with the new state change
        if ( pGapRoles_AppCGs && pGapRoles_AppCGs->pfnStateChange )
        {
          pGapRoles_AppCGs->pfnStateChange( gapRole_state );
        }
      }
    }
    return ( events ^ START_ADVERTISING_EVT );
  }
.............................................................
}

这里给params结构体赋值,包括了广播类型,广播通道等等!


0 0
原创粉丝点击