vg_lite_os.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. #include "vg_lite_os.h"
  2. #include "rtthread.h"
  3. #include "vg_lite_hw.h"
  4. #include "vg_lite_hal.h"
  5. /* If bit31 is activated this indicates a bus error */
  6. #define IS_AXI_BUS_ERR(x) ((x)&(1U << 31))
  7. #if !defined(VG_DRIVER_SINGLE_THREAD)
  8. #define ISR_WAIT_TIME 0x1FFFF
  9. #define MAX_MUTEX_TIME 100
  10. #define THREAD_WAIT_TIME 20
  11. /* command queue task parameter */
  12. #define QUEUE_THREAD_NAME "queue_thread"
  13. #ifndef QUEUE_THREAD_PRIO
  14. // #define QUEUE_THREAD_PRIO (configMAX_PRIORITIES - 1)
  15. #define QUEUE_THREAD_PRIO 0
  16. #endif /* QUEUE_THREAD_PRIO */
  17. #define QUEUE_THREAD_SIZE 1024
  18. #define QUEUE_LENGTH 8
  19. #define MAX_QUEUE_WAIT_NUM 10
  20. /* The array stores one or more tlss, which is pointed by user_data of current thread. Set it to 1 when only vglite is used, otherwise set it to 2 if elementary is applied. */
  21. #define TLS_ARRAY_LENGTH 2
  22. #ifndef FALSE
  23. #define FALSE 0
  24. #endif
  25. #ifndef TURE
  26. #define TURE 1
  27. #endif
  28. typedef struct vg_lite_queue{
  29. uint32_t cmd_physical;
  30. uint32_t cmd_offset;
  31. uint32_t cmd_size;
  32. vg_lite_os_async_event_t *event;
  33. }
  34. vg_lite_queue_t;
  35. rt_uint32_t tls_array[TLS_ARRAY_LENGTH] = {NULL};
  36. typedef struct vg_lite_os{
  37. rt_thread_t task_hanlde;
  38. rt_mq_t queue_handle;
  39. }
  40. vg_lite_os_t;
  41. static rt_mutex_t mutex;
  42. static vg_lite_os_t os_obj = {0};
  43. rt_sem_t semaphore[THREAD_LENGTH] = {NULL};
  44. rt_sem_t command_semaphore = NULL;
  45. uint32_t curContext;
  46. #endif /* not defined(VG_DRIVER_SINGLE_THREAD) */
  47. rt_sem_t int_queue;
  48. volatile uint32_t int_flags;
  49. void __attribute__((weak)) vg_lite_bus_error_handler()
  50. {
  51. /*
  52. * Default implementation of the bus error handler does nothing. Application
  53. * should override this handler if it requires to be notified when a bus
  54. * error event occurs.
  55. */
  56. return;
  57. }
  58. #if !defined(VG_DRIVER_SINGLE_THREAD)
  59. /* command queue function */
  60. void command_queue(void * parameters)
  61. {
  62. vg_lite_queue_t* peek_queue;
  63. uint32_t even_got;
  64. uint32_t len;
  65. os_obj.queue_handle = rt_mq_create("queue_vglite", sizeof(vg_lite_queue_t * ), QUEUE_LENGTH, RT_IPC_FLAG_PRIO);
  66. if(os_obj.queue_handle == RT_NULL)
  67. {
  68. /*command queue create fail, delete queue task */
  69. rt_thread_delete(rt_thread_self());
  70. }
  71. command_semaphore = rt_sem_create("cs", 0, RT_IPC_FLAG_PRIO);
  72. while(1)
  73. {
  74. even_got = 0;
  75. if (rt_sem_take((rt_sem_t)command_semaphore, RT_WAITING_FOREVER) == RT_EOK) {
  76. if(os_obj.queue_handle->entry)
  77. {
  78. len = rt_mq_recv(os_obj.queue_handle, (void*) &peek_queue, os_obj.queue_handle->msg_size, (rt_int32_t) ((rt_int64_t)THREAD_WAIT_TIME * RT_TICK_PER_SECOND / 1000));
  79. if(len)
  80. {
  81. #if defined(PRINT_COMMAND_BUFFER)
  82. int i = 0;
  83. for(i=0;i < (peek_queue->cmd_size + 3) / 4; i++)
  84. {
  85. if(i % 4 == 0)
  86. printf("\r\n");
  87. printf("0x%08x ",((uint32_t*)(peek_queue->cmd_physical + peek_queue->cmd_offset))[i]);
  88. }
  89. #endif
  90. vg_lite_hal_poke(VG_LITE_HW_CMDBUF_ADDRESS, peek_queue->cmd_physical + peek_queue->cmd_offset);
  91. vg_lite_hal_poke(VG_LITE_HW_CMDBUF_SIZE, (peek_queue->cmd_size +7)/8 );
  92. if(vg_lite_hal_wait_interrupt(ISR_WAIT_TIME, (uint32_t)~0, &even_got))
  93. peek_queue->event->signal = VG_LITE_HW_FINISHED;
  94. else
  95. #if defined(PRINT_DEBUG_REGISTER)
  96. {
  97. unsigned int debug;
  98. unsigned int iter;
  99. for(iter =0; iter < 16 ; iter ++)
  100. {
  101. vg_lite_hal_poke(0x470, iter);
  102. debug = vg_lite_hal_peek(0x450);
  103. printf("0x450[%d] = 0x%x\n", iter,debug);
  104. }
  105. for(iter =0; iter < 16 ; iter ++)
  106. {
  107. vg_lite_hal_poke(0x470, iter <<16);
  108. debug = vg_lite_hal_peek(0x454);
  109. printf("0x454[%d] = 0x%x\n", iter,debug);
  110. }
  111. for(iter =0; iter < 16 ; iter ++)
  112. {
  113. vg_lite_hal_poke(0x478, iter);
  114. debug = vg_lite_hal_peek(0x468);
  115. printf("0x468[%d] = 0x%x\n", iter,debug);
  116. }
  117. for(iter =0; iter < 16 ; iter ++)
  118. {
  119. vg_lite_hal_poke(0x478, iter);
  120. debug = vg_lite_hal_peek(0x46C);
  121. printf("0x46C[%d] = 0x%x\n", iter,debug);
  122. }
  123. #endif
  124. /* wait timeout */
  125. peek_queue->event->signal = VG_LITE_IDLE;
  126. #if defined(PRINT_DEBUG_REGISTER)
  127. }
  128. #endif
  129. if(semaphore[peek_queue->event->semaphore_id]){
  130. rt_sem_release(semaphore[peek_queue->event->semaphore_id]);
  131. }
  132. vg_lite_os_free((void *) peek_queue);
  133. }
  134. }
  135. }
  136. }
  137. }
  138. int32_t vg_lite_os_init_tls_array(void)
  139. {
  140. rt_thread_t rt_TCB;
  141. rt_TCB = rt_thread_self();
  142. RT_ASSERT( rt_TCB != NULL );
  143. rt_TCB->user_data = (rt_uint32_t) tls_array;
  144. return VG_LITE_SUCCESS;
  145. }
  146. void vg_lite_os_deinit_tls_array(void)
  147. {
  148. rt_thread_t rt_TCB;
  149. rt_TCB = rt_thread_self();
  150. RT_ASSERT( rt_TCB != NULL );
  151. rt_TCB->user_data = NULL;
  152. }
  153. int32_t vg_lite_os_set_tls(void* tls)
  154. {
  155. if(tls == NULL)
  156. return VG_LITE_INVALID_ARGUMENT;
  157. rt_thread_t rt_TCB;
  158. rt_TCB = rt_thread_self();
  159. RT_ASSERT( rt_TCB != NULL );
  160. rt_uint32_t * tls_ptr = (rt_uint32_t *) rt_TCB->user_data;
  161. *tls_ptr = (rt_uint32_t) tls;
  162. return VG_LITE_SUCCESS;
  163. }
  164. void * vg_lite_os_get_tls( )
  165. {
  166. rt_thread_t rt_TCB;
  167. void * pvReturn = NULL;
  168. rt_TCB = rt_thread_self();
  169. rt_uint32_t * tls_ptr = (rt_uint32_t *) rt_TCB->user_data;
  170. pvReturn = (void *) (*tls_ptr);
  171. return pvReturn;
  172. }
  173. #endif /* not defined(VG_DRIVER_SINGLE_THREAD) */
  174. void * vg_lite_os_malloc(uint32_t size)
  175. {
  176. return rt_malloc((rt_size_t)size);
  177. }
  178. void vg_lite_os_free(void * memory)
  179. {
  180. rt_free(memory);
  181. }
  182. #if !defined(VG_DRIVER_SINGLE_THREAD)
  183. void vg_lite_os_reset_tls()
  184. {
  185. rt_thread_t rt_TCB;
  186. rt_TCB = rt_thread_self();
  187. RT_ASSERT( rt_TCB != NULL );
  188. rt_uint32_t * tls_ptr = (rt_uint32_t *) rt_TCB->user_data;
  189. *tls_ptr = NULL;
  190. }
  191. #endif /* not defined(VG_DRIVER_SINGLE_THREAD) */
  192. void vg_lite_os_sleep(uint32_t msec)
  193. {
  194. rt_thread_mdelay(msec);
  195. }
  196. int32_t vg_lite_os_initialize(void)
  197. {
  198. #if !defined(VG_DRIVER_SINGLE_THREAD)
  199. static int task_number = 0;
  200. #endif /* not defined(VG_DRIVER_SINGLE_THREAD) */
  201. int_queue = rt_sem_create("iq", 0, RT_IPC_FLAG_PRIO);
  202. int_flags = 0;
  203. #if !defined(VG_DRIVER_SINGLE_THREAD)
  204. if(mutex == NULL)
  205. {
  206. mutex = rt_mutex_create("mut", RT_IPC_FLAG_PRIO);
  207. if(mutex == NULL)
  208. return VG_LITE_MULTI_THREAD_FAIL;
  209. }
  210. if(task_number == 0)
  211. {
  212. if(rt_mutex_take(mutex, (rt_int32_t) ((rt_int64_t)THREAD_WAIT_TIME * RT_TICK_PER_SECOND / 1000)) == RT_EOK)
  213. {
  214. if(os_obj.task_hanlde == NULL)
  215. {
  216. os_obj.task_hanlde = rt_thread_create(QUEUE_THREAD_NAME, command_queue, NULL, QUEUE_THREAD_SIZE, QUEUE_THREAD_PRIO, 1);
  217. if(os_obj.task_hanlde == RT_NULL)
  218. {
  219. /* command queue task create fail */
  220. rt_mutex_release(mutex);
  221. return VG_LITE_MULTI_THREAD_FAIL;
  222. }
  223. else
  224. rt_thread_startup(os_obj.task_hanlde);
  225. }
  226. task_number++;
  227. rt_mutex_release(mutex);
  228. return VG_LITE_SUCCESS;
  229. }
  230. }
  231. #endif /* not defined(VG_DRIVER_SINGLE_THREAD) */
  232. return VG_LITE_SUCCESS;
  233. }
  234. void vg_lite_os_deinitialize(void)
  235. {
  236. /* TODO: Remove clock. */
  237. #if !defined(VG_DRIVER_SINGLE_THREAD)
  238. rt_mutex_delete(mutex);
  239. mutex = 0;
  240. #endif /* VG_DRIVER_SINGLE_THREAD */
  241. rt_sem_delete(int_queue);
  242. /* TODO: Remove power. */
  243. }
  244. #if !defined(VG_DRIVER_SINGLE_THREAD)
  245. int32_t vg_lite_os_lock()
  246. {
  247. if(mutex == NULL)
  248. return VG_LITE_NOT_SUPPORT;
  249. if(rt_mutex_take(mutex, (rt_int32_t) ((rt_int64_t)MAX_MUTEX_TIME * RT_TICK_PER_SECOND / 1000)) != RT_EOK)
  250. return VG_LITE_MULTI_THREAD_FAIL;
  251. return VG_LITE_SUCCESS;
  252. }
  253. int32_t vg_lite_os_unlock()
  254. {
  255. if(rt_mutex_release(mutex) != RT_EOK)
  256. return VG_LITE_MULTI_THREAD_FAIL;
  257. return VG_LITE_SUCCESS;
  258. }
  259. int32_t vg_lite_os_submit(uint32_t context, uint32_t physical, uint32_t offset, uint32_t size, vg_lite_os_async_event_t *event)
  260. {
  261. vg_lite_queue_t* queue_node;
  262. if(os_obj.queue_handle == RT_NULL)
  263. return VG_LITE_NOT_SUPPORT;
  264. queue_node = (vg_lite_queue_t*) vg_lite_os_malloc(sizeof(vg_lite_queue_t));
  265. if(queue_node == NULL)
  266. return VG_LITE_MULTI_THREAD_FAIL;
  267. queue_node->cmd_physical = physical;
  268. queue_node->cmd_offset = offset;
  269. queue_node->cmd_size = size;
  270. queue_node->event = event;
  271. /* Current command buffer has been sent to the command queue. */
  272. event->signal = VG_LITE_IN_QUEUE;
  273. if(rt_mq_send_wait(os_obj.queue_handle, (void *) &queue_node, os_obj.queue_handle->msg_size, (rt_int32_t) ((rt_int64_t)ISR_WAIT_TIME * RT_TICK_PER_SECOND / 1000)) != RT_EOK)
  274. return VG_LITE_MULTI_THREAD_FAIL;
  275. curContext = context;
  276. if (vg_lite_os_wait_event(event) == VG_LITE_SUCCESS) {
  277. if(rt_sem_release(command_semaphore) != RT_EOK)
  278. return VG_LITE_MULTI_THREAD_FAIL;
  279. return VG_LITE_SUCCESS;
  280. }
  281. return VG_LITE_MULTI_THREAD_FAIL;
  282. }
  283. int32_t vg_lite_os_wait(uint32_t timeout, vg_lite_os_async_event_t *event)
  284. {
  285. if (semaphore[event->semaphore_id]) {
  286. if (rt_sem_take(semaphore[event->semaphore_id], RT_WAITING_FOREVER) == RT_EOK) {
  287. if(event->signal == VG_LITE_HW_FINISHED){
  288. rt_sem_release(semaphore[event->semaphore_id]);
  289. return VG_LITE_SUCCESS;
  290. }
  291. else{
  292. rt_sem_release(semaphore[event->semaphore_id]);
  293. return VG_LITE_TIMEOUT;
  294. }
  295. }
  296. }
  297. return VG_LITE_TIMEOUT;
  298. }
  299. #endif /* not defined(VG_DRIVER_SINGLE_THREAD) */
  300. void vg_lite_os_IRQHandler(void)
  301. {
  302. uint32_t flags = vg_lite_hal_peek(VG_LITE_INTR_STATUS);
  303. if (flags) {
  304. /* Combine with current interrupt flags. */
  305. int_flags |= flags;
  306. /* Wake up any waiters. */
  307. if(int_queue){
  308. rt_sem_release(int_queue);
  309. }
  310. }
  311. }
  312. int32_t vg_lite_os_wait_interrupt(uint32_t timeout, uint32_t mask, uint32_t * value)
  313. {
  314. #if _BAREMETAL
  315. uint32_t int_status=0;
  316. int_status = vg_lite_hal_peek(VG_LITE_INTR_STATUS);
  317. (void)value;
  318. while (int_status==0){
  319. int_status = vg_lite_hal_peek(VG_LITE_INTR_STATUS);
  320. usleep(1);
  321. }
  322. if (IS_AXI_BUS_ERR(*value))
  323. {
  324. vg_lite_bus_error_handler();
  325. }
  326. return 1;
  327. #else /*for rt500*/
  328. if(int_queue) {
  329. if (rt_sem_take(int_queue, (rt_int32_t) ((rt_int64_t)timeout * RT_TICK_PER_SECOND / 1000)) == RT_EOK) {
  330. if (value != NULL) {
  331. *value = int_flags & mask;
  332. if (IS_AXI_BUS_ERR(*value))
  333. {
  334. vg_lite_bus_error_handler();
  335. }
  336. }
  337. int_flags = 0;
  338. return 1;
  339. }
  340. }
  341. return 0;
  342. #endif
  343. }
  344. #if !defined(VG_DRIVER_SINGLE_THREAD)
  345. int32_t vg_lite_os_init_event(vg_lite_os_async_event_t *event,
  346. uint32_t semaphore_id,
  347. int32_t state)
  348. {
  349. if (event->semaphore_id >= THREAD_LENGTH)
  350. return VG_LITE_INVALID_ARGUMENT;
  351. if (semaphore[semaphore_id])
  352. return VG_LITE_ALREADY_EXISTS;
  353. char name[RT_NAME_MAX] = {0};
  354. rt_snprintf(name, RT_NAME_MAX, "s%d", semaphore_id);
  355. semaphore[semaphore_id] = rt_sem_create(name, 0, RT_IPC_FLAG_PRIO);
  356. if (!semaphore[semaphore_id])
  357. return VG_LITE_OUT_OF_MEMORY;
  358. rt_sem_release(semaphore[semaphore_id]);
  359. event->semaphore_id = semaphore_id;
  360. event->signal = state;
  361. return VG_LITE_SUCCESS;
  362. }
  363. int32_t vg_lite_os_delete_event(vg_lite_os_async_event_t *event)
  364. {
  365. if (event->semaphore_id >= THREAD_LENGTH)
  366. return VG_LITE_INVALID_ARGUMENT;
  367. if (semaphore[event->semaphore_id]){
  368. rt_sem_delete(semaphore[event->semaphore_id]);
  369. semaphore[event->semaphore_id] = NULL;
  370. }
  371. return VG_LITE_SUCCESS;
  372. }
  373. int32_t vg_lite_os_wait_event(vg_lite_os_async_event_t *event)
  374. {
  375. if (event->semaphore_id >= THREAD_LENGTH)
  376. return VG_LITE_INVALID_ARGUMENT;
  377. if (rt_sem_take(semaphore[event->semaphore_id], RT_WAITING_FOREVER) != RT_EOK)
  378. return VG_LITE_MULTI_THREAD_FAIL;
  379. return VG_LITE_SUCCESS;
  380. }
  381. int32_t vg_lite_os_signal_event(vg_lite_os_async_event_t *event)
  382. {
  383. if (event->semaphore_id >= THREAD_LENGTH)
  384. return VG_LITE_INVALID_ARGUMENT;
  385. rt_sem_release(semaphore[event->semaphore_id]);
  386. return VG_LITE_SUCCESS;
  387. }
  388. int8_t vg_lite_os_query_context_switch(uint32_t context)
  389. {
  390. if(!curContext || curContext == context)
  391. return FALSE;
  392. return TURE;
  393. }
  394. #endif /* not defined(VG_DRIVER_SINGLE_THREAD) */