• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Chipsea Technologies (Shenzhen) Corp., 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 #include <stdlib.h>
16 #include <string.h>
17 #include "al_rtos.h"
18 #include "dbg_assert.h"
19 #include "co_main.h"
20 #include "sleep_api.h"
21 #include "reg_sysctrl.h"
22 #include "sysctrl_api.h"
23 #include "gpadc_api.h"
24 #include "pwrkey_api.h"
25 #include "dbg.h"
26 #define COTIMER_DEBUG_PRINTF(fmt, ...)       //dbg(fmt, ##__VA_ARGS__)
27 #define MAX_LOCAL_BATT_VAULE                 4200//mV
28 #define MIN_LOCAL_BATT_VAULE                 3300//mV
29 #define CO_BATT_CHECK_TIME_IN_ACTIVE         10000//10s
30 #define CO_BATT_CHECK_TIME_IN_SLEEP          30000//30s
31 #define CO_BATT_REG_CALLBACK_NUM             4
32 
33 #ifndef max
34 #define max(a,b)            (((a) > (b)) ? (a) : (b))
35 #endif /* max */
36 
37 #ifndef min
38 #define min(a,b)            (((a) < (b)) ? (a) : (b))
39 #endif /* min */
40 
41 
42 static TimerHandle_t co_main_timer = NULL;
43 static struct co_list co_main_time_list;
44 static rtos_task_handle co_main_task_handle = NULL;
45 static rtos_queue co_main_evt_queue = NULL;
46 static CO_EVT_HANDLER_T evt_handler[CO_MODUAL_NUM] = {NULL,};
47 #if CO_MAIN_AUTO_POWER_DOWEN
48 static co_timer *co_batt_check_timer = NULL;
49 static co_main_batt_reg_cb_t co_batt_reg_cb[CO_BATT_REG_CALLBACK_NUM] = {NULL,};
50 static uint8_t co_batt_reg_cb_num = 0;
51 #endif
co_event_send(CO_MODUAL_EVENT * msg_src,bool isr)52 int co_event_send(CO_MODUAL_EVENT *msg_src, bool isr)
53 {
54     int res = 0;
55     if(!co_main_evt_queue)
56         return 1;
57     res = rtos_queue_write(co_main_evt_queue, msg_src, 0, isr);
58     if (res) {
59         return -1;
60     }
61     return 0;
62 }
63 
co_event_get(CO_MODUAL_EVENT * msg_p)64 int co_event_get(CO_MODUAL_EVENT* msg_p)
65 {
66     int res = rtos_queue_read(co_main_evt_queue, msg_p, -1, false);
67     if (res) {
68         return -1;
69     }
70     return 0;
71 }
72 
RTOS_TASK_FCT(co_main_task)73 static RTOS_TASK_FCT(co_main_task)
74 {
75     if (pwrctrl_pwrmd_cpusys_sw_record_getf() >= CPU_SYS_POWER_DOWN) {
76         #if PLF_AON_SUPPORT
77         co_timer_restore();
78         #endif
79     }
80     while (1) {
81         CO_MODUAL_EVENT msg;
82         int res = co_event_get(&msg);
83         if (res == 0) {
84             if(msg.mod_id < CO_MODUAL_NUM){
85                 if (evt_handler[msg.mod_id]){
86                     evt_handler[msg.mod_id](&(msg.mod_evt));
87                 }
88             }
89         } else {
90             dbg("co_main_task mbox get err\n");
91         }
92     }
93 }
94 /**
95  ****************************************************************************************
96  * @brief * basic timer function for  co_timer .Users don't have to pay attention to it
97  ****************************************************************************************
98  */
co_main_timer_start(uint32_t t)99 void co_main_timer_start(uint32_t t)
100 {
101     rtos_timer_change_period(co_main_timer, t, 0);
102 }
103 /**
104  ****************************************************************************************
105  * @brief * basic timer function for  co_timer .Users don't have to pay attention to it
106  ****************************************************************************************
107  */
co_main_timer_cancel(void)108 void co_main_timer_cancel(void)
109 {
110     rtos_timer_stop(co_main_timer,0);
111 }
112 /**
113  ****************************************************************************************
114  * @brief * basic timer function for  co_timer .Users don't have to pay attention to it
115  ****************************************************************************************
116  */
co_main_timer_notify(void)117 static void co_main_timer_notify(void)
118 {
119     CO_MODUAL_EVENT msg;
120     int res = 0;
121     msg.mod_id = CO_MODUAL_TIMER;
122     res = co_event_send(&msg, false);
123     ASSERT_ERR(res == 0 || res == 1);
124 }
125 /**
126  ****************************************************************************************
127  * @brief * basic timer function for  co_timer .Users don't have to pay attention to it
128  ****************************************************************************************
129  */
co_main_timer_cb(TimerHandle_t xTimer)130 static void co_main_timer_cb( TimerHandle_t xTimer )
131 {
132     co_main_timer_notify();
133 }
134 /**
135  ****************************************************************************************
136  * @brief * basic timer function for  co_timer .Users don't have to pay attention to it
137  ****************************************************************************************
138  */
co_main_timer_init(void)139 static void co_main_timer_init(void)
140 {
141     if (co_main_timer == NULL)
142         co_main_timer = rtos_timer_create("co_main_timer",\
143                         10000,pdFALSE,NULL,co_main_timer_cb);
144     co_list_init(&co_main_time_list);
145 }
146 /**
147  ****************************************************************************************
148  * @brief * basic timer function for  co_timer .Users don't have to pay attention to it
149  ****************************************************************************************
150  */
co_timer_list_reset(void)151 static void co_timer_list_reset(void)
152 {
153     uint16_t list_len = 0;
154     uint32_t elapsed_time;
155     uint32_t min_duration = (uint32_t)(-1);
156     struct co_list_hdr *element = NULL;
157     co_timer *current_timer;
158     uint32_t time_now = rtos_now(false);
159 
160     list_len = co_list_size(&co_main_time_list);
161     if(list_len){
162         element = co_main_time_list.first;
163         while(element != NULL){
164             current_timer = (co_timer *)element;
165             elapsed_time = time_now - current_timer->time_start;
166             if(elapsed_time < current_timer->time_duration){
167                 min_duration = min(min_duration,(current_timer->time_duration - elapsed_time));
168             }
169             element = element->next;
170         }
171     }
172     COTIMER_DEBUG_PRINTF("duration %d ,now 0x%x\n",min_duration,time_now);
173     if(min_duration < (uint32_t)(-1)){
174         co_main_timer_start(min_duration);
175     }else{
176         co_main_timer_cancel();
177     }
178 }
179 /**
180  ****************************************************************************************
181  *           co_timer_start
182  *
183  * @brief * It is described by co_main.h
184  *
185  ****************************************************************************************
186  */
co_timer_start(co_timer ** timer,uint32_t duration,void * cb_param,co_timer_callback cb,uint32_t is_period)187 void co_timer_start(co_timer **timer, uint32_t duration, void *cb_param, co_timer_callback cb, uint32_t is_period)
188 {
189     co_timer *tmp_timer = NULL;
190     uint16_t list_len = 0;
191     uint8_t is_in_list = 0;
192     if(timer == NULL || cb == NULL){
193         COTIMER_DEBUG_PRINTF("co_timer error\n");
194         ASSERT_ERR(0);
195         return;
196     }
197     COTIMER_DEBUG_PRINTF("%s timer 0x%x\n",__func__,timer);
198     list_len = co_list_size(&co_main_time_list);
199     if(list_len){
200         struct co_list_hdr *tmp_list_hdr = co_main_time_list.first;
201         while(tmp_list_hdr != NULL){
202             co_timer *_cur_timer = (co_timer *)tmp_list_hdr;
203             COTIMER_DEBUG_PRINTF("%s timer 0x%x ,timer_addr 0x%x\n",__func__,_cur_timer,_cur_timer->timer_addr);
204             if(_cur_timer->timer_addr == (uint32_t)timer){
205                 is_in_list = 1;
206                 COTIMER_DEBUG_PRINTF("%s timer is in list\n",__func__);
207             }
208             tmp_list_hdr = tmp_list_hdr->next;
209         }
210     }
211     if(is_in_list == 0){
212         tmp_timer = (co_timer *)rtos_malloc(sizeof(co_timer));
213         COTIMER_DEBUG_PRINTF("%s tmp_timer alloc 0x%x,cb 0x%x\n",__func__,tmp_timer,cb);
214         if(tmp_timer){
215             *timer = tmp_timer;
216             tmp_timer->cb = cb;
217             tmp_timer->cb_param = cb_param;
218             tmp_timer->timer_addr = (uint32_t)timer;
219             tmp_timer->time_duration = duration;
220             tmp_timer->time_start = rtos_now(false);
221             tmp_timer->is_period = is_period;
222         }else{
223             COTIMER_DEBUG_PRINTF("co_timer malloc error\n");
224             ASSERT_ERR(0);
225             return;
226         }
227         co_list_push_back(&co_main_time_list,&tmp_timer->node);
228     }
229     co_timer_list_reset();
230 }
231 /**
232  ****************************************************************************************
233  *           co_timer_stop
234  *
235  * @brief * It is described by co_main.h
236  *
237  ****************************************************************************************
238  */
co_timer_stop(co_timer * timer)239 void co_timer_stop(co_timer *timer)
240 {
241     co_timer *current_timer;
242     struct co_list_hdr *prev_element = NULL;
243     struct co_list_hdr *element = NULL;
244     uint16_t list_len = 0;
245     if(timer == NULL ){
246         COTIMER_DEBUG_PRINTF("co_timer stop error\n");
247         ASSERT_ERR(0);
248         return;
249     }
250 
251     list_len = co_list_size(&co_main_time_list);
252     if(list_len){
253         element = co_main_time_list.first;
254         while(element != NULL){
255             current_timer = (co_timer *)element;
256             if(current_timer == timer){
257                 co_list_remove(&co_main_time_list,prev_element,element);
258                 rtos_free(current_timer);
259                 COTIMER_DEBUG_PRINTF("%s tmp_timer free 0x%x\n",__func__,current_timer);
260                 co_timer_list_reset();
261                 break;
262             }
263             prev_element = element;
264             element = element->next;
265         }
266     }
267 }
268 /**
269  ****************************************************************************************
270  * @brief * basic timer function for  co_timer .Users don't have to pay attention to it
271  ****************************************************************************************
272  */
co_timer_list_check(void)273 static void co_timer_list_check(void)
274 {
275     co_timer *current_timer;
276     struct co_list_hdr *prev_element = NULL;
277     struct co_list_hdr *element = NULL;
278     uint16_t list_len = 0;
279     uint8_t time_done = 0;
280     uint32_t elapsed_time;
281     uint32_t time_now = rtos_now(false);
282 
283     list_len = co_list_size(&co_main_time_list);
284     if(list_len){
285         element = co_main_time_list.first;
286         COTIMER_DEBUG_PRINTF("%s 0x%x,0x%x\n",__func__,time_now,element);
287         while(element != NULL){
288             current_timer = (co_timer *)element;
289             elapsed_time = time_now - current_timer->time_start;
290             if(elapsed_time >= current_timer->time_duration){
291                 co_timer_callback cb = current_timer->cb;
292                 void* cb_param = current_timer->cb_param;
293                 COTIMER_DEBUG_PRINTF("%s tmp_timer free 0x%x ,cb 0x%x\n",__func__,current_timer,cb);
294                 if(current_timer->is_period){
295                     current_timer->time_start = time_now;
296                 }else{
297                     co_list_remove(&co_main_time_list,prev_element,element);
298                     rtos_free(current_timer);
299                 }
300                 if(cb){
301                     cb(cb_param);
302                 }
303                 time_done = 1;
304                 break;
305             }
306             prev_element = element;
307             element = element->next;
308         }
309         if(time_done){
310             co_main_timer_notify();
311             co_timer_list_reset();
312         }
313     }
314 }
315 /**
316  ****************************************************************************************
317  * @brief * basic timer function for  co_timer .Users don't have to pay attention to it
318  ****************************************************************************************
319  */
co_timer_handle_process(CO_EVENT * evt)320 static bool co_timer_handle_process(CO_EVENT *evt)
321 {
322     co_timer_list_check();
323     return true;
324 }
325 
co_main_evt_handler_rigister(CO_MODUAL_ID_T mod_id,CO_EVT_HANDLER_T handler)326 int co_main_evt_handler_rigister(CO_MODUAL_ID_T mod_id, CO_EVT_HANDLER_T handler)
327 {
328     if (mod_id>=CO_MODUAL_NUM) {
329         return -1;
330     }
331     evt_handler[mod_id] = handler;
332     return 0;
333 }
334 #if CO_MAIN_AUTO_POWER_DOWEN
co_main_batt_register_cb(co_main_batt_reg_cb_t callback)335 void co_main_batt_register_cb(co_main_batt_reg_cb_t callback)
336 {
337     uint8_t ret = 0;
338     for(uint8_t i = 0; i < CO_BATT_REG_CALLBACK_NUM; i++){
339         if(co_batt_reg_cb[i] == NULL &&  callback){
340             co_batt_reg_cb[i] = callback;
341             co_batt_reg_cb_num++;
342             ret = 1;
343             break;
344         }
345     }
346     if(ret == 0){
347         TRACE("batt cb reg error!\n");
348     }
349 }
350 
co_main_batt_get_lvl(void)351 static uint8_t co_main_batt_get_lvl(void)
352 {
353     int volt_mv = 0;
354     uint8_t batt_level = 0;// batt level will in 0~9,when value is 0 ,it will run power down process.
355 
356     volt_mv = gpadc_measure(GPADC_TYPE_VBAT);
357 
358     if(volt_mv < MIN_LOCAL_BATT_VAULE){
359         return batt_level;
360     }
361     if(volt_mv >= MAX_LOCAL_BATT_VAULE){
362         batt_level = 9;
363         return batt_level;
364     }
365     batt_level = (uint8_t)(((volt_mv-MIN_LOCAL_BATT_VAULE)*10)/(MAX_LOCAL_BATT_VAULE-MIN_LOCAL_BATT_VAULE));
366     return batt_level;
367 }
368 
co_main_batt_check_timer(void * cb_param)369 static void co_main_batt_check_timer(void *cb_param)
370 {
371     uint8_t batt_level = 0;
372 
373     batt_level = co_main_batt_get_lvl();
374     TRACE("batt_level = %x\n",batt_level);
375     co_batt_check_timer = NULL;
376     if(batt_level){
377         co_timer_start(&co_batt_check_timer,CO_BATT_CHECK_TIME_IN_ACTIVE,NULL,co_main_batt_check_timer,0);
378         for(uint8_t i = 0; i < co_batt_reg_cb_num; i++){
379             if(co_batt_reg_cb[i]){
380                 co_batt_reg_cb[i](APP_MSG_BATT|(uint32_t)batt_level);
381             }
382         }
383         // notify some task current batt level.
384     }else{
385         //need power down or notify some task to do some process before power down.
386         if(co_batt_reg_cb_num){
387             for(uint8_t i = 0; i < co_batt_reg_cb_num; i++){
388                 if(co_batt_reg_cb[i]){
389                     if(co_batt_reg_cb_num - 1 == i)
390                         co_batt_reg_cb[i](APP_MSG_POWER_DOWN|(uint32_t)batt_level);
391                     else
392                         co_batt_reg_cb[i](APP_MSG_LOW_POWER|(uint32_t)batt_level);
393                 }
394             }
395         }else{
396             pmic_chip_shutdown();
397         }
398     }
399 }
400 
co_main_batt_timer_change(uint8_t is_sleep)401 static void co_main_batt_timer_change(uint8_t is_sleep)
402 {
403     uint32_t duration = 0;
404 
405     if(is_sleep)
406         duration = CO_BATT_CHECK_TIME_IN_SLEEP;
407     else
408         duration = CO_BATT_CHECK_TIME_IN_ACTIVE;
409 
410     if(co_batt_check_timer){
411         co_timer_stop(co_batt_check_timer);
412         co_batt_check_timer = NULL;
413         co_timer_start(&co_batt_check_timer,duration,NULL,co_main_batt_check_timer,0);
414     }
415 }
416 
co_main_batt_timer_init(void)417 static void co_main_batt_timer_init(void)
418 {
419     uint32_t pwrmd = pwrctrl_pwrmd_cpusys_sw_record_getf();
420 
421     if (pwrmd == CPU_SYS_POWER_ON_RESET) {
422         if(co_batt_check_timer == NULL){
423             co_timer_start(&co_batt_check_timer,CO_BATT_CHECK_TIME_IN_ACTIVE,NULL,co_main_batt_check_timer,0);
424         }
425     }
426 }
427 #endif
428 
429 #if PLF_AON_SUPPORT
430 static uint32_t co_main_timer_min_duration = (uint32_t)-1;
431 #define TIMER_LIST_SLEEP_ENTRY_MAX                     5
432 co_timer co_timer_list_sleep_entry[TIMER_LIST_SLEEP_ENTRY_MAX];
433 PRIVATE_HOST_ARRAY_DECLARE(G0RTOS, co_timer, TIMER_LIST_SLEEP_ENTRY_MAX, co_timer_list_sleep_entry);
434 
435 uint8_t co_timer_lp_level = CO_TIMER_LP_LEVEL_HIBERNATE;
436 
co_timer_save(void)437 void co_timer_save(void)
438 {
439     uint16_t list_len = 0;
440     list_len = co_list_size(&co_main_time_list);
441 
442     COTIMER_DEBUG_PRINTF("%s list_len 0x%x\n",__func__,list_len);
443     memset(&co_timer_list_sleep_entry[0],0,sizeof(co_timer_list_sleep_entry));
444     if(list_len){
445         uint8_t i = 0;
446         struct co_list_hdr *element = NULL;
447         co_timer *current_timer;
448         element = co_main_time_list.first;
449         COTIMER_DEBUG_PRINTF("%s element 0x%x\n",__func__,element);
450         while(element != NULL){
451             current_timer = (co_timer *)element;
452             memcpy(&co_timer_list_sleep_entry[i++],current_timer,sizeof(co_timer));
453             element = element->next;
454             if(i == TIMER_LIST_SLEEP_ENTRY_MAX){
455                 break;
456             }
457         }
458     }
459     memcpy(&backup_co_timer_list_sleep_entry[0], &co_timer_list_sleep_entry[0], sizeof(co_timer_list_sleep_entry));
460 }
461 
co_timer_restore(void)462 void co_timer_restore(void)
463 {
464     co_timer *tmp_timer = NULL;
465     co_timer *cur_timer = NULL;
466 
467     memcpy(&co_timer_list_sleep_entry[0], &backup_co_timer_list_sleep_entry[0], sizeof(co_timer_list_sleep_entry));
468     for(uint8_t i = 0; i < TIMER_LIST_SLEEP_ENTRY_MAX; i++){
469         COTIMER_DEBUG_PRINTF("%s timer_addr 0x%x\n",__func__,co_timer_list_sleep_entry[i].timer_addr);
470         if(co_timer_list_sleep_entry[i].timer_addr){
471             cur_timer = &co_timer_list_sleep_entry[i];
472             tmp_timer = (co_timer *)rtos_malloc(sizeof(co_timer));
473             COTIMER_DEBUG_PRINTF("%s tmp_timer alloc 0x%x\n",__func__,tmp_timer);
474             if(tmp_timer){
475                 *((co_timer **)cur_timer->timer_addr) = tmp_timer;
476                 tmp_timer->cb = cur_timer->cb;
477                 tmp_timer->cb_param = cur_timer->cb_param;
478                 tmp_timer->timer_addr = cur_timer->timer_addr;
479                 tmp_timer->time_duration = cur_timer->time_duration;
480                 tmp_timer->time_start = cur_timer->time_start;
481                 tmp_timer->is_period = cur_timer->is_period;
482                 COTIMER_DEBUG_PRINTF("%d,  0x%x, 0x%x\n",tmp_timer->time_duration,tmp_timer->time_start,tmp_timer->cb);
483             }else{
484                 COTIMER_DEBUG_PRINTF("co_timer malloc error\n");
485                 ASSERT_ERR(0);
486                 return;
487             }
488             co_list_push_back(&co_main_time_list,&tmp_timer->node);
489             //co_timer_lp_level = CO_TIMER_LP_LEVEL_ACTIVE;
490         }
491     }
492     co_main_timer_notify();
493 }
494 
co_timer_sleep_level_set(POWER_MODE_LEVEL_T level)495 void co_timer_sleep_level_set(POWER_MODE_LEVEL_T level)
496 {
497     if (level == PM_LEVEL_ACTIVE) {
498         co_timer_lp_level = CO_TIMER_LP_LEVEL_ACTIVE;
499     }else{
500         co_timer_lp_level = CO_TIMER_LP_LEVEL_HIBERNATE;
501     }
502 }
503 
co_timer_is_sleep_allowed(void)504 int co_timer_is_sleep_allowed(void)
505 {
506     int ret = 0;
507     uint16_t list_len = 0;
508     uint32_t elapsed_time;
509     uint32_t min_duration = (uint32_t)(-1);
510     struct co_list_hdr *element = NULL;
511     co_timer *current_timer;
512     uint32_t time_now = rtos_now(false);
513 
514 
515     do {
516         if (co_timer_lp_level == CO_TIMER_LP_LEVEL_HIBERNATE) {
517             list_len = co_list_size(&co_main_time_list);
518             if ( list_len == 0 ) {
519                 ret = 1;
520                 break;
521             } else {
522                 element = co_main_time_list.first;
523                 while(element != NULL){
524                     current_timer = (co_timer *)element;
525                     elapsed_time = time_now - current_timer->time_start;
526                     if(elapsed_time < current_timer->time_duration){
527                         min_duration = min(min_duration,(current_timer->time_duration - elapsed_time));
528                     }
529                     element = element->next;
530                 }
531 
532                 COTIMER_DEBUG_PRINTF("m_d %d\n",min_duration);
533                 if(min_duration >= CO_TIMER_ALLOW_MIN_SLEEP_DURATION){
534                     ret = 1;
535                     co_main_timer_min_duration = min_duration;
536                     break;
537                 }
538             }
539         }
540     } while (0);
541 
542     return ret;
543 }
544 
get_co_main_timer_min_duration(void)545 uint32_t get_co_main_timer_min_duration(void)
546 {
547     return co_main_timer_min_duration;
548 }
549 
co_timer_sleep_indicate(POWER_MODE_LEVEL_T level)550 void co_timer_sleep_indicate(POWER_MODE_LEVEL_T level)
551 {
552     //todo
553 #if CO_MAIN_AUTO_POWER_DOWEN
554     co_main_batt_timer_change(1);
555 #endif
556 }
557 
co_timer_wakeup_indicate(void)558 void co_timer_wakeup_indicate(void)
559 {
560     //todo
561 #if CO_MAIN_AUTO_POWER_DOWEN
562     co_main_batt_timer_change(0);
563 #endif
564 }
565 
co_timer_sleep_entry_init(void)566 void co_timer_sleep_entry_init(void)
567 {
568     uint32_t pwrmd = pwrctrl_pwrmd_cpusys_sw_record_getf();
569 
570     if (pwrmd == CPU_SYS_POWER_ON_RESET) {
571         sleep_entry_t co_timer_sleep_entry = {
572             co_timer_sleep_level_set,
573             co_timer_is_sleep_allowed,
574             co_timer_sleep_indicate,
575             co_timer_wakeup_indicate,
576         };
577         sleep_entry_register(&co_timer_sleep_entry);
578     }
579 }
580 #endif /* PLF_AON_SUPPORT */
581 
co_main_init(void)582 void co_main_init(void)
583 {
584     co_main_timer_init();
585     co_main_evt_handler_rigister(CO_MODUAL_TIMER,co_timer_handle_process);
586     #if PLF_AON_SUPPORT
587     co_timer_sleep_entry_init();
588     #endif
589     #if CO_MAIN_AUTO_POWER_DOWEN
590     co_main_batt_timer_init();
591     #endif
592     // create the co main evt queue
593     if (rtos_queue_create(sizeof(CO_MODUAL_EVENT), CO_EVT_MAX, &co_main_evt_queue)) {
594         dbg("failed to create co_main_mbox\n");
595         return;
596     }
597     // Create the co main task
598     if (rtos_task_create(co_main_task, "CO_TASK", CO_TASK,
599                          TASK_STACK_SIZE_CO_MAIN, NULL, TASK_PRIORITY_CO_MAIN, &co_main_task_handle)) {
600         dbg("failed to create co_main_task\n");
601         rtos_queue_delete(co_main_evt_queue);
602         co_main_evt_queue = NULL;
603         return;
604     }
605 }
606 
607