diff --git a/components/utilities/ulog/ulog.c b/components/utilities/ulog/ulog.c index 76100892982dde363d1e80b7439dc57a1c06d530..8be20ae1152942195f74d827e57fa1c1260b17eb 100644 --- a/components/utilities/ulog/ulog.c +++ b/components/utilities/ulog/ulog.c @@ -77,7 +77,7 @@ struct rt_ulog { rt_bool_t init_ok; - struct rt_mutex output_locker; + struct rt_semaphore output_locker; /* all backends */ rt_slist_t backend_list; /* the thread log's line buffer */ @@ -90,6 +90,7 @@ struct rt_ulog #endif /* ULOG_USING_ISR_LOG */ #ifdef ULOG_USING_ASYNC_OUTPUT + rt_bool_t async_enabled; rt_rbb_t async_rbb; rt_thread_t async_th; struct rt_semaphore async_notice; @@ -186,7 +187,7 @@ static void output_unlock(void) /* is in thread context */ if (rt_interrupt_get_nest() == 0) { - rt_mutex_release(&ulog.output_locker); + rt_sem_release(&ulog.output_locker); } else { @@ -201,7 +202,7 @@ static void output_lock(void) /* is in thread context */ if (rt_interrupt_get_nest() == 0) { - rt_mutex_take(&ulog.output_locker, RT_WAITING_FOREVER); + rt_sem_take(&ulog.output_locker, RT_WAITING_FOREVER); } else { @@ -393,6 +394,10 @@ void ulog_output_to_all_backend(rt_uint32_t level, const char *tag, rt_bool_t is for (node = rt_slist_first(&ulog.backend_list); node; node = rt_slist_next(node)) { backend = rt_slist_entry(node, struct ulog_backend, list); + if (backend->out_level < level) + { + continue; + } #if !defined(ULOG_USING_COLOR) || defined(ULOG_USING_SYSLOG) backend->output(backend, level, tag, is_raw, log, size); #else @@ -738,6 +743,42 @@ void ulog_hexdump(const char *tag, rt_size_t width, rt_uint8_t *buf, rt_size_t s } #ifdef ULOG_USING_FILTER +/** + * Set the filter's level by different backend. + * The log on this backend which level is less than it will stop output. + * + * @param be_name backend name + * @param level The filter level. When the level is LOG_FILTER_LVL_SILENT, the log enter silent mode. + * When the level is LOG_FILTER_LVL_ALL, it will remove this tag's level filer. + * Then all level log will resume output. + * + * @return 0 : success + * -10: level is out of range + */ +int ulog_be_lvl_filter_set(const char *be_name, rt_uint32_t level) +{ + rt_slist_t *node = RT_NULL; + ulog_backend_t backend; + int result = RT_EOK; + + if (level > LOG_FILTER_LVL_ALL) + return -RT_EINVAL; + + if (!ulog.init_ok) + return result; + + for (node = rt_slist_first(&ulog.backend_list); node; node = rt_slist_next(node)) + { + backend = rt_slist_entry(node, struct ulog_backend, list); + if (rt_strncmp(backend->name, be_name, RT_NAME_MAX) == 0) + { + backend->out_level = level; + } + } + + return result; +} + /** * Set the filter's level by different tag. * The log on this tag which level is less than it will stop output. @@ -945,6 +986,47 @@ const char *ulog_global_filter_kw_get(void) #if defined(RT_USING_FINSH) && defined(FINSH_USING_MSH) #include +static void _print_lvl_info(void) +{ +#ifndef ULOG_USING_SYSLOG + rt_kprintf("Assert : 0\n"); + rt_kprintf("Error : 3\n"); + rt_kprintf("Warning : 4\n"); + rt_kprintf("Info : 6\n"); + rt_kprintf("Debug : 7\n"); +#else + rt_kprintf("EMERG : 1 (1 << 0)\n"); + rt_kprintf("ALERT : 2 (1 << 1)\n"); + rt_kprintf("CRIT : 4 (1 << 2)\n"); + rt_kprintf("ERR : 8 (1 << 3)\n"); + rt_kprintf("WARNING : 16 (1 << 4)\n"); + rt_kprintf("NOTICE : 32 (1 << 5)\n"); + rt_kprintf("INFO : 64 (1 << 6)\n"); + rt_kprintf("DEBUG : 128 (1 << 7)\n"); +#endif /* ULOG_USING_SYSLOG */ +} + +static void ulog_be_lvl(uint8_t argc, char **argv) +{ + if (argc > 2) + { + if ((atoi(argv[2]) <= LOG_FILTER_LVL_ALL) && (atoi(argv[2]) >= 0)) + { + ulog_be_lvl_filter_set(argv[1], atoi(argv[2])); + } + else + { + rt_kprintf("Please input correct level (0-%d).\n", LOG_FILTER_LVL_ALL); + } + } + else + { + rt_kprintf("Please input: ulog_be_lvl .\n"); + _print_lvl_info(); + } +} +MSH_CMD_EXPORT(ulog_be_lvl, Set ulog filter level by different backend.); + static void ulog_tag_lvl(uint8_t argc, char **argv) { if (argc > 2) @@ -961,22 +1043,7 @@ static void ulog_tag_lvl(uint8_t argc, char **argv) else { rt_kprintf("Please input: ulog_tag_lvl .\n"); -#ifndef ULOG_USING_SYSLOG - rt_kprintf("Assert : 0\n"); - rt_kprintf("Error : 3\n"); - rt_kprintf("Warning : 4\n"); - rt_kprintf("Info : 6\n"); - rt_kprintf("Debug : 7\n"); -#else - rt_kprintf("EMERG : 1 (1 << 0)\n"); - rt_kprintf("ALERT : 2 (1 << 1)\n"); - rt_kprintf("CRIT : 4 (1 << 2)\n"); - rt_kprintf("ERR : 8 (1 << 3)\n"); - rt_kprintf("WARNING : 16 (1 << 4)\n"); - rt_kprintf("NOTICE : 32 (1 << 5)\n"); - rt_kprintf("INFO : 64 (1 << 6)\n"); - rt_kprintf("DEBUG : 128 (1 << 7)\n"); -#endif /* ULOG_USING_SYSLOG */ + _print_lvl_info(); } } MSH_CMD_EXPORT(ulog_tag_lvl, Set ulog filter level by different tag.); @@ -997,22 +1064,7 @@ static void ulog_lvl(uint8_t argc, char **argv) else { rt_kprintf("Please input: ulog_lvl .\n"); -#ifndef ULOG_USING_SYSLOG - rt_kprintf("Assert : 0\n"); - rt_kprintf("Error : 3\n"); - rt_kprintf("Warning : 4\n"); - rt_kprintf("Info : 6\n"); - rt_kprintf("Debug : 7\n"); -#else - rt_kprintf("EMERG : 1 (1 << 0)\n"); - rt_kprintf("ALERT : 2 (1 << 1)\n"); - rt_kprintf("CRIT : 4 (1 << 2)\n"); - rt_kprintf("ERR : 8 (1 << 3)\n"); - rt_kprintf("WARNING : 16 (1 << 4)\n"); - rt_kprintf("NOTICE : 32 (1 << 5)\n"); - rt_kprintf("INFO : 64 (1 << 6)\n"); - rt_kprintf("DEBUG : 128 (1 << 7)\n"); -#endif /* ULOG_USING_SYSLOG */ + _print_lvl_info(); } } MSH_CMD_EXPORT(ulog_lvl, Set ulog global filter level.); @@ -1124,6 +1176,7 @@ rt_err_t ulog_backend_register(ulog_backend_t backend, const char *name, rt_bool } backend->support_color = support_color; + backend->out_level = LOG_FILTER_LVL_ALL; rt_memcpy(backend->name, name, RT_NAME_MAX); level = rt_hw_interrupt_disable(); @@ -1163,6 +1216,11 @@ void ulog_async_output(void) rt_rbb_blk_t log_blk; ulog_frame_t log_frame; + if (!ulog.async_enabled) + { + return; + } + while ((log_blk = rt_rbb_blk_get(ulog.async_rbb)) != NULL) { log_frame = (ulog_frame_t) log_blk->buf; @@ -1176,6 +1234,17 @@ void ulog_async_output(void) } } +/** + * enable or disable asynchronous output mode + * the log will be output directly when mode is disabled + * + * @param enabled RT_TRUE: enabled, RT_FALSE: disabled + */ +void ulog_async_output_enabled(rt_bool_t enabled) +{ + ulog.async_enabled = enabled; +} + /** * waiting for get asynchronous output log * @@ -1230,7 +1299,7 @@ int ulog_init(void) if (ulog.init_ok) return 0; - rt_mutex_init(&ulog.output_locker, "ulog lock", RT_IPC_FLAG_FIFO); + rt_sem_init(&ulog.output_locker, "ulog lock", 1, RT_IPC_FLAG_FIFO); rt_slist_init(&ulog.backend_list); #ifdef ULOG_USING_FILTER @@ -1239,29 +1308,16 @@ int ulog_init(void) #ifdef ULOG_USING_ASYNC_OUTPUT RT_ASSERT(ULOG_ASYNC_OUTPUT_STORE_LINES >= 2); + ulog.async_enabled = RT_TRUE; /* async output ring block buffer */ ulog.async_rbb = rt_rbb_create(RT_ALIGN(ULOG_ASYNC_OUTPUT_BUF_SIZE, RT_ALIGN_SIZE), ULOG_ASYNC_OUTPUT_STORE_LINES); if (ulog.async_rbb == NULL) { rt_kprintf("Error: ulog init failed! No memory for async rbb.\n"); - rt_mutex_detach(&ulog.output_locker); + rt_sem_detach(&ulog.output_locker); return -RT_ENOMEM; } - /* async output thread */ - ulog.async_th = rt_thread_create("ulog_async", async_output_thread_entry, &ulog, ULOG_ASYNC_OUTPUT_THREAD_STACK, - ULOG_ASYNC_OUTPUT_THREAD_PRIORITY, 20); - if (ulog.async_th == NULL) - { - rt_kprintf("Error: ulog init failed! No memory for async output thread.\n"); - rt_mutex_detach(&ulog.output_locker); - rt_rbb_destroy(ulog.async_rbb); - return -RT_ENOMEM; - } - rt_sem_init(&ulog.async_notice, "ulog", 0, RT_IPC_FLAG_FIFO); - /* async output thread startup */ - rt_thread_startup(ulog.async_th); - #endif /* ULOG_USING_ASYNC_OUTPUT */ #ifdef ULOG_USING_FILTER @@ -1272,7 +1328,28 @@ int ulog_init(void) return 0; } -INIT_PREV_EXPORT(ulog_init); +INIT_BOARD_EXPORT(ulog_init); + +#ifdef ULOG_USING_ASYNC_OUTPUT +int ulog_async_init(void) +{ + if (ulog.async_th == NULL) + { + /* async output thread */ + ulog.async_th = rt_thread_create("ulog_async", async_output_thread_entry, &ulog, ULOG_ASYNC_OUTPUT_THREAD_STACK, + ULOG_ASYNC_OUTPUT_THREAD_PRIORITY, 20); + if (ulog.async_th == NULL) + { + rt_kprintf("Error: ulog init failed! No memory for async output thread.\n"); + return -RT_ENOMEM; + } + /* async output thread startup */ + rt_thread_startup(ulog.async_th); + } + return 0; +} +INIT_PREV_EXPORT(ulog_async_init); +#endif /* ULOG_USING_ASYNC_OUTPUT */ void ulog_deinit(void) { @@ -1304,7 +1381,7 @@ void ulog_deinit(void) } #endif /* ULOG_USING_FILTER */ - rt_mutex_detach(&ulog.output_locker); + rt_sem_detach(&ulog.output_locker); #ifdef ULOG_USING_ASYNC_OUTPUT rt_rbb_destroy(ulog.async_rbb); diff --git a/components/utilities/ulog/ulog.h b/components/utilities/ulog/ulog.h index c78d72eda5e012f30599943e5bcc860f235255ec..670644bb30019aab399d88c62b176c1173d4e95d 100644 --- a/components/utilities/ulog/ulog.h +++ b/components/utilities/ulog/ulog.h @@ -24,6 +24,7 @@ extern "C" { * ulog init and deint */ int ulog_init(void); +int ulog_async_init(void); void ulog_deinit(void); /* @@ -78,6 +79,7 @@ void ulog_flush(void); * asynchronous output API */ void ulog_async_output(void); +void ulog_async_output_enabled(rt_bool_t enabled); void ulog_async_waiting_log(rt_int32_t time); #endif diff --git a/components/utilities/ulog/ulog_def.h b/components/utilities/ulog/ulog_def.h index de5e82fcc55a274dec932c466a95463d631f3cbd..771e76a601ab18e93d081eb0dfe67489bc7fc0b0 100644 --- a/components/utilities/ulog/ulog_def.h +++ b/components/utilities/ulog/ulog_def.h @@ -201,6 +201,7 @@ struct ulog_backend { char name[RT_NAME_MAX]; rt_bool_t support_color; + rt_uint32_t out_level; void (*init) (struct ulog_backend *backend); void (*output)(struct ulog_backend *backend, rt_uint32_t level, const char *tag, rt_bool_t is_raw, const char *log, size_t len); void (*flush) (struct ulog_backend *backend);