PIC24 Support Libraries
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
app_semaphore2.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 /** \file
31  * ESOS application program to where two tasks increment a counter local to
32  * each task 10 times. Between each counter increment, the tasks wait for
33  * a random length of time. After the 10th iteration, the tasks "rendez-vous"
34  * before continuing.
35  * \note Application demonstrates rendez-vous synchronization using ESOS semaphores
36  */
37 
38 
39 // INCLUDEs go here (First include the main esos.h file)
40 // After that, the user can include what they need
41 #include "esos.h"
42 #ifdef __linux
43 #include "esos_pc.h"
44 #include "esos_pc_stdio.h"
45 
46 // INCLUDE these so that printf() and our PC hacks work
47 #include <stdio.h>
48 #include <sys/select.h>
49 #include <termios.h>
50 #include <unistd.h>
51 #else
52 #include "esos_pic24.h"
53 #include "esos_pic24_rs232.h"
54 #endif
55 
56 // DEFINEs go here
57 #ifndef __linux
58 #define CONFIG_LED1() CONFIG_RB15_AS_DIG_OUTPUT()
59 #define LED1 _LATB15
60 #else
61 #define CONFIG_LED1() printf("called CONFIG_LED1()\n");
62 uint8_t LED1 = TRUE; // LED1 is initially "on"
63 #endif
64 
65 // PROTOTYPEs go here
66 
67 // GLOBALs go here
68 // Generally, the user-created semaphores will be defined/allocated here
69 char psz_CRNL[3]= {0x0D, 0x0A, 0};
70 char psz_T1[] = "Task 1: ";
71 char psz_T2[] = "Task 2: ";
72 char psz_rv[] = "rendez-vous!";
73 
74 ESOS_SEMAPHORE( sem_T1CanRun );
75 ESOS_SEMAPHORE( sem_T2CanRun );
76 
77 #ifdef __linux
78 /*
79  * Simulate the timer ISR found on a MCU
80  * The PC doesn't have a timer ISR, so this task will periodically
81  * call the timer services callback instead.
82  * USED ONLY FOR DEVELOPMENT AND TESTING ON PC.
83  * Real MCU hardware doesn't need this task
84  */
85 ESOS_USER_TASK( __simulated_isr ) {
87  while (TRUE) {
88  // call the ESOS timer services callback just like a real H/W ISR would
89  __esos_tmrSvcsExecute();
91 
92  } // endof while(TRUE)
93  ESOS_TASK_END();
94 } // end child_task
95 #endif
96 
97 /************************************************************************
98  * User supplied functions
99  ************************************************************************
100  */
101 
102 /*
103  * return an uint32_t that can be used for a reasonable delay
104  * should not be too short (~255 ticks) and not too long (~4096 ticks)
105  */
106 inline uint32_t getRandomDelay() {
107  return ((esos_GetRandomUint32() & 0x0FFF)|0x100);
108 }
109 
110 /*
111  * An ESOS software timer callback function strobe the heartbeat LED.
112  *
113  * Toggles LED1 everytime the callback is called. Exact period is
114  * determined by application when this timer callback function is
115  * registered with ESOS. See \ref esos_RegisterTimer
116  * Application can change timer period on-the-fly with \ref esos_ChangeTimerPeriod
117  *
118  * \note Since this heartbeat is performed in an ESOS software
119  * timer callabck, a flashing LED indicates that the ESOS system
120  * tick ISR is being called properly. If the LED quits flashing,
121  * then the ESOS system tick has ceased working. This probably indicates
122  * some catastrophic failure of the system. However, the cause could
123  * be poorly-behaved user code that is manipulating the hardware registers
124  * with the timer or interrupt enables directly. ESOS provides functions
125  * to change state of interrupts and user code should never modify the
126  * hardware used by ESOS to implement the system tick.
127  * \hideinitializer
128  */
129 
130 // user-created timer callback
131 ESOS_USER_TIMER( swTimerLED ) {
132  LED1 = !LED1;
133 #ifdef __linux
134  if (LED1) {
135  printf("\a");
136  fflush(stdout);
137  }
138 #endif
139 } //endof swTimerLED
140 
141 /* == task1 ==
142  * Print out a counter value local to this task, then delay
143  * for a random period of time. (Delays range from approx.
144  * 0.25 - 4.1 seconds)
145  */
146 ESOS_USER_TASK(task1) {
147  static uint8_t u8_cnt=0;
148 
149  ESOS_TASK_BEGIN();
150  while (u8_cnt < 10) {
154  ESOS_TASK_WAIT_ON_SEND_STRING( psz_CRNL );
156  u8_cnt++;
157  ESOS_TASK_WAIT_TICKS( getRandomDelay() );
158  } // endof while
159  ESOS_SIGNAL_SEMAPHORE(sem_T2CanRun, 1);
160  ESOS_TASK_WAIT_SEMAPHORE(sem_T1CanRun, 1);
163  ESOS_TASK_WAIT_ON_SEND_STRING( psz_CRNL );
164  ESOS_TASK_END();
165 } // end task1()
166 
167 /* == task2 ==
168  * Wait for a signal from task1, then
169  * Print out a counter value local to this task
170  */
171 ESOS_USER_TASK(task2) {
172  static uint8_t u8_cnt=0;
173 
174  ESOS_TASK_BEGIN();
175  while (u8_cnt<10) {
179  ESOS_TASK_WAIT_ON_SEND_STRING( psz_CRNL );
181  u8_cnt++;
182  ESOS_TASK_WAIT_TICKS( getRandomDelay() );
183  } // endof while()
184  ESOS_SIGNAL_SEMAPHORE(sem_T1CanRun, 1);
185  ESOS_TASK_WAIT_SEMAPHORE(sem_T2CanRun, 1);
188  ESOS_TASK_WAIT_ON_SEND_STRING( psz_CRNL );
189  ESOS_TASK_END();
190 } // end task2()
191 
192 
193 /****************************************************
194  * user_init()
195  ****************************************************
196  */
197 void user_init(void) {
198 
199  // Call the hardware-provided routines to print the
200  // HELLO_MSG to the screen. Must use this call because
201  // the ESOS communications subsystems is not yet fully
202  // initialized, since this call is in user_init()
203  //
204  // In general, users should call hardware-specific
205  // function like this.
206  __esos_unsafe_PutString( HELLO_MSG );
207 
208 #ifdef __linux
209  // register our little ESOS task to mimic MCU's TIMER T1 IRQ which kicks off
210  // the ESOS S/W timers when they expire
211  esos_RegisterTask( __simulated_isr );
212 #endif
213 
214  // configure our hardware to support to support our application
215  CONFIG_LED1();
216 
217  // initialize the semaphore (initially blocking)
218  ESOS_INIT_SEMAPHORE( sem_T1CanRun, 0 );
219  ESOS_INIT_SEMAPHORE( sem_T2CanRun, 0 );
220 
221  // user_init() should register at least one user task
222  esos_RegisterTask(task1);
223  esos_RegisterTask(task2);
224 
225  // register our callback function with ESOS to create a software timer
226  esos_RegisterTimer( swTimerLED, 250 );
227 
228 } // end user_init()