PIC24 Support Libraries
esos_mail.h
Go to the documentation of this file.
1 /*
2  * "Copyright (c) 2013 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 
31 /**
32  * \addtogroup ESOS_Task_Mail_Service
33  * @{
34  */
35 
36 
37 /** \file
38  * This file contains macros, prototypes, and definitions for
39  * mail services for ESOS tasks.
40  *
41  \note For now, these routines are safe from data corruption
42  because mailboxes are modified only in the task context.
43  */
44 
45 
46 #ifndef ESOS_MAIL_H
47 #define ESOS_MAIL_H
48 
49 /* I N C L U D E S **********************************************************/
50 #include "esos.h"
51 #include "esos_cb.h"
52 
53 // TODO we have included esos.h but for some reason the MAX_NUM_USER_TASKS
54 // define is not being found in the declaration of mailboxes below??????
55 
56 /* S T R U C T U R E S ******************************************************/
57 
58 /**
59 * structure to contain a set of descriptors about the buffers used
60 * to implement ESOS task mailboxes
61 **/
62 typedef struct __stMAILBOX {
63  CBUFFER* pst_CBuffer; // ptr to structure that describes mailbox circular buffer
64  struct stTask* pst_Task; // ptr to ESOS_TASK_HANDLE that owns mailbox
65 } MAILBOX;
66 
67 /**
68 * structure to contain a mail message "envelope" -- a set of descriptors
69 * about a mail message and the contents within
70 **/
71 
72 /* DEPRECATED MAIL MESSAGE structure
73 typedef struct __stMAILMSG {
74  uint16_t u16_Header; // bits F-C RESERVED; bits B-4 fromTaskHash?; bits 3-0 payload length
75  uint32_t u32_Postmark; // ESOS tick timestamp
76  uint8_t au8_Contents[__MAIL_MSG_MAX_LEN]; // data storage
77 } MAILMSG;
78 */
79 
80 #define __MAIL_MSG_MAX_DATA_LEN 16 // can be no BIGGER than 16 bytes
81 
82 typedef struct __stMAILMESSAGE {
83  uint8_t u8_flags; // various bits to help us decode message
84  uint16_t u16_FromTaskID; // an unique? 16-bit ID number identifying the sender task
85  uint8_t u8_DataLength; // how many bytes in data payload
86  uint32_t u32_Postmark; // ESOS tick timestamp on message
87  union {
88  uint8_t au8_Contents[__MAIL_MSG_MAX_DATA_LEN]; // message contents
89  uint16_t au16_Contents[__MAIL_MSG_MAX_DATA_LEN/2]; // message contents
90  uint32_t au32_Contents[__MAIL_MSG_MAX_DATA_LEN/4]; // message contents
91  char ach_Contents[__MAIL_MSG_MAX_DATA_LEN]; // message contents
92  };
93 } MAILMESSAGE;
94 
95 /* D E F I N E S ************************************************************/
96 // DEFINEs user can NOT change
97 #define ESOS_MAILMESSAGE_STRING 0x0
98 #define ESOS_MAILMESSAGE_UINT8 0x1
99 #define ESOS_MAILMESSAGE_UINT16 0x2
100 #define ESOS_MAILMESSAGE_UINT32 0x4
101 #define ESOS_MAILMESSAGE_REQUEST_ACK 0x8
102 
103 // verify these against the MAILMESSAGE struct above
104 #define __MAIL_MSG_HEADER_LEN (1+2+1+4)
105 #define __MAIL_MSG_MAX_LEN (__MAIL_MSG_HEADER_LEN+__MAIL_MSG_MAX_DATA_LEN)
106 
107 // size of each task's mailbox (in bytes)
108 #define MAX_SIZE_TASK_MAILBOX 5*__MAIL_MSG_MAX_LEN
109 
110 /* M A C R O S ************************************************************/
111 
112 /**
113  * Determines if a task has mail ready to be read/consumed.
114  *
115  * \param pstTask A pointer to the \ref ESOS_TASK_HANDLE of the task being queried
116  * \sa ESOS_TASK_GET_TASK_HANDLE
117  * \hideinitializer
118  */
119 #define ESOS_TASK_HAS_MAIL(pstTask) (__ESOS_CB_IS_NOT_EMPTY((pstTask)->pst_Mailbox->pst_CBuffer))
120 
121 /**
122  * Determines if a task is waiting on an acknowledgment from another task
123  * reading its mail... a.k.a. "signature confirmation" or "delivery confirmation"
124  *
125  * \param TaskHandle The \ref ESOS_TASK_HANDLE of the task being queried
126  * \sa ESOS_TASK_GET_TASK_HANDLE
127  * \hideinitializer
128  */
129 #define ESOS_TASK_IS_WAITING_MAIL_DELIVERY(TaskHandle) IS_BIT_SET_MASK((TaskHandle)->flags, __TASK_MAILNACK_MASK)
130 
131 /**
132  * Determines if the current task has mail to be read
133  *
134  * Returns TRUE if the current task has mail ready to be read.
135  * else it returns FALSE.
136  *
137  * \sa ESOS_TASK_HAS_MAIL
138  *
139  * \hideinitializer
140  */
141 #define ESOS_TASK_IVE_GOT_MAIL() ESOS_TASK_HAS_MAIL(__pstSelf)
142 
143 /**
144  * Blocks the current task until a mailbox message has arrived
145  *
146  * This function blocks and waits until the task has a message in its mailbox.
147  *
148  * \hideinitializer
149  */
150 #define ESOS_TASK_WAIT_FOR_MAIL() ESOS_TASK_WAIT_UNTIL(ESOS_TASK_IVE_GOT_MAIL())
151 
152 
153 /**
154 * Block current task until the specified task's mailbox
155 * has <em>at least</em> x bytes available for holding messages
156 *
157 * \param pstTask pointer to task structure (ESOS_TASK_HANDLE)
158 * \param x number of bytes to check for
159 * \retval TRUE if task's mailbox has x bytes <em>or more</em>
160 * \retval FALSE otherwise
161 *
162 * \hideinitializer
163 */
164 #define ESOS_TASK_WAIT_ON_TASKS_MAILBOX_HAS_AT_LEAST(pstTask, x) ESOS_TASK_WAIT_UNTIL(ESOS_TASK_MAILBOX_GOT_AT_LEAST_DATA_BYTES((pstTask), ((x)+__MAIL_MSG_HEADER_LEN)))
165 
166 /**
167 * Block the current task until the specified recipient task mailbox
168 * has room for the specified message
169 *
170 * \param pstTask pointer to task structure (ESOS_TASK_HANDLE)
171 * \param pstMsg message for which room must be found
172 * \retval TRUE if task's mailbox has x bytes <em>or more</em>;
173 * \retval FALSE otherwise
174 *
175 * \hideinitializer
176 * \todo BRAIN-DEAD implementation. needs to properly parse the message
177 * header and computer the data payload size. A bit harder than it
178 * first appears
179 */
180 #define ESOS_TASK_WAIT_ON_TASKS_MAILBOX_HAS_ROOM_MESSAGE(pstTask, pstMsg) \
181  ESOS_TASK_WAIT_ON_TASKS_MAILBOX_HAS_AT_LEAST(pstTask, __MAIL_MSG_MAX_DATA_LEN )
182 
183 
184 /**
185 * Evaluates to the number of bytes available in the mailbox association
186 * with an arbitrary task pstTask
187 * \param pstTask pointer to task structure
188 * \retval N number of bytes available for writing in task's mailbox
189 * \hideinitializer
190 */
191 #define ESOS_TASK_MAILBOX_GET_AVAILABLE_LEN(pstTask) ((__ESOS_CB_GET_AVAILABLE((pstTask)->pst_Mailbox->pst_CBuffer))-__MAIL_MSG_HEADER_LEN)
192 /**
193 * Evaluates to the booelan to determine if the specified task's mailbox
194 * has <em>exactly</em> x bytes available for holding messages
195 *
196 * \param pstTask pointer to task structure (ESOS_TASK_HANDLE)
197 * \param x number of bytes to check for
198 * \retval TRUE if task's mailbox has <em>exactly</em> x bytes
199 * \retval FALSE otherwise
200 *
201 * \hideinitializer
202 */
203 #define ESOS_TASK_MAILBOX_GOT_EXACTLY_DATA_BYTES(pstTask,x) (ESOS_TASK_MAILBOX_GET_AVAILABLE_LEN((pstTask)) == ((x)+__MAIL_MSG_HEADER_LEN))
204 
205 /**
206 * Evaluates to the booelan to determine if the specified task's mailbox
207 * has <em>at least</em> x bytes available for holding messages
208 *
209 * \param pstTask pointer to task structure (ESOS_TASK_HANDLE)
210 * \param x number of bytes to check for
211 * \retval TRUE if task's mailbox has x bytes <em>or more</em>
212 * \retval FALSE otherwise
213 *
214 * \hideinitializer
215 */
216 #define ESOS_TASK_MAILBOX_GOT_AT_LEAST_DATA_BYTES(pstTask, x) (ESOS_TASK_MAILBOX_GET_AVAILABLE_LEN((pstTask)) >= ((x)+__MAIL_MSG_HEADER_LEN))
217 
218 /**
219 * Flushes the specified task's mailbox contents. All unread data in the mailbox
220 * will be lost.
221 *
222 * \param pstTask pointer to task structure (ESOS_TASK_HANDLE) whose mailbox will be flushed
223 * \note Use this function only if you want to reset some task's mailbox back
224 * to its empty state.
225 * \note Not really sure why any task would call this except possibly on its own mailbox, e.g.
226 * the argument <em>pstTask</em> would be __pstSelf.
227 *
228 * \hideinitializer
229 */
230 #define ESOS_TASK_FLUSH_TASK_MAILBOX(pstTask) __ESOS_CB_FLUSH((pstTask)->pst_Mailbox->pst_CBuffer)
231 
232 #define ESOS_TASK_SEND_MESSAGE(pst_ToTask, pst_Msg) __esos_SendMailMessage((pst_ToTask),(pst_Msg))
233 
234 #define ESOS_TASK_WAIT_ON_DELIVERY(pst_ToTask, pstMsg) \
235  do{ \
236  (pstMsg)->u8_flags |= ESOS_MAILMESSAGE_REQUEST_ACK; \
237  ESOS_TASK_SEND_MESSAGE((pst_ToTask),(pstMsg)); \
238  __ESOS_SET_TASK_MAILNACK_FLAG((__pstSelf)); \
239  ESOS_TASK_WAIT_WHILE( ESOS_TASK_IS_WAITING_MAIL_DELIVERY( __pstSelf ) ); \
240  } while(0)
241 
242 #define ESOS_TASK_GET_NEXT_MESSAGE(pst_Msg) __esos_ReadMailMessage(__pstSelf, (pst_Msg))
243 
244 #define ESOS_TASK_GET_LAST_MESSAGE(pst_Msg) \
245  do { \
246  while ( ESOS_TASK_IVE_GOT_MAIL() ) { \
247  __esos_ReadMailMessage(__pstSelf, (pst_Msg) ); \
248  } \
249  }while(0)
250 
251 /********************
252 *** QUICKIE MACROS
253 ********************/
254 #define ESOS_IS_TASK_SENDER(hTask, stMsg) (hTask->u16_taskID==stMsg.u16_FromTaskID)
255 
256 #define ESOS_SET_MSG_FLAGS(stMsg, flags) stMsg.u8_flags=(flags)
257 #define ESOS_SET_MSG_FROMTASK(stMsg, pstFromTask) stMsg.u16_FromTaskID=pstFromTask->u16_taskID
258 #define ESOS_SET_MSG_DATA_LENGTH(stMsg, len) stMsg.u8_DataLength=(len)
259 #define ESOS_GET_MSG_FLAGS(stMsg) (stMsg.u8_flags)
260 #define ESOS_GET_MSG_FROMTASK(stMsg) (stMsg.u16_FromTaskID)
261 #define ESOS_GET_MSG_DATA_LENGTH(stMsg) (stMsg.u8_DataLength)
262 #define ESOS_GET_MSG_POSTMARK(stMsg) (stMsg.u32_Postmark)
263 
264 #define ESOS_SET_PMSG_FLAGS(pstMsg, flags) pstMsg->u8_flags=(flags)
265 #define ESOS_SET_PMSG_FROMTASK(pstMsg, pstFromTask) pstMsg->u16_FromTaskID=pstFromTask->u16_taskID
266 #define ESOS_SET_PMSG_DATA_LENGTH(pstMsg, len) pstMsg->u8_DataLength=(len)
267 #define ESOS_GET_PMSG_FLAGS(pstMsg) (pstMsg->u8_flags)
268 #define ESOS_GET_PMSG_FROMTASK(pstMsg) (pstMsg->u16_FromTaskID)
269 #define ESOS_GET_PMSG_DATA_LENGTH(pstMsg) (pstMsg->u8_DataLength)
270 #define ESOS_GET_PMSG_POSTMARK(pstMsg) (pstMsg->u32_Postmark)
271 
272 #define ESOS_TASK_MAKE_MSG_EMPTY(stMsg) \
273  do{ \
274  ESOS_SET_MSG_FLAGS(stMsg, ESOS_MAILMESSAGE_UINT8); \
275  ESOS_SET_MSG_FROMTASK(stMsg, __pstSelf); \
276  ESOS_SET_MSG_DATA_LENGTH(stMsg, 0); \
277  } while(0)
278 
279 #define ESOS_TASK_MAKE_MSG_UINT8(stMsg, u8x) \
280  do{ \
281  ESOS_SET_MSG_FLAGS(stMsg, ESOS_MAILMESSAGE_UINT8); \
282  ESOS_SET_MSG_FROMTASK(stMsg, __pstSelf); \
283  ESOS_SET_MSG_DATA_LENGTH(stMsg, 1); \
284  stMsg.au8_Contents[0] = (u8x); \
285  } while(0)
286 
287 #define ESOS_TASK_MAKE_MSG_UINT8_X2(stMsg, u8x0, u8x1) \
288  do{ \
289  ESOS_SET_MSG_FLAGS(stMsg, ESOS_MAILMESSAGE_UINT8); \
290  ESOS_SET_MSG_FROMTASK(stMsg, __pstSelf); \
291  ESOS_SET_MSG_DATA_LENGTH(stMsg, 2); \
292  stMsg.au8_Contents[0] = (u8x0); \
293  stMsg.au8_Contents[1] = (u8x1); \
294  } while(0)
295 
296 #define ESOS_TASK_MAKE_MSG_UINT8_X3(stMsg, u8x0, u8x1, u8x2) \
297  do{ \
298  ESOS_SET_MSG_FLAGS(stMsg, ESOS_MAILMESSAGE_UINT8); \
299  ESOS_SET_MSG_FROMTASK(stMsg, __pstSelf); \
300  ESOS_SET_MSG_DATA_LENGTH(stMsg, 3); \
301  stMsg.au8_Contents[0] = (u8x0); \
302  stMsg.au8_Contents[1] = (u8x1); \
303  stMsg.au8_Contents[2] = (u8x2); \
304  } while(0)
305 
306 #define ESOS_TASK_MAKE_MSG_UINT8_X4(stMsg, u8x0, u8x1, u8x2, u8x3) \
307  do{ \
308  ESOS_SET_MSG_FLAGS(stMsg, ESOS_MAILMESSAGE_UINT8); \
309  ESOS_SET_MSG_FROMTASK(stMsg, __pstSelf); \
310  ESOS_SET_MSG_DATA_LENGTH(stMsg, 4); \
311  stMsg.au8_Contents[0] = (u8x0); \
312  stMsg.au8_Contents[1] = (u8x1); \
313  stMsg.au8_Contents[2] = (u8x2); \
314  stMsg.au8_Contents[3] = (u8x3); \
315  } while(0)
316 
317 #define ESOS_TASK_MAKE_MSG_AUINT8(stMsg, pau8x, len) \
318  do{ \
319  ESOS_SET_MSG_FLAGS(stMsg, ESOS_MAILMESSAGE_UINT8); \
320  ESOS_SET_MSG_FROMTASK(stMsg, __pstSelf); \
321  ESOS_SET_MSG_DATA_LENGTH(stMsg, len); \
322  for (__u8_esos_mail_routines_dummy_uint8=0; __u8_esos_mail_routines_dummy_uint8<len; __u8_esos_mail_routines_dummy_uint8++) { \
323  stMsg.au8_Contents[__u8_esos_mail_routines_dummy_uint8] = pau8x[__u8_esos_mail_routines_dummy_uint8]; \
324  } \
325  } while(0)
326 
327 #define ESOS_TASK_MAKE_MSG_UINT16(stMsg, u16x) \
328  do{ \
329  ESOS_SET_MSG_FLAGS(stMsg, ESOS_MAILMESSAGE_UINT16); \
330  ESOS_SET_MSG_FROMTASK(stMsg, __pstSelf); \
331  ESOS_SET_MSG_DATA_LENGTH(stMsg, 1); \
332  stMsg.au16_Contents[0] = (u16x); \
333  } while(0)
334 
335 #define ESOS_TASK_MAKE_MSG_UINT16_X2(stMsg, u16x0, u16x1) \
336  do{ \
337  ESOS_SET_MSG_FLAGS(stMsg, ESOS_MAILMESSAGE_UINT16); \
338  ESOS_SET_MSG_FROMTASK(stMsg, __pstSelf); \
339  ESOS_SET_MSG_DATA_LENGTH(stMsg, 2); \
340  stMsg.au16_Contents[0] = (u16x0); \
341  stMsg.au16_Contents[1] = (u16x1); \
342  } while(0)
343 
344 #define ESOS_TASK_MAKE_MSG_UINT16_X3(stMsg, u16x0, u16x1, u16x2) \
345  do{ \
346  ESOS_SET_MSG_FLAGS(stMsg, ESOS_MAILMESSAGE_UINT16); \
347  ESOS_SET_MSG_FROMTASK(stMsg, __pstSelf); \
348  ESOS_SET_MSG_DATA_LENGTH(stMsg, 3); \
349  stMsg.au16_Contents[0] = (u16x0); \
350  stMsg.au16_Contents[1] = (u16x1); \
351  stMsg.au16_Contents[2] = (u16x2); \
352  } while(0)
353 
354 #define ESOS_TASK_MAKE_MSG_UINT16_X4(stMsg, u16x0, u16x1, u16x2, u16x3) \
355  do{ \
356  ESOS_SET_MSG_FLAGS(stMsg, ESOS_MAILMESSAGE_UINT16); \
357  ESOS_SET_MSG_FROMTASK(stMsg, __pstSelf); \
358  ESOS_SET_MSG_DATA_LENGTH(stMsg, 4); \
359  stMsg.au16_Contents[0] = (u16x0); \
360  stMsg.au16_Contents[1] = (u16x1); \
361  stMsg.au16_Contents[2] = (u16x2); \
362  stMsg.au16_Contents[3] = (u16x3); \
363  } while(0)
364 
365 #define ESOS_TASK_MAKE_MSG_UINT32(stMsg, u32x) \
366  do{ \
367  ESOS_SET_MSG_FLAGS(stMsg, ESOS_MAILMESSAGE_UINT32); \
368  ESOS_SET_MSG_FROMTASK(stMsg, __pstSelf); \
369  ESOS_SET_MSG_DATA_LENGTH(stMsg, 1); \
370  stMsg.au32_Contents[0] = (u32x); \
371  } while(0)
372 
373 #define ESOS_TASK_MAKE_MSG_UINT32_X2(stMsg, u32x0, u32x1) \
374  do{ \
375  ESOS_SET_MSG_FLAGS(stMsg, ESOS_MAILMESSAGE_UINT32); \
376  ESOS_SET_MSG_FROMTASK(stMsg, __pstSelf); \
377  ESOS_SET_MSG_DATA_LENGTH(stMsg, 2); \
378  stMsg.au32_Contents[0] = (u32x0); \
379  stMsg.au32_Contents[1] = (u32x1); \
380  } while(0)
381 
382 
383 #define PRINTF_MESSAGE(stMsg) \
384  do{ \
385  printf("MESSAGE u8_flags = %02X\n",ESOS_GET_MSG_FLAGS(stMsg) ); \
386  printf(" u16_FromTaskID = %d\n",ESOS_GET_MSG_FROMTASK(stMsg) ); \
387  printf(" u8_DataLength = %d\n",ESOS_GET_MSG_DATA_LENGTH(stMsg) ); \
388  printf(" u32_PostMark = %d\n",ESOS_GET_MSG_POSTMARK(stMsg) ); \
389  printf(" first byte = %d\n",stMsg.au8_Contents[0]); \
390  } while(0)
391 
392 /* E X T E R N S ************************************************************/
393 extern MAILBOX __astMailbox[MAX_NUM_USER_TASKS];
394 extern uint8_t __au8_MBData[MAX_NUM_USER_TASKS][MAX_SIZE_TASK_MAILBOX];
395 extern uint8_t __u8_esos_mail_routines_dummy_uint8;
396 
397 /* P U B L I C P R O T O T Y P E S *****************************************/
398 
399 /* P R I V A T E P R O T O T Y P E S ***********************************/
400 
401 /**
402 *
403 */
404 void __esos_InitMailbox(MAILBOX* pst_Mailbox, uint8_t* pau8_ptr);
405 
406 //void __esos_WriteMailboxUINT8(MAILBOX* pst_Mailbox, uint8_t u8_x );
407 #define __esos_WriteMailboxUINT8(pstMB, u8x) __esos_CB_WriteUINT8((pstMB)->pst_CBuffer, (u8x) )
408 
409 //uint8_t __esos_ReadMailboxUINT8(MAILBOX* pst_Mailbox );
410 #define __esos_ReadMailboxUINT8(pstMB, u8x) __esos_CB_ReadUINT8((pstMB)->pst_CBuffer )
411 
412 /**
413 * Writes a mail message into some task's mailbox
414 * \param pst_Task handle tretval verNum Version number. Exact value and meaning depends on hardware
415 * \param pst_Mailbox Pointer to struct instance of MAILBOX.
416 * \param pau8_data Pointer to mail data to send.
417 * \param u8_len Local instance of length of message.
418 * \hideinitializer
419 */
420 void __esos_SendMailUint8(struct stTask* pst_Task, MAILBOX* pst_Mailbox, uint8_t* pau8_data, uint8_t u8_len );
421 void __esos_ReadMailMessage(struct stTask* pst_Task, MAILMESSAGE* pst_Message );
422 void __esos_SendMailMessage(struct stTask* pst_RcvrTask, MAILMESSAGE* pst_Msg );
423 
424 /** @} */
425 
426 #endif // ESOS_MAIL_H
#define __MAIL_MSG_MAX_DATA_LEN
Definition: esos_mail.h:80
void __esos_SendMailUint8(struct stTask *pst_Task, MAILBOX *pst_Mailbox, uint8_t *pau8_data, uint8_t u8_len)
unsigned char uint8_t
An abbreviation for an 8-bit unsigned integer.
Definition: dataXferImpl.h:194