fix log + add program end fallback func + fix make info
This commit is contained in:
parent
03c65be18a
commit
4ff8850be3
4
Makefile
4
Makefile
@ -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
|
||||||
|
|||||||
@ -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")
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|
||||||
|
|||||||
@ -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,7 +95,7 @@ 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;
|
||||||
}
|
}
|
||||||
@ -103,12 +103,12 @@ int launch_task(AppState *s, FnJob f) {
|
|||||||
#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
|
||||||
100
buzzer/log.c
100
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 <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);
|
||||||
|
|
||||||
|
vfprintf(stdout, format, args);
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void trace(const char *format, ...) {
|
||||||
|
if (LOG_LEVEL >= TRACE) {
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
vfprintf(stdout, format, args);
|
_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);
|
va_end(args);
|
||||||
|
|
||||||
fprintf(stdout, "\n");
|
if (fallback != NULL)
|
||||||
#endif
|
fallback();
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
12
buzzer/log.h
12
buzzer/log.h
@ -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
|
||||||
@ -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(¶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
|
#else
|
||||||
|
info("application init with success");
|
||||||
check_btn_state(¶ms);
|
check_btn_state(¶ms);
|
||||||
#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
6
buzzer/utils.c
Normal 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
9
buzzer/utils.h
Normal 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
|
||||||
Loading…
x
Reference in New Issue
Block a user