gx_system_rtos_bind_rtthread.c 11 KB

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