| ISF 2.1 Intelligent Sensing Framework for Kinetis with Processor Expert

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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