This article is based on the protocol stack 1.3.2, please respect the original
General Introduction :
Osal provides a timer that can function with a callback function, which is implemented mainly in the OSAL_CTIMER.C and osal_cbtimer.h two files. The callback timer is a callback function registered on the basis of the Osal software timer, which executes the pre-registered callback function when the timer time is reached. Compared to the event timer comparison is: Callback timer with a task to handle all callback timer related events, each task can handle 15 callback timer events, event flag Events bit0 ~ bit14 is the callback Timer event flag, bit15 is Sys_event_ MSG System message events, can not be used for callback timers, of course, you can define the two consecutive tasks to handle the callback timer related events, then how much 30 of the callback timer event could be handled.
is an instance of a task used to handle callback timer events. Bit0 ~bit14 is the event ID corresponding to the callback timer, and each bit is a callback timer event
Technical details Resolution 1, defining the structure of the callback timer
The structure of the callback timer is very simple and requires only two elements: one is a function pointer to the callback function, and the other is the argument to pass to the callback function . As follows:
// Callback Timer structurestruct{ // callback function to be called when timer expires uint8 *pData; // data to be passed in to callback function} cbTimer_t;
pfncbtimer_t is a defined function pointer type with a parameter that executes the function that the pointer points to when the timer time is reached:
typedef void (*pfnCbTimer_t)( uint8 *pData );
//definitions of several constant macros//The most callback timers available for each task #define num_cbtimers_per_task//Total number of callback timers#define num_cbtimers (Osal_cbtimer_num_tasks * num_cbtimers_per_task)//Where Osal_cbtimer_num_tasks is set in the Pre-compilation option and is set to Osal_cbtimer_num_tasks=1 by default//Find out event ID using timer ID//To find the event ID based on the Timer ID, each task handling the callback function can handle 15 callback events. Each task's 15 callback timer corresponds to the event ID of the Bit0 ~ bit14 bit, bit15 corresponding SYS_EVENT_MSG system message events, can not be used for callback timer use, just here to take the remainder of 15 to remove, so the traversal will not traverse to the timer ID 15. #define event_id (Timerid) (0x0001 << ((timerid)% num_cbtimers_per_task))//Find out task ID using timer ID//Find the task ID according to the timer ID, note that the following is divisible, the macro used to take the remainder. #define task_id (Timerid) (((Timerid)/num_cbtimers_per_task) + Basetaskid)Basetaskid is that the system continuously allocates multiple tasks for processing the callback timer, then the task ID (task ID) of the first task is basetaskid; For example, the system continuously assigns two tasks to handle callback timer events, their task IDs are8,9, then the value of Basetaskid is8。//Find out bank task ID using task ID//Find the starting number of the callback timer corresponding to the task ID according to the task ID#define bank_task_id (taskId) ((Basetaskid-(taskId)) * num_cbtimers)This macro definition may be ble Stack1.3Version of a bug. As I said before, Basetaskid is the task ID of the first task that the system continuously assigns to handle multiple tasks of the callback timer, while TaskID is the corresponding callback timer Taks Id,taskid should be greater than basetaskid, so the above macro definition should be changed to:#define bank_task_id (TaskId) (((taskId)-basetaskid) * num_cbtimers)The bank_task_id can be understood as the starting number for different tasks corresponding to the callback timer. For example, the system assigns a task ID of8、9Tasks to handle callback timer events, and each task corresponds to a theCallback timers, giving these timers a0~ inNumber, so bank_task_id (8) represents TaskID as8The starting number of the callback timer that corresponds to the task (8-8)* the=0, bank_task_id (9) indicates that the task ID is9The starting number of the callback timer that corresponds to the task (9-8)* the= the。
Several variable initialization
// Callback Timer base task id回调定时器的基任务IDuint160xFF,在初始化回调定时器时它则会记录起始的task id。// Callback Timers table.#if ( NUM_CBTIMERS > 0 ) cbTimer_t cbTimers[NUM_CBTIMERS];#endif//定义一个回调定时器的数组,这个数组的类型是cbTimer_t,每个数组元素对应一个回调定时器都管理着对应的回调函数指针与要传递的参数。
API parsing Osal_cbtimerinit
void osal_CbTimerInit( uint8 taskId ){ if ( baseTaskID == TASK_NO_TASK ) { // Only initialize the base task id//初始化回调定时器的基址任务id, baseTaskID baseTaskID = taskId; // Initialize all timer structures对所有回调定时器结构清零 0sizeof( cbTimers ) ); }}
Call the Osal_cbtimerinit () function in the osal_simpleblecentral.c file, as you can see from the code below, if Osal_cbtimer_num_tasks = 2 then TaskID will add 2, In other words, there are two events that handle the callback function, which can handle 30 callback events. However, in the project, the default is 1, only 15 callback timers can be defined, in response to 15 callback functions
#if defined ( OSAL_CBTIMER_NUM_TASKS ) /* Callback Timer Tasks */ osal_CbTimerInit( taskID ); taskID += OSAL_CBTIMER_NUM_TASKS;#endif
The event execution function of the callback function osal_cbtimerprocessevent
uint16Osal_cbtimerprocessevent (uint8TaskId,uint16Events) {//Judgment there is a seizure to the system message if(Events & Sys_event_msg) {//Process osal messages //Return unprocessed events return(events ^ sys_event_msg); }if(events) {uint8Iuint16Event//Process Event Timers //Handling TaskID callback Timer events for(i =0; i < Num_cbtimers_per_task; i++) {//processing logic is a callback event that discovers the event set ID, events, enters the if structure and then exits if(Events >> i) &0x0001) {//Get TaskID expiration callback timer struct, assign to struct pointercbtimer_t *ptimer = &cbtimers[bank_task_id (taskId) +i];//Found the first event //Find the event ID of the callback timer for this processing, and then, with the return time, remove the event ID from event set eventsevent =0x0001 << i;//Timer expired, call the registered callback function //callback function to execute the callback timer registrationPtimer->pfncbtimer (Ptimer->pdata);after executing the callback function of the callback timer, clear the callback function and its arguments //Mark entry as freePtimer->pfncbtimer = NULL;//Null out data pointerPtimer->pdata = NULL;//We only process one event at a time //Each entry executes an event Break; } }//Return unprocessed events return(events ^ event); }//If reach here, the events is unknown //Discard or make more handlers//Execute to Here Description No callback Timer event sent return0;}
Osal_cbtimerstart
Osal_cbtimerstart () starts a callback timer, timed only once, the function is essentially the same as starting a osal software timer, but also to pass the address and data address of the callback function, but the difference between him and the software timer is:
1, the number of software timers is unlimited, and the callback timer is limited.
2. Start a software timer to pass the task ID and Event ID and timeout, while starting a callback timer passes the address and data address of the callback function, as well as the time-out and the variable address of the record timer ID.
Parameters:
pfncbtimer-the callback function pointer to be registered
pdata-the data parameters to pass
Timing time of the timeout-timer
Ptimerid-Find the callback timer ID, use that pointer to point to it
1. Find the first available callback timer
for(i =0; i < num_cbtimers; i++) {if(Cbtimers[i].pfncbtimer = =NULL)//NULL indicates that the timer is available{//Start the Osal event timer FirstTimer service to start the timersif(Osal_start_timerex (task_id (i), event_id (i), timeout) = = SUCCESS) {//Set up the callback timer //Fill callback function address and parametersCbtimers[i].pfncbtimer = Pfncbtimer; Cbtimers[i].pdata = PData;if(Ptimerid! =NULL) {//Caller is intreseted in the timer ID //Assign the ID of the callback timer to the contents of the Ptimerid pointer*ptimerid = i; }return(SUCCESS); } } }
When the timer is started, the time expires, and the processing entry address of the callback function is obtained in the task event polling;
In the entry address array
#if defined ( OSAL_CBTIMER_NUM_TASKS ) OSAL_CBTIMER_PROCESS_EVENT( osal_CbTimerProcessEvent ),#endif
This code means if Osal_cbtimer_num_tasks = 2, then there are two callback handler functions osal_cbtimerprocessevent, the processing function is the same, but the task ID is not the same, so the processing of callback timer events are not the same.
Osal_cbtimerupdate
status_t osal_cbtimerupdate (uint8 timerid, uint16 timeout)
Parameters:
Timerid-Callback Timer ID
timeout-the timing value to update
The function is to update the timer with the callback timer ID Timerid to timeout, and if it does not time out, update its timeout with timeout.
if ( timerId < NUM_CBTIMERS )//定时器id不能超过总的回调定时器数 { ifNULL )//确保该定时器id已经启动 { // Make sure the corresponding OSAL event timer is still running//如果相应的定时器还在运行 if0 ) { // Timer exists; update it更行已存在的回调定时器的超时时间 osal_start_timerEx( TASK_ID( timerId ), EVENT_ID( timerId ), timeout ); return ( SUCCESS ); } } }
Osal_cbtimerstop
status_t osal_cbtimerstop (uint8 timerid)
Parameter: Timerid is the ID of the callback timer to be canceled
The function implements the function is to stop a callback timer
// Look for the existing timer if ( timerId < NUM_CBTIMERS ) { ifNULL ) { // Timer exists; stop the OSAL event timer first //可以看到也只是停止了相应的定时器,然后回调地址和数据指针清空 osal_stop_timerEx( TASK_ID( timerId ), EVENT_ID( timerId ) ); // Mark entry as free NULL; // Null out data pointer NULL; return ( SUCCESS ); } }
Correlation analysis of callback timer of Osal