PIC24 Support Libraries
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
app_mail_B.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_B0);
59 ESOS_USER_TASK(sender_B1);
60 ESOS_USER_TASK(recipient_B);
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 ESOS_USER_TASK( sender_B0 ) {
145  uint32_t u32_rnd;
146  static uint8_t u8_cnt;
147  static ESOS_TASK_HANDLE hTask, hTask16, hTask32;
148  static MAILMESSAGE st_Message;
149 
150  ESOS_TASK_BEGIN();
151  u8_cnt=0;
152  // store handle to our recipient ESOS task
153  hTask = esos_GetTaskHandle( recipient_B );
154 
155  while (TRUE) {
156 
157  // create/fill in the local copy of the message
158  // we will send a single uint8 as data payload
159  ESOS_TASK_MAKE_MSG_UINT8(st_Message, u8_cnt);
160 
161  // simulate a task that does other things if the
162  // receipient task mailbox is full
163 
164  if (ESOS_TASK_MAILBOX_GOT_AT_LEAST_DATA_BYTES( hTask, sizeof(uint8_t) ) ) {
165  // ESOS task mailboxes are stored locally in each task.
166  // but we already now the recipient task has enough space
167  // in their mailbox, so send message
168  printf("B0 sending MESSAGE %d\n", u8_cnt);
169  ESOS_TASK_SEND_MESSAGE(hTask, &st_Message);
170  } else {
171  printf("B0 doing useful work instead of mailing. Discarding MESSAGE %d.\n", u8_cnt );
172  }
173 
174  u8_cnt++;
175  if (u8_cnt>50) u8_cnt=0;
176 
177  // wait a random amount of time between sending mail messages
178  u32_rnd = 1+(0x0F & esos_GetRandomUint32());
179  u32_rnd <<= 6;
180  ESOS_TASK_WAIT_TICKS( u32_rnd);
181 
182  } // endof while(TRUE)
183  ESOS_TASK_END();
184 } // end sender_B0()
185 
186 //TASK that doesn't check mail very often
187 ESOS_USER_TASK( recipient_B ) {
188  uint32_t u32_rnd;
189  uint8_t u8_x;
190  static uint8_t u8_cnt;
191  static MAILMESSAGE stMsg;
192  static ESOS_TASK_HANDLE hSenderB0;
193 
194  ESOS_TASK_BEGIN();
195  hSenderB0 = esos_GetTaskHandle (sender_B0);
196  while (TRUE) {
197 
198  // create a random delay to simulate being "busy"
199  u32_rnd = 1+(0x0F & esos_GetRandomUint32());
200  u32_rnd <<= 10;
201  ESOS_TASK_WAIT_TICKS( u32_rnd );
202 
203  // check for incoming mail
205  u8_cnt=0;
206 
207  // keep reading mail messages until they are all processed
208  while ( ESOS_TASK_IVE_GOT_MAIL() ) {
209  // make local copy of message (frees up mailbox space)
210  __esos_ReadMailMessage(__pstSelf, &stMsg );
211  printf("Got a message from ");
212  if ( ESOS_IS_TASK_SENDER( hSenderB0, stMsg) ) {
213  printf("sender_B0");
214  } else {
215  printf("UNKNOWN");
216  }
217  printf (" containing %d enroute time = %d ms\n", stMsg.au8_Contents[0], esos_GetSystemTick()-stMsg.u32_Postmark );
218  } //endof while()
219  } // endof while(TRUE)
220  ESOS_TASK_END();
221 } // end recipient_B()
222 
223 
224 
225 /******************************************************************************
226  * Function: void user_init(void)
227  *
228  * PreCondition: None
229  *
230  * Input: None
231  *
232  * Output: None
233  *
234  * Side Effects: None
235  *
236  * Overview: user_init is a centralized initialization routine where
237  * the user can setup their application. It is called
238  * automagically by ES_OS during the operating system
239  * initialization.
240  *
241  * Note: The user should set up any state machines and init
242  * all application variables. They can also turn on
243  * any needed peripherals here.
244  *
245  * The user SHALL NOT mess with the interrupt hardware
246  * directly!!! The ES_OS must be aware of the interrupts
247  * and provides osXXXXXXX functions for the user to use.
248  * Using these ES_OS-provided functions, the user may
249  * (and probably should) initialize, register, and enable
250  * interrupts in this routine.
251  *
252  * Furthermore, the user should register AT LEAST one
253  * user application task here (via esos_RegisterTask) or
254  * the ES_OS scheduler will have nothing to schedule
255  * to run when this function returns.
256  *
257  *****************************************************************************/
258 void user_init(void) {
259  uint16_t* pu16_ptr;
260  uint16_t u16_junk;
261  ESOS_TMR_HANDLE tmrhnd_t1,tmrhnd_t2,tmrhnd_t3;
262 
263  __esos_unsafe_PutString( HELLO_MSG );
264 
265  /*
266  * Now, let's get down and dirty with ESOS and our user tasks
267  *
268  * Once tasks are registered, they will start executing in
269  * the ESOS scheduler.
270  */
271 
272  // register our little ESOS task to mimic MCU's TIMER T1 IRQ which kicks off
273  // the ESOS S/W timers when they expire
274  esos_RegisterTask( __simulated_isr );
275 
276  /* ====================================================================
277  * REGISTER SOME USER TASKS
278  * ====================================================================
279  */
280 
281 
282 // here are several combinations of tasks that should work together
283 
284  //esos_RegisterTimer( swTimerLED, 1000 );
285  esos_RegisterTask( sender_B0 );
286  esos_RegisterTask( recipient_B );
287 
288 
289 
290 } // end user_init()