aboutsummaryrefslogtreecommitdiffstats
path: root/src/gos/gos.h
blob: 09b278bcf9bf5af3ba6d4a3159838d5fb52f6e2e (plain)
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
/*
 * 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.org/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 use slightly different definitions to these
	 * @{
	 */
	typedef unsigned char	bool_t;
	typedef char			int8_t;
	typedef unsigned char	uint8_t;
	typedef short			int16_t;
	typedef unsigned short	uint16_t;
	typedef long			int32_t;
	typedef unsigned long	uint32_t;
	/** @} */

	/**
	 * @name	Various platform (and operating system) dependent types
	 * @note	Your platform may use slightly different definitions to these
	 * @{
	 */
	typedef unsigned long	size_t;
	typedef unsigned long	delaytime_t;
	typedef unsigned long	systemticks_t;
	typedef short			semcount_t;
	typedef int				threadreturn_t;
	typedef int				threadpriority_t;
	/** @} */

	/**
	 * @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)	threadreturn_t fnName(void *param)

	/**
	 * @brief	Declare a thread stack
	 *
	 * @param[in] name 		The name of the stack
	 * @param[in] sz 		The size of the stack
	 */
	#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 FALSE						0
	#define TRUE						1
	#define TIME_IMMEDIATE				0
	#define TIME_INFINITE				((delaytime_t)-1)
	#define MAX_SEMAPHORE_COUNT			((semcount_t)(((unsigned long)((semcount_t)(-1))) >> 1))
	#define LOW_PRIORITY				0
	#define NORMAL_PRIORITY				1
	#define HIGH_PRIORITY				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 * gfxThreadHandle;

	/*===========================================================================*/
	/* Function declarations.                                                    */
	/*===========================================================================*/

	#ifdef __cplusplus
	extern "C" {
	#endif

	/**
	 * @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			FALSE
	#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 TIME_IMMEDIATE will yield the current thread but return
	 * 				on the next time slice.
	 * @note		Specifying TIME_INFINITE will sleep forever.
	 *
	 * @api
	 */
	void gfxSleepMilliseconds(delaytime_t ms);

	/**
	 * @brief	Put the current thread to sleep for the specified period in microseconds
	 *
	 * @param[in] us	The number microseconds to sleep
	 *
	 * @note		Specifying TIME_IMMEDIATE will return immediately (no sleeping)
	 * @note		Specifying TIME_INFINITE will sleep forever.
	 *
	 * @api
	 */
	void gfxSleepMicroseconds(delaytime_t 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
	 */
	systemticks_t 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
	 */
	systemticks_t gfxMillisecondsToTicks(delaytime_t 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, semcount_t val, semcount_t 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	FALSE if the wait timeout occurred otherwise TRUE
	 *
	 * @param[in] psem		A pointer to the semaphore
	 * @param[in] ms		The maximum time to wait for the semaphore
	 *
	 * @api
	 */
	bool_t gfxSemWait(gfxSem *psem, delaytime_t ms);

	/**
	 * @brief	Test if a wait on a semaphore can be satisfied immediately
	 * @details	Equivalent to @p gfxSemWait(psem, TIME_IMMEDIATE) except it can be called at interrupt level
	 * @return	FALSE if the wait would occur occurred otherwise TRUE
	 *
	 * @param[in] psem		A pointer to the semaphore
	 *
	 * @iclass
	 * @api
	 */
	bool_t 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	Get the current semaphore count
	 * @return	The current semaphore count
	 *
	 * @param[in] psem		A pointer to the semaphore
	 *
	 * @api
	 */
	semcount_t gfxSemCounter(gfxSem *psem);

	/**
	 * @brief	Get the current semaphore count
	 * @return	The current semaphore count
	 *
	 * @param[in] psem		A pointer to the semaphore
	 *
	 * @iclass
	 * @api
	 */
	semcount_t gfxSemCounterI(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
	 */
	gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t 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
	 */
	threadreturn_t gfxThreadWait(gfxThreadHandle thread);

	/**
	 * @brief	Get the current thread handle.
	 * @return	A thread handle
	 *
	 * @api
	 */
	gfxThreadHandle 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(gfxThreadHandle thread);

	#ifdef __cplusplus
	}
	#endif

/**
 * 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_KEIL
    #include "gos_keil.h"
#elif GFX_USE_OS_NIOS
    #include "gos_nios.h"
#elif GFX_USE_OS_QT
    #include "gos_qt.h"
#else
	#error "Your operating system is not supported yet"
#endif

#endif /* _GOS_H */
/** @} */