请选择 进入手机版 | 继续访问电脑版

CC2540蓝牙开发二 OSAL系统

[复制链接]
陈雪霜 发表于 2021-1-1 10:30:59 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
前言

简朴的运行了下2540的蓝牙Demo,为了应用能顺利跑起来,还需要相识OSAL系统的机制和原理
如有异议,接待留言指正
概述

OSAL 操纵系统抽象层 (Operating System Abstraction Layer),一种类多任务运行的系统资源分配机制,并不是真正意义上的操纵调治系统,但是上层抽象出的API接口对应用开发者比力友好,而且占用资源较少,适用于资源极其有限的硬件平台
框架

OSAL提供调治、内存管理和消息通报功能;HAL提供了对硬件层抽象的访问,将软件层与硬件层举行关联,方便移植

流程

事件可以由中断或其他任务中举行触发,被需要处理惩罚事件的任务获取执行;事件触发后可附带消息体举行数据通报交互


代码解读

初始化事件任务



  • 在主函数 main() 中会调用osalInitTasks举行任务初始化,内部为任务各自维护的初始化函数,自定义新增的任务也可以在此函数内举行初始化
  1. void osalInitTasks( void ){  uint8 taskID = 0;  tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt); //开发事件缓存2 * tasksCnt  /* The tasksEvents allocated pointer must be valid */  if (tasksEvents != NULL)  {          osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));//清除事件缓存  }  else  {    HAL_ASSERT_FORCED();  }    /* LL Task */  LL_Init( taskID++ );  /* Hal Task */  Hal_Init( taskID++ );  /* HCI Task */  HCI_Init( taskID++ );#if defined ( OSAL_CBTIMER_NUM_TASKS )  /* Callback Timer Tasks */  osal_CbTimerInit( taskID );  taskID += OSAL_CBTIMER_NUM_TASKS;#endif  /* L2CAP Task */  L2CAP_Init( taskID++ );  /* GAP Task */  GAP_Init( taskID++ );  /* SM Task */  SM_Init( taskID++ );    /* GATT Task */  GATT_Init( taskID++ );  /* Profiles */  GAPRole_Init( taskID++ );  GAPBondMgr_Init( taskID++ );  GATTServApp_Init( taskID++ );  /* Application */  SimpleBLEPeripheral_Init( taskID );}
复制代码
启动OSAL

简化了未生效的预编译


  • osal_start_system:OSAL启动函数,在for循环中执行osal_run_system()
  1. void osal_start_system( void ){        for(;;)  // Forever Loop        {                osal_run_system(); //osal运行系统        }}
复制代码
任务事件管理



  • 根据tasksEvents来判断是否有事件,序号idx从0开始遍历,所以tasksArr函数指针数组中靠前的任务优先级较高;const uint8 tasksCnt = sizeof( tasksArr ) / sizeof( tasksArr[0] );与任务事件表长度对应

  • tasksEvents开发的缓存中,为每个任务分配了两个字节(与任务偏移序号一一对应),每个bit代表一个事件(每个任务支持最大16个事件),非0则体现存在需要处理惩罚的事件
  1. void osal_run_system( void ){        uint8 idx = 0;        do {                if (tasksEvents[idx])  // 从高优先级判断是否有事件                {                        break;                }        } while (++idx < tasksCnt);        if (idx < tasksCnt)//判断索引是否有效        {                uint16 events;                halIntState_t intState;                HAL_ENTER_CRITICAL_SECTION(intState); // 关中断                events = tasksEvents[idx]; //提取任务事件                tasksEvents[idx] = 0;  // 清除当前任务事件                HAL_EXIT_CRITICAL_SECTION(intState);//开中断                activeTaskID = idx; //生效任务标志,在osal内部使用                events = (tasksArr[idx])( idx, events );//执行对应事件的任务函数                activeTaskID = TASK_NO_TASK;//执行完成 失效任务标志                HAL_ENTER_CRITICAL_SECTION(intState);//关中断                tasksEvents[idx] |= events;  // 增加任务返回的事件                HAL_EXIT_CRITICAL_SECTION(intState);//开中断        }}
复制代码
应用任务

在SimpleBle工程中自定义了两个事件


  • 设备启动事件(SBP_START_DEVICE_EVT):用于蓝牙启动想要执行的操纵(蓝牙状态回调);
  • 周期性定时事件(SBP_PERIODIC_EVT):定时处理惩罚事件
  1. // Simple BLE Peripheral Task Events#define SBP_START_DEVICE_EVT                              0x0001 //设备启动事件#define SBP_PERIODIC_EVT                                   0x0002 //周期性定时事件
复制代码
工程协议栈中定义了全局的事件 SYS_EVENT_MSG,固定为0x8000
  1. uint16 SimpleBLEPeripheral_ProcessEvent( uint8 task_id, uint16 events ){        VOID task_id; // OSAL required parameter that isn&#39;t used in this function        if ( events & SYS_EVENT_MSG ) // 系统自带的全局事件        {                uint8 *pMsg;//吸收消息指针                if ( (pMsg = osal_msg_receive( simpleBLEPeripheral_TaskID )) != NULL )//读取缓存数据                {                        simpleBLEPeripheral_ProcessOSALMsg( (osal_event_hdr_t *)pMsg );//处理惩罚数据                        // Release the OSAL message                        VOID osal_msg_deallocate( pMsg );//释放数据缓存资源                }                // return unprocessed events                return (events ^ SYS_EVENT_MSG);//清除当前执行事件,返回未处理惩罚事件        }        if ( events & SBP_START_DEVICE_EVT )//启动事件        {                // Start the Device                VOID GAPRole_StartDevice( &simpleBLEPeripheral_PeripheralCBs );//设备启动                // Start Bond Manager                VOID GAPBondMgr_Register( &simpleBLEPeripheral_BondMgrCBs );//注册绑定回调                // Set timer for first periodic event                osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_PERIODIC_EVT, SBP_PERIODIC_EVT_PERIOD );//启动周期事件                return ( events ^ SBP_START_DEVICE_EVT );//清除当前执行事件,返回未处理惩罚事件        }        if ( events & SBP_PERIODIC_EVT )//周期事件        {                // Restart timer                if ( SBP_PERIODIC_EVT_PERIOD )//时间有效                {                        osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_PERIODIC_EVT, SBP_PERIODIC_EVT_PERIOD );//每次生效后需要重新启动                }                // Perform periodic application task                performPeriodicTask();//定时处理惩罚的任务                return (events ^ SBP_PERIODIC_EVT);//清除当前执行事件,返回未处理惩罚事件        }        // Discard unknown events        return 0; //无事件返回0}
复制代码
消息收发

任务间需要有数据交互时,可以使用消息机制举行数据收发



  • 系统使用了堆空间分配的方法,在TSK1任务一中开发缓存存储需要发送的数据,TSK2任务二吸收到消息处理惩罚完成后举行释放,通过指针所在的方式举行通报
消息发送接口:uint8 osal_msg_send( uint8 destination_task, uint8 *msg_ptr ),内部会自动触发SYS_EVENT_MSG系统事件


  • destination_task :任务id,系统初始化时唯一分配
  • msg_ptr:消息缓存
截取一段按键消息发送的例子


  • 消息的数据布局可以参考按键消息的数据布局举行修改,必须指定通报给的任务Id
  1. uint8 OnBoard_SendKeys( uint8 keys, uint8 state ){        keyChange_t *msgPtr;        if ( registeredKeysTaskID != NO_TASK_ID )        {                // Send the address to the task                msgPtr = (keyChange_t *)osal_msg_allocate( sizeof(keyChange_t) ); //分配消息缓存,数据布局可自定义                if ( msgPtr )                {                        msgPtr->hdr.event = KEY_CHANGE;//消息类型                        msgPtr->state = state;                         msgPtr->keys = keys;                        osal_msg_send( registeredKeysTaskID, (uint8 *)msgPtr ); //发送消息                }                return ( SUCCESS );        }        else        return ( FAILURE );}
复制代码
消息吸收接口:uint8 *osal_msg_receive( uint8 task_id )匹配任务Id乐成后返回吸收到的消息缓存所在,数据调用完成后必须释放,否则会出现内存泄漏
  1. if ( events & SYS_EVENT_MSG ) // 系统自带的全局事件{    uint8 *pMsg;    if ( (pMsg = osal_msg_receive( simpleBLEPeripheral_TaskID )) != NULL )//读取缓存数据    {        simpleBLEPeripheral_ProcessOSALMsg( (osal_event_hdr_t *)pMsg );//处理惩罚数据        // Release the OSAL message        VOID osal_msg_deallocate( pMsg );//释放数据缓存资源    }    // return unprocessed events    return (events ^ SYS_EVENT_MSG);//清除当前执行事件,返回未处理惩罚事件}
复制代码
事件发送函数:uint8 osal_set_event( uint8 task_id, uint16 event_flag )可以自定义事件并调取该接口触发事件任务
消息数据通报机制:osal系统通过单链表的方式举行对消息缓存的增删管理
  1. typedef struct{    void   *next;     #ifdef OSAL_PORT2TIRTOS    /* Limited OSAL port to TI-RTOS requires compatibility with ROM    * code compiled with USE_ICALL compile flag.  */    uint32 reserved;    #endif /* OSAL_PORT2TIRTOS */    uint16 len;    uint8  dest_id;} osal_msg_hdr_t;#endif /* USE_ICALL */
复制代码
总结

OSAL适用于资源有限的硬件平台,通过遍历事件缓存列表来调治到指定的任务中, 任务间通过可消息来举行通信,对其举行裁剪后可以方便移植到自己的其他应用平台中

来源:https://blog.csdn.net/libin55/article/details/111942621
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

发布主题

专注素材教程免费分享
全国免费热线电话

18768367769

周一至周日9:00-23:00

反馈建议

27428564@qq.com 在线QQ咨询

扫描二维码关注我们

Powered by Discuz! X3.4© 2001-2013 Comsenz Inc.( 蜀ICP备2021001884号-1 )