tinyusb  0.4
Click here to lend your support to tinyusb donation and make a donation at pledgie.com
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
osal_none.h
Go to the documentation of this file.
1 /**************************************************************************/
37 /**************************************************************************/
38 
43 #ifndef _TUSB_OSAL_NONE_H_
44 #define _TUSB_OSAL_NONE_H_
45 
46 #include "osal_common.h"
47 
48 #ifdef __cplusplus
49  extern "C" {
50 #endif
51 
52 //--------------------------------------------------------------------+
53 // TICK API
54 //--------------------------------------------------------------------+
55 uint32_t tusb_tick_get(void);
56 #define osal_tick_get tusb_tick_get
57 
58 //--------------------------------------------------------------------+
59 // TASK API
60 // NOTES: Each blocking OSAL_NONE services such as semaphore wait,
61 // queue receive embedded return statement, therefore local variable
62 // retain value before/after such services needed to declare as static
63 // OSAL_TASK_LOOP
64 // {
65 // OSAL_TASK_LOOP_BEGIN
66 //
67 // task body statements
68 //
69 // OSAL_TASK_LOOP_ENG
70 // }
71 //--------------------------------------------------------------------+
72 #define OSAL_TASK_DEF(code, stack_depth, prio)
73 #define OSAL_TASK_REF
74 #define osal_task_create(x) TUSB_ERROR_NONE
75 
76 #define OSAL_TASK_FUNCTION(task_func, p_para) tusb_error_t task_func(void * p_para)
77 
78 #define TASK_RESTART \
79  state = 0
80 
81 #define OSAL_TASK_LOOP_BEGIN \
82  ATTR_UNUSED static uint32_t timeout = 0;\
83  static uint16_t state = 0;\
84  (void) timeout; /* timemout can possible unsued */ \
85  switch(state) { \
86  case 0: { \
87 
88 #define OSAL_TASK_LOOP_END \
89  default:\
90  TASK_RESTART;\
91  }}\
92  return TUSB_ERROR_NONE;
93 
94 
95 #define osal_task_delay(msec) \
96  do {\
97  timeout = osal_tick_get();\
98  state = __LINE__; case __LINE__:\
99  if ( timeout + osal_tick_from_msec(msec) > osal_tick_get() ) /* time out */ \
100  return TUSB_ERROR_OSAL_WAITING;\
101  }while(0)
102 
103 //--------------------------------------------------------------------+
104 // SUBTASK (a sub function that uses OS blocking services & called by a task
105 //--------------------------------------------------------------------+
106 #define OSAL_SUBTASK_INVOKED_AND_WAIT(subtask, status) \
107  do {\
108  state = __LINE__; case __LINE__:\
109  {\
110  status = subtask; /* invoke sub task */\
111  if (TUSB_ERROR_OSAL_WAITING == status) /* sub task not finished -> continue waiting */\
112  return TUSB_ERROR_OSAL_WAITING;\
113  }\
114  }while(0)
115 
116 #define OSAL_SUBTASK_BEGIN OSAL_TASK_LOOP_BEGIN
117 #define OSAL_SUBTASK_END OSAL_TASK_LOOP_END
118 
119 //------------- Sub Task Assert -------------//
120 #define SUBTASK_EXIT(error) \
121  do {\
122  TASK_RESTART; return error;\
123  }while(0)
124 
125 #define _SUBTASK_ASSERT_ERROR_HANDLER(error, func_call) \
126  func_call; TASK_RESTART; return error
127 
128 #define SUBTASK_ASSERT_STATUS(sts) \
129  ASSERT_DEFINE_WITH_HANDLER(_SUBTASK_ASSERT_ERROR_HANDLER, , tusb_error_t status = (tusb_error_t)(sts),\
130  TUSB_ERROR_NONE == status, status, "%s", TUSB_ErrorStr[status])
131 
132 #define SUBTASK_ASSERT_STATUS_WITH_HANDLER(sts, func_call) \
133  ASSERT_DEFINE_WITH_HANDLER(_SUBTASK_ASSERT_ERROR_HANDLER, func_call, tusb_error_t status = (tusb_error_t)(sts),\
134  TUSB_ERROR_NONE == status, status, "%s", TUSB_ErrorStr[status])
135 
136 // TODO allow to specify error return
137 #define SUBTASK_ASSERT(condition) \
138  ASSERT_DEFINE_WITH_HANDLER(_SUBTASK_ASSERT_ERROR_HANDLER, , , \
139  (condition), TUSB_ERROR_OSAL_TASK_FAILED, "%s", "evaluated to false")
140 // TODO remove assert with handler by catching error in enum main task
141 #define SUBTASK_ASSERT_WITH_HANDLER(condition, func_call) \
142  ASSERT_DEFINE_WITH_HANDLER(_SUBTASK_ASSERT_ERROR_HANDLER, func_call, ,\
143  condition, TUSB_ERROR_OSAL_TASK_FAILED, "%s", "evaluated to false")
144 
145 //--------------------------------------------------------------------+
146 // Semaphore API
147 //--------------------------------------------------------------------+
148 typedef volatile uint8_t osal_semaphore_t;
149 typedef osal_semaphore_t * osal_semaphore_handle_t;
150 
151 #define OSAL_SEM_DEF(name)\
152  osal_semaphore_t name
153 
154 #define OSAL_SEM_REF(name)\
155  &name
156 
157 static inline osal_semaphore_handle_t osal_semaphore_create(osal_semaphore_t * p_sem) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
158 static inline osal_semaphore_handle_t osal_semaphore_create(osal_semaphore_t * p_sem)
159 {
160  (*p_sem) = 0; // TODO consider to have initial count parameter
161  return (osal_semaphore_handle_t) p_sem;
162 }
163 
164 static inline tusb_error_t osal_semaphore_post(osal_semaphore_handle_t sem_hdl) ATTR_ALWAYS_INLINE;
165 static inline tusb_error_t osal_semaphore_post(osal_semaphore_handle_t sem_hdl)
166 {
167  (*sem_hdl)++;
168 
169  return TUSB_ERROR_NONE;
170 }
171 
172 static inline void osal_semaphore_reset(osal_semaphore_handle_t sem_hdl) ATTR_ALWAYS_INLINE;
173 static inline void osal_semaphore_reset(osal_semaphore_handle_t sem_hdl)
174 {
175  (*sem_hdl) = 0;
176 }
177 
178 #define osal_semaphore_wait(sem_hdl, msec, p_error) \
179  do {\
180  timeout = osal_tick_get();\
181  state = __LINE__; case __LINE__:\
182  if( *(sem_hdl) == 0 ) {\
183  if ( ( ((uint32_t) (msec)) != OSAL_TIMEOUT_WAIT_FOREVER) && (timeout + osal_tick_from_msec(msec) <= osal_tick_get()) ) /* time out */ \
184  *(p_error) = TUSB_ERROR_OSAL_TIMEOUT;\
185  else\
186  return TUSB_ERROR_OSAL_WAITING;\
187  } else{\
188  (*(sem_hdl))--; /*TODO mutex hal_interrupt_disable consideration*/\
189  *(p_error) = TUSB_ERROR_NONE;\
190  }\
191  }while(0)
192 
193 //--------------------------------------------------------------------+
194 // MUTEX API (priority inheritance)
195 //--------------------------------------------------------------------+
196 typedef osal_semaphore_t osal_mutex_t;
197 typedef osal_semaphore_handle_t osal_mutex_handle_t;
198 
199 #define OSAL_MUTEX_DEF(name)\
200  osal_mutex_t name
201 
202 #define OSAL_MUTEX_REF(name)\
203  &name
204 
205 static inline osal_mutex_handle_t osal_mutex_create(osal_mutex_t * p_mutex) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
206 static inline osal_mutex_handle_t osal_mutex_create(osal_mutex_t * p_mutex)
207 {
208  (*p_mutex) = 1;
209  return (osal_mutex_handle_t) p_mutex;
210 }
211 
212 static inline tusb_error_t osal_mutex_release(osal_mutex_handle_t mutex_hdl) ATTR_ALWAYS_INLINE;
213 static inline tusb_error_t osal_mutex_release(osal_mutex_handle_t mutex_hdl)
214 {
215  (*mutex_hdl) = 1; // mutex is a binary semaphore
216 
217  return TUSB_ERROR_NONE;
218 }
219 
220 static inline void osal_mutex_reset(osal_mutex_handle_t mutex_hdl) ATTR_ALWAYS_INLINE;
221 static inline void osal_mutex_reset(osal_mutex_handle_t mutex_hdl)
222 {
223  (*mutex_hdl) = 1;
224 }
225 
226 #define osal_mutex_wait osal_semaphore_wait
227 
228 //--------------------------------------------------------------------+
229 // QUEUE API
230 //--------------------------------------------------------------------+
231 typedef struct{
232  uint8_t* const buffer ;
233  uint8_t const depth ;
234  uint8_t const item_size ;
235  volatile uint8_t count ;
236  volatile uint8_t wr_idx ;
237  volatile uint8_t rd_idx ;
238 } osal_queue_t;
239 
241 
242 // use to declare a queue, within the scope of tinyusb, should only use primitive type only
243 #define OSAL_QUEUE_DEF(name, queue_depth, type)\
244  STATIC_ASSERT(queue_depth < 256, "OSAL Queue only support up to 255 depth");\
245  type name##_buffer[queue_depth];\
246  osal_queue_t name = {\
247  .buffer = (uint8_t*) name##_buffer,\
248  .depth = queue_depth,\
249  .item_size = sizeof(type)\
250  }
251 
252 #define OSAL_QUEUE_REF(name) (&name)
253 
254 static inline osal_queue_handle_t osal_queue_create(osal_queue_t * const p_queue) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
255 static inline osal_queue_handle_t osal_queue_create(osal_queue_t * const p_queue)
256 {
257  p_queue->count = p_queue->wr_idx = p_queue->rd_idx = 0;
258  return (osal_queue_handle_t) p_queue;
259 }
260 
261 // TODO move to osal_none.c
262 // when queue is full, it will overwrite the oldest data in the queue
263 static inline tusb_error_t osal_queue_send(osal_queue_handle_t const queue_hdl, void const * data) ATTR_ALWAYS_INLINE;
264 static inline tusb_error_t osal_queue_send(osal_queue_handle_t const queue_hdl, void const * data)
265 {
266  //TODO mutex lock hal_interrupt_disable
267 
268  memcpy( queue_hdl->buffer + (queue_hdl->wr_idx * queue_hdl->item_size),
269  data,
270  queue_hdl->item_size);
271 
272  queue_hdl->wr_idx = (queue_hdl->wr_idx + 1) % queue_hdl->depth;
273 
274  if (queue_hdl->depth == queue_hdl->count) // queue is full, 1st rd is overwritten
275  {
276  queue_hdl->rd_idx = queue_hdl->wr_idx; // keep full state
277  }else
278  {
279  queue_hdl->count++;
280  }
281 
282  //TODO mutex unlock hal_interrupt_enable
283 
284  return TUSB_ERROR_NONE;
285 }
286 
287 static inline void osal_queue_flush(osal_queue_handle_t const queue_hdl) ATTR_ALWAYS_INLINE;
288 static inline void osal_queue_flush(osal_queue_handle_t const queue_hdl)
289 {
290  queue_hdl->count = queue_hdl->rd_idx = queue_hdl->wr_idx = 0;
291 }
292 
293 #define osal_queue_receive(queue_hdl, p_data, msec, p_error) \
294  do {\
295  timeout = osal_tick_get();\
296  state = __LINE__; case __LINE__:\
297  if( queue_hdl->count == 0 ) {\
298  if ( (msec != OSAL_TIMEOUT_WAIT_FOREVER) && ( timeout + osal_tick_from_msec(msec) <= osal_tick_get() )) /* time out */ \
299  *(p_error) = TUSB_ERROR_OSAL_TIMEOUT;\
300  else\
301  return TUSB_ERROR_OSAL_WAITING;\
302  } else{\
303  /*TODO mutex lock hal_interrupt_disable */\
304  memcpy(p_data, queue_hdl->buffer + (queue_hdl->rd_idx * queue_hdl->item_size), queue_hdl->item_size);\
305  queue_hdl->rd_idx = (queue_hdl->rd_idx + 1) % queue_hdl->depth;\
306  queue_hdl->count--;\
307  /*TODO mutex unlock hal_interrupt_enable */\
308  *(p_error) = TUSB_ERROR_NONE;\
309  }\
310  }while(0)
311 
312 #ifdef __cplusplus
313  }
314 #endif
315 
316 #endif /* _TUSB_OSAL_NONE_H_ */
317 
#define ATTR_WARN_UNUSED_RESULT
The warn_unused_result attribute causes a warning to be emitted if a caller of the function with this...
Definition: compiler_gcc.h:118
uint8_t const item_size
size of each item
volatile uint8_t rd_idx
read pointer
Definition: osal_none.h:237
volatile uint8_t count
number of items in queue
Definition: osal_none.h:235
volatile uint8_t wr_idx
write pointer
Definition: osal_none.h:236
tusb_error_t
Error Code returned.
Definition: tusb_errors.h:97
uint8_t *const buffer
buffer pointer
Definition: osal_none.h:232
uint8_t const depth
buffer size
#define ATTR_ALWAYS_INLINE
Generally, functions are not inlined unless optimization is specified. For functions declared inline...
Definition: compiler_gcc.h:89