gx_system_rtos_bind_rtthread.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  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. * V1.1 2020-12-03 HelloByeAll 修改互斥量等初始化方法
  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. static rt_mutex_t 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. rt_sem_t count_sem; /* number of queued events */
  55. rt_mutex_t 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. guix_system_lock_mutex = rt_mutex_create("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. guix_event_queue.lock = rt_mutex_create("gx_queue_lock", RT_IPC_FLAG_FIFO);
  83. /* create counting semaphore to track queue entries */
  84. guix_event_queue.count_sem = rt_sem_create("gx_queue_count", 0, RT_IPC_FLAG_FIFO);
  85. }
  86. VOID(*gx_system_thread_entry)
  87. (ULONG);
  88. // A small shell function to convert the void * arg expected by uC/OS to
  89. // a ULONG parameter expected by GUIX thread entry
  90. void gx_system_thread_entry_shell(void *parg)
  91. {
  92. gx_system_thread_entry((ULONG)parg);
  93. }
  94. /* thread_start: start the GUIX thread running. */
  95. UINT gx_generic_thread_start(VOID (*guix_thread_entry)(ULONG))
  96. {
  97. /* save the GUIX system thread entry function pointer */
  98. gx_system_thread_entry = guix_thread_entry;
  99. /* create the main GUIX task */
  100. rt_thread_init(&guix_tcb, "guix_task",
  101. gx_system_thread_entry_shell,
  102. GX_NULL,
  103. &guix_task_stack[0],
  104. GX_THREAD_STACK_SIZE,
  105. GX_SYSTEM_THREAD_PRIORITY,
  106. 20);
  107. /* create a simple task to generate timer events into GUIX */
  108. rt_thread_init(&guix_timer_tcb, "guix_timer_task",
  109. guix_timer_task_entry,
  110. GX_NULL,
  111. &guix_timer_task_stack[0],
  112. GX_TIMER_TASK_STACK_SIZE,
  113. GX_TIMER_TASK_PRIORITY,
  114. 20);
  115. rt_thread_startup(&guix_tcb);
  116. rt_thread_startup(&guix_timer_tcb);
  117. /* suspend the timer task until needed */
  118. rt_thread_suspend(&guix_timer_tcb);
  119. return GX_SUCCESS;
  120. }
  121. /* event_post: push an event into the fifo event queue */
  122. UINT gx_generic_event_post(GX_EVENT *event_ptr)
  123. {
  124. GUIX_LINKED_EVENT *linked_event;
  125. /* lock down the guix event queue */
  126. rt_mutex_take(guix_event_queue.lock, RT_WAITING_FOREVER);
  127. /* grab a free event slot */
  128. if (!guix_event_queue.free)
  129. {
  130. /* there are no free events, return failure */
  131. rt_mutex_release(guix_event_queue.lock);
  132. return GX_FAILURE;
  133. }
  134. linked_event = guix_event_queue.free;
  135. guix_event_queue.free = guix_event_queue.free->next;
  136. if (!guix_event_queue.free)
  137. {
  138. guix_event_queue.free_end = GX_NULL;
  139. }
  140. /* copy the event data into this slot */
  141. linked_event->event_data = *event_ptr;
  142. linked_event->next = GX_NULL;
  143. /* insert this event into fifo queue */
  144. if (guix_event_queue.last)
  145. {
  146. guix_event_queue.last->next = linked_event;
  147. }
  148. else
  149. {
  150. guix_event_queue.first = linked_event;
  151. }
  152. guix_event_queue.last = linked_event;
  153. /* Unlock the guix queue */
  154. rt_mutex_release(guix_event_queue.lock);
  155. /* increment event count */
  156. rt_sem_release(guix_event_queue.count_sem);
  157. return GX_SUCCESS;
  158. }
  159. /* event_fold: update existing matching event, otherwise post new event */
  160. UINT gx_generic_event_fold(GX_EVENT *event_ptr)
  161. {
  162. GUIX_LINKED_EVENT *pTest;
  163. /* Lock down the guix queue */
  164. rt_mutex_take(guix_event_queue.lock, RT_WAITING_FOREVER);
  165. // see if the same event is already in the queue:
  166. pTest = guix_event_queue.first;
  167. while (pTest)
  168. {
  169. if (pTest->event_data.gx_event_type == event_ptr->gx_event_type)
  170. {
  171. /* found matching event, update it and return */
  172. pTest->event_data.gx_event_payload.gx_event_ulongdata = event_ptr->gx_event_payload.gx_event_ulongdata;
  173. rt_mutex_release(guix_event_queue.lock);
  174. return GX_SUCCESS;
  175. }
  176. pTest = pTest->next;
  177. }
  178. /* did not find a match, push new event */
  179. rt_mutex_release(guix_event_queue.lock);
  180. gx_generic_event_post(event_ptr);
  181. return GX_SUCCESS;
  182. }
  183. /* event_pop: pop oldest event from fifo queue, block if wait and no events exist */
  184. UINT gx_generic_event_pop(GX_EVENT *put_event, GX_BOOL wait)
  185. {
  186. if (!wait)
  187. {
  188. if (guix_event_queue.first == GX_NULL)
  189. {
  190. /* the queue is empty, just return */
  191. return GX_FAILURE;
  192. }
  193. }
  194. /* wait for an event to arrive in queue */
  195. rt_sem_take(guix_event_queue.count_sem, RT_WAITING_FOREVER);
  196. /* lock down the queue */
  197. rt_mutex_take(guix_event_queue.lock, RT_WAITING_FOREVER);
  198. /* copy the event into destination */
  199. *put_event = guix_event_queue.first->event_data;
  200. /* link this event holder back into free list */
  201. if (guix_event_queue.free_end)
  202. {
  203. guix_event_queue.free_end->next = guix_event_queue.first;
  204. }
  205. else
  206. {
  207. guix_event_queue.free = guix_event_queue.first;
  208. }
  209. guix_event_queue.free_end = guix_event_queue.first;
  210. guix_event_queue.first = guix_event_queue.first->next;
  211. guix_event_queue.free_end->next = GX_NULL;
  212. if (!guix_event_queue.first)
  213. {
  214. guix_event_queue.last = GX_NULL;
  215. }
  216. /* check for popping out a timer event */
  217. if (put_event->gx_event_type == GX_EVENT_TIMER)
  218. {
  219. guix_timer_event_pending = GX_FALSE;
  220. }
  221. /* unlock the queue */
  222. rt_mutex_release(guix_event_queue.lock);
  223. return GX_SUCCESS;
  224. }
  225. /* event_purge: delete events targetted to particular widget */
  226. VOID gx_generic_event_purge(GX_WIDGET *target)
  227. {
  228. GX_BOOL Purge;
  229. GUIX_LINKED_EVENT *pTest;
  230. /* Lock down the guix queue */
  231. rt_mutex_take(guix_event_queue.lock, RT_WAITING_FOREVER);
  232. // look for events targetted to widget or widget children:
  233. pTest = guix_event_queue.first;
  234. while (pTest)
  235. {
  236. Purge = GX_FALSE;
  237. if (pTest->event_data.gx_event_target)
  238. {
  239. if (pTest->event_data.gx_event_target == target)
  240. {
  241. Purge = GX_TRUE;
  242. }
  243. else
  244. {
  245. gx_widget_child_detect(target, pTest->event_data.gx_event_target, &Purge);
  246. }
  247. if (Purge)
  248. {
  249. pTest->event_data.gx_event_target = GX_NULL;
  250. pTest->event_data.gx_event_type = 0;
  251. }
  252. }
  253. pTest = pTest->next;
  254. }
  255. rt_mutex_release(guix_event_queue.lock);
  256. }
  257. /* start the RTOS timer */
  258. VOID gx_generic_timer_start(VOID)
  259. {
  260. rt_thread_resume(&guix_timer_tcb);
  261. }
  262. /* stop the RTOS timer */
  263. VOID gx_generic_timer_stop(VOID)
  264. {
  265. rt_thread_suspend(&guix_timer_tcb);
  266. }
  267. /* lock the system protection mutex */
  268. VOID gx_generic_system_mutex_lock(VOID)
  269. {
  270. rt_mutex_take(guix_system_lock_mutex, RT_WAITING_FOREVER);
  271. }
  272. /* unlock system protection mutex */
  273. VOID gx_generic_system_mutex_unlock(VOID)
  274. {
  275. rt_mutex_release(guix_system_lock_mutex);
  276. }
  277. /* return number of low-level system timer ticks. Used for pen speed caculations */
  278. ULONG gx_generic_system_time_get(VOID)
  279. {
  280. return ((ULONG)rt_tick_get());
  281. }
  282. /* thread_identify: return current thread identifier, cast as VOID * */
  283. VOID *gx_generic_thread_identify(VOID)
  284. {
  285. return rt_thread_self();
  286. }
  287. /* a simple task to drive the GUIX timer mechanism */
  288. void guix_timer_task_entry(void *unused)
  289. {
  290. int TickCount = OS_CFG_TICK_RATE_HZ / GX_TICKS_SECOND;
  291. if (TickCount <= 0)
  292. {
  293. TickCount = 1;
  294. }
  295. while (1)
  296. {
  297. rt_thread_mdelay(TickCount);
  298. /* prevent sending timer events faster than they can be processed */
  299. if (!guix_timer_event_pending)
  300. {
  301. guix_timer_event_pending = GX_TRUE;
  302. _gx_system_timer_expiration(0);
  303. }
  304. }
  305. }
  306. VOID gx_generic_time_delay(int ticks)
  307. {
  308. rt_thread_mdelay(ticks);
  309. }
  310. #endif //(GUIX_BINDING_RT_THREAD)
  311. #endif //(GX_THREADX_BINDING)
  312. /*************************************** (END OF FILE) ****************************************/