PIC24 Support Libraries
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
app_timer.c
Go to the documentation of this file.
1 /*
2  * "Copyright (c) 2008 Robert B. Reese, Bryan A. Jones, J. W. Bruce ("AUTHORS")"
3  * All rights reserved.
4  * (R. Reese, reese_AT_ece.msstate.edu, Mississippi State University)
5  * (B. A. Jones, bjones_AT_ece.msstate.edu, Mississippi State University)
6  * (J. W. Bruce, jwbruce_AT_ece.msstate.edu, Mississippi State University)
7  *
8  * Permission to use, copy, modify, and distribute this software and its
9  * documentation for any purpose, without fee, and without written agreement is
10  * hereby granted, provided that the above copyright notice, the following
11  * two paragraphs and the authors appear in all copies of this software.
12  *
13  * IN NO EVENT SHALL THE "AUTHORS" BE LIABLE TO ANY PARTY FOR
14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
15  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE "AUTHORS"
16  * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17  *
18  * THE "AUTHORS" SPECIFICALLY DISCLAIMS ANY WARRANTIES,
19  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21  * ON AN "AS IS" BASIS, AND THE "AUTHORS" HAS NO OBLIGATION TO
22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
23  *
24  * Please maintain this header in its entirety when copying/modifying
25  * these files.
26  *
27  *
28  */
29 
30 #define ESOS_USE_IRQS
31 
32 // INCLUDEs go here (First include the main esos.h file)
33 // After that, the user can include what they need
34 #include "esos.h"
35 #include "esos_pc.h"
36 #include "esos_pc_stdio.h"
37 
38 #include <stdio.h>
39 #include <sys/select.h>
40 #include <termios.h>
41 #include <unistd.h>
42 
43 
44 
45 // DEFINEs go here
46 
47 /*
48  * PROTOTYPEs go here
49  *
50  */
51 uint32_t randomNumInRange(uint32_t u32_lo, uint32_t u32_hi);
52 
53 
54 // GLOBALs go here
55 // Generally, the user-created semaphores will be defined/allocated here
56 volatile uint32_t u32_T2Count;
57 volatile uint32_t u32_T3Count;
58 static uint8_t psz_T2Is[]="T2 is ";
59 static uint8_t psz_T3Is[]="T3 is ";
60 static uint8_t psz_Enabled[]="enabled.";
61 static uint8_t psz_Disabled[]="disabled.";
62 static uint8_t psz_CRNL[3]= {0x0D, 0x0A, 0};
63 
64 
65 // timer globals
66 uint32_t u32_myT1Count = 0;
67 uint8_t LED1 = TRUE;
68 uint8_t LED2 = TRUE;
69 
70 struct stTask* pst_MyTasks[3];
71 
72 /************************************************************************
73  * User supplied functions
74  ************************************************************************
75  */
76 
77 // Simulate the timer ISR on a MCU
78 // The PC doesn't have a timer ISR, so this task will periodically
79 // call the timer services callback instead.
80 // USED ONLY FOR DEVELOPMENT AND TESTING!
81 ESOS_USER_TASK( __simulated_isr ) {
82  static uint32_t u32_count, u32_tick;
83 
84  ESOS_TASK_BEGIN(pstTask);
85  u32_count = 0;
86  while (TRUE) {
87  // call the ESOS timer services callback like the ISR would
88  __esos_tmrSvcsExecute();
89  ESOS_TASK_WAIT_TICKS( pstTask, 1 );
90 
91  } // endof while(TRUE)
92  ESOS_TASK_END(pstTask);
93 } // end child_task
94 
95 uint32_t randomNumInRange(uint32_t u32_lo, uint32_t u32_hi) {
96  uint32_t u32_d1, u32_d2, u32_d4, u32_ret;
97  UINT32 U32_temp;
98 
99  while (TRUE) {
100  u32_d4 = esos_GetRandomUint32();
101  u32_ret = u32_lo + u32_d4;
102  if (u32_ret <= u32_hi) return u32_ret;
103 
104  U32_temp._uint32_t = u32_d4;
105  u32_d2 = U32_temp.u16LoWord ^ U32_temp.u16HiWord;
106  u32_ret = u32_lo + u32_d2;
107  if (u32_ret <= u32_hi) return u32_ret;
108 
109  u32_d1 = U32_temp.u8LoLsb ^ U32_temp.u8LoMsb ^ U32_temp.u8HiLsb ^ U32_temp.u8HiMsb;
110  u32_ret = u32_lo + u32_d1;
111  if (u32_ret <= u32_hi) return u32_ret;
112  } //endwhile
113 } //end randomNumInRange
114 
115 
116 // user-created timer callback
117 ESOS_USER_TIMER( swTimerCounter ) {
118  u32_myT1Count++;
119 } //endof swTimerCounter
120 
121 // user-created timer callback
122 ESOS_USER_TIMER( swTimerLED ) {
123  // LED2 = !LED2;
124  if (LED2)
125  printf("\a");
126  else
127  printf("\a");
128  fflush(stdout);
129  LED2 = !LED2;
130 } //endof sw_Timer_LED
131 
132 uint32_t u32_cnt1, u32_cnt2, u32_cnt3;
133 
134 // user-created timer callback
135 ESOS_USER_TIMER( swTimerPrintA ) {
136 
137  printf("A:%d\n", u32_cnt1++);
138  fflush(stdout);
139 } //endof sw_Timer_LED
140 
141 ESOS_USER_TIMER( swTimerPrintB ) {
142 
143  printf("B:%d\n", u32_cnt2++);
144  fflush(stdout);
145 } //endof sw_Timer_LED
146 
147 ESOS_USER_TIMER( swTimerPrintC ) {
148 
149  printf("C:%d\n", u32_cnt3++);
150  fflush(stdout);
151 } //endof sw_Timer_LED
152 
153 ESOS_USER_TASK( task1 ) {
154  uint32_t u32_rnd;
155 
156  ESOS_TASK_BEGIN(pstTask);
157  while (TRUE) {
158  u32_rnd = 100*randomNumInRange(1, 30);
159  printf("T1 (%d)\n", u32_rnd);
160  ESOS_TASK_WAIT_TICKS(pstTask, u32_rnd);
161  } // endof while(TRUE)
162  ESOS_TASK_END(pstTask);
163 } // end task1()
164 
165 ESOS_USER_TASK( task2 ) {
166  uint32_t u32_rnd;
167 
168  ESOS_TASK_BEGIN(pstTask);
169  while (TRUE) {
170  u32_rnd = 100*randomNumInRange(1, 30);
171  printf("T2 (%d)\n", u32_rnd);
172  ESOS_TASK_WAIT_TICKS(pstTask, u32_rnd);
173  } // endof while(TRUE)
174  ESOS_TASK_END(pstTask);
175 } // end task1()
176 
177 ESOS_USER_TASK( task3 ) {
178  uint32_t u32_rnd;
179 
180  ESOS_TASK_BEGIN(pstTask);
181  while (TRUE) {
182  u32_rnd = 100*randomNumInRange(1, 30);
183  printf("T3 (%d)\n", u32_rnd);
184  ESOS_TASK_WAIT_TICKS(pstTask, u32_rnd);
185  } // endof while(TRUE)
186  ESOS_TASK_END(pstTask);
187 } // end task1()
188 
189 ESOS_USER_TASK( task_LED ) {
190  ESOS_TASK_BEGIN(pstTask);
191  while (TRUE) {
192  // LED2 = !LED2;
193  ESOS_TASK_WAIT_TICKS(pstTask, 1000);
194  printf("\a\a");
195  fflush(stdout);
196  } // endof while(TRUE)
197  ESOS_TASK_END(pstTask);
198 } // end upper_case()
199 
200 // user task to randomly turn on and off some timer service
201 //
202 ESOS_USER_TASK( random_tmr ) {
203  static uint32_t u32_RandomNumber;
204  static uint8_t u8_RandomNumber;
205  static uint8_t u8_Count;
206  static ESOS_TMR_HANDLE tmrhnd_t1;
207  UINT32 U32_Temp;
208 
209  ESOS_TASK_BEGIN(pstTask);
210  while (TRUE) {
211  ESOS_TASK_WAIT_TICKS(pstTask, randomNumInRange( 5000, 15000 ) );
214  ESOS_TASK_WAIT_ON_SEND_STRING( "starting timer 1 (");
217  ESOS_TASK_WAIT_ON_SEND_STRING( psz_CRNL );
219  tmrhnd_t1 = esos_RegisterTimer( swTimerCounter, 500 );
220  ESOS_TASK_WAIT_TICKS(pstTask, randomNumInRange( 5000, 15000 ) );
223  ESOS_TASK_WAIT_ON_SEND_STRING( "stopping timer 1 by handle (");
226  ESOS_TASK_WAIT_ON_SEND_STRING( psz_CRNL );
228  esos_UnregisterTimer( tmrhnd_t1 );
229 
230  ESOS_TASK_WAIT_TICKS(pstTask, randomNumInRange( 5000, 15000 ) );
233  ESOS_TASK_WAIT_ON_SEND_STRING( "starting timer 1 (");
236  ESOS_TASK_WAIT_ON_SEND_STRING( psz_CRNL );
238  tmrhnd_t1 = esos_RegisterTimer( swTimerCounter, 500 );
239  ESOS_TASK_WAIT_TICKS(pstTask, randomNumInRange( 5000, 15000 ) );
242  ESOS_TASK_WAIT_ON_SEND_STRING( "stopping timer 1 by function (");
245  ESOS_TASK_WAIT_ON_SEND_STRING( psz_CRNL );
247  esos_UnregisterTimer( esos_GetTimerHandle( swTimerCounter) );
248 
249  } // endof while(TRUE)
250  ESOS_TASK_END(pstTask);
251 } // end child_task
252 
253 // user task to randomly turn on and off some timer service
254 //
255 ESOS_USER_TASK( random_tmr_dbg ) {
256  static uint32_t u32_RandomNumber;
257  static uint8_t u8_RandomNumber;
258  static uint8_t u8_Count;
259  static ESOS_TMR_HANDLE tmrhnd_t1;
260  static ESOS_TMR_HANDLE tmrhnd_ret;
261  UINT32 U32_Temp;
262 
263  ESOS_TASK_BEGIN(pstTask);
264  while (TRUE) {
265  ESOS_TASK_WAIT_TICKS(pstTask, 1*1000 );
266  u32_myT1Count = 0;
269  ESOS_TASK_WAIT_ON_SEND_STRING( "starting timer 10s/0.1 (");
272  ESOS_TASK_WAIT_ON_SEND_STRING( psz_CRNL );
274  // our simulated ISR only runs at 100ms intervals
275  tmrhnd_t1 = esos_RegisterTimer( swTimerCounter, 1 );
276  ESOS_TASK_WAIT_TICKS(pstTask, 10*1000 );
279  ESOS_TASK_WAIT_ON_SEND_STRING( "stopping timer 1 by handle (");
282  ESOS_TASK_WAIT_ON_SEND_STRING( psz_CRNL );
284  esos_UnregisterTimer( tmrhnd_t1 );
285 
286  ESOS_TASK_WAIT_TICKS(pstTask, randomNumInRange( 1*1000, 10*1000 ) );
287  u32_myT1Count = 0;
290  ESOS_TASK_WAIT_ON_SEND_STRING( "starting timer 10s/0.2 (");
293  ESOS_TASK_WAIT_ON_SEND_STRING( psz_CRNL );
295  // our simulated ISR only runs at 100ms interval
296  tmrhnd_t1 = esos_RegisterTimer( swTimerCounter, 2 );
297  ESOS_TASK_WAIT_TICKS(pstTask, 10*1000 );
300  ESOS_TASK_WAIT_ON_SEND_STRING( "stopping timer 1 by function (");
303  ESOS_TASK_WAIT_ON_SEND_STRING( psz_CRNL );
305  esos_UnregisterTimer( esos_GetTimerHandle( swTimerCounter) );
306 
307  ESOS_TASK_WAIT_TICKS(pstTask, randomNumInRange( 1*1000, 10*1000 ) );
308  u32_myT1Count = 0;
311  ESOS_TASK_WAIT_ON_SEND_STRING( "starting timer 10s/0.15 (");
314  ESOS_TASK_WAIT_ON_SEND_STRING( psz_CRNL );
316  // our simulated ISR only runs at 100ms intervals
317  tmrhnd_t1 = esos_RegisterTimer( swTimerCounter, 1 );
318  ESOS_TASK_WAIT_TICKS(pstTask, 5*1000 );
319  tmrhnd_ret = esos_ChangeTimerPeriod( tmrhnd_t1, 2 );
320  if (tmrhnd_ret == ESOS_TMR_FAILURE) {
323  ESOS_TASK_WAIT_ON_SEND_STRING( "change period failed");
324  ESOS_TASK_WAIT_ON_SEND_STRING( psz_CRNL );
326  } //endif
327  ESOS_TASK_WAIT_TICKS(pstTask, 5*1000 );
330  ESOS_TASK_WAIT_ON_SEND_STRING( "stopping timer 1 by function (");
333  ESOS_TASK_WAIT_ON_SEND_STRING( psz_CRNL );
335  esos_UnregisterTimer( esos_GetTimerHandle( swTimerCounter) );
336 
337 
338  } // endof while(TRUE)
339  ESOS_TASK_END(pstTask);
340 } // end child_task
341 
342 ESOS_USER_TASK( upper_case ) {
343  static uint8_t u8_char;
344 
345  ESOS_TASK_BEGIN(pstTask);
346  while (TRUE) {
349  ESOS_TASK_WAIT_ON_GET_UINT8( u8_char );
351  if ((u8_char >= 'a') && (u8_char <= 'z') )
352  u8_char = u8_char - 'a' + 'A';
357  } // endof while(TRUE)
358  ESOS_TASK_END(pstTask);
359 } // end upper_case()
360 
361 ESOS_USER_TASK( upper_case2 ) {
362  static uint8_t u8_i;
363  static uint8_t au8_x[257];
364  static uint8_t au8_y[257];
365 
366  ESOS_TASK_BEGIN(pstTask);
367  while (TRUE) {
372  u8_i = 0;
373  while (TRUE) {
374  if ((au8_x[u8_i] >= 'a') && (au8_x[u8_i] <= 'z') )
375  au8_y[u8_i] = au8_x[u8_i] - 'a' + 'A';
376  else
377  au8_y[u8_i] = au8_x[u8_i];
378  if (au8_x[u8_i] == 0) break;
379  u8_i++;
380  }
385  } // endof while(TRUE)
386  ESOS_TASK_END(pstTask);
387 } // end upper_case()
388 
389 
390 ESOS_USER_TASK( reverse_string ) {
391  static uint8_t u8_char;
392  \
393  static char* sz_in[257];
394  static char* sz_out[257];
395 
396  ESOS_TASK_BEGIN(pstTask);
397  while (TRUE) {
402  reverseString( sz_in, sz_out );
408  } // endof while(TRUE)
409  ESOS_TASK_END(pstTask);
410 } // end upper_case()
411 
412 /** \file
413  * Inputs a string, outputs the reverse. This file is used
414  * in three MPLAB projects:
415  * reverse_string.mcp - polled RX, TX I/O
416  * uartrx_fifo.mcp - interrupt RX, polled TX I/O
417  * uartrxtx_fifo.mcp - interrupt RX, interrupt TX I/O
418  * Interrupt RX inChar1() is selected by defining UART1_RX_INTERRUPT macro
419  * Interrupt TX outChar1() is selected by defining UART1_TX_INTERRUPT macro
420  * These macros are defined in their respective MPLAB projects.
421 */
422 void reverseString(char *psz_s1, char *psz_s2) {
423  char *psz_s1end;
424  if (!(*psz_s1)) {
425  *psz_s2 = 0; //psz_s1 is empty, return.
426  return;
427  }
428  psz_s1end = psz_s1;
429  //find end of first string
430  while (*psz_s1end) psz_s1end++;
431  psz_s1end--; //backup one to first non-zero byte
432  //now copy to S2 in reverse order
433  while (psz_s1end != psz_s1) {
434  *psz_s2 = *psz_s1end;
435  psz_s1end--;
436  psz_s2++;
437  }
438  //copy last byte
439  *psz_s2 = *psz_s1end;
440  psz_s2++;
441  //mark end of string
442  *psz_s2 = 0;
443 }
444 
445 /******************************************************************************
446  * Function: void user_init(void)
447  *
448  * PreCondition: None
449  *
450  * Input: None
451  *
452  * Output: None
453  *
454  * Side Effects: None
455  *
456  * Overview: user_init is a centralized initialization routine where
457  * the user can setup their application. It is called
458  * automagically by ES_OS during the operating system
459  * initialization.
460  *
461  * Note: The user should set up any state machines and init
462  * all application variables. They can also turn on
463  * any needed peripherals here.
464  *
465  * The user SHALL NOT mess with the interrupt hardware
466  * directly!!! The ES_OS must be aware of the interrupts
467  * and provides osXXXXXXX functions for the user to use.
468  * Using these ES_OS-provided functions, the user may
469  * (and probably should) initialize, register, and enable
470  * interrupts in this routine.
471  *
472  * Furthermore, the user should register AT LEAST one
473  * user application task here (via esos_RegisterTask) or
474  * the ES_OS scheduler will have nothing to schedule
475  * to run when this function returns.
476  *
477  *****************************************************************************/
478 void user_init(void) {
479  uint16_t* pu16_ptr;
480  uint16_t u16_junk;
481  ESOS_TMR_HANDLE tmrhnd_t1,tmrhnd_t2,tmrhnd_t3;
482 
483  __esos_hw_PutString( HELLO_MSG );
484 
485  /*
486  * Now, let's get down and dirty with ESOS and our user tasks
487  *
488  * Once tasks are registered, they will start executing in
489  * the ESOS scheduler.
490  */
491 
492  // register our ESOS task to mimic MCU's TIMER T1 IRQ which kicks off
493  // the ESOS S/W timers
494  esos_RegisterTask( __simulated_isr );
495 
496 
497  // here are several combinations of tasks that should work together
498 #if 0
499  esos_RegisterTask( random_tmr);
500 #endif
501 #if 0
502  esos_RegisterTask( random_tmr_dbg);
503 #endif
504 #if 0
505  esos_RegisterTask( upper_case );
506  tmrhnd_t2 = esos_RegisterTimer( swTimerCounter, 500 );
507 #endif
508 #if 0
509  esos_RegisterTask( upper_case2 );
510  tmrhnd_t2 = esos_RegisterTimer( swTimerLED, 1000 );
511 #endif
512 #if 0
513  esos_RegisterTask( reverse_string );
514  esos_RegisterTask( task_LED );
515 #endif
516 #if 0
517  esos_RegisterTask( reverse_string );
518  tmrhnd_t2 = esos_RegisterTimer( sw_Timer_LED, 1000 );
519 #endif
520 #if 0
521  esos_RegisterTask( upper_case2 );
522  esos_RegisterTimer( swTimerLED);
523  tmrhnd_t1 = esos_RegisterTimer( swTimerPrintA, 400 );
524  tmrhnd_t2 = esos_RegisterTimer( swTimerPrintB, 500 );
525  tmrhnd_t3 = esos_RegisterTimer( swTimerPrintC, 750 );
526 #endif
527 #if 1
528  esos_RegisterTimer( swTimerLED);
529  esos_RegisterTask( task1 );
530  esos_RegisterTask( task2 );
531  esos_RegisterTask( task3 );
532 #endif
533 
534 
535 
536 
537 
538 } // end user_init()