ISF  2.2 rev 5
Intelligent Sensing Framework for Kinetis with Processor Expert
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
38 #endif
43 
44 // Internal bus manager data.
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 
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);
79 
80 // Internal functions
83 void bm_sort_cb_list(void);
84 void bm_reset_period(void);
86 
87 // Declare externs to variables for PIT instance constants.
88 extern uint32 bmPITInstance;
90 extern void bm_timer_init(void);
91 
92 // Schedule a callback at a particular rate
93 //
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
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;
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 
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 //
179 {
180 
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 
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
232 
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 
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.
279 {
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  {
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 
350 {
351 
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 
389 
390  }
391  else
392  {
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  {
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  */
446 {
447  uint32 i;
448 
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  }
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 
505 {
506  int i = 0;
507 
508  uint32 callbacks = 0;
509 
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.
534  else
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.
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];
590  bm.pipeline_index = (bm.pipeline_index + 1);
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.
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  */
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  */
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  */
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  */
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 
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  */
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  */
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 
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  */
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  */
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 
#define TRUE
Definition: isf_types.h:82
BM_VOLATILE bm_callback_token_t cb_token_registered_mask
Definition: bm_internal.h:80
uint32 bmPITInstance
uint32 isf_time_util_get_usec(void)
This API returns the time in microseconds.
Definition: isf_util.c:55
void isf_system_sync(void)
This function synchronizes the user tasks and the system initialization.
Definition: isf_init.c:50
#define BM_TASK_PRIORITY
#define BM_MINIMUM_CB_TIMELEFT_USEC
Definition: bm_internal.h:50
void isr_bm_callback_tmr(void *dummy)
#define ISF_BM_PIT_INSTANCE
void bm_timer_init(void)
#define FALSE
Definition: isf_types.h:86
uint32 Cur_period
Definition: bm_internal.h:72
unsigned long long uint64
This defines uint64 as unsigned long long.
Definition: isf_types.h:61
API definitions, types, and macros for the Intelligent Sensing Framework (ISF) Bus Manager (BM)...
#define BM_TASK_STACK_SIZE
bool bm_cb_occurred_query(void)
Tells caller if a callback was scheduled to be called since setting bus manager for powerdown mode...
#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
bool bm_statechange_query(void)
Tells caller if there a change in the state of the bus manager. Change could be: ...
void BM_task(os_task_param_t task_init_data)
BM Task . .
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.
uint32 bm_get_num_callback(void)
This API returns the number of callbacks registered.
isf_duration_t Period
Definition: bm_internal.h:69
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:73
bool bm_active_cb_query(void)
Tells caller if there are active callbacks. .
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 BM_ALLOC_MEM_ZERO(x)
Definition: bm_internal.h:55
#define MAX_BM_CALLBACKS
The maximum number of callbacks registered with the Bus Manager.
Definition: isf_bm.h:29
task_param_t os_task_param_t
Definition: mqx_ksdk.h:354
uint32 bmRolloverPeriod
#define BM_PIPELINE_STAGES
Definition: bm_internal.h:65
void * pCbData
Definition: bm_internal.h:71
BM_VOLATILE uint32 cb_events[BM_PIPELINE_STAGES]
Definition: bm_internal.h:85
void swdelay(int32 cnt)
#define BM_FREE_MEM(x)
Definition: bm_internal.h:56
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:81
bm_callback_t * pCallback
Definition: bm_internal.h:70
BM_VOLATILE uint32 time_keeper_usec
Definition: bm_internal.h:83
isf_status_t bm_init(void)
Bus management initialization .
BM_STATIC BM_VOLATILE bool gBm_firsttime_flag
BM_STATIC BM_VOLATILE bool gBm_state_change
uint32 bm_update_cb_list(void)
#define BM_STATIC
Definition: bm_internal.h:31
BM_VOLATILE int32 cb_list_cur_cnt
Definition: bm_internal.h:79
ISF bus management internal header file.
#define BM_CURRENT_PERIOD
Definition: bm_internal.h:64
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:30
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:84
Main ISF header file. Contains code common to all ISF components.
#define BM_TASK_NAME
void( bm_callback_t)(void *)
Type for the prototype for a Bus Manager periodic callback function.
Definition: isf_bm.h:71
signed long int int32
Definition: isf_types.h:74
OSA_TASK_DEFINE(BM, BM_TASK_STACK_SIZE)
void bm_statechange_reset(void)
Reset the state change.
BM_STATIC BM_VOLATILE bool gBm_cb_occurred
The isf_init.h file contains the task initialization attributes required for initialization of the fo...
#define BM_FULL_PERIOD
Definition: bm_internal.h:63
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_VOLATILE uint32 pipeline_index
Definition: bm_internal.h:84
#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:76
BM_STATIC semaphore_t sema_bm_access
#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
unsigned long int uint32
Definition: isf_types.h:78
#define ISF_BM_PIT_CHANNEL_NO
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.
BM_STATIC event_t event_bm_callback
signed char int8
Definition: isf_types.h:72