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