1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
|
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.io/license.html
*/
/**
* @file src/gos/gos.h
* @brief GOS - Operating System Support header file
*
* @addtogroup GOS
*
* @brief Module to build a uniform abstraction layer between uGFX and the underlying system
*
* @note Some of the routines specified below may be implemented simply as
* a macro to the real operating system call.
* @{
*/
#ifndef _GOS_H
#define _GOS_H
#if defined(__DOXYGEN__)
/*===========================================================================*/
/* Type definitions */
/*===========================================================================*/
/**
* @name Various integer sizes
* @note Your platform may define these differently to these.
* @note These sizes are guaranteed minimum sizes for the type. It might actually be larger.
* eg gI8 may actually be 9 bits.
* @{
*/
typedef unsigned char gBool;
typedef signed char gI8;
typedef unsigned char gU8;
typedef short gI16;
typedef unsigned short gU16;
typedef long gI32;
typedef unsigned long gU32;
/** @} */
/**
* @name More integer sizes
* @pre These are only available if GFX_TYPE_64 is GFXON as not all compilers support 64 bit.
* @note GFX_TYPE_64 is set to GFXON or GFXOFF by the compiler detector. It is not a user configuration macro.
* @{
*/
typedef long long gI64;
typedef unsigned long long gU64;
/** @} */
/**
* @name Various platform (and operating system) dependent types
* @note Your platform may use slightly different definitions to these
* @{
*/
typedef unsigned long gDelay;
typedef unsigned long gTicks;
typedef short gSemcount;
typedef int gThreadreturn;
typedef int gThreadpriority;
/** @} */
/**
* @brief Declare a thread function
*
* @param[in] fnName The name of the function
* @param[in] param A custom parameter that is passed to the function
*/
#define DECLARE_THREAD_FUNCTION(fnName, param) gThreadreturn fnName(void *param)
/**
* @brief Declare a thread stack
*
* @param[in] name The name of the stack
* @param[in] sz The size of the stack in bytes
*
* @note The size provided is just a suggestion to the required stack size.
* Many platforms will round the size to ensure correct stack alignment.
* Other platforms may entirely ignore the suggested size.
*/
#define DECLARE_THREAD_STACK(name, sz) uint8_t name[sz];
/*
* @brief Return from a thread
*
* @details Some underlying operating systems allow to return a value from a thread while others don't.
* For systems that don't allow to return a value from a thread function this call is simply ignored.
*
* @param[in] reval The value which should be returned
*/
#define THREAD_RETURN(retval) return retval
/**
* @name Various platform (and operating system) constants
* @note Your platform may use slightly different definitions to these
* @{
*/
#define gDelayNone 0
#define gDelayForever ((gDelay)-1)
#define MAX_SEMAPHORE_COUNT ((gSemcount)(((unsigned long)((gSemcount)(-1))) >> 1))
#define gThreadpriorityLow 0
#define gThreadpriorityNormal 1
#define gThreadpriorityHigh 2
/** @} */
/**
* @brief A semaphore
* @note Your operating system will have a proper definition for this structure
*/
typedef struct {} gfxSem;
/**
* @brief A mutex
* @note Your operating system will have a proper definition for this structure
*/
typedef struct {} gfxMutex;
/**
* @brief A thread handle
* @note Your operating system will have a proper definition for this.
*/
typedef void * gThread;
/*===========================================================================*/
/* Function declarations. */
/*===========================================================================*/
/**
* @brief Halt the GFX application due to an error.
*
* @param[in] msg An optional debug message to show (Can be NULL)
*
* @api
*/
void gfxHalt(const char *msg);
/**
* @brief Exit the GFX application.
*
* @api
*/
void gfxExit(void);
/**
* @brief Allocate memory
* @return A pointer to the memory allocated or NULL if there is no more memory available
*
* @param[in] sz The size in bytes of the area to allocate
*
* @api
*/
void *gfxAlloc(size_t sz);
/**
* @brief Re-allocate memory
* @return A pointer to the new memory area or NULL if there is no more memory available
*
* @param[in] ptr The old memory area to be increased/decreased in size
* @param[in] oldsz The size in bytes of the old memory area
* @param[in] newsz The size in bytes of the new memory area
*
* @note Some operating systems don't use the oldsz parameter as they implicitly know the size of
* old memory area. The parameter must always be supplied however for API compatibility.
* @note gfxRealloc() can make the area smaller or larger but may have to return a different pointer.
* If this occurs the new area contains a copy of the data from the old area. The old memory
* pointer should not be used after this routine as the original area may have been freed.
* @note If there is insufficient memory to create the new memory region, NULL is returned and the
* old memory area is left unchanged.
*
* @api
*/
void *gfxRealloc(void *ptr, size_t oldsz, size_t newsz);
/**
* @brief Free memory
*
* @param[in] ptr The memory to free
*
* @api
*/
void gfxFree(void *ptr);
/**
* @brief Use gfxAlloc and gfxFree to implement malloc() and free()
*
* @note Sometimes your application will include functions that
* want to internally use malloc() and free(). As the default
* implementations of these in your C library are almost
* invariably incorrect for an embedded platform, this option
* allows you to emulate those calls with gfxAlloc() and gfxFree().
* An example is the C library routine rand() which on many
* implementations internally uses malloc().
*
* @api
*/
#ifndef GFX_EMULATE_MALLOC
#define GFX_EMULATE_MALLOC GFXOFF
#endif
/**
* @brief Yield the current thread
* @details Give up the rest of the current time slice for this thread in order to give other threads
* a chance to run.
*
* @api
*/
void gfxYield(void);
/**
* @brief Put the current thread to sleep for the specified period in milliseconds
*
* @param[in] ms The number milliseconds to sleep
*
* @note Specifying gDelayNone will yield the current thread but return
* on the next time slice.
* @note Specifying gDelayForever will sleep forever.
*
* @api
*/
void gfxSleepMilliseconds(gDelay ms);
/**
* @brief Put the current thread to sleep for the specified period in microseconds
*
* @param[in] us The number microseconds to sleep
*
* @note Specifying gDelayNone will return immediately (no sleeping)
* @note Specifying gDelayForever will sleep forever.
*
* @api
*/
void gfxSleepMicroseconds(gDelay us);
/**
* @brief Get the current operating system tick time
* @return The current tick time
*
* @note A "tick" is an arbitrary period of time that the operating
* system uses to mark time.
* @note The absolute value of this call is relatively meaningless. Its usefulness
* is in calculating periods between two calls to this function.
* @note As the value from this function can wrap it is important that any periods are calculated
* as t2 - t1 and then compared to the desired period rather than comparing
* t1 + period to t2
*
* @api
*/
gTicks gfxSystemTicks(void);
/**
* @brief Convert a given number of millseconds to a number of operating system ticks
* @return The period in system ticks.
*
* @note A "tick" is an arbitrary period of time that the operating
* system uses to mark time.
*
* @param[in] ms The number of millseconds
*
* @api
*/
gTicks gfxMillisecondsToTicks(gDelay ms);
/**
* @brief Lock the operating system to protect a sequence of code
*
* @note Calling this will lock out all other threads from executing even at interrupt level
* within the GFX system. On hardware this may be implemented as a disabling of interrupts,
* however in an operating system which hides real interrupt level code it may simply use a
* mutex lock.
* @note The thread MUST NOT block whilst the system is locked. It must execute in this state for
* as short a period as possible as this can seriously affect interrupt latency on some
* platforms.
* @note While locked only interrupt level (iclass) GFX routines may be called.
*
* @api
*/
void gfxSystemLock(void);
/**
* @brief Unlock the operating system previous locked by gfxSystemLock()
*
* @api
*/
void gfxSystemUnlock(void);
/**
* @brief Initialise a mutex to protect a region of code from other threads.
*
* @param[in] pmutex A pointer to the mutex
*
* @note Whilst a counting semaphore with a limit of 1 can be used for similiar purposes
* on many operating systems using a seperate mutex structure is more efficient.
*
* @api
*/
void gfxMutexInit(gfxMutex *pmutex);
/**
* @brief Destroy a Mutex.
*
* @param[in] pmutex A pointer to the mutex
*
* @api
*/
void gfxMutexDestroy(gfxMutex *pmutex);
/**
* @brief Enter the critical code region protected by the mutex.
* @details Blocks until there is no other thread in the critical region.
*
* @param[in] pmutex A pointer to the mutex
*
* @api
*/
void gfxMutexEnter(gfxMutex *pmutex);
/**
* @brief Exit the critical code region protected by the mutex.
* @details May cause another thread waiting on the mutex to now be placed into the run queue.
*
* @param[in] pmutex A pointer to the mutex
*
* @api
*/
void gfxMutexExit(gfxMutex *pmutex);
/**
* @brief Initialise a Counted Semaphore
*
* @param[in] psem A pointer to the semaphore
* @param[in] val The initial value of the semaphore
* @param[in] limit The maxmimum value of the semaphore
*
* @note Operations defined for counted semaphores:
* Signal: The semaphore counter is increased and if the result is non-positive then a waiting thread
* is queued for execution. Note that once the thread reaches "limit", further signals are
* ignored.
* Wait: The semaphore counter is decreased and if the result becomes negative the thread is queued
* in the semaphore and suspended.
*
* @api
*/
void gfxSemInit(gfxSem *psem, gSemcount val, gSemcount limit);
/**
* @brief Destroy a Counted Semaphore
*
* @param[in] psem A pointer to the semaphore
*
* @note Any threads waiting on the semaphore will be released
*
* @api
*/
void gfxSemDestroy(gfxSem *psem);
/**
* @brief Wait on a semaphore
* @details The semaphore counter is decreased and if the result becomes negative the thread waits for it to become
* non-negative again
* @return gFalse if the wait timeout occurred otherwise gTrue
*
* @param[in] psem A pointer to the semaphore
* @param[in] ms The maximum time to wait for the semaphore
*
* @api
*/
gBool gfxSemWait(gfxSem *psem, gDelay ms);
/**
* @brief Test if a wait on a semaphore can be satisfied immediately
* @details Equivalent to @p gfxSemWait(psem, gDelayNone) except it can be called at interrupt level
* @return gFalse if the wait would occur occurred otherwise gTrue
*
* @param[in] psem A pointer to the semaphore
*
* @iclass
* @api
*/
gBool gfxSemWaitI(gfxSem *psem);
/**
* @brief Signal a semaphore
* @details The semaphore counter is increased and if the result is non-positive then a waiting thread
* is queued for execution. Note that once the thread reaches "limit", further signals are
* ignored.
*
* @param[in] psem A pointer to the semaphore
*
* @api
*/
void gfxSemSignal(gfxSem *psem);
/**
* @brief Signal a semaphore
* @details The semaphore counter is increased and if the result is non-positive then a waiting thread
* is queued for execution. Note that once the thread reaches "limit", further signals are
* ignored.
*
* @param[in] psem A pointer to the semaphore
*
* @iclass
* @api
*/
void gfxSemSignalI(gfxSem *psem);
/**
* @brief Start a new thread.
* @return Returns a thread handle if the thread was started, NULL on an error
*
* @param[in] stackarea A pointer to the area for the new threads stack or NULL to dynamically allocate it
* @param[in] stacksz The size of the thread stack. 0 means the default operating system size although this
* is only valid when stackarea is dynamically allocated.
* @param[in] prio The priority of the new thread
* @param[in] fn The function the new thread will run
* @param[in] param A parameter to pass the thread function.
*
* @api
*/
gThread gfxThreadCreate(void *stackarea, size_t stacksz, gThreadpriority prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param);
/**
* @brief Wait for a thread to finish.
* @return Returns the thread exit code.
*
* @param[in] thread The Thread Handle
*
* @note This will also close the thread handle as it is no longer useful
* once the thread has ended.
* @api
*/
gThreadreturn gfxThreadWait(gThread thread);
/**
* @brief Get the current thread handle.
* @return A thread handle
*
* @api
*/
gThread gfxThreadMe(void);
/**
* @brief Close the thread handle.
*
* @param[in] thread The Thread Handle
*
* @note This does not affect the thread, it just closes our handle to the thread.
*
* @api
*/
void gfxThreadClose(gThread thread);
/**
* All the above was just for the doxygen documentation. All the implementation of the above
* (without any of the documentation overheads) is in the files below.
*/
#elif GFX_USE_OS_RAWRTOS
#include "gos_rawrtos.h"
#elif GFX_USE_OS_CHIBIOS
#include "gos_chibios.h"
#elif GFX_USE_OS_FREERTOS
#include "gos_freertos.h"
#elif GFX_USE_OS_WIN32
#include "gos_win32.h"
#elif GFX_USE_OS_LINUX
#include "gos_linux.h"
#elif GFX_USE_OS_OSX
#include "gos_osx.h"
#elif GFX_USE_OS_RAW32
#include "gos_raw32.h"
#elif GFX_USE_OS_ECOS
#include "gos_ecos.h"
#elif GFX_USE_OS_ARDUINO
#include "gos_arduino.h"
#elif GFX_USE_OS_CMSIS
#include "gos_cmsis.h"
#elif GFX_USE_OS_CMSIS2
#include "gos_cmsis2.h"
#elif GFX_USE_OS_KEIL
#include "gos_keil.h"
#elif GFX_USE_OS_RTX5
#include "gos_rtx5.h"
#elif GFX_USE_OS_NIOS
#include "gos_nios.h"
#elif GFX_USE_OS_ZEPHYR
#include "gos_zephyr.h"
#elif GFX_USE_OS_QT
#include "gos_qt.h"
#else
#error "Your operating system is not supported yet"
#endif
#if GFX_COMPAT_V2
typedef gDelay delaytime_t;
#if !GFX_USE_OS_CHIBIOS
// These values are defined by ChibiOS itself
#define TIME_IMMEDIATE gDelayNone
#define TIME_INFINITE gDelayForever
#endif
typedef gTicks systemticks_t;
typedef gThread gfxThreadHandle;
typedef gThreadreturn threadreturn_t;
typedef gThreadpriority threadpriority_t;
#define LOW_PRIORITY gThreadpriorityLow
#define NORMAL_PRIORITY gThreadpriorityNormal
#define HIGH_PRIORITY gThreadpriorityHigh
#endif
#endif /* _GOS_H */
/** @} */
|