PIC24 Support Libraries
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
app_mail_C.c
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 #ifdef __linux
36 #include "esos_pc.h"
37 #include "esos_pc_stdio.h"
38 #else
39 #include "esos_pic24.h"
40 #include "esos_pic24_rs232.h"
41 #endif
42 
43 // INCLUDE these so our printf and other PC hacks work
44 #include <stdio.h>
45 #include <sys/select.h>
46 #include <termios.h>
47 #include <unistd.h>
48 
49 // DEFINEs go here
50 
51 /*
52  * PROTOTYPEs go here
53  *
54  */
55 void reverseString(char *psz_s1, char *psz_s2);
56 uint32_t randomNumInRange(uint32_t u32_lo, uint32_t u32_hi);
57 
58 ESOS_USER_TASK(sender_C0);
59 ESOS_USER_TASK(sender_C1);
60 ESOS_USER_TASK(recipient_C);
61 
62 // GLOBALs go here
63 // Generally, the user-created semaphores will be defined/allocated here
64 static uint8_t psz_CRNL[3]= {0x0D, 0x0A, 0};
65 
66 
67 // timer globals
68 uint32_t u32_myT1Count = 0;
69 uint8_t LED1 = TRUE;
70 uint8_t LED2 = TRUE;
71 
72 struct stTask* pst_MyTasks[3];
73 
74 /*
75  * Simulate the timer ISR found on a MCU
76  * The PC doesn't have a timer ISR, so this task will periodically
77  * call the timer services callback instead.
78  * USED ONLY FOR DEVELOPMENT AND TESTING ON PC.
79  * Real MCU hardware doesn't need this task
80  */
81 ESOS_USER_TASK( __simulated_isr ) {
83  while (TRUE) {
84  // call the ESOS timer services callback just like a real H/W ISR would
85  __esos_tmrSvcsExecute();
87 
88  } // endof while(TRUE)
89  ESOS_TASK_END();
90 } // end child_task
91 
92 
93 /************************************************************************
94  * User supplied functions
95  ************************************************************************
96  */
97 
98 /*
99  * Returns a random number with a value between the two arguments.
100  *
101  * /todo Yes, I know this routine is cheesy. But, it works and
102  * I am in a really big hurry right now.
103  */
104 
105 uint32_t randomNumInRange(uint32_t u32_lo, uint32_t u32_hi) {
106  uint32_t u32_d1, u32_d2, u32_d4, u32_ret;
107  UINT32 U32_temp;
108 
109  while (TRUE) {
110  u32_d4 = esos_GetRandomUint32();
111  u32_ret = u32_lo + u32_d4;
112  if (u32_ret <= u32_hi) return u32_ret;
113 
114  U32_temp._uint32 = u32_d4;
115  u32_d2 = U32_temp.u16LoWord ^ U32_temp.u16HiWord;
116  u32_ret = u32_lo + u32_d2;
117  if (u32_ret <= u32_hi) return u32_ret;
118 
119  u32_d1 = U32_temp.u8LoLsb ^ U32_temp.u8LoMsb ^ U32_temp.u8HiLsb ^ U32_temp.u8HiMsb;
120  u32_ret = u32_lo + u32_d1;
121  if (u32_ret <= u32_hi) return u32_ret;
122  } //endwhile
123 } //end randomNumInRange
124 
125 
126 // user-created timer callback
127 ESOS_USER_TIMER( swTimerCounter ) {
128  u32_myT1Count++;
129 } //endof swTimerCounter
130 
131 // user-created timer callback
132 ESOS_USER_TIMER( swTimerLED ) {
133  LED2 = !LED2;
134  printf("\a");
135  fflush(stdout);
136 } //endof swTimerLED
137 
138 
139 /**********************************************************
140 **
141 ** a few tasks to send mail messages to each other
142 **
143 ************************************************************/
144 
145 ESOS_USER_TASK( sender_C0 ) {
146  uint32_t u32_rnd;
147  static uint8_t u8_cnt;
148  static ESOS_TASK_HANDLE hTask, hTask16, hTask32;
149  static MAILMESSAGE st_Message;
150 
151  ESOS_TASK_BEGIN();
152  u8_cnt=0;
153  // store handle to our recipient ESOS task
154  hTask = esos_GetTaskHandle( recipient_C );
155 
156  while (TRUE) {
157 
158  // create/fill in the local copy of the message
159  // we will send a single uint8 as data payload
160  ESOS_TASK_MAKE_MSG_UINT8(st_Message, u8_cnt);
161 
162  // simulate a task that does other things if the
163  // receipient task mailbox is full
164 
165  if (ESOS_TASK_MAILBOX_GOT_AT_LEAST_DATA_BYTES( hTask, sizeof(uint8_t) ) ) {
166  // ESOS task mailboxes are stored locally in each task.
167  // but we already now the recipient task has enough space
168  // in their mailbox, so send message
169  printf("C0 sending MESSAGE %d\n", u8_cnt);
170  ESOS_TASK_SEND_MESSAGE(hTask, &st_Message);
171  } else {
172  printf("C0 doing useful work instead of mailing. Discarding MESSAGE %d.\n", u8_cnt );
173  }
174 
175  u8_cnt++;
176  if (u8_cnt>50) u8_cnt=0;
177 
178  // wait a random amount of time between sending mail messages
179  u32_rnd = 1+(0x0F & esos_GetRandomUint32());
180  u32_rnd <<= 7;
181  ESOS_TASK_WAIT_TICKS( u32_rnd);
182 
183  } // endof while(TRUE)
184  ESOS_TASK_END();
185 } // end sender_C0()
186 
187 ESOS_USER_TASK( sender_C1 ) {
188  uint32_t u32_rnd;
189  static uint8_t u8_cnt;
190  static ESOS_TASK_HANDLE hTask, hTask16, hTask32;
191  static MAILMESSAGE st_Message;
192 
193  ESOS_TASK_BEGIN();
194  u8_cnt= 100;
195  hTask = esos_GetTaskHandle( recipient_C );
196 
197  while (TRUE) {
198  ESOS_TASK_MAKE_MSG_UINT8(st_Message, u8_cnt); // create message locally
199  ESOS_TASK_WAIT_ON_TASKS_MAILBOX_HAS_AT_LEAST(hTask, sizeof(uint8_t)); // wait until recipient has mailbox space
200 
201  // get a random number
202  u32_rnd = 1+(0x0F & esos_GetRandomUint32());
203  // create a random message that wants delivery confirmation (1-in-4 chance)
204  if ( (u32_rnd % 4) == 0 ) {
205  st_Message.u8_flags |= ESOS_MAILMESSAGE_REQUEST_ACK;
206  printf("C1 sending MESSAGE with ACK request %d\n", u8_cnt);
207  ESOS_TASK_SEND_MESSAGE_WAIT_DELIVERY(hTask, &st_Message);
208  } else {
209  printf("C1 sending MESSAGE %d\n", u8_cnt );
210  ESOS_TASK_SEND_MESSAGE(hTask, &st_Message);
211  }
212 
213  u8_cnt++;
214  if (u8_cnt>150) u8_cnt=100;
215 
216 
217  u32_rnd <<= 7;
218  ESOS_TASK_WAIT_TICKS( u32_rnd);
219 
220  } // endof while(TRUE)
221  ESOS_TASK_END();
222 } // end sender_C1()
223 
224 
225 //TASK that doesn't check mail very often
226 ESOS_USER_TASK( recipient_C ) {
227  uint32_t u32_rnd;
228  uint8_t u8_x;
229  static uint8_t u8_cnt;
230  static MAILMESSAGE stMsg;
231  static ESOS_TASK_HANDLE hSenderC0, hSenderC1;
232 
233  ESOS_TASK_BEGIN();
234  hSenderC0 = esos_GetTaskHandle( sender_C0);
235  hSenderC1 = esos_GetTaskHandle( sender_C1);
236  while (TRUE) {
237 
238  // create a random delay to simulate being "busy"
239  u32_rnd = 1+(0x0F & esos_GetRandomUint32());
240  u32_rnd <<= 10;
241  ESOS_TASK_WAIT_TICKS( u32_rnd );
242 
243  // check for incoming mail
245  u8_cnt=0;
246 
247  // keep reading mail messages until they are all processed
248  while ( ESOS_TASK_IVE_GOT_MAIL() ) {
249  // make local copy of message (frees up mailbox space)
250  __esos_ReadMailMessage(__pstSelf, &stMsg );
251  printf("Got a message from ");
252  if (ESOS_IS_TASK_SENDER( hSenderC0, stMsg)) {
253  printf("sender_C0");
254  } else if (ESOS_IS_TASK_SENDER( hSenderC1, stMsg)) {
255  printf("sender_C1");
256  } else {
257  printf("UNKNOWN");
258  }
259  printf (" containing %d enroute time = %d ms\n", stMsg.au8_Contents[0], esos_GetSystemTick()-stMsg.u32_Postmark );
260  } //endof while()
261  } // endof while(TRUE)
262  ESOS_TASK_END();
263 } // end recipient_C()
264 
265 
266 
267 /******************************************************************************
268  * Function: void user_init(void)
269  *
270  * PreCondition: None
271  *
272  * Input: None
273  *
274  * Output: None
275  *
276  * Side Effects: None
277  *
278  * Overview: user_init is a centralized initialization routine where
279  * the user can setup their application. It is called
280  * automagically by ES_OS during the operating system
281  * initialization.
282  *
283  * Note: The user should set up any state machines and init
284  * all application variables. They can also turn on
285  * any needed peripherals here.
286  *
287  * The user SHALL NOT mess with the interrupt hardware
288  * directly!!! The ES_OS must be aware of the interrupts
289  * and provides osXXXXXXX functions for the user to use.
290  * Using these ES_OS-provided functions, the user may
291  * (and probably should) initialize, register, and enable
292  * interrupts in this routine.
293  *
294  * Furthermore, the user should register AT LEAST one
295  * user application task here (via esos_RegisterTask) or
296  * the ES_OS scheduler will have nothing to schedule
297  * to run when this function returns.
298  *
299  *****************************************************************************/
300 void user_init(void) {
301  uint16_t* pu16_ptr;
302  uint16_t u16_junk;
303  ESOS_TMR_HANDLE tmrhnd_t1,tmrhnd_t2,tmrhnd_t3;
304 
305  __esos_unsafe_PutString( HELLO_MSG );
306 
307  /*
308  * Now, let's get down and dirty with ESOS and our user tasks
309  *
310  * Once tasks are registered, they will start executing in
311  * the ESOS scheduler.
312  */
313 
314  // register our little ESOS task to mimic MCU's TIMER T1 IRQ which kicks off
315  // the ESOS S/W timers when they expire
316  esos_RegisterTask( __simulated_isr );
317 
318  /* ====================================================================
319  * REGISTER SOME USER TASKS
320  * ====================================================================
321  */
322 
323 
324 // here are several combinations of tasks that should work together
325 
326  //esos_RegisterTimer( swTimerLED, 1000 );
327  esos_RegisterTask( sender_C0 );
328  esos_RegisterTask( sender_C1 );
329  esos_RegisterTask( recipient_C );
330 
331 
332 
333 } // end user_init()