gx_system_rtos_bind_rtthread.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. /**************************************************************************/
  2. /**************************************************************************/
  3. /** */
  4. /** GUIX Component */
  5. /** */
  6. /** System Management (System) */
  7. /** */
  8. /**************************************************************************/
  9. //#define GX_SOURCE_CODE
  10. /* Include necessary system files. */
  11. #include "gx_api.h"
  12. #include "gx_system.h"
  13. #include "gx_system_rtos_bind.h"
  14. #ifndef GX_THREADX_BINDING
  15. /* This is an example of a generic RTOS binding. We have #ifdefed this code out
  16. of the GUIX library build, so that the user attempting to port to a new RTOS
  17. will intentionally observe a series of linker errors. These functions need to
  18. be implemented in a way that works correctly with the target RTOS.
  19. */
  20. #if defined(GUIX_BINDING_RT_THREAD)
  21. #include "rtthread.h"
  22. #ifndef OS_CFG_TICK_RATE_HZ
  23. #define OS_CFG_TICK_RATE_HZ 1000
  24. #endif
  25. #define GX_TIMER_TASK_PRIORITY (GX_SYSTEM_THREAD_PRIORITY + 1)
  26. #define GX_TIMER_TASK_STACK_SIZE 512
  27. void guix_timer_task_entry(void *);
  28. /* a few global status variables */
  29. GX_BOOL guix_timer_event_pending;
  30. /* define stack space for GUIX task */
  31. char guix_task_stack[GX_THREAD_STACK_SIZE];
  32. /* define stack space for timer task */
  33. char guix_timer_task_stack[GX_TIMER_TASK_STACK_SIZE];
  34. /* define semaphore for lock/unlock macros */
  35. struct rt_mutex guix_system_lock_mutex;
  36. struct rt_thread guix_tcb;
  37. struct rt_thread guix_timer_tcb;
  38. /* a custom event structure, to hold event and linked list */
  39. typedef struct guix_linked_event_struct
  40. {
  41. GX_EVENT event_data; /* the GUIX event structure */
  42. struct guix_linked_event_struct *next; /* add link member */
  43. } GUIX_LINKED_EVENT;
  44. /* a custom fifo event queue structure */
  45. typedef struct guix_event_queue_struct
  46. {
  47. GUIX_LINKED_EVENT *first; /* first (oldest) event in fifo */
  48. GUIX_LINKED_EVENT *last; /* last (newest) event in fifo */
  49. GUIX_LINKED_EVENT *free; /* linked list of free events */
  50. GUIX_LINKED_EVENT *free_end; /* end of the free list */
  51. struct rt_semaphore count_sem; /* number of queued events */
  52. struct rt_mutex lock; /* lock to protect queue update */
  53. } GUIX_EVENT_QUEUE;
  54. /* an array of GX_EVENTs used to implement fifo queue */
  55. GUIX_LINKED_EVENT guix_event_array[GX_MAX_QUEUE_EVENTS];
  56. GUIX_EVENT_QUEUE guix_event_queue;
  57. /* rtos initialize: perform any setup that needs to be done before the GUIX task runs here */
  58. VOID gx_generic_rtos_initialize(VOID)
  59. {
  60. int Loop;
  61. GUIX_LINKED_EVENT *current;
  62. guix_timer_event_pending = GX_FALSE;
  63. rt_mutex_init(&guix_system_lock_mutex, "gx_system_lock", RT_IPC_FLAG_FIFO);
  64. /* initialize a custom fifo queue structure */
  65. guix_event_queue.first = GX_NULL;
  66. guix_event_queue.last = GX_NULL;
  67. guix_event_queue.free = guix_event_array;
  68. current = guix_event_queue.free;
  69. /* link all the structures together */
  70. for (Loop = 0; Loop < GX_MAX_QUEUE_EVENTS - 1; Loop++)
  71. {
  72. current->next = (current + 1);
  73. current = current->next;
  74. }
  75. current->next = GX_NULL; /* terminate the list */
  76. guix_event_queue.free_end = current;
  77. /* create mutex for lock access to this queue */
  78. rt_mutex_init(&guix_event_queue.lock, "gx_queue_lock", RT_IPC_FLAG_FIFO);
  79. /* create counting semaphore to track queue entries */
  80. rt_sem_init(&guix_event_queue.count_sem, "gx_queue_count", 0, RT_IPC_FLAG_FIFO);
  81. }
  82. VOID (*gx_system_thread_entry)(ULONG);
  83. // A small shell function to convert the void * arg expected by uC/OS to
  84. // a ULONG parameter expected by GUIX thread entry
  85. void gx_system_thread_entry_shell(void *parg)
  86. {
  87. gx_system_thread_entry((ULONG)parg);
  88. }
  89. /* thread_start: start the GUIX thread running. */
  90. UINT gx_generic_thread_start(VOID (*guix_thread_entry)(ULONG))
  91. {
  92. /* save the GUIX system thread entry function pointer */
  93. gx_system_thread_entry = guix_thread_entry;
  94. /* create the main GUIX task */
  95. rt_thread_init(&guix_tcb, "guix_task",
  96. gx_system_thread_entry_shell,
  97. GX_NULL,
  98. &guix_task_stack[0],
  99. GX_THREAD_STACK_SIZE,
  100. GX_SYSTEM_THREAD_PRIORITY,
  101. 20);
  102. /* create a simple task to generate timer events into GUIX */
  103. rt_thread_init(&guix_timer_tcb, "guix_timer_task",
  104. guix_timer_task_entry,
  105. GX_NULL,
  106. &guix_timer_task_stack[0],
  107. GX_TIMER_TASK_STACK_SIZE,
  108. GX_TIMER_TASK_PRIORITY,
  109. 20);
  110. rt_thread_startup(&guix_tcb);
  111. rt_thread_startup(&guix_timer_tcb);
  112. /* suspend the timer task until needed */
  113. rt_thread_suspend(&guix_timer_tcb);
  114. return GX_SUCCESS;
  115. }
  116. /* event_post: push an event into the fifo event queue */
  117. UINT gx_generic_event_post(GX_EVENT *event_ptr)
  118. {
  119. GUIX_LINKED_EVENT *linked_event;
  120. /* lock down the guix event queue */
  121. rt_mutex_take(&guix_event_queue.lock, RT_WAITING_FOREVER);
  122. /* grab a free event slot */
  123. if (!guix_event_queue.free)
  124. {
  125. /* there are no free events, return failure */
  126. rt_mutex_release(&guix_event_queue.lock);
  127. return GX_FAILURE;
  128. }
  129. linked_event = guix_event_queue.free;
  130. guix_event_queue.free = guix_event_queue.free->next;
  131. if (!guix_event_queue.free)
  132. {
  133. guix_event_queue.free_end = GX_NULL;
  134. }
  135. /* copy the event data into this slot */
  136. linked_event->event_data = *event_ptr;
  137. linked_event->next = GX_NULL;
  138. /* insert this event into fifo queue */
  139. if (guix_event_queue.last)
  140. {
  141. guix_event_queue.last->next = linked_event;
  142. }
  143. else
  144. {
  145. guix_event_queue.first = linked_event;
  146. }
  147. guix_event_queue.last = linked_event;
  148. /* Unlock the guix queue */
  149. rt_mutex_release(&guix_event_queue.lock);
  150. /* increment event count */
  151. rt_sem_release(&guix_event_queue.count_sem);
  152. return GX_SUCCESS;
  153. }
  154. /* event_fold: update existing matching event, otherwise post new event */
  155. UINT gx_generic_event_fold(GX_EVENT *event_ptr)
  156. {
  157. GUIX_LINKED_EVENT *pTest;
  158. /* Lock down the guix queue */
  159. rt_mutex_take(&guix_event_queue.lock, RT_WAITING_FOREVER);
  160. // see if the same event is already in the queue:
  161. pTest = guix_event_queue.first;
  162. while (pTest)
  163. {
  164. if (pTest->event_data.gx_event_type == event_ptr->gx_event_type)
  165. {
  166. /* found matching event, update it and return */
  167. pTest->event_data.gx_event_payload.gx_event_ulongdata = event_ptr->gx_event_payload.gx_event_ulongdata;
  168. rt_mutex_release(&guix_event_queue.lock);
  169. return GX_SUCCESS;
  170. }
  171. pTest = pTest->next;
  172. }
  173. /* did not find a match, push new event */
  174. rt_mutex_release(&guix_event_queue.lock);
  175. gx_generic_event_post(event_ptr);
  176. return GX_SUCCESS;
  177. }
  178. /* event_pop: pop oldest event from fifo queue, block if wait and no events exist */
  179. UINT gx_generic_event_pop(GX_EVENT *put_event, GX_BOOL wait)
  180. {
  181. if (!wait)
  182. {
  183. if (guix_event_queue.first == GX_NULL)
  184. {
  185. /* the queue is empty, just return */
  186. return GX_FAILURE;
  187. }
  188. }
  189. /* wait for an event to arrive in queue */
  190. rt_sem_take(&guix_event_queue.count_sem, RT_WAITING_FOREVER);
  191. /* lock down the queue */
  192. rt_mutex_take(&guix_event_queue.lock, RT_WAITING_FOREVER);
  193. /* copy the event into destination */
  194. *put_event = guix_event_queue.first->event_data;
  195. /* link this event holder back into free list */
  196. if (guix_event_queue.free_end)
  197. {
  198. guix_event_queue.free_end->next = guix_event_queue.first;
  199. }
  200. else
  201. {
  202. guix_event_queue.free = guix_event_queue.first;
  203. }
  204. guix_event_queue.free_end = guix_event_queue.first;
  205. guix_event_queue.first = guix_event_queue.first->next;
  206. guix_event_queue.free_end->next = GX_NULL;
  207. if (!guix_event_queue.first)
  208. {
  209. guix_event_queue.last = GX_NULL;
  210. }
  211. /* check for popping out a timer event */
  212. if (put_event->gx_event_type == GX_EVENT_TIMER)
  213. {
  214. guix_timer_event_pending = GX_FALSE;
  215. }
  216. /* unlock the queue */
  217. rt_mutex_release(&guix_event_queue.lock);
  218. return GX_SUCCESS;
  219. }
  220. /* event_purge: delete events targetted to particular widget */
  221. VOID gx_generic_event_purge(GX_WIDGET *target)
  222. {
  223. GX_BOOL Purge;
  224. GUIX_LINKED_EVENT *pTest;
  225. /* Lock down the guix queue */
  226. rt_mutex_take(&guix_event_queue.lock, RT_WAITING_FOREVER);
  227. // look for events targetted to widget or widget children:
  228. pTest = guix_event_queue.first;
  229. while (pTest)
  230. {
  231. Purge = GX_FALSE;
  232. if (pTest->event_data.gx_event_target)
  233. {
  234. if (pTest->event_data.gx_event_target == target)
  235. {
  236. Purge = GX_TRUE;
  237. }
  238. else
  239. {
  240. gx_widget_child_detect(target, pTest->event_data.gx_event_target, &Purge);
  241. }
  242. if (Purge)
  243. {
  244. pTest->event_data.gx_event_target = GX_NULL;
  245. pTest->event_data.gx_event_type = 0;
  246. }
  247. }
  248. pTest = pTest->next;
  249. }
  250. rt_mutex_release(&guix_event_queue.lock);
  251. }
  252. /* start the RTOS timer */
  253. VOID gx_generic_timer_start(VOID)
  254. {
  255. rt_thread_resume(&guix_timer_tcb);
  256. }
  257. /* stop the RTOS timer */
  258. VOID gx_generic_timer_stop(VOID)
  259. {
  260. rt_thread_suspend(&guix_timer_tcb);
  261. }
  262. /* lock the system protection mutex */
  263. VOID gx_generic_system_mutex_lock(VOID)
  264. {
  265. rt_mutex_take(&guix_system_lock_mutex, RT_WAITING_FOREVER);
  266. }
  267. /* unlock system protection mutex */
  268. VOID gx_generic_system_mutex_unlock(VOID)
  269. {
  270. rt_mutex_release(&guix_system_lock_mutex);
  271. }
  272. /* return number of low-level system timer ticks. Used for pen speed caculations */
  273. ULONG gx_generic_system_time_get(VOID)
  274. {
  275. return ((ULONG)rt_tick_get());
  276. }
  277. /* thread_identify: return current thread identifier, cast as VOID * */
  278. VOID *gx_generic_thread_identify(VOID)
  279. {
  280. return rt_thread_self();
  281. }
  282. /* a simple task to drive the GUIX timer mechanism */
  283. void guix_timer_task_entry(void *unused)
  284. {
  285. int TickCount = OS_CFG_TICK_RATE_HZ / GX_TICKS_SECOND;
  286. if (TickCount <= 0)
  287. {
  288. TickCount = 1;
  289. }
  290. while (1)
  291. {
  292. rt_thread_mdelay(TickCount);
  293. /* prevent sending timer events faster than they can be processed */
  294. if (!guix_timer_event_pending)
  295. {
  296. guix_timer_event_pending = GX_TRUE;
  297. _gx_system_timer_expiration(0);
  298. }
  299. }
  300. }
  301. VOID gx_generic_time_delay(int ticks)
  302. {
  303. rt_thread_mdelay(ticks);
  304. }
  305. #endif //(GUIX_BINDING_RT_THREAD)
  306. #endif //(GX_THREADX_BINDING)