SYD8801是一款低功耗高性能蓝牙低功耗SOC,集成了高性能2.4GHz射频收发机、32位ARM Cortex-M0处理器、128kB Flash存储器、以及丰富的数字接口。SYD8801片上集成了Balun无需阻抗匹配网络、高效率DCDC降压转换器,适合用于可穿戴、物联网设备等。具体可咨询:http://www.sydtek.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, ¶ms ) != 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结构体赋值,包括了广播类型,广播通道等等!