From 4ff8850be3e530914f230477a391cc45f4bfe6a6 Mon Sep 17 00:00:00 2001 From: rmanach Date: Tue, 4 Mar 2025 13:48:41 +0100 Subject: [PATCH] fix log + add program end fallback func + fix make info --- Makefile | 4 +- buzzer/CMakeLists.txt | 2 +- buzzer/gpio.c | 40 +++++----------- buzzer/gpio.h | 4 +- buzzer/jobs.c | 53 +++++++++++---------- buzzer/log.c | 104 +++++++++++++++++++++++++++++++++++++----- buzzer/log.h | 12 +++++ buzzer/main.c | 30 ++++++------ buzzer/utils.c | 6 +++ buzzer/utils.h | 9 ++++ 10 files changed, 180 insertions(+), 84 deletions(-) create mode 100644 buzzer/utils.c create mode 100644 buzzer/utils.h diff --git a/Makefile b/Makefile index c03f194..c07f300 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ install: @./scripts/install_freertos.bash info: - @$(PICOTOOL) info -a + $(picotool) info -a .check-name: ifeq ($(strip $(name)), "") @@ -42,7 +42,7 @@ format: .check-name run-debug: format @rm -f ${name}/${name}.debug - @gcc -DDEBUG -std=c99 -o2 ${name}/*.c -lm -o ${name}/${name}.debug && ./${name}/${name}.debug + @gcc -DLOG_LEVEL=TRACE -std=c99 -o2 ${name}/*.c -lm -o ${name}/${name}.debug && ./${name}/${name}.debug compile: format @rm -f ${name}/build/CMakeCache.txt diff --git a/buzzer/CMakeLists.txt b/buzzer/CMakeLists.txt index d6fb81b..3194566 100644 --- a/buzzer/CMakeLists.txt +++ b/buzzer/CMakeLists.txt @@ -50,7 +50,7 @@ set(FREERTOS_PORT_FILES # Add executable. Default name is the project name, version 0.1 -add_executable(buzzer main.c log.c gpio.c jobs.c ${FREERTOS_SOURCES} ${FREERTOS_PORT_FILES}) +add_executable(buzzer main.c log.c gpio.c jobs.c utils.c ${FREERTOS_SOURCES} ${FREERTOS_PORT_FILES}) add_definitions(-DPICO) pico_set_program_name(buzzer "buzzer") diff --git a/buzzer/gpio.c b/buzzer/gpio.c index 39da6db..74869ab 100644 --- a/buzzer/gpio.c +++ b/buzzer/gpio.c @@ -53,10 +53,8 @@ void gpio_set_state(gpio *g, bool state) { if (!g->has_pwm && g->direction == GPIO_OUT) { #ifdef PICO gpio_put(g->pin, state); -#else - // must be trace instead - // debug("", g->pin, state); #endif + trace("", g->pin, state); } } @@ -71,39 +69,23 @@ bool gpio_get_input(gpio* g) { return false; } g->state = GPIO_INPUT_MOCK_COUNTER++ % value == 0; - debug("gpio get input (state: %d)", g->state); #endif + trace("", g->pin, g->state); return g->state; } return false; } -void blink_failed(size_t pin, uint32_t delay_ms) { -#ifdef PICO - for (;;) { - gpio_put(pin, false); - _sleep_ms(delay_ms); +void gpio_onoff(gpio* g, uint32_t delay_ms, size_t times) { + if (g->direction == GPIO_OUT) { + for (size_t i = 0; i < times; i++) { + gpio_set_state(g, true); + _sleep_ms(delay_ms); - gpio_put(pin, true); - _sleep_ms(delay_ms); + gpio_set_state(g, false); + _sleep_ms(delay_ms); + } } -#else - for(;;) { - debug("fatal error occurred, please restart the application"); - _sleep_ms(delay_ms); - } -#endif -} - -void blink_passed(size_t pin, uint32_t delay_ms, char* msg) { -#ifdef PICO - gpio_put(pin, true); - _sleep_ms(delay_ms); - gpio_put(pin, false); - _sleep_ms(delay_ms); -#else - debug(msg); -#endif } void init_gpio(void) { @@ -119,6 +101,6 @@ void init_gpio(void) { pwm_set_wrap(slice_num, DEFAULT_WRAP_LEVEL); } } - blink_passed(GPIOS[0]->pin, 200, "gpios init with success"); + gpio_onoff(GPIOS[0], 200, 1); #endif } diff --git a/buzzer/gpio.h b/buzzer/gpio.h index 238bef8..70119a3 100644 --- a/buzzer/gpio.h +++ b/buzzer/gpio.h @@ -50,12 +50,10 @@ static gpio* GPIOS[NB_GPIO] = {&GPIO_DEFAULT_LED, &GPIO_BUTTON, &GPIO_BUZZER}; void gpio_set_level(gpio *g, uint16_t level); void gpio_set_state(gpio *g, bool state); bool gpio_get_input(gpio* g); +void gpio_onoff(gpio* g, uint32_t delay_ms, size_t times); void init_gpio(void); -void blink_failed(size_t pin, uint32_t delay_ms); -void blink_passed(size_t pin, uint32_t delay_ms, char* msg); - void _sleep_ms(size_t value); void _sleep_us(size_t value); diff --git a/buzzer/jobs.c b/buzzer/jobs.c index ce92ca9..d128b0d 100644 --- a/buzzer/jobs.c +++ b/buzzer/jobs.c @@ -15,28 +15,27 @@ #include "gpio.h" #include "jobs.h" #include "log.h" +#include "utils.h" #define BUTTON_BUFFETING_SLEEP_DURATION_MS 20 int init_app_state(AppState *s) { s->action = STOP; - #ifdef PICO s->lock = xSemaphoreCreateMutex(); #else if (pthread_mutex_init(&s->lock, NULL) != 0) { - printf("error: mutex init failed\n"); + error("mutex init failed"); return -1; } #endif - return 0; } int lock(AppState *s) { #ifdef PICO if (xSemaphoreTake(s->lock, (TickType_t)10) != pdTRUE) { - printf("unable to lock the FreeRTOS task\n"); + error("unable to lock the FreeRTOS task"); return -1; } return 0; @@ -66,12 +65,12 @@ int cancel_task(AppState *s) { #else if (s->task != NULL) { if (pthread_cancel(*s->task) != 0) { - perror("error: unable to cancel the thread task\n"); + error("unable to cancel the thread task"); return -1; } if (pthread_join(*s->task, NULL) != 0) { - perror("error: unable to wait for finished task\n"); + error("unable to wait for finished task"); return -1; } free(s->task); @@ -83,11 +82,12 @@ int cancel_task(AppState *s) { int launch_task(AppState *s, FnJob f) { - debug("starting task thread..."); + debug("starting app task..."); #ifdef PICO TaskHandle_t* task = malloc(sizeof(TaskHandle_t)); if (task == NULL) { - blink_failed(GPIOS[0]->pin, 300); + error("unable allocate memory for the app task"); + return -1; } BaseType_t res = @@ -95,20 +95,20 @@ int launch_task(AppState *s, FnJob f) { NULL, configMAX_PRIORITIES - 1U, task); if (res != pdPASS) { - printf("error: unable to launch run alarm task task, code error: %d\n", - res); + error("unable to launch run alarm task task, code error: %d", + res); return -1; } s->task = task; #else pthread_t* task = malloc(sizeof(task)); if (task == NULL) { - perror("error: unable to allocate memory for task thread"); + error("unable to allocate memory for task thread"); return -1; } if (pthread_create(task, NULL, f, s) != 0) { - perror("error: thread task creation failed\n"); + error("thread task creation failed"); return -1; } @@ -117,6 +117,13 @@ int launch_task(AppState *s, FnJob f) { return 0; } +/** + * Main app loop. + * + * Check the button state and if the button state is pushed (LOW level) + * the app task is launched. + * + */ void check_btn_state(void* args) { TaskParam* params = (TaskParam*) args; AppState *s = params->s; @@ -130,16 +137,14 @@ void check_btn_state(void* args) { _sleep_ms(BUTTON_BUFFETING_SLEEP_DURATION_MS); #endif if(!gpio_get_input(GPIOS[1]) && !has_proceed) { - if (lock(s) != 0) { - blink_failed(PICO_DEFAULT_LED_PIN, 200); - } + if (lock(s) != 0) + fatal(stop_app_fallback, "unable to lock app mutex"); if (s->action == START) { s->action = STOP; cancel_task(s); - if (release(s) != 0) { - blink_failed(PICO_DEFAULT_LED_PIN, 200); - } + if (release(s) != 0) + fatal(stop_app_fallback, "unable to release app mutex"); gpio_set_state(GPIOS[0], false); has_proceed = true; continue; @@ -147,13 +152,11 @@ void check_btn_state(void* args) { s->action = START; - if (launch_task(s, params->f) != 0) { - blink_failed(PICO_DEFAULT_LED_PIN, 200); - } + if (launch_task(s, params->f) != 0) + fatal(stop_app_fallback, "unable to launch app task"); - if (release(s) != 0) { - blink_failed(PICO_DEFAULT_LED_PIN, 200); - } + if (release(s) != 0) + fatal(stop_app_fallback, "unable to release app mutex"); gpio_set_state(GPIOS[0], true); has_proceed = true; @@ -166,6 +169,6 @@ void check_btn_state(void* args) { #ifdef PICO void vApplicationStackOverflowHook(TaskHandle_t pxTask, char *pcTaskName) { - blink_failed(PICO_DEFAULT_LED_PIN, 200); + fatal(stop_app_fallback, "a task stack overflow, please fix it"); } #endif \ No newline at end of file diff --git a/buzzer/log.c b/buzzer/log.c index 610e6de..47a4896 100644 --- a/buzzer/log.c +++ b/buzzer/log.c @@ -1,28 +1,110 @@ +// #define PICO + +#ifdef PICO +#include "pico/stdio.h" +#include "pico/stdlib.h" +#include "pico/time.h" +#else +#include +#include +#endif + #include #include -#include #include "log.h" -void debug(const char *format, ...) { -#ifdef DEBUG - if (format == NULL) { - return; +char* _level_to_str(LogLevel level) { + switch (level) { + case TRACE: + return "TRACE"; + case DEBUG: + return "DEBUG"; + case INFO: + return "INFO"; + case WARNING: + return "WARNING"; + case ERROR: + return "ERROR"; + case FATAL: + return "FATAL"; + default: + return "INFO"; } +} +void _log(LogLevel level, const char *format, va_list args) { time_t now; time(&now); char time_str[26]; ctime_r(&now, time_str); time_str[24] = '\0'; - fprintf(stdout, "[DEBUG] [%s] ", time_str); + FILE* output = stdout; + if (level == ERROR || level == FATAL) + output = stderr; + + fprintf(output, "[%s] [%s] ", _level_to_str(level), time_str); - va_list args; - va_start(args, format); vfprintf(stdout, format, args); - va_end(args); - fprintf(stdout, "\n"); -#endif +} + +void trace(const char *format, ...) { + if (LOG_LEVEL >= TRACE) { + va_list args; + va_start(args, format); + _log(TRACE, format, args); + va_end(args); + } +} + +void debug(const char *format, ...) { + if (LOG_LEVEL >= DEBUG) { + va_list args; + va_start(args, format); + _log(DEBUG, format, args); + va_end(args); + } +} + +void info(const char *format, ...) { + if (LOG_LEVEL >= INFO) { + va_list args; + va_start(args, format); + _log(INFO, format, args); + va_end(args); + } +} + +void warning(const char *format, ...) { + if (LOG_LEVEL >= WARNING) { + va_list args; + va_start(args, format); + _log(WARNING, format, args); + va_end(args); + } +} + +void error(const char *format, ...) { + if (LOG_LEVEL >= ERROR) { + va_list args; + va_start(args, format); + _log(ERROR, format, args); + va_end(args); + } +} + +void fatal(void (*fallback)(void), const char *format, ...) { + if (LOG_LEVEL >= FATAL) { + va_list args; + va_start(args, format); + _log(FATAL, format, args); + va_end(args); + + if (fallback != NULL) + fallback(); + + exit(1); + } } \ No newline at end of file diff --git a/buzzer/log.h b/buzzer/log.h index dc06d79..23ccfac 100644 --- a/buzzer/log.h +++ b/buzzer/log.h @@ -1,6 +1,18 @@ #ifndef LOG_H #define LOG_H +#ifndef LOG_LEVEL +#define LOG_LEVEL INFO +#endif + +typedef enum {FATAL, ERROR, WARNING, INFO, DEBUG, TRACE} LogLevel; + +void trace(const char *format, ...); void debug(const char *format, ...); +void info(const char *format, ...); +void warning(const char *format, ...); +void error(const char *format, ...); +void fatal(void (*fallback)(void), const char *format, ...); + #endif \ No newline at end of file diff --git a/buzzer/main.c b/buzzer/main.c index 6bcfc66..64a676a 100644 --- a/buzzer/main.c +++ b/buzzer/main.c @@ -22,6 +22,7 @@ #include "log.h" #include "jobs.h" #include "gpio.h" +#include "utils.h" #define ALARM_BASE_FREQ 2000 // auditive frequency human range: [20; 20000] hertz #define ALARM_PERIOD_MS 500 @@ -73,16 +74,17 @@ void run_alarm(void *const params) { } } -/* Initialize the main FreeRTOS task */ -void init_rtos_main(TaskParam *params) { +// Initialize the main FreeRTOS task. +int init_rtos_main(TaskParam *params) { #ifdef PICO BaseType_t res = xTaskCreate(check_btn_state, "main", configMINIMAL_STACK_SIZE, (void *const)params, configMAX_PRIORITIES - 1U, NULL); - if (res != pdPASS) { - blink_failed(GPIOS[0]->pin, 500); - } + if (res != pdPASS) + return -1; + + return 0; #endif } @@ -99,7 +101,7 @@ void init_rtos_main(TaskParam *params) { * - 1 NPN transistor for signal amplification * - 1x 1k ohm resistor (NPN collector) * - 2x 10k ohm resistor - * + * * You can run the application in "DEBUG" mode using: * `make run-debug name=buzzer` * The FreeRTOS engine is replaced by threads. @@ -108,7 +110,8 @@ int main() { init_gpio(); AppState as; - init_app_state(&as); + if (init_app_state(&as) != 0) + fatal(stop_app_fallback, "unable to initilize the application"); TaskParam params = (TaskParam) { .s = &as, @@ -116,14 +119,15 @@ int main() { }; #ifdef PICO - init_rtos_main(¶ms); + if (init_rtos_main(¶ms) != 0) + fatal(stop_app_fallback, "unable to launch to FreeRTOS main task"); + + info("application init with success"); + vTaskStartScheduler(); #else + info("application init with success"); check_btn_state(¶ms); #endif -#ifdef PICO - vTaskStartScheduler(); -#endif - - blink_failed(PICO_DEFAULT_LED_PIN, 200); + fatal(stop_app_fallback, "unable to launch the application"); } diff --git a/buzzer/utils.c b/buzzer/utils.c new file mode 100644 index 0000000..87591ca --- /dev/null +++ b/buzzer/utils.c @@ -0,0 +1,6 @@ +#include "gpio.h" + +void stop_app_fallback(void) { + for (;;) + gpio_onoff(GPIOS[0], 400, 1); +} \ No newline at end of file diff --git a/buzzer/utils.h b/buzzer/utils.h new file mode 100644 index 0000000..18dd014 --- /dev/null +++ b/buzzer/utils.h @@ -0,0 +1,9 @@ +#ifndef UTILS_H +#define UTILS_H + +#include "gpio.h" + +// Common function to stop the application. +void stop_app_fallback(void); + +#endif \ No newline at end of file