1 /*
2 * Copyright (c) 2022 ASR Microelectronics (Shanghai) Co., Ltd. All rights reserved.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <string.h>
17 #include <stdlib.h>
18 #include "duet_common.h"
19 #include "cmsis_os2.h"
20 #include "include/kal.h"
21 #include "target_config.h"
22 #include "lega_rtos.h"
23
24 #ifdef LEGA_CM4
25 #include "lega_cm4.h"
26 #else
27 #ifdef DUET_CM4
28 #include "duet_cm4.h"
29 #endif
30 #endif
31
32 #define CM4_ICSR 0xE000ED04
33
34 #define COMPRESS_LEN(x) (sizeof(size_t))
35
36 lega_task_config_t task_cfg[LEGA_TASK_CONFIG_MAX] = {
37 #ifdef USE_SMALL_STACK
38 {LEGA_WPA3_AUTH_TASK_PRIORITY, 2560},
39 {LEGA_LWIFI_TASK_PRIORITY, 2560},
40 #else
41 {LEGA_WPA3_AUTH_TASK_PRIORITY, 13312},
42 {LEGA_LWIFI_TASK_PRIORITY, 2048},
43 #endif
44 {LEGA_UWIFI_RX_TASK_PRIORITY, 4096},
45 {LEGA_UWIFI_TASK_PRIORITY, 7168},
46 {LEGA_LWIP_DHCP_TASK_PRIORITY, 1536},
47 {LEGA_BLE_SCHEDULER_PRIORITY, 4096},
48 };
49
lega_rtos_is_in_interrupt_context(void)50 OSBool lega_rtos_is_in_interrupt_context(void)
51 {
52 unsigned int state = 0;
53
54 state = (*(unsigned int *) CM4_ICSR) & 0x3FF; // bit0:9 is IRQ NO.
55
56 if (state != 0) {
57 return TRUE;
58 }
59
60 return FALSE;
61 }
62
lega_vector_table_reloc(void)63 void lega_vector_table_reloc(void)
64 {
65
66 }
67 /*******************************************************************
68 * Name: lega_task_cfg_init
69 * Description: this api get wifi task config
70 * input param: task index defined in lega_rtos.h
71 * output param: config data of wifi task
72 * return: OSSatus value
73 *******************************************************************/
lega_rtos_task_cfg_get(uint32_t index,lega_task_config_t * cfg)74 OSStatus lega_rtos_task_cfg_get(uint32_t index, lega_task_config_t *cfg)
75 {
76 if (!cfg || (index >= LEGA_TASK_CONFIG_MAX)) {
77 return kGeneralErr;
78 }
79 cfg->task_priority = task_cfg[index].task_priority;
80 cfg->stack_size = task_cfg[index].stack_size;
81
82 return kNoErr;
83 }
84 /*******************************************************************
85 * Name: lega_rtos_create_thread
86 * Description: this api call freeRTOS function "xTaskCreate" to create task
87 * input param: task priority, stack_size, function, name
88 * output param: thread
89 * return: OSSatus value
90 *******************************************************************/
lega_rtos_create_thread(lega_thread_t * thread,uint8_t priority,const char * name,lega_thread_function_t function,uint32_t stack_size,lega_thread_arg_t arg)91 OSStatus lega_rtos_create_thread(lega_thread_t *thread, uint8_t priority, const char *name,
92 lega_thread_function_t function, uint32_t stack_size, lega_thread_arg_t arg)
93 {
94 uint8_t autorun = 1;
95 osThreadAttr_t attr = {0};
96 osThreadId_t threadId;
97
98 if (thread == NULL || name == NULL || function == NULL) {
99 printf("thread create fail\r\n");
100 return kGeneralErr;
101 }
102
103 attr.name = name;
104 attr.attr_bits = 0U;
105 attr.cb_mem = NULL;
106 attr.cb_size = 0U;
107 attr.stack_mem = NULL;
108 attr.stack_size = stack_size;
109 // here should add bound check!
110 attr.priority = priority;
111 if (autorun == 1) {
112 threadId = osThreadNew((osThreadFunc_t)function, (void *)arg, &attr);
113 if (threadId == 0) {
114 printf("thread %s create fail %d\r\n", name, (int)threadId);
115 return kGeneralErr;
116 }
117 *(unsigned int *)thread = (unsigned int)threadId;
118 }
119 return kNoErr;
120 }
121
122 /*******************************************************************
123 * Name: lega_rtos_delete_thread
124 * Description: this api calls FreeRTOS function "xTaskDelete" to delete a task
125 * input param: thread
126 * output param: none
127 * return: OSStatus
128 *******************************************************************/
lega_rtos_delete_thread(lega_thread_t * thread)129 OSStatus lega_rtos_delete_thread(lega_thread_t *thread)
130 {
131 osThreadId_t threadId;
132 if (thread == NULL) {
133 threadId = osThreadGetId();
134 } else {
135 threadId = (osThreadId_t)(*(unsigned int *)thread);
136 }
137
138 if (osThreadTerminate(threadId) != 0) {
139 printf("thread delete fail\r\n");
140 return kGeneralErr;
141 }
142
143 if (thread != NULL) {
144 *(unsigned int *)thread = 0;
145 }
146 return kNoErr;
147 }
148 ///////////////////////////// semaphore //////////////////////////////////////
149
150 /*******************************************************************
151 * Name:lega_rtos_init_semaphore
152 * Description: create a count semaphore
153 * input param: init value,
154 * output param: lega_semaphore_t* semaphore
155 * return: kNoErr or kGeneralErr;
156 *******************************************************************/
lega_rtos_init_semaphore(lega_semaphore_t * semaphore,int count)157 OSStatus lega_rtos_init_semaphore(lega_semaphore_t *semaphore, int count)
158 {
159 osSemaphoreId_t semId;
160
161 semId = osSemaphoreNew(0xFF, (uint32_t)count, 0);
162 if (semId == 0) {
163 printf("sema init fail %d\r\n", (int)semId);
164 return kGeneralErr;
165 }
166
167 *semaphore = (lega_semaphore_t *)semId;
168 return kNoErr;
169 }
170 /*******************************************************************
171 * Name:lega_rtos_get_semaphore
172 * Description: get semaphore value
173 * input param:semaphore, timeout_ms
174 * output param: semaphore
175 * return: kNoErr or kGeneralErr
176 *******************************************************************/
lega_rtos_get_semaphore(lega_semaphore_t * semaphore,uint32_t timeout_ms)177 OSStatus lega_rtos_get_semaphore(lega_semaphore_t *semaphore, uint32_t timeout_ms)
178 {
179 osStatus_t ret;
180
181 ret = osSemaphoreAcquire((osSemaphoreId_t)(*semaphore), timeout_ms);
182 if (ret != osOK) {
183 printf("sem get fail %d\r\n", ret);
184 return kGeneralErr;
185 }
186
187 return kNoErr;
188 }
189
lega_rtos_set_semaphore(lega_semaphore_t * semaphore)190 FLASH_COMMON2_SEG OSStatus lega_rtos_set_semaphore(lega_semaphore_t *semaphore)
191 {
192 osStatus_t ret;
193
194 ret = osSemaphoreRelease((osSemaphoreId_t)(*semaphore));
195 if (ret != osOK) {
196 printf("sema set fail %d\r\n", ret);
197 return kGeneralErr;
198 }
199
200 return kNoErr;
201 }
202
lega_rtos_deinit_semaphore(lega_semaphore_t * semaphore)203 OSStatus lega_rtos_deinit_semaphore(lega_semaphore_t *semaphore)
204 {
205 osStatus_t ret;
206
207 ret = osSemaphoreDelete((osSemaphoreId_t)(*semaphore));
208 if (ret != osOK) {
209 printf("sema deinit fail %d\r\n", ret);
210 return kGeneralErr;
211 }
212 *semaphore = NULL;
213 return kNoErr;
214 }
215
lega_rtos_semaphore_pending_task_null(lega_semaphore_t * semaphore)216 OSBool lega_rtos_semaphore_pending_task_null(lega_semaphore_t *semaphore)
217 {
218 osStatus_t ret;
219
220 ret = osSemaphorePendingNoTask((osSemaphoreId_t)(*semaphore));
221 if (ret == osOK) {
222 return TRUE;
223 } else {
224 return FALSE;
225 }
226 }
227
lega_rtos_init_mutex(lega_mutex_t * mutex)228 OSStatus lega_rtos_init_mutex(lega_mutex_t *mutex)
229 {
230 osMutexId_t mutexId;
231 mutexId = osMutexNew(0);
232 if (mutexId == 0) {
233 printf("mutex init fail %d\r\n", (int)mutexId);
234 return kGeneralErr;
235 }
236
237 *mutex = (lega_mutex_t)mutexId;
238 return kNoErr;
239 }
240
lega_rtos_lock_mutex(lega_mutex_t * mutex,uint32_t timeout_ms)241 OSStatus lega_rtos_lock_mutex(lega_mutex_t *mutex, uint32_t timeout_ms)
242 {
243 osStatus_t ret;
244
245 ret = osMutexAcquire((osMutexId_t)(*mutex), timeout_ms);
246 if (ret != osOK) {
247 printf("mutex lock fail %d\r\n", ret);
248 return kGeneralErr;
249 }
250
251 return kNoErr;
252 }
253
lega_rtos_unlock_mutex(lega_mutex_t * mutex)254 OSStatus lega_rtos_unlock_mutex(lega_mutex_t *mutex)
255 {
256 osStatus_t ret;
257
258 ret = osMutexRelease((osMutexId_t)(*mutex));
259 if (ret != osOK) {
260 printf("mutex unlock fail %d", ret);
261 return kGeneralErr;
262 }
263
264 return kNoErr;
265 }
266
lega_rtos_deinit_mutex(lega_mutex_t * mutex)267 OSStatus lega_rtos_deinit_mutex(lega_mutex_t *mutex)
268 {
269 osStatus_t ret;
270
271 ret = osMutexDelete((osMutexId_t)(*mutex));
272 if (ret != osOK) {
273 printf("mutex deinit fail %d\r\n", ret);
274 return kGeneralErr;
275 }
276
277 *mutex = NULL;
278 return kNoErr;
279 }
280
lega_rtos_init_queue(lega_queue_t * queue,const char * name,uint32_t message_size,uint32_t number_of_messages)281 OSStatus lega_rtos_init_queue(lega_queue_t *queue, const char *name, uint32_t message_size,
282 uint32_t number_of_messages)
283 {
284 osMessageQueueId_t queId;
285
286 (void)name;
287 queId = osMessageQueueNew(number_of_messages, message_size, 0);
288 if (queId == 0) {
289 printf("queue init fail %d\r\n", (int)queId);
290 return kGeneralErr;
291 }
292
293 *queue = queId;
294 return kNoErr;
295 }
296
lega_rtos_push_to_queue(lega_queue_t * queue,void * message,uint32_t timeout_ms)297 OSStatus lega_rtos_push_to_queue(lega_queue_t *queue, void *message, uint32_t timeout_ms)
298 {
299 osStatus_t ret;
300
301 if (lega_rtos_is_in_interrupt_context()) {
302 ret = osMessageQueuePut((osMessageQueueId_t)(*queue), message, 0, 0);
303 } else {
304 ret = osMessageQueuePut((osMessageQueueId_t)(*queue), message, 0, timeout_ms);
305 }
306 if (ret != osOK) {
307 printf("push_to_queue fail:%d\r\n", ret);
308 return kGeneralErr;
309 }
310
311 return kNoErr;
312 }
313
lega_rtos_pop_from_queue(lega_queue_t * queue,void * message,uint32_t timeout_ms)314 OSStatus lega_rtos_pop_from_queue(lega_queue_t *queue, void *message, uint32_t timeout_ms)
315 {
316 osStatus_t ret;
317
318 ret = osMessageQueueGet((osMessageQueueId_t)(*queue), message, 0, timeout_ms);
319 if (ret != osOK) {
320 if (timeout_ms) {
321 printf("pop_from_queue fail:%d\r\n", ret);
322 }
323 return kGeneralErr;
324 }
325
326 return kNoErr;
327 }
328
lega_rtos_deinit_queue(lega_queue_t * queue)329 OSStatus lega_rtos_deinit_queue(lega_queue_t *queue)
330 {
331 osStatus_t ret;
332
333 ret = osMessageQueueDelete((osMessageQueueId_t)(*queue));
334 if (ret != osOK) {
335 printf("queue deinit fail:%d\r\n", ret);
336 return kGeneralErr;
337 }
338
339 return kNoErr;
340 }
341
lega_rtos_is_queue_empty(lega_queue_t * queue)342 OSBool lega_rtos_is_queue_empty(lega_queue_t *queue)
343 {
344 OSBool ret;
345 lega_rtos_declare_critical();
346
347 if (!lega_rtos_is_in_interrupt_context()) {
348 lega_rtos_enter_critical();
349 }
350
351 if (osMessageQueueGetCount((osMessageQueueId_t)(*queue)) == 0) {
352 ret = TRUE;
353 } else {
354 ret = FALSE;
355 }
356
357 if (!lega_rtos_is_in_interrupt_context()) {
358 lega_rtos_exit_critical();
359 }
360
361 return ret;
362 }
363
lega_rtos_is_queue_full(lega_queue_t * queue)364 OSBool lega_rtos_is_queue_full(lega_queue_t *queue)
365 {
366 OSBool ret;
367 lega_rtos_declare_critical();
368
369 if (!lega_rtos_is_in_interrupt_context()) {
370 lega_rtos_enter_critical();
371 }
372
373 if (osMessageQueueGetSpace((osMessageQueueId_t)(*queue)) == 0) {
374 ret = TRUE;
375 } else {
376 ret = FALSE;
377 }
378
379 if (!lega_rtos_is_in_interrupt_context()) {
380 lega_rtos_exit_critical();
381 }
382
383 return ret;
384 }
385
386 #if 1
387
lega_rtos_ms_to_ticks(uint32_t ms)388 uint32_t lega_rtos_ms_to_ticks(uint32_t ms)
389 {
390 uint32_t ticks;
391
392 uint64_t padding;
393
394 padding = MS_PER_SECONED / LOSCFG_BASE_CORE_TICK_PER_SECOND;
395 padding = (padding > 0) ? (padding - 1) : 0;
396
397 ticks = ((ms + padding) * LOSCFG_BASE_CORE_TICK_PER_SECOND) / MS_PER_SECONED;
398 return ticks;
399 }
400
401 #if 1
lega_rtos_init_timer(lega_timer_t * timer,uint32_t time_ms,timer_handler_t function,void * arg)402 OSStatus lega_rtos_init_timer(lega_timer_t *timer, uint32_t time_ms, timer_handler_t function, void *arg)
403 {
404 timer->function = function;
405 timer->arg = arg;
406
407 KalTimerType kalType = KAL_TIMER_PERIODIC;
408 KalTimerId timeId;
409
410 timeId = KalTimerCreate(function, kalType, arg, time_ms);
411 if (timeId == 0) {
412 printf("rtos_init_timer err %d\r\n", (int)timeId);
413 return kGeneralErr;
414 }
415 timer->handle = timeId;
416
417 return kNoErr;
418 }
419 #else
lega_rtos_init_timer_name(lega_timer_t * timer,uint32_t time_ms,timer_handler_t function,void * arg,uint8_t * name)420 OSStatus lega_rtos_init_timer_name(lega_timer_t *timer, uint32_t time_ms, timer_handler_t function, void *arg,
421 uint8_t *name)
422 {
423 if (!timer) {
424 printf("%s %s timer err\n", __FUNCTION__, name);
425 return kGeneralErr;
426 }
427 timer->function = function;
428 if (!arg) {
429 timer->arg = name;
430 } else {
431 timer->arg = arg;
432 }
433
434 KalTimerType kalType = KAL_TIMER_PERIODIC;
435 KalTimerId timeId;
436
437 timeId = KalTimerCreate(timer->function, kalType, timer->arg, time_ms);
438 if (timeId == 0) {
439 printf("rtos_init_timer err %d\r\n", (int)timeId);
440 return kGeneralErr;
441 }
442 timer->handle = timeId;
443
444 return kNoErr;
445 }
446 #endif
447
lega_rtos_start_timer(lega_timer_t * timer)448 OSStatus lega_rtos_start_timer(lega_timer_t *timer)
449 {
450 if (!timer) {
451 printf("%s timer err\n", __FUNCTION__);
452 return kGeneralErr;
453 }
454 if (KalTimerStart((KalTimerId)(timer->handle)) == KAL_OK) {
455 return kNoErr;
456 }
457
458 return kGeneralErr;
459 }
460
lega_rtos_stop_timer(lega_timer_t * timer)461 OSStatus lega_rtos_stop_timer(lega_timer_t *timer)
462 {
463 if (!timer) {
464 printf("%s timer err\n", __FUNCTION__);
465 return kGeneralErr;
466 }
467 if (KalTimerStop((KalTimerId)(timer->handle)) == KAL_OK) {
468 // printf("rtos_stop_timer\r\n");
469 return kNoErr;
470 }
471
472 return kGeneralErr;
473 }
474
lega_rtos_reload_timer(lega_timer_t * timer)475 OSStatus lega_rtos_reload_timer(lega_timer_t *timer)
476 {
477 if (!timer) {
478 printf("%s timer err\n", __FUNCTION__);
479 return kGeneralErr;
480 }
481 if (KalTimerStop((KalTimerId)(timer->handle)) != KAL_OK) {
482 printf("rtos_reload_timer err1\r\n");
483 return kGeneralErr;
484 }
485
486 if (KalTimerStart((KalTimerId)(timer->handle)) != KAL_OK) {
487 printf("rtos_reload_timer err2\r\n");
488 return kGeneralErr;
489 }
490
491 return kNoErr;
492 }
493
lega_rtos_deinit_timer(lega_timer_t * timer)494 OSStatus lega_rtos_deinit_timer(lega_timer_t *timer)
495 {
496 if (!timer) {
497 printf("%s timer err\n", __FUNCTION__);
498 return kGeneralErr;
499 }
500 if (KalTimerStop((KalTimerId)(timer->handle)) != KAL_OK) {
501 printf("rtos_stop_timer err\r\n");
502 return kGeneralErr;
503 }
504 if (KalTimerDelete((KalTimerId)(timer->handle)) == KAL_OK) {
505
506 timer->handle = 0;
507 return kNoErr;
508 }
509 timer->handle = 0;
510
511 return kGeneralErr;
512 }
513
lega_rtos_is_timer_running(lega_timer_t * timer)514 OSBool lega_rtos_is_timer_running(lega_timer_t *timer)
515 {
516 if (!timer) {
517 printf("%s timer err\n", __FUNCTION__);
518 return kGeneralErr;
519 }
520
521 if (KalTimerIsRunning((KalTimerId)(timer->handle))) {
522
523 return TRUE;
524 }
525 return FALSE;
526 }
527
lega_rtos_ticks_to_ms(uint32_t ticks)528 uint32_t lega_rtos_ticks_to_ms(uint32_t ticks)
529 {
530 uint64_t padding;
531 uint32_t time;
532
533 padding = LOSCFG_BASE_CORE_TICK_PER_SECOND / 1000;
534 padding = (padding > 0) ? (padding - 1) : 0;
535
536 time = ((ticks + padding) * 1000) / LOSCFG_BASE_CORE_TICK_PER_SECOND;
537
538 return time;
539 }
540
lega_rtos_get_time(void)541 uint32_t lega_rtos_get_time(void)
542 {
543 return (uint32_t)lega_rtos_ticks_to_ms((unsigned int)osKernelGetTickCount());
544 }
545
lega_rtos_get_system_ticks(void)546 uint32_t lega_rtos_get_system_ticks(void)
547 {
548 return (uint32_t)osKernelGetTickCount();
549 }
550
lega_rtos_delay_milliseconds(uint32_t num_ms)551 OSStatus lega_rtos_delay_milliseconds(uint32_t num_ms)
552 {
553 uint32_t ticks;
554
555 ticks = lega_rtos_ms_to_ticks(num_ms);
556 if (ticks == 0) {
557 ticks = 1;
558 }
559
560 osDelay(ticks);
561
562 return kNoErr;
563 }
564
565 #endif
566 int32_t lega_malloc_cnt = 0;
_lega_rtos_malloc(uint32_t xWantedSize,const char * function,uint32_t line)567 void *_lega_rtos_malloc(uint32_t xWantedSize, const char *function, uint32_t line)
568 {
569 void *p = malloc(xWantedSize);
570 uint32_t size_cache = xWantedSize;
571 if (p) {
572 lega_malloc_cnt++;
573 } else {
574 if (size_cache != 0) {
575 printf("rtos malloc %u fail %s:%u\r\n", (unsigned int)xWantedSize, function, (unsigned int)line);
576 }
577 }
578 while (size_cache) {
579 if (size_cache >= (sizeof(int))) {
580 size_cache -= sizeof(int);
581 * (int *)(p + size_cache) = 0;
582 } else {
583 size_cache--;
584 * (char *)(p + size_cache) = 0; // clear memory alloced
585 }
586 }
587 return p;
588 }
589
lega_rtos_free(void * mem)590 void lega_rtos_free(void *mem)
591 {
592 if (mem) {
593 lega_malloc_cnt--;
594 } else {
595 printf("rtos free null\r\n");
596 return;
597 }
598
599 free(mem);
600 }
601
lega_rtos_realloc(void * mem,uint32_t xWantedSize)602 void lega_rtos_realloc(void *mem, uint32_t xWantedSize)
603 {
604 if (mem) {
605 realloc(mem, xWantedSize);
606 } else {
607 printf("rtos realloc null\r\n");
608 }
609 return;
610 }
611
pvPortMalloc(uint32_t xWantedSize)612 void *pvPortMalloc(uint32_t xWantedSize)
613 {
614 return lega_rtos_malloc(xWantedSize);
615 }
616
vPortFree(void * pv)617 void vPortFree(void *pv)
618 {
619 lega_rtos_free(pv);
620 }
621
622 /*******************************************************************
623 * Name:lega_rtos_enter_critical
624 * Description: get system into critical area where there is no context switch
625 * input param: none
626 * output param: none
627 * return:none
628 *******************************************************************/
_lega_rtos_enter_critical(void)629 lega_cpsr_t _lega_rtos_enter_critical(void)
630 {
631 lega_cpsr_t cpsr_save = LOS_IntLock();
632 return cpsr_save;
633 }
634
635 /*******************************************************************
636 * Name:lega_rtos_exit_critical
637 * Description: get system out of critical area
638 * input param: none
639 * output param:none
640 * return:none
641 *******************************************************************/
_lega_rtos_exit_critical(lega_cpsr_t cpsr_store)642 void _lega_rtos_exit_critical(lega_cpsr_t cpsr_store)
643 {
644 LOS_IntRestore(cpsr_store);
645 }
646
lega_intrpt_enter(void)647 void lega_intrpt_enter(void)
648 {
649 }
650
651 /*******************************************************************
652 * Name:lega_intrpt_exit
653 * Description: exit interrupt
654 * input param: none
655 * output param:none
656 * return:none
657 *******************************************************************/
lega_intrpt_exit(void)658 void lega_intrpt_exit(void)
659 {
660 }
661