diff --git a/Makefile.dep b/Makefile.dep index 85facbec086ed29ef269891945974f0739580736..58642b82190dfcea72c6fec8e04e0d9245d2a4c8 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -249,3 +249,8 @@ endif ifneq (,$(filter ng_at86rf2%,$(USEMODULE))) USEMODULE += ng_at86rf2xx endif + +# if any log_* is used, also use LOG pseudomodule +ifneq (,$(filter log_%,$(USEMODULE))) + USEMODULE += log +endif diff --git a/Makefile.pseudomodules b/Makefile.pseudomodules index 9b6867efccd91a3fc520c871d51a45e09ee8e7ee..f23954e445e28f211eac473e1885c0d7b9e935ae 100644 --- a/Makefile.pseudomodules +++ b/Makefile.pseudomodules @@ -6,6 +6,8 @@ PSEUDOMODULES += ng_ipv6_router_default PSEUDOMODULES += pktqueue PSEUDOMODULES += ng_netbase PSEUDOMODULES += ng_sixlowpan_default +PSEUDOMODULES += log +PSEUDOMODULES += log_printfnoformat # include variants of the AT86RF2xx drivers as pseudo modules PSEUDOMODULES += ng_at86rf23% diff --git a/core/hwtimer.c b/core/hwtimer.c index 3c7152b458a2c675b647511ee62b696a3f3aa767..89e9e961696be9803c6c28ecd5ddb3dd19f7d16a 100644 --- a/core/hwtimer.c +++ b/core/hwtimer.c @@ -34,6 +34,8 @@ #define ENABLE_DEBUG (0) #include "debug.h" +#include "log.h" + #include "hwtimer.h" #include "hwtimer_cpu.h" #include "arch/hwtimer_arch.h" @@ -157,7 +159,7 @@ static int _hwtimer_set(unsigned long offset, void (*callback)(void*), void *ptr if (n == -1) { restoreIRQ(state); - puts("No hwtimer left."); + LOG_WARNING("No hwtimer left."); return -1; } diff --git a/core/include/log.h b/core/include/log.h new file mode 100644 index 0000000000000000000000000000000000000000..ecd1831f538db7bdb3a341472b6e91bc97ba4df4 --- /dev/null +++ b/core/include/log.h @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de> + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @addtogroup core_util + * @{ + * + * @brief System logging header + * + * This header offers a bunch of "LOG_*" functions that, with the default + * implementation, just use printf, but honour a verbosity level. + * + * If desired, it is possible to implement a log module which then will be used + * instead the default printf-based implementation. In order to do so, the log + * module has to + * + * 1. provide "log_module.h" + * 2. have a name starting with "log_" *or* depend on the pseudo-module LOG, + * 3. implement log_write() + * + * See "sys/log/log_printfnoformat" for an example. + * + * @author Kaspar Schleiser <kaspar@schleiser.de> + */ + +#ifndef __LOG_H +#define __LOG_H + +#ifdef __cplusplus + extern "C" { +#endif + +/** + * @brief defined log levels + * + * These are the logging levels a user can choose. + * The idea is to set LOG_LEVEL to one of these values in the application's Makefile. + * That will restrict output of log statements to those with equal or lower log level. + * + * The default log level is LOG_INFO, which will print every message. + * + * The log function calls of filtered messages will be optimized out at compile + * time, so a lower log level might result in smaller code size. + */ +enum { + LOG_NONE, /**< Lowest log level, will output nothing */ + LOG_ERROR, /**< Error log level, will print only critical, + non-recoverable errors like hardware initialization + failures */ + LOG_WARNING, /**< Warning log level, will print warning messages for + temporary errors */ + LOG_INFO, /**< Informational log level, will print purely + informational messages like successful system bootup, + network link state, ...*/ + LOG_DEBUG, /**< Debug log level, printing developer stuff considered + too verbose for production use */ + LOG_ALL /**< print everything */ +}; + +#ifndef LOG_LEVEL +/** + * @brief Default log level define + */ +#define LOG_LEVEL LOG_INFO +#endif + +/** + * @brief Log message if level <= LOG_LEVEL + */ +#define LOG(level, ...) if (level <= LOG_LEVEL) log_write(level, __VA_ARGS__) + +/** + * @brief logging convenience defines + * @{ + */ +#define LOG_ERROR(...) LOG(LOG_ERROR, __VA_ARGS__) +#define LOG_WARNING(...) LOG(LOG_WARNING, __VA_ARGS__) +#define LOG_INFO(...) LOG(LOG_INFO, __VA_ARGS__) +#define LOG_DEBUG(...) LOG(LOG_DEBUG, __VA_ARGS__) +/** @} */ + +#ifdef MODULE_LOG +#include "log_module.h" +#else +#include <stdio.h> + +/** + * @brief Default log_write function, just maps to printf + */ +#define log_write(level, ...) printf(__VA_ARGS__) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __LOG_H */ +/** @} */ diff --git a/core/kernel_init.c b/core/kernel_init.c index a57f119acb299da517ca3a8c3bbee469feb3464f..678f9759e8b4016306ae38a1cb6a43de4e90b6eb 100644 --- a/core/kernel_init.c +++ b/core/kernel_init.c @@ -18,7 +18,6 @@ * @} */ -#include <stdio.h> #include <stdint.h> #include <stdbool.h> #include <errno.h> @@ -32,6 +31,7 @@ #include "thread.h" #include "hwtimer.h" #include "irq.h" +#include "log.h" #define ENABLE_DEBUG (0) #include "debug.h" @@ -82,19 +82,19 @@ static char idle_stack[KERNEL_CONF_STACKSIZE_IDLE]; void kernel_init(void) { (void) disableIRQ(); - printf("kernel_init(): This is RIOT! (Version: %s)\n", RIOT_VERSION); + LOG_INFO("kernel_init(): This is RIOT! (Version: %s)\n", RIOT_VERSION); hwtimer_init(); if (thread_create(idle_stack, sizeof(idle_stack), PRIORITY_IDLE, CREATE_WOUT_YIELD | CREATE_STACKTEST, idle_thread, NULL, idle_name) < 0) { - printf("kernel_init(): error creating idle task.\n"); + LOG_ERROR("kernel_init(): error creating idle task.\n"); } if (thread_create(main_stack, sizeof(main_stack), PRIORITY_MAIN, CREATE_WOUT_YIELD | CREATE_STACKTEST, main_trampoline, NULL, main_name) < 0) { - printf("kernel_init(): error creating main task.\n"); + LOG_ERROR("kernel_init(): error creating main task.\n"); } - printf("kernel_init(): jumping into first task...\n"); + LOG_INFO("kernel_init(): jumping into first task...\n"); cpu_switch_context_exit(); } diff --git a/core/lifo.c b/core/lifo.c index 2451c42ed3a0d3e355fc39f8d88a3d2fc03dc391..7c6ce59ba1be831218053d5a4a58a4d5c84181cf 100644 --- a/core/lifo.c +++ b/core/lifo.c @@ -17,6 +17,7 @@ */ #include "lifo.h" +#include "log.h" #define ENABLE_DEBUG (0) #include "debug.h" @@ -42,7 +43,7 @@ void lifo_insert(int *array, int i) #if DEVELHELP if ((array[index] != -1) && (array[0] != -1)) { - printf("lifo_insert: overwriting array[%i] == %i with %i\n\n\n\t\tThe lifo is broken now.\n\n\n", index, array[index], array[0]); + LOG_WARNING("lifo_insert: overwriting array[%i] == %i with %i\n\n\n\t\tThe lifo is broken now.\n\n\n", index, array[index], array[0]); } #endif diff --git a/core/sched.c b/core/sched.c index 9d404789fed9d911297ae1bd5aa41dffa30186d3..28ab4db244624260578c12345f865a2005633fd3 100644 --- a/core/sched.c +++ b/core/sched.c @@ -29,6 +29,7 @@ #include "irq.h" #include "thread.h" #include "irq.h" +#include "log.h" #if SCHEDSTATISTICS #include "hwtimer.h" @@ -86,7 +87,7 @@ int sched_run(void) #ifdef SCHED_TEST_STACK if (*((uintptr_t *) active_thread->stack_start) != (uintptr_t) active_thread->stack_start) { - printf("scheduler(): stack overflow detected, pid=%" PRIkernel_pid "\n", active_thread->pid); + LOG_WARNING("scheduler(): stack overflow detected, pid=%" PRIkernel_pid "\n", active_thread->pid); } #endif diff --git a/sys/Makefile b/sys/Makefile index b5ce3cd2bc0395cd1c71963e786aae1ea5a9244d..49919cef4b38c47ef86d8862261dbcac806827d9 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -143,6 +143,9 @@ endif ifneq (,$(filter hwtimer_compat,$(USEMODULE))) DIRS += compat/hwtimer endif +ifneq (,$(filter log_%,$(USEMODULE))) + DIRS += log +endif DIRS += $(dir $(wildcard $(addsuffix /Makefile, ${USEMODULE}))) diff --git a/sys/Makefile.include b/sys/Makefile.include index ca3bce1556e38cb1e12ed39df91a7ae7f1a602ef..68137f6cfb886bb76e22836e0c4db9c230ebfd9e 100644 --- a/sys/Makefile.include +++ b/sys/Makefile.include @@ -90,3 +90,6 @@ ifneq (,$(filter embunit,$(USEMODULE))) CFLAGS += -DOUTPUT=OUTPUT_COMPILER endif endif +ifneq (,$(filter log_%,$(USEMODULE))) + include $(RIOTBASE)/sys/log/Makefile.include +endif diff --git a/sys/log/Makefile b/sys/log/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..f1eb9fa686a0c9a51647e82737df848f7af5cc5a --- /dev/null +++ b/sys/log/Makefile @@ -0,0 +1,3 @@ +DIRS += $(dir $(wildcard $(addsuffix /Makefile, ${USEMODULE}))) + +include $(RIOTBASE)/Makefile.base diff --git a/sys/log/Makefile.include b/sys/log/Makefile.include new file mode 100644 index 0000000000000000000000000000000000000000..769761aef444ed0dc9d3ced27109be77a8e28ce7 --- /dev/null +++ b/sys/log/Makefile.include @@ -0,0 +1,3 @@ +ifneq (,$(filter log_printfnoformat,$(USEMODULE))) + USEMODULE_INCLUDES += $(RIOTBASE)/sys/log/log_printfnoformat +endif diff --git a/sys/log/log_printfnoformat/log_module.h b/sys/log/log_printfnoformat/log_module.h new file mode 100644 index 0000000000000000000000000000000000000000..9725290a2a231f8b101d11806a451755da874c69 --- /dev/null +++ b/sys/log/log_printfnoformat/log_module.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de> + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @defgroup sys_log_printfnoformat puts log module + * @ingroup sys + * @brief This module implements an example logging module + * @{ + * + * @file log_module.h + * @brief log_module header + * + * @author Jason Linehan <patientulysses@gmail.com> + * @author Christian Mehlis <mehlis@inf.fu-berlin.de> + * @author Kaspar Schleiser <kaspar@schleiser.de> + */ + +#ifndef __LOG_FORMAT_H +#define __LOG_FORMAT_H + +#include <stdio.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief log_write overridden function + * + * This example function will only print the log's format string. + * Use it where printf might be too heavy. + * + * @param[in] level (unused) + * @param[in] format String that the function will print + */ +static inline void log_write(unsigned level, const char *format, ...) { + (void)level; + puts(format); +} + +#ifdef __cplusplus +} +#endif +/**@}*/ +#endif /* __LOG_FORMAT_H */