| ISF 2.2 rev 5 Intelligent Sensing Framework for Kinetis with Processor Expert

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

bus_management.c
Go to the documentation of this file.
1 /*
2 *
3 * Copyright (c) 2015, Freescale Semiconductor, Inc.
4 *
5 */
6
7 /*!
8 * @file bus_management.c
9 * @brief Implements the ISF bus management functionality. This file is
10 * internal ISF code.
11 *
12 */
13
14
15 #include "isf.h"
16 #include "fsl_pit_hal.h"
17 #include "fsl_pit_driver.h"
18 #include "isf_bm.h"
19 #include "bm_internal.h"
20 #include "isf_init.h"
21
22
23 #if (MAX_BM_CALLBACKS > 32)
24 // Note that we use a 32 bit variable for token values of callbacks. Each bit
25 // if for one callback. Thus, the absolute maximum number of callbacks we can
26 // have is 32. Ideally though, we really should have less than this because the
27 // system will experience additional latency in handling each callback added.
28 #error MAX_BM_CALLBACKS exceeds maximum
29 #endif
30
31 #define BM_TOKEN_STARTING_VAL (0x100) // Must be a non-zero value!
32 #if OS_MQXLITE
33 BM_STATIC LWEVENT_STRUCT event_bm_callback;
34 BM_STATIC LWSEM_STRUCT sema_bm_access;
35 #else
36 BM_STATIC event_t event_bm_callback;
37 BM_STATIC semaphore_t sema_bm_access;
38 #endif
39 BM_STATIC BM_VOLATILE bm_cb_config_t *gpBm_cb_list[MAX_BM_CALLBACKS];
40 BM_STATIC BM_VOLATILE bool gBm_firsttime_flag = FALSE;
41 BM_STATIC BM_VOLATILE bool gBm_state_change = FALSE;
42 BM_STATIC BM_VOLATILE bool gBm_cb_occurred = FALSE;
43
44 // Internal bus manager data.
45 bm_t bm;
46
47 /* Task1 task name */
48 #define BM_TASK_NAME ISF_TASK_BM_NAME
49 /* Task1 task stack size */
50 #define BM_TASK_STACK_SIZE ISF_TASK_BM_STACK_SIZE
51 /* Task1 task priority value */
52 #define BM_TASK_PRIORITY ISF_TASK_BM_PRIORITY
53
54 OSA_TASK_DEFINE(BM, BM_TASK_STACK_SIZE);
55
56 void BM_task(os_task_param_t task_init_data);
57 extern void isf_system_sync(void);
58
59 #ifdef BM_DEBUG_TRACE_BUFFER
60 typedef struct
61 {
62 volatile uint32 timestamp;
63 volatile uint32 current_period_before_adj;
64 volatile uint32 current_period_after_adj;
65 volatile uint32 cb_timeleft[2];
66 volatile uint32 cb_event;
67 } bm_debug_t;
68
69 #define BM_DEBUG_TRACEBUF_MAX 50
70 volatile int32 bmdebug_idx = 0;
71 volatile uint32 bmdebug_isr_cnt = 0;
72 volatile bm_debug_t bmdebug[BM_DEBUG_TRACEBUF_MAX];
73 #endif
74
75 void isr_bm_callback_tmr (void *dummy);
76 isf_status_t bm_init(void);
77 void task_bm(uint32 initial_data);
78 uint32 bm_update_cb_list(void);
79
80 // Internal functions
81 int bm_find_cb(bm_callback_token_t aToken);
82 bm_callback_token_t bm_generate_token(void);
83 void bm_sort_cb_list(void);
84 void bm_reset_period(void);
85 uint32 bm_find_smallest_active_period(int8 period_type);
86
87 // Declare externs to variables for PIT instance constants.
88 extern uint32 bmPITInstance;
89 extern uint32 bmRolloverPeriod;
90 extern void bm_timer_init(void);
91
92 // Schedule a callback at a particular rate
93 //
94 bm_callback_token_t bm_register_periodic_callback(
95 isf_duration_t aPeriod,
96 bm_callback_t *pCallback,
97 void *pCbData
98 )
99 {
100
101 bm_callback_token_t ret_token = BM_ERROR;
102
103 #if OS_MQXLITE
104 _lwsem_wait_ticks(&sema_bm_access, 0);
105 #else
106 OSA_SemaWait(&sema_bm_access, OSA_WAIT_FOREVER);
107 #endif
108 if (bm.cb_list_cur_cnt >= MAX_BM_CALLBACKS)
109 {
110 // Error: Number of callbacks exceeds limit.
111 ret_token |= COMM_ERROR_NOEXIST;
112 }
113 else if (pCallback == NULL)
114 {
115 // Error: Callback is null.
116 ret_token |= COMM_ERROR_NULL_PTR;
117 }
118 else if ((aPeriod < MIN_BM_PERIOD_USEC) || (aPeriod > MAX_BM_PERIOD_USEC))
119 {
120 // Error: period is outside of valid range.
121 ret_token |= COMM_ERROR_NOEXIST;
122 }
123 else
124 {
125 void *pCb;
126
127 ret_token = bm_generate_token();
128 if (ret_token)
129 {
130 // If new token is non-zero then its a valid unique token.
131
132 //Create new callback.
133 pCb = BM_ALLOC_MEM_ZERO(sizeof(bm_cb_config_t));
134
135 if (pCb != NULL)
136 {
137
138 gpBm_cb_list[bm.cb_list_cur_cnt] = pCb;
139 gpBm_cb_list[bm.cb_list_cur_cnt]->Period = aPeriod;
140 gpBm_cb_list[bm.cb_list_cur_cnt]->Cur_period = gpBm_cb_list[bm.cb_list_cur_cnt]->Period;
141 gpBm_cb_list[bm.cb_list_cur_cnt]->pCallback = pCallback;
142 gpBm_cb_list[bm.cb_list_cur_cnt]->pCbData = pCbData;
143 gpBm_cb_list[bm.cb_list_cur_cnt]->nToken = ret_token;
144
145 // Marked new callback as registered.
146 bm.cb_token_registered_mask |= ret_token;
147
148 bm.cb_list_cur_cnt++;
149
150 // Sort the list with smallest period first.
151 bm_sort_cb_list();
152
153 gBm_state_change = TRUE;
154
155 }
156 }
157
158 if ( (!ret_token) || (pCb == NULL) )
159 {
160 // Maximum callbacks reached or could not alloc mem for callback.
161 ret_token |= COMM_ERROR_NOEXIST;
162 }
163 }
164 #if OS_MQXLITE
165 _lwsem_post(&sema_bm_access);
166 #else
167 OSA_SemaPost(&sema_bm_access);
168 #endif
169 return ret_token;
170 }
171
172
173
174
175
176 // Unregister a callback
177 //
178 isf_status_t bm_unregister_callback( bm_callback_token_t aToken )
179 {
180
181 isf_status_t ret = ISF_SUCCESS;
182 int cb_index;
183
184 #if OS_MQXLITE
185 _lwsem_wait_ticks(&sema_bm_access, 0);
186 #else
187 OSA_SemaWait(&sema_bm_access, OSA_WAIT_FOREVER);
188 #endif
189
190 // Find index in the list with matching token.
191 cb_index = bm_find_cb(aToken);
192
193 if (cb_index != -1)
194 {
195 // List compactor.
196
197 // Note that it is possible to get interrupted during unregistration
198 // process. Must disable irq.
199 #if OS_MQXLITE
200 __disable_interrupt();
201 #else
202 OSA_EnterCritical(kCriticalDisableInt);
203 #endif
204 // Remove callback.
205 BM_FREE_MEM((void*)gpBm_cb_list[cb_index]);
206
207 // Compact the list to keep it contiguous. Move cbs down lower in array.
208 while((cb_index+1) < bm.cb_list_cur_cnt) // If cb exist one index higher...
209 {
210 gpBm_cb_list[cb_index] = gpBm_cb_list[cb_index+1]; // ...then move it down.
211 ++cb_index;
212 }
213 gpBm_cb_list[cb_index] = NULL; // Last index is NULL
214
215 // Remove callback from the masks.
216 bm.cb_token_registered_mask &= ~aToken;
217 bm.cb_token_active_mask &= ~aToken;
218
219 gBm_state_change = TRUE;
220
221 --bm.cb_list_cur_cnt;
222 #if OS_MQXLITE
223 // Startup irq again.
224 __enable_interrupt();
225 #else
226 OSA_ExitCritical(kCriticalDisableInt);
227 #endif
228
229 }
230 else
231 ret = BM_ERROR | COMM_ERROR_NOEXIST;
232
233 if (bm.cb_token_registered_mask)
234 {
235 // Restart timer only if there's callback(s) registered.
236 // TODO: Figure out how to restart timer OR whether this is necessary code anymore.
237 }
238
239 #if OS_MQXLITE
240 _lwsem_post(&sema_bm_access);
241 #else
242 OSA_SemaPost(&sema_bm_access);
243 #endif
244
245
246 return ret;
247 }
248
249
250
251
252 uint32 bm_get_num_callback(void)
253 {
254 uint32 num_callback;
255
256 #if OS_MQXLITE
257 _lwsem_wait_ticks(&sema_bm_access, 0);
258 #else
259 OSA_SemaWait(&sema_bm_access, OSA_WAIT_FOREVER);
260 #endif
261
262 num_callback = (uint32)bm.cb_list_cur_cnt;
263
264 #if OS_MQXLITE
265 _lwsem_post(&sema_bm_access);
266 #else
267 OSA_SemaPost(&sema_bm_access);
268 #endif
269
270 return num_callback;
271 }
272
273
274
275 // TODO - Add interface to allow initialization of the first period to be a fixed phase offset inside the overall period/rate selected.
276 // This will require a new BM configuration parameter called "phase". The parameter must be validated to be less than the period.
277 // The gpBm_cb_list should be initialized to contain this first period and include it in the first CurPeriod calculation, then zero it.
278 isf_status_t bm_start(boolean aSync, bm_callback_token_t aTokens)
279 {
280 isf_status_t ret = ISF_SUCCESS;
281 bm_callback_token_t tokens_start;
282
283 #if OS_MQXLITE
284 _lwsem_wait_ticks(&sema_bm_access, 0);
285 #else
286 OSA_SemaWait(&sema_bm_access, OSA_WAIT_FOREVER);
287 #endif
288
289
290 if (aTokens == BM_ALL_TOKENS)
291 aTokens = bm.cb_token_registered_mask;
292
293 // This will mask out unregistered callbacks.
294 tokens_start = bm.cb_token_registered_mask & aTokens;
295
296 // The masked token value should equal to given token value. If not,
297 // it means that caller is trying to start unregistered callbacks which
298 // is an error.
299 if ( (bm.cb_list_cur_cnt) && (tokens_start == aTokens) && (aTokens) )
300 {
301 // Stop the timer.
302 PIT_DRV_StopTimer(ISF_BM_PIT_INSTANCE,ISF_BM_PIT_CHANNEL_NO);
303
304 // Enable desired callbacks. For those callbacks already enabled, we
305 // leave their state as is.
306 bm.cb_token_active_mask |= tokens_start;
307
308 // To sync all callbacks, reset all current period.
309 bm_reset_period();
310
311 // capture the callback events into the pipeline buffer.
312 bm.cb_events[0] = bm_update_cb_list();
313
314 //pit_set_timer_period_us(bmPITInstance,bm.time_keeper_usec);
315 PIT_DRV_SetTimerPeriodByUs(ISF_BM_PIT_INSTANCE,ISF_BM_PIT_CHANNEL_NO,bm.time_keeper_usec);
316
317 // Just clear the interrupt flag
318 PIT_HAL_ClearIntFlag(g_pitBase[ISF_BM_PIT_INSTANCE], 0U);
319
320 // Need to stop timer.
321 PIT_DRV_StopTimer(ISF_BM_PIT_INSTANCE,ISF_BM_PIT_CHANNEL_NO);
322
323 // Start the PIT timer running.
324 PIT_DRV_StartTimer(ISF_BM_PIT_INSTANCE,ISF_BM_PIT_CHANNEL_NO);
325
326 // We know that we are going to fill the pipeline, so we can set the values here.
327 bm.cb_events[1] = bm_update_cb_list();
328 bm.pipeline_index = 0;
329
330 // PIT timer is running with last value after pit_timer_start() call above.
331 // We now need to set the LDVAL to the next interval.
332 PIT_DRV_SetTimerPeriodByUs(ISF_BM_PIT_INSTANCE,ISF_BM_PIT_CHANNEL_NO,bm.time_keeper_usec);
333 }
334 else
335 {
336 ret = BM_ERROR | COMM_ERROR_NOEXIST;
337 }
338
339 #if OS_MQXLITE
340 _lwsem_post(&sema_bm_access);
341 #else
342 OSA_SemaPost(&sema_bm_access);
343 #endif
344
345 return ret;
346 }
347
348
349 isf_status_t bm_stop(bm_callback_token_t aTokens)
350 {
351
352 isf_status_t ret = ISF_SUCCESS;
353 bm_callback_token_t tokens_stop;
354
355
356 #if OS_MQXLITE
357 _lwsem_wait_ticks(&sema_bm_access, 0);
358 #else
359 OSA_SemaWait(&sema_bm_access, OSA_WAIT_FOREVER);
360 #endif
361
362
363 if (aTokens == BM_ALL_TOKENS)
364 {
365 // All registered callbacks will be stopped.
366 aTokens = bm.cb_token_registered_mask;
367 }
368
369 // This will mask out unregistered callbacks.
370 tokens_stop = bm.cb_token_registered_mask & aTokens;
371
372
373 // The masked token value should equal to given token value. If not,
374 // it means that caller is trying to stop unregistered callbacks which
375 // is an error.
376 if ( (bm.cb_list_cur_cnt) && (tokens_stop == aTokens) && (aTokens) )
377 {
378 // Remove callbacks from active mask.
379 bm.cb_token_active_mask &= ~tokens_stop;
380
381 if (bm.cb_token_active_mask)
382 {
383 // Start timer again only if at least one callback still active.
384 // Otherwise leave timer inactive.
385 // TODO: Figure out how to restart timer OR whether this is necessary code anymore.
386 }
387
388 gBm_state_change = TRUE;
389
390 }
391 else
392 {
393 ret = BM_ERROR | COMM_ERROR_NOEXIST;
394 }
395
396 #if OS_MQXLITE
397 _lwsem_post(&sema_bm_access);
398 #else
399 OSA_SemaPost(&sema_bm_access);
400 #endif
401
402 return ret;
403
404 }
405
406
407
408 // Reset callback current period state.
409 void bm_reset_period(void)
410 {
411
412 if (bm.cb_list_cur_cnt)
413 {
414 int i = 0;
415
416 while(i < bm.cb_list_cur_cnt)
417 {
418 gpBm_cb_list[i]->Cur_period = gpBm_cb_list[i]->Period;
419 ++i;
420 }
421 }
422
423 }
424
425
426
427 /*!
428 *
429 * @brief Bus management initialization\n
430 *
431 * @return ISF_SUCCESS if initialization is successful.
432 * ISF_ERR_LIB_INIT if initialization failed.
433 *
434 * @errors \n
435 *
436 * @constraints \n
437 *
438 * @reentrant No.
439 *
440 * @libs \n
441 *
442 * @see \n
443 *
444 */
445 isf_status_t bm_init(void)
446 {
447 uint32 i;
448
449 isf_status_t ret = ISF_SUCCESS;
450 #if OS_MQXLITE
451 // Zero out the cb list.
452 _mem_zero(&gpBm_cb_list, sizeof(gpBm_cb_list));
453 #else
454 memset(&gpBm_cb_list, 0, sizeof(gpBm_cb_list));
455 #endif
456 bm.cb_list_cur_cnt = 0;
457
458 bm.pipeline_index = 0;
459
460 for (i=0; i<BM_PIPELINE_STAGES; i++)
461 {
462 bm.cb_events[i] = 0;
463 }
464 bm.cb_token_registered_mask = 0;
465 bm.cb_token_active_mask = 0;
466
467 #ifdef BM_DEBUG
468 bmdebug_isr_cnt = 0;
469 #endif
470
471 #ifdef BM_DEBUG_TRACE_BUFFER
472 _mem_zero((void*)bmdebug, sizeof(bm_debug_t) * BM_DEBUG_TRACEBUF_MAX);
473 #endif
474
475 #if OS_MQXLITE
476 // Create slave port event.
477 _lwevent_create(&event_bm_callback, LWEVENT_AUTO_CLEAR); // Each bit corresponds to a callback in list
478 _lwevent_clear(&event_bm_callback, 0xFFFFFFFF);
479
480 // Create semaphore for access to bm callback list.
481 _lwsem_create(&sema_bm_access, 1);
482 #else
483 OSA_EventCreate(&event_bm_callback, kEventAutoClear);
484 OSA_EventClear(&event_bm_callback, 0x00FFFFFF);
485 OSA_SemaCreate(&sema_bm_access, 1);
486
487 #endif
488 // Init bm timer. Timer is in stop state after init.
489 bm_timer_init();
490 // Create the BM Task
491 OSA_TaskCreate(BM_task, /* The task function entry */
492 (uint8_t *)BM_TASK_NAME, /* The name of this task */
493 BM_TASK_STACK_SIZE, /* The stack size in byte */
494 BM_stack, /* Pointer to the stack */
495 BM_TASK_PRIORITY, /* Initial priority of the task */
496 (task_param_t)(NULL), /* Pointer to be passed to the task when it is created */
497 false, /* This task will use not float register */
498 &BM_task_handler); /* Pointer to the task handler */
499
500
501 return ret;
502 }
503
504 uint32 bm_update_cb_list(void)
505 {
506 int i = 0;
507
508 uint32 callbacks = 0;
509
510 bm.time_keeper_usec = bm_find_smallest_active_period(BM_CURRENT_PERIOD);
511
512 while(i < bm.cb_list_cur_cnt)
513 {
514
515 // Only process callbacks that are enabled.
516 if (gpBm_cb_list[i]->nToken & bm.cb_token_active_mask)
517 {
518
519 // Test code to make sure underflow does not occur.
520 //if (gpBm_cb_list[i]->Cur_period < bm.time_keeper_usec)
521 // gpBm_cb_list[i]->Cur_period = 0;
522 //else
523 // gpBm_cb_list[i]->Cur_period -= bm.time_keeper_usec;
524
525 if (gpBm_cb_list[i]->Cur_period < bm.time_keeper_usec)
526 // NOTE: This situation could occur when cbs are started and stopped
527 // without syncing up. In this case we reset the cb's period. What
528 // this means is that if a new cb was started during the period time
529 // of another cb, then the new cb's period *may* not start until the
530 // current period of the current cb is reached. Another choice is to
531 // set new cb's period to zero which would cause it to be scheduled
532 // as soon as the current's period ends.
533 gpBm_cb_list[i]->Cur_period = gpBm_cb_list[i]->Period;
534 else
535 gpBm_cb_list[i]->Cur_period -= bm.time_keeper_usec;
536
537
538 // For callbacks that have remaining time that are very small
539 // we could snap them to current time event.
540 if (gpBm_cb_list[i]->Cur_period <= BM_MINIMUM_CB_TIMELEFT_USEC)
541 gpBm_cb_list[i]->Cur_period = 0;
542
543 // Check if a callback is scheduled to run.
544 if (gpBm_cb_list[i]->Cur_period == 0)
545 {
546 // Schedule callback for execution.
547 callbacks |= (1 << i);
548
549 // Reset its current period.
550 gpBm_cb_list[i]->Cur_period = gpBm_cb_list[i]->Period;
551
552 }
553
554 } // if
555
556 ++i;
557
558 } // while
559
560 return callbacks;
561 }
562
563 //#define PTE20 (1 << 20)
564 //#define PTE21 (1 << 21)
565 //#define PTE22 (1 << 22)
566
567 //extern void SetPortE_Gpio(uint32 gpio_mask, uint8 hilow);
568 extern void swdelay(int32 cnt);
569
570 void isr_bm_callback_tmr (void *dummy)
571 {
572 //#pragma unused (dummy)
573
574 #ifdef BM_LOW_LEVEL_GPIOS
575 GPIO_DRV_WritePinOutput(J1_2, 1);
576 #endif
577
578 // -----------------------------------------------------
579 // Schedule a callback to run if its time has expired.
580 {
581 uint32 callbacks = 0;
582 // int i = 0;
583
584 #ifdef BM_DEBUG_TRACE_BUFFER
585 bmdebug[bmdebug_idx].current_period_before_adj = bm.time_keeper_usec;
586 #endif
587 // extract the callback mask from the pipeline fifo and update the index into the pipeline.
588 callbacks = bm.cb_events[bm.pipeline_index];
589 bm.cb_events[bm.pipeline_index] = bm_update_cb_list();
590 bm.pipeline_index = (bm.pipeline_index + 1);
591 if (bm.pipeline_index == BM_PIPELINE_STAGES)
592 {
593 bm.pipeline_index = 0;
594 }
595
596 // PIT timer is running with last value.
597 // We now need to set the LDVAL to the next interval.
598 PIT_DRV_SetTimerPeriodByUs(ISF_BM_PIT_INSTANCE, ISF_BM_PIT_CHANNEL_NO, bm.time_keeper_usec);
599
600 #ifdef BM_DEBUG_TRACE_BUFFER
601 {
602 //extern uint_32 timer_tpm_get_usec(void);
603 extern uint32 isf_time_util_get_usec(void);
604
605 ++bmdebug_isr_cnt;
606 bmdebug[bmdebug_idx].timestamp = isf_time_util_get_usec();
607 bmdebug[bmdebug_idx].current_period_after_adj = bm.time_keeper_usec;
608 bmdebug[bmdebug_idx].cb_event = callbacks;
609 bmdebug[bmdebug_idx].cb_timeleft[0] = gpBm_cb_list[0]->Cur_period;
610 bmdebug[bmdebug_idx].cb_timeleft[1] = gpBm_cb_list[1]->Cur_period;
611
612 ++bmdebug_idx;
613 if (bmdebug_idx >= BM_DEBUG_TRACEBUF_MAX)
614 bmdebug_idx = 0;
615 }
616 #endif
617
618
619 #ifdef BM_LOW_LEVEL_GPIOS
620 if ((callbacks & 0x01) == 0x01)
621 {
622 GPIO_DRV_WritePinOutput(J1_3, 1);
623 swdelay(10);
624 GPIO_DRV_WritePinOutput(J1_3, 0);
625 }
626
627 if ((callbacks & 0x02) == 0x02)
628 {
629 GPIO_DRV_WritePinOutput(J1_4, 1);
630 swdelay(10);
631 GPIO_DRV_WritePinOutput(J1_4, 0);
632 }
633 #endif
634 #if OS_MQXLITE
635 _lwevent_set(&event_bm_callback, callbacks);
636 #else
637 OSA_EventSet(&event_bm_callback, callbacks);
638 #endif
639 // Let power managment know that a cb will occur.
640 gBm_cb_occurred = TRUE;
641
642 } // Schedule callback to run.
643
644
645 #ifdef BM_LOW_LEVEL_GPIOS
646 GPIO_DRV_WritePinOutput(J1_2, 0);
647 #endif
648
649 }
650
651
652
653 /*!
654 *
655 * @brief Bus Manager Task - main task to handle communication \n
656 * via mailboxes with the host.
657 *
658 * @param initial_data - value passed in when task is created, not used.
659 *
660 * @return None
661 *
662 * @errors \n
663 *
664 * @constraints \n
665 *
666 * @reentrant No.
667 *
668 * @libs \n
669 *
670 * @see main.c/MQX_template_list[]\n
671 *
672 */
673 void task_bm(uint32 initial_data)
674 {
675
676
677 uint32 callbacks;
678 int i;
679
680
681 while(1)
682 {
683 #if OS_MQXLITE
684 while (_lwevent_wait_for(&event_bm_callback, 0xffffffff, FALSE, 0) != 0) {};
685
686 callbacks = _lwevent_get_signalled();
687 #else
688 OSA_EventWait(&event_bm_callback, 0x00FFFFFF, FALSE, OSA_WAIT_FOREVER, &callbacks);
689 #endif
690 i = 0;
691
692 // Find out which callbacks to execute.
693
694 while(i < 32)
695 {
696 if (callbacks & (1 << i))
697 {
698
699
700 // Note that a higher priority task called bm API like unregister
701 // or stop that changes the cb array list (or its content) after
702 // the bm ISR runs but before this point is reached. So we must
703 // check for null pointer bm task and make sure it is not stopped.
704 if (gpBm_cb_list[i] != NULL)
705 {
706 if (gpBm_cb_list[i]->nToken & bm.cb_token_active_mask)
707 gpBm_cb_list[i]->pCallback(gpBm_cb_list[i]->pCbData);
708 }
709
710 }
711 ++i;
712 }
713
714 } // while loop
715 }
716
717
718
719
720
721
722
723 /*!
724 *
725 * @brief Bus management generate token. This token generator assigns
726 * one bit out of 32 bits as a token value.\n
727 *
728 * @return BM_TOKEN_STARTING_VAL to BM_TOKEN_VAL_MAX if successful
729 * 0 for failure (all tokens used up).
730 *
731 * @errors \n
732 *
733 * @constraints The maximum number of callbacks that this token generator
734 * can handle is 32. Each bit in a 32bit variable is assigned
735 * to one callback.\n
736 *
737 * The callback current count variable bm.cb_list_cur_cnt
738 * should have the current count value before the new callback
739 * is added. For example if this is the first callback being
740 * registered, then bm.cb_list_cur_cnt should be 0 when this
741 * function is called. The caller then increments bm.cb_list_cur_cnt
742 * after this function returns the new token.\n
743 *
744 *
745 * @reentrant No.
746 *
747 * @libs \n
748 *
749 * @see \n
750 *
751 */
752 bm_callback_token_t bm_generate_token(void)
753 {
754
755 bm_callback_token_t new_token;
756 int bit = 0;
757
758 do
759 {
760 new_token = (1 << bit);
761
762 if ( (new_token & bm.cb_token_registered_mask) == 0)
763 break;
764
765 } while(++bit < MAX_BM_CALLBACKS);
766
767 if (bit == MAX_BM_CALLBACKS)
768 // Could not find open slot for token.
769 new_token = 0;
770
771 return new_token;
772 }
773
774
775
776 /*!
777 *
778 * @brief Sort the callback list based on period in ascending order
779 * (callback with smallest period is first in the array).\n
780 *
781 * @return \n
782 *
783 * @errors \n
784 *
785 * @constraints \n
786 *
787 * @reentrant No.
788 *
789 * @libs \n
790 *
791 * @see \n
792 *
793 */
794 void bm_sort_cb_list(void)
795 {
796
797 int i, j; // Start at 1, not zero!
798 bm_cb_config_t *pCb;
799
800
801 // Bubble sort
802 j = 0;
803 while(j < (bm.cb_list_cur_cnt-1))
804 {
805 i = 0;
806 while(i < (bm.cb_list_cur_cnt-j-1))
807 {
808 if (gpBm_cb_list[i]->Period > gpBm_cb_list[i+1]->Period )
809 {
810 pCb = (bm_cb_config_t *)gpBm_cb_list[i+1];
811 gpBm_cb_list[i+1] = gpBm_cb_list[i];
812 gpBm_cb_list[i] = pCb;
813
814 }
815 ++i;
816 }
817
818 ++j;
819 }
820
821
822 // For callbacks that have the same period, synchronize them
823 // and have their timer interrupts happen at the same time by
824 // forcing the same current period.
825 //i = 0;
826 //while(i < (bm.cb_list_cur_cnt-1))
827 //{
828 // if (gpBm_cb_list[i]->Period == gpBm_cb_list[i+1]->Period )
829 // {
830 // gpBm_cb_list[i]->Cur_Period > gpBm_cb_list[i+1]->Cur_Period;
831 // }
832 //
833 // ++i;
834 //}
835 }
836
837
838
839
840 /*!
841 *
842 * @brief Find the callback associated with the given a token.\n
843 *
844 * @param aToken - [in] Token of callback to search for
845 *
846 * @return Index of the list of callbacks that points to the one
847 * with matching token value. Most signficant bit is
848 * set (negative return value) if no matching token was
849 * found.
850 *
851 * @errors \n
852 *
853 * @constraints \n
854 *
855 * @reentrant No.
856 *
857 * @libs \n
858 *
859 * @see \n
860 *
861 */
862 int bm_find_cb(bm_callback_token_t aToken)
863 {
864
865 int i = 0;
866
867 while(i < bm.cb_list_cur_cnt)
868 {
869 if (gpBm_cb_list[i]->nToken == aToken)
870 {
871 return i;
872 }
873 ++i;
874 }
875 // Did not find matching token.
876 return -1;
877 }
878
879 /*!
880 *
881 * @brief Find the smallest current period.\n
882 *
883 * @return Smallest current period found in the callback list.
884 *
885 * @errors \n
886 *
887 * @constraints \n
888 *
889 * @reentrant No.
890 *
891 * @libs \n
892 *
893 * @see \n
894 *
895 */
896 uint32 bm_find_smallest_active_period(int8 period_type)
897 {
898
899 uint32 smallest = MAX_BM_PERIOD_USEC;
900 int i = 0;
901 bm_callback_token_t tokens_enabled_mask = bm.cb_token_active_mask;
902
903 if (period_type == BM_FULL_PERIOD)
904 {
905 while ( (i < bm.cb_list_cur_cnt) && (tokens_enabled_mask) )
906 {
907 // Compare only if callbacks are enabled.
908 if (tokens_enabled_mask & gpBm_cb_list[i]->nToken)
909 {
910 if (gpBm_cb_list[i]->Period < smallest)
911 smallest = gpBm_cb_list[i]->Period;
912 }
913 tokens_enabled_mask &= ~gpBm_cb_list[i]->nToken;
914
915 ++i;
916 }
917 }
918 else
919 {
920 while ( (i < bm.cb_list_cur_cnt) && (tokens_enabled_mask) )
921 {
922 // Compare only if callbacks are enabled.
923 if (tokens_enabled_mask & gpBm_cb_list[i]->nToken)
924 {
925 if (gpBm_cb_list[i]->Cur_period < smallest)
926 smallest = gpBm_cb_list[i]->Cur_period;
927 }
928 tokens_enabled_mask &= ~gpBm_cb_list[i]->nToken;
929
930 ++i;
931 }
932 }
933
934 // Make sure that the period is not greater than the maximum range of the hardware counter.
935 if (smallest >= bmRolloverPeriod)
936 {
937 smallest = bmRolloverPeriod;
938 }
939
940 return smallest;
941 }
942
943
944 /*!
945 *
946 * @brief Prepare bm for powerdown state. Called by power manager.\n
947 *
948 * @return Remaining time to next callback scheduled in microseconds.
949 *
950 * @errors \n
951 *
952 * @constraints \n
953 *
954 * @reentrant No.
955 *
956 * @libs \n
957 *
958 * @see \n
959 *
960 */
961 uint32 bm_powerdown(void)
962 {
963 uint64 remainingtime_usec = 0;
964
965 // NOTE: This func gets called by power manager task at lowest
966 // priority. Its unlikely that someone has access to bm internal
967 // variables at this point. So don't wait for sema to reduce latency.
968 //_lwsem_wait_ticks(&sema_bm_access, 0);
969
970
971 gBm_state_change = FALSE;
972 gBm_cb_occurred = FALSE;
973
974 // If there are active callbacks, then return time to next scheduled callback.
975 if (bm.cb_token_active_mask)
976 {
977 // Stop timer. Do this just before grabbing the timer count to get
978 // best accuracy.
979 PIT_DRV_StopTimer(ISF_BM_PIT_INSTANCE,ISF_BM_PIT_CHANNEL_NO);
980
981 remainingtime_usec = bm.time_keeper_usec;
982 }
983
984
985 // NOTE: See note above on waiting for sema.
986 //_lwsem_post(&sema_bm_access);
987
988 return (uint32)remainingtime_usec;
989 }
990
991
992
993 /*!
994 *
995 * @brief Tells caller if there a change in the state of the\n
996 * bus manager. Change could be:
997 * - New registerd callback(s)
998 * - Unregister of callback(s)
999 * - Change of start to stop state
1000 *
1001 * Note that this function is typically called by the power
1002 * manager (at lowest priority) in ilde mode and all other
1003 * tasks are blocked. Which means we do not need to protect
1004 * the read with semaphores and incur latency associated with
1005 * it.
1006 *
1007 *
1008 * @return TRUE if there was a state change
1009 * FALSE otherwise.
1010 *
1011 * @errors \n
1012 *
1013 * @constraints \n
1014 *
1015 * @reentrant No.
1016 *
1017 * @libs \n
1018 *
1019 * @see \n
1020 *
1021 */
1022 bool bm_statechange_query(void)
1023 {
1024
1025 bool oldstate = gBm_state_change;
1026
1027 //gBm_state_change = FALSE;
1028
1029 return oldstate;
1030 }
1031
1032
1033 /*!
1034 *
1035 * @brief Reset the state change.
1036 *
1037 *
1038 * @errors \n
1039 *
1040 * @constraints \n
1041 *
1042 * @reentrant No.
1043 *
1044 * @libs \n
1045 *
1046 * @see \n
1047 *
1048 */
1049 void bm_statechange_reset(void)
1050 {
1051
1052 #if OS_MQXLITE
1053 _lwsem_wait_ticks(&sema_bm_access, 0);
1054 #else
1055 OSA_SemaWait(&sema_bm_access, OSA_WAIT_FOREVER);
1056 #endif
1057
1058 gBm_state_change = FALSE;
1059 #if OS_MQXLITE
1060 _lwsem_post(&sema_bm_access);
1061 #else
1062 OSA_SemaPost(&sema_bm_access);
1063 #endif
1064 }
1065
1066
1067
1068
1069 /*!
1070 *
1071 * @brief Tells caller if a callback was scheduled to be called
1072 * since setting bus manager for powerdown mode.
1073 *
1074 * @return TRUE if there was a state change
1075 * FALSE otherwise.
1076 *
1077 * @errors \n
1078 *
1079 * @constraints \n
1080 *
1081 * @reentrant No.
1082 *
1083 * @libs \n
1084 *
1085 * @see \n
1086 *
1087 */
1088 bool bm_cb_occurred_query(void)
1089 {
1090 return gBm_cb_occurred;
1091 }
1092
1093
1094 /*!
1095 *
1096 * @brief Tells caller if there are active callbacks.\n
1097 *
1098 * @return TRUE if there are active callbacks.
1099 * FALSE otherwise.
1100 *
1101 * @errors \n
1102 *
1103 * @constraints \n
1104 *
1105 * @reentrant No.
1106 *
1107 * @libs \n
1108 *
1109 * @see \n
1110 *
1111 */
1112 bool bm_active_cb_query(void)
1113 {
1114 bool ret;
1115
1116 #if OS_MQXLITE
1117 _lwsem_wait_ticks(&sema_bm_access, 0);
1118 #else
1119 OSA_SemaWait(&sema_bm_access, OSA_WAIT_FOREVER);
1120 #endif
1121
1122 if (bm.cb_token_active_mask)
1123 ret = TRUE;
1124 else
1125 ret = FALSE;
1126
1127 #if OS_MQXLITE
1128 _lwsem_post(&sema_bm_access);
1129 #else
1130 OSA_SemaPost(&sema_bm_access);
1131 #endif
1132
1133 return ret;
1134 }
1135
1136 /*!
1137 *
1138 * @brief BM Task .\n
1139 *
1140 * @return void
1141 *
1142 * @errors \n
1143 *
1144 * @constraints \n
1145 *
1146 * @reentrant No.
1147 *
1148 * @libs \n
1149 *
1150 * @see \n
1151 *
1152 */
1153
1154
1155 void BM_task(os_task_param_t task_init_data)
1156 {
1157 isf_system_sync();
1158 task_bm(0);
1159 }
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
bm_cb_config_t
Definition: bm_internal.h:67
TRUE
#define TRUE
Definition: isf_types.h:82
bm_t::cb_token_registered_mask
BM_VOLATILE bm_callback_token_t cb_token_registered_mask
Definition: bm_internal.h:80
bmPITInstance
uint32 bmPITInstance
Definition: ISFBusManager1.c:43
ISF_SUCCESS
Definition: isf.h:31
isf_time_util_get_usec
uint32 isf_time_util_get_usec(void)
This API returns the time in microseconds.
Definition: isf_util.c:55
isf_system_sync
void isf_system_sync(void)
This function synchronizes the user tasks and the system initialization.
Definition: isf_init.c:50
BM_TASK_PRIORITY
#define BM_TASK_PRIORITY
Definition: bus_management.c:52
BM_MINIMUM_CB_TIMELEFT_USEC
#define BM_MINIMUM_CB_TIMELEFT_USEC
Definition: bm_internal.h:50
isr_bm_callback_tmr
void isr_bm_callback_tmr(void *dummy)
Definition: bus_management.c:570
ISF_BM_PIT_INSTANCE
#define ISF_BM_PIT_INSTANCE
Definition: BM_pit_instance.h:16
COMM_ERROR_NOEXIST
Definition: isf_comm.h:41
bm_timer_init
void bm_timer_init(void)
Definition: ISFBusManager1.c:49
FALSE
#define FALSE
Definition: isf_types.h:86
bm_cb_config_t::Cur_period
uint32 Cur_period
Definition: bm_internal.h:72
uint64
unsigned long long uint64
This defines uint64 as unsigned long long.
Definition: isf_types.h:61
isf_bm.h
API definitions, types, and macros for the Intelligent Sensing Framework (ISF) Bus Manager (BM)...
BM_TASK_STACK_SIZE
#define BM_TASK_STACK_SIZE
Definition: bus_management.c:50
bm_cb_occurred_query
bool bm_cb_occurred_query(void)
Tells caller if a callback was scheduled to be called since setting bus manager for powerdown mode...
Definition: bus_management.c:1088
MAX_BM_PERIOD_USEC
#define MAX_BM_PERIOD_USEC
The maximum period of a callback is provided in microseconds. Attempting to register a callback perio...
Definition: isf_bm.h:35
bm_statechange_query
bool bm_statechange_query(void)
Tells caller if there a change in the state of the bus manager. Change could be: ...
Definition: bus_management.c:1022
BM_task
void BM_task(os_task_param_t task_init_data)
BM Task . .
Definition: bus_management.c:1155
bm_find_smallest_active_period
uint32 bm_find_smallest_active_period(int8 period_type)
Find the smallest current period. .
Definition: bus_management.c:896
bm_callback_token_t
uint32 bm_callback_token_t
This type defines the Bus Manager token. Each callback registered with the Bus Manager receives a uni...
Definition: isf_bm.h:79
bm_unregister_callback
isf_status_t bm_unregister_callback(bm_callback_token_t aToken)
This API unregisters one or more callbacks.
Definition: bus_management.c:178
bm_get_num_callback
uint32 bm_get_num_callback(void)
This API returns the number of callbacks registered.
Definition: bus_management.c:252
bm_cb_config_t::Period
isf_duration_t Period
Definition: bm_internal.h:69
bm_reset_period
void bm_reset_period(void)
Definition: bus_management.c:409
gpBm_cb_list
BM_STATIC BM_VOLATILE bm_cb_config_t * gpBm_cb_list[MAX_BM_CALLBACKS]
Definition: bus_management.c:39
bm_cb_config_t::nToken
bm_callback_token_t nToken
Definition: bm_internal.h:73
bm_active_cb_query
bool bm_active_cb_query(void)
Tells caller if there are active callbacks. .
Definition: bus_management.c:1112
bm_sort_cb_list
void bm_sort_cb_list(void)
Sort the callback list based on period in ascending order (callback with smallest period is first in ...
Definition: bus_management.c:794
bm_powerdown
uint32 bm_powerdown(void)
Prepare bm for powerdown state. Called by power manager. .
Definition: bus_management.c:961
BM_ALL_TOKENS
#define BM_ALL_TOKENS
This value specifies an action to be taken on all callbacks registered with the Bus Manager...
Definition: isf_bm.h:62
BM_ALLOC_MEM_ZERO
#define BM_ALLOC_MEM_ZERO(x)
Definition: bm_internal.h:55
MAX_BM_CALLBACKS
#define MAX_BM_CALLBACKS
The maximum number of callbacks registered with the Bus Manager.
Definition: isf_bm.h:29
os_task_param_t
task_param_t os_task_param_t
Definition: mqx_ksdk.h:354
bmRolloverPeriod
uint32 bmRolloverPeriod
Definition: ISFBusManager1.c:44
BM_PIPELINE_STAGES
#define BM_PIPELINE_STAGES
Definition: bm_internal.h:65
bm_cb_config_t::pCbData
void * pCbData
Definition: bm_internal.h:71
bm_t::cb_events
BM_VOLATILE uint32 cb_events[BM_PIPELINE_STAGES]
Definition: bm_internal.h:85
swdelay
void swdelay(int32 cnt)
BM_FREE_MEM
#define BM_FREE_MEM(x)
Definition: bm_internal.h:56
bm_register_periodic_callback
bm_callback_token_t bm_register_periodic_callback(isf_duration_t aPeriod, bm_callback_t *pCallback, void *pCbData)
This API schedules a callback at the specified period.
Definition: bus_management.c:94
bm_t::cb_token_active_mask
BM_VOLATILE bm_callback_token_t cb_token_active_mask
Definition: bm_internal.h:81
bm_cb_config_t::pCallback
bm_callback_t * pCallback
Definition: bm_internal.h:70
bm_t::time_keeper_usec
BM_VOLATILE uint32 time_keeper_usec
Definition: bm_internal.h:83
bm_init
isf_status_t bm_init(void)
Bus management initialization .
Definition: bus_management.c:445
gBm_firsttime_flag
BM_STATIC BM_VOLATILE bool gBm_firsttime_flag
Definition: bus_management.c:40
gBm_state_change
BM_STATIC BM_VOLATILE bool gBm_state_change
Definition: bus_management.c:41
bm_update_cb_list
uint32 bm_update_cb_list(void)
Definition: bus_management.c:504
BM_STATIC
#define BM_STATIC
Definition: bm_internal.h:31
bm_t
Definition: bm_internal.h:77
bm_t::cb_list_cur_cnt
BM_VOLATILE int32 cb_list_cur_cnt
Definition: bm_internal.h:79
bm_internal.h
ISF bus management internal header file.
BM_CURRENT_PERIOD
#define BM_CURRENT_PERIOD
Definition: bm_internal.h:64
bm_stop
isf_status_t bm_stop(bm_callback_token_t aTokens)
This API stops one or more callback(s) by setting them to the inactive state.
Definition: bus_management.c:349
BM_VOLATILE
#define BM_VOLATILE
Definition: bm_internal.h:30
bm_start
isf_status_t bm_start(boolean aSync, bm_callback_token_t aTokens)
This API sets one or more callback(s) to the active state.
Definition: bus_management.c:278
isf_duration_t
uint32 isf_duration_t
ISF time duration in microseconds.
Definition: isf.h:84
isf.h
Main ISF header file. Contains code common to all ISF components.
BM_TASK_NAME
#define BM_TASK_NAME
Definition: bus_management.c:48
bm_callback_t
void( bm_callback_t)(void *)
Type for the prototype for a Bus Manager periodic callback function.
Definition: isf_bm.h:71
int32
signed long int int32
Definition: isf_types.h:74
COMM_ERROR_NULL_PTR
Definition: isf_comm.h:40
OSA_TASK_DEFINE
OSA_TASK_DEFINE(BM, BM_TASK_STACK_SIZE)
bm_statechange_reset
void bm_statechange_reset(void)
Reset the state change.
Definition: bus_management.c:1049
gBm_cb_occurred
BM_STATIC BM_VOLATILE bool gBm_cb_occurred
Definition: bus_management.c:42
isf_init.h
The isf_init.h file contains the task initialization attributes required for initialization of the fo...
BM_FULL_PERIOD
#define BM_FULL_PERIOD
Definition: bm_internal.h:63
bm
bm_t bm
Definition: bus_management.c:45
bm_generate_token
bm_callback_token_t bm_generate_token(void)
Bus management generate token. This token generator assigns one bit out of 32 bits as a token value...
Definition: bus_management.c:752
bm_t::pipeline_index
BM_VOLATILE uint32 pipeline_index
Definition: bm_internal.h:84
BM_ERROR
#define BM_ERROR
This value specifies a general Bus Manager error. If an error occurs in registering a callback...
Definition: isf_bm.h:57
isf_status_t
int32 isf_status_t
ISF return status type.
Definition: isf.h:76
sema_bm_access
BM_STATIC semaphore_t sema_bm_access
Definition: bus_management.c:37
MIN_BM_PERIOD_USEC
#define MIN_BM_PERIOD_USEC
The minimum period of a callback is provided in microseconds. Attempting to register a callback perio...
Definition: isf_bm.h:41
uint32
unsigned long int uint32
Definition: isf_types.h:78
ISF_BM_PIT_CHANNEL_NO
#define ISF_BM_PIT_CHANNEL_NO
Definition: BM_pit_instance.h:17
bm_find_cb
int bm_find_cb(bm_callback_token_t aToken)
Find the callback associated with the given a token. .
Definition: bus_management.c:862
task_bm
void task_bm(uint32 initial_data)
Bus Manager Task - main task to handle communication via mailboxes with the host.
Definition: bus_management.c:673
event_bm_callback
BM_STATIC event_t event_bm_callback
Definition: bus_management.c:36
int8
signed char int8
Definition: isf_types.h:72
- © Freescale Semiconductor, Inc. 2016. All Rights Reserved.