fix log + add program end fallback func + fix make info

This commit is contained in:
rmanach 2025-03-04 13:48:41 +01:00
parent 03c65be18a
commit 4ff8850be3
10 changed files with 180 additions and 84 deletions

View File

@ -17,7 +17,7 @@ install:
@./scripts/install_freertos.bash @./scripts/install_freertos.bash
info: info:
@$(PICOTOOL) info -a $(picotool) info -a
.check-name: .check-name:
ifeq ($(strip $(name)), "") ifeq ($(strip $(name)), "")
@ -42,7 +42,7 @@ format: .check-name
run-debug: format run-debug: format
@rm -f ${name}/${name}.debug @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 compile: format
@rm -f ${name}/build/CMakeCache.txt @rm -f ${name}/build/CMakeCache.txt

View File

@ -50,7 +50,7 @@ set(FREERTOS_PORT_FILES
# Add executable. Default name is the project name, version 0.1 # 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) add_definitions(-DPICO)
pico_set_program_name(buzzer "buzzer") pico_set_program_name(buzzer "buzzer")

View File

@ -53,10 +53,8 @@ void gpio_set_state(gpio *g, bool state) {
if (!g->has_pwm && g->direction == GPIO_OUT) { if (!g->has_pwm && g->direction == GPIO_OUT) {
#ifdef PICO #ifdef PICO
gpio_put(g->pin, state); gpio_put(g->pin, state);
#else
// must be trace instead
// debug("<GPIO.set_state (pin=%ld) (level=%d)>", g->pin, state);
#endif #endif
trace("<GPIO.set_state (pin=%ld) (level=%d)>", g->pin, state);
} }
} }
@ -71,39 +69,23 @@ bool gpio_get_input(gpio* g) {
return false; return false;
} }
g->state = GPIO_INPUT_MOCK_COUNTER++ % value == 0; g->state = GPIO_INPUT_MOCK_COUNTER++ % value == 0;
debug("gpio get input (state: %d)", g->state);
#endif #endif
trace("<GPIO.get_input (pin=%ld) (level=%d)>", g->pin, g->state);
return g->state; return g->state;
} }
return false; return false;
} }
void blink_failed(size_t pin, uint32_t delay_ms) { void gpio_onoff(gpio* g, uint32_t delay_ms, size_t times) {
#ifdef PICO if (g->direction == GPIO_OUT) {
for (;;) { for (size_t i = 0; i < times; i++) {
gpio_put(pin, false); gpio_set_state(g, true);
_sleep_ms(delay_ms); _sleep_ms(delay_ms);
gpio_put(pin, true); gpio_set_state(g, false);
_sleep_ms(delay_ms); _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) { void init_gpio(void) {
@ -119,6 +101,6 @@ void init_gpio(void) {
pwm_set_wrap(slice_num, DEFAULT_WRAP_LEVEL); 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 #endif
} }

View File

@ -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_level(gpio *g, uint16_t level);
void gpio_set_state(gpio *g, bool state); void gpio_set_state(gpio *g, bool state);
bool gpio_get_input(gpio* g); bool gpio_get_input(gpio* g);
void gpio_onoff(gpio* g, uint32_t delay_ms, size_t times);
void init_gpio(void); 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_ms(size_t value);
void _sleep_us(size_t value); void _sleep_us(size_t value);

View File

@ -15,28 +15,27 @@
#include "gpio.h" #include "gpio.h"
#include "jobs.h" #include "jobs.h"
#include "log.h" #include "log.h"
#include "utils.h"
#define BUTTON_BUFFETING_SLEEP_DURATION_MS 20 #define BUTTON_BUFFETING_SLEEP_DURATION_MS 20
int init_app_state(AppState *s) { int init_app_state(AppState *s) {
s->action = STOP; s->action = STOP;
#ifdef PICO #ifdef PICO
s->lock = xSemaphoreCreateMutex(); s->lock = xSemaphoreCreateMutex();
#else #else
if (pthread_mutex_init(&s->lock, NULL) != 0) { if (pthread_mutex_init(&s->lock, NULL) != 0) {
printf("error: mutex init failed\n"); error("mutex init failed");
return -1; return -1;
} }
#endif #endif
return 0; return 0;
} }
int lock(AppState *s) { int lock(AppState *s) {
#ifdef PICO #ifdef PICO
if (xSemaphoreTake(s->lock, (TickType_t)10) != pdTRUE) { 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 -1;
} }
return 0; return 0;
@ -66,12 +65,12 @@ int cancel_task(AppState *s) {
#else #else
if (s->task != NULL) { if (s->task != NULL) {
if (pthread_cancel(*s->task) != 0) { if (pthread_cancel(*s->task) != 0) {
perror("error: unable to cancel the thread task\n"); error("unable to cancel the thread task");
return -1; return -1;
} }
if (pthread_join(*s->task, NULL) != 0) { 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; return -1;
} }
free(s->task); free(s->task);
@ -83,11 +82,12 @@ int cancel_task(AppState *s) {
int launch_task(AppState *s, FnJob f) { int launch_task(AppState *s, FnJob f) {
debug("starting task thread..."); debug("starting app task...");
#ifdef PICO #ifdef PICO
TaskHandle_t* task = malloc(sizeof(TaskHandle_t)); TaskHandle_t* task = malloc(sizeof(TaskHandle_t));
if (task == NULL) { if (task == NULL) {
blink_failed(GPIOS[0]->pin, 300); error("unable allocate memory for the app task");
return -1;
} }
BaseType_t res = BaseType_t res =
@ -95,20 +95,20 @@ int launch_task(AppState *s, FnJob f) {
NULL, configMAX_PRIORITIES - 1U, task); NULL, configMAX_PRIORITIES - 1U, task);
if (res != pdPASS) { if (res != pdPASS) {
printf("error: unable to launch run alarm task task, code error: %d\n", error("unable to launch run alarm task task, code error: %d",
res); res);
return -1; return -1;
} }
s->task = task; s->task = task;
#else #else
pthread_t* task = malloc(sizeof(task)); pthread_t* task = malloc(sizeof(task));
if (task == NULL) { if (task == NULL) {
perror("error: unable to allocate memory for task thread"); error("unable to allocate memory for task thread");
return -1; return -1;
} }
if (pthread_create(task, NULL, f, s) != 0) { if (pthread_create(task, NULL, f, s) != 0) {
perror("error: thread task creation failed\n"); error("thread task creation failed");
return -1; return -1;
} }
@ -117,6 +117,13 @@ int launch_task(AppState *s, FnJob f) {
return 0; 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) { void check_btn_state(void* args) {
TaskParam* params = (TaskParam*) args; TaskParam* params = (TaskParam*) args;
AppState *s = params->s; AppState *s = params->s;
@ -130,16 +137,14 @@ void check_btn_state(void* args) {
_sleep_ms(BUTTON_BUFFETING_SLEEP_DURATION_MS); _sleep_ms(BUTTON_BUFFETING_SLEEP_DURATION_MS);
#endif #endif
if(!gpio_get_input(GPIOS[1]) && !has_proceed) { if(!gpio_get_input(GPIOS[1]) && !has_proceed) {
if (lock(s) != 0) { if (lock(s) != 0)
blink_failed(PICO_DEFAULT_LED_PIN, 200); fatal(stop_app_fallback, "unable to lock app mutex");
}
if (s->action == START) { if (s->action == START) {
s->action = STOP; s->action = STOP;
cancel_task(s); cancel_task(s);
if (release(s) != 0) { if (release(s) != 0)
blink_failed(PICO_DEFAULT_LED_PIN, 200); fatal(stop_app_fallback, "unable to release app mutex");
}
gpio_set_state(GPIOS[0], false); gpio_set_state(GPIOS[0], false);
has_proceed = true; has_proceed = true;
continue; continue;
@ -147,13 +152,11 @@ void check_btn_state(void* args) {
s->action = START; s->action = START;
if (launch_task(s, params->f) != 0) { if (launch_task(s, params->f) != 0)
blink_failed(PICO_DEFAULT_LED_PIN, 200); fatal(stop_app_fallback, "unable to launch app task");
}
if (release(s) != 0) { if (release(s) != 0)
blink_failed(PICO_DEFAULT_LED_PIN, 200); fatal(stop_app_fallback, "unable to release app mutex");
}
gpio_set_state(GPIOS[0], true); gpio_set_state(GPIOS[0], true);
has_proceed = true; has_proceed = true;
@ -166,6 +169,6 @@ void check_btn_state(void* args) {
#ifdef PICO #ifdef PICO
void vApplicationStackOverflowHook(TaskHandle_t pxTask, char *pcTaskName) { 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 #endif

View File

@ -1,28 +1,110 @@
// #define PICO
#ifdef PICO
#include "pico/stdio.h"
#include "pico/stdlib.h"
#include "pico/time.h"
#else
#include <time.h>
#include <stdlib.h>
#endif
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <time.h>
#include "log.h" #include "log.h"
void debug(const char *format, ...) { char* _level_to_str(LogLevel level) {
#ifdef DEBUG switch (level) {
if (format == NULL) { case TRACE:
return; 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_t now;
time(&now); time(&now);
char time_str[26]; char time_str[26];
ctime_r(&now, time_str); ctime_r(&now, time_str);
time_str[24] = '\0'; 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); vfprintf(stdout, format, args);
va_end(args);
fprintf(stdout, "\n"); 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);
}
} }

View File

@ -1,6 +1,18 @@
#ifndef LOG_H #ifndef LOG_H
#define 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 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 #endif

View File

@ -22,6 +22,7 @@
#include "log.h" #include "log.h"
#include "jobs.h" #include "jobs.h"
#include "gpio.h" #include "gpio.h"
#include "utils.h"
#define ALARM_BASE_FREQ 2000 // auditive frequency human range: [20; 20000] hertz #define ALARM_BASE_FREQ 2000 // auditive frequency human range: [20; 20000] hertz
#define ALARM_PERIOD_MS 500 #define ALARM_PERIOD_MS 500
@ -73,16 +74,17 @@ void run_alarm(void *const params) {
} }
} }
/* Initialize the main FreeRTOS task */ // Initialize the main FreeRTOS task.
void init_rtos_main(TaskParam *params) { int init_rtos_main(TaskParam *params) {
#ifdef PICO #ifdef PICO
BaseType_t res = BaseType_t res =
xTaskCreate(check_btn_state, "main", configMINIMAL_STACK_SIZE, xTaskCreate(check_btn_state, "main", configMINIMAL_STACK_SIZE,
(void *const)params, configMAX_PRIORITIES - 1U, NULL); (void *const)params, configMAX_PRIORITIES - 1U, NULL);
if (res != pdPASS) { if (res != pdPASS)
blink_failed(GPIOS[0]->pin, 500); return -1;
}
return 0;
#endif #endif
} }
@ -108,7 +110,8 @@ int main() {
init_gpio(); init_gpio();
AppState as; AppState as;
init_app_state(&as); if (init_app_state(&as) != 0)
fatal(stop_app_fallback, "unable to initilize the application");
TaskParam params = (TaskParam) { TaskParam params = (TaskParam) {
.s = &as, .s = &as,
@ -116,14 +119,15 @@ int main() {
}; };
#ifdef PICO #ifdef PICO
init_rtos_main(&params); if (init_rtos_main(&params) != 0)
fatal(stop_app_fallback, "unable to launch to FreeRTOS main task");
info("application init with success");
vTaskStartScheduler();
#else #else
info("application init with success");
check_btn_state(&params); check_btn_state(&params);
#endif #endif
#ifdef PICO fatal(stop_app_fallback, "unable to launch the application");
vTaskStartScheduler();
#endif
blink_failed(PICO_DEFAULT_LED_PIN, 200);
} }

6
buzzer/utils.c Normal file
View File

@ -0,0 +1,6 @@
#include "gpio.h"
void stop_app_fallback(void) {
for (;;)
gpio_onoff(GPIOS[0], 400, 1);
}

9
buzzer/utils.h Normal file
View File

@ -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