ISF  2.1
Intelligent Sensing Framework for Kinetis with Processor Expert
 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 
39 
44 
45 // Internal bus manager data.
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);
76 
77 // Internal functions
80 void bm_sort_cb_list(void);
81 void bm_reset_period(void);
83 
84 // Declare externs to variables for PIT instance constants.
85 extern uint32 bmPITInstance;
87 
88 // Schedule a callback at a particular rate
89 //
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 
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;
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 
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 //
171 {
172 
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 
205 
206  --bm.cb_list_cur_cnt;
207 
208  // Startup irq again.
209  __enable_interrupt();
210 
211  }
212  else
214 
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 
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.
249 {
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 
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 = {
284  .isTimerChained = FALSE,
285  .periodUs = bm.time_keeper_usec
286  };
288  pit_init_channel(bmPITInstance,&pit_config);
289 
291 
292  // Just clear the interrupt flag
294 
295  // Need to stop timer.
297 
298  // Start the PIT timer running.
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.
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 
322 {
323 
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 
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  {
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  */
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  }
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 
458 {
459  int i = 0;
460 
461  uint32 callbacks = 0;
462 
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.
487  else
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.
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];
547  bm.pipeline_index = (bm.pipeline_index + 1);
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.
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.
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  */
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  */
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  */
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  */
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 
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();
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  */
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  */
1029 {
1030 
1031  _lwsem_wait_ticks(&sema_bm_access, 0);
1032 
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  */
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 
void SetPortE_Gpio(uint32 gpio_mask, uint8 hilow)
ISF board support header files.
unsigned char uint8
This defines uint8 as unsigned char.
Definition: isf_types.h:18
#define TRUE
Definition: isf_types.h:52
#define PTE21
BM_VOLATILE bm_callback_token_t cb_token_registered_mask
Definition: bm_internal.h:79
uint32 bmPITInstance
uint32 isf_time_util_get_usec(void)
This API returns the time in microseconds.
Definition: isf_util.c:52
BM_STATIC BM_VOLATILE boolean gBm_firsttime_flag
boolean bm_cb_occurred_query(void)
Tells caller if a callback was scheduled to be called since setting bus manager for powerdown mode...
#define BM_MINIMUM_CB_TIMELEFT_USEC
Definition: bm_internal.h:53
#define FALSE
Definition: isf_types.h:56
uint32 Cur_period
Definition: bm_internal.h:71
unsigned long long uint64
This defines uint64 as unsigned long long.
Definition: isf_types.h:45
API definitions, types, and macros for the Intelligent Sensing Framework (ISF) Bus Manager (BM)...
boolean bm_active_cb_query(void)
Tells caller if there are active callbacks. .
#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
void pit_set_timer_period_us(uint32_t timer, uint32_t us)
Set timer period in microsecond units.
void pit_init_module(bool isRunInDebug)
Initialize PIT module.
#define BM_ALLOC_MEM_ZERO(x)
Definition: bm_internal.h:55
signed char int8
Definition: basic_types.h:12
unsigned long uint32
This defines uint32 as unsigned long.
Definition: isf_types.h:36
uint32 bm_find_smallest_active_period(int8 period_type)
Find the smallest current period. .
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
isf_status_t bm_unregister_callback(bm_callback_token_t aToken)
This API unregisters one or more callbacks.
void pit_init_channel(uint32_t timer, const pit_user_config_t *config)
Initialize PIT channel.
#define TIMER_TPM_INIT()
Definition: bm_timer.h:115
uint32 bm_get_num_callback(void)
This API returns the number of callbacks registered.
isf_duration_t Period
Definition: bm_internal.h:68
BM_STATIC LWSEM_STRUCT sema_bm_access
void pit_hal_clear_interrupt_flag(uint32_t timer)
Clear timer interrupt flag.
Definition: fsl_pit_hal.c:105
void bm_reset_period(void)
BM_STATIC BM_VOLATILE bm_cb_config_t * gpBm_cb_list[MAX_BM_CALLBACKS]
bm_callback_token_t nToken
Definition: bm_internal.h:72
void pit_timer_stop(uint32_t timer)
Stop timer counting.
void bm_sort_cb_list(void)
Sort the callback list based on period in ascending order (callback with smallest period is first in ...
uint32 bm_powerdown(void)
Prepare bm for powerdown state. Called by power manager. .
#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
#define MAX_BM_CALLBACKS
The maximum number of callbacks registered with the Bus Manager.
Definition: isf_bm.h:29
uint32 bmRolloverPeriod
#define BM_PIPELINE_STAGES
Definition: bm_internal.h:64
void * pCbData
Definition: bm_internal.h:70
BM_VOLATILE uint32 cb_events[BM_PIPELINE_STAGES]
Definition: bm_internal.h:84
BM_STATIC BM_VOLATILE boolean gBm_state_change
bool isInterruptEnabled
void swdelay(int32 cnt)
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.
BM_VOLATILE bm_callback_token_t cb_token_active_mask
Definition: bm_internal.h:80
void( bm_callback_t)(void *)
Type for the prototype for a Bus Manager periodic callback function.
Definition: isf_bm.h:71
bm_callback_t * pCallback
Definition: bm_internal.h:69
BM_VOLATILE uint32 time_keeper_usec
Definition: bm_internal.h:82
isf_status_t bm_init(void)
Bus management initialization .
#define PTE20
uint32 bm_update_cb_list(void)
#define BM_STATIC
Definition: bm_internal.h:34
BM_VOLATILE int32 cb_list_cur_cnt
Definition: bm_internal.h:78
ISF bus management internal header file.
#define BM_CURRENT_PERIOD
Definition: bm_internal.h:63
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.
#define BM_VOLATILE
Definition: bm_internal.h:33
isf_status_t bm_start(boolean aSync, bm_callback_token_t aTokens)
This API sets one or more callback(s) to the active state.
uint32 isf_duration_t
ISF time duration in microseconds.
Definition: isf.h:59
long int32
This defines int32 as long.
Definition: isf_types.h:32
Main ISF header file. Contains code common to all ISF components.
void isr_bm_callback_tmr(pointer dummy)
void bm_statechange_reset(void)
Reset the state change.
void pit_hal_timer_reset(uint32_t timer)
Start timer counting.
Definition: fsl_pit_hal.c:66
#define BM_FULL_PERIOD
Definition: bm_internal.h:62
void pit_timer_start(uint32_t timer)
Start timer counting.
bm_t bm
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...
BM_STATIC LWEVENT_STRUCT event_bm_callback
#define TIMER_TPM_START()
Definition: bm_timer.h:108
BM_VOLATILE uint32 pipeline_index
Definition: bm_internal.h:83
#define BM_ERROR
This value specifies a general Bus Manager error. If an error occurs in registering a callback...
Definition: isf_bm.h:57
int32 isf_status_t
ISF return status type.
Definition: isf.h:51
BM_STATIC BM_VOLATILE boolean gBm_cb_occurred
#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
#define PTE22
fsl_pit_driver.h defines structures and types for the PIT driver.
PIT timer configuration structure.
boolean bm_statechange_query(void)
Tells caller if there a change in the state of the bus manager. Change could be: ...
#define BM_FREE_MEM(x)
Definition: bm_internal.h:56
void bm_timer_init(boolean bEnableirq, uint32 usec)
Timer initialization .
Definition: bm_timer.c:31
Bus managment internal header file.
int bm_find_cb(bm_callback_token_t aToken)
Find the callback associated with the given a token. .
void task_bm(uint32 initial_data)
Bus Manager Task - main task to handle communication via mailboxes with the host.
#define TIMER_TPM_GET_CNT()
Definition: bm_timer.h:105