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