174 lines
4.0 KiB
C
174 lines
4.0 KiB
C
//#define PICO
|
|
|
|
#ifdef PICO
|
|
#include <pico/printf.h>
|
|
#include <pico/stdlib.h>
|
|
#include "FreeRTOS.h"
|
|
#include "task.h"
|
|
#include "semphr.h"
|
|
#else
|
|
#include <stdio.h>
|
|
#include <stdbool.h>
|
|
#include <pthread.h>
|
|
#endif
|
|
|
|
#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) {
|
|
error("mutex init failed");
|
|
return -1;
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
int lock(AppState *s) {
|
|
#ifdef PICO
|
|
if (xSemaphoreTake(s->lock, (TickType_t)10) != pdTRUE) {
|
|
error("unable to lock the FreeRTOS task");
|
|
return -1;
|
|
}
|
|
return 0;
|
|
#else
|
|
return pthread_mutex_lock(&s->lock);
|
|
#endif
|
|
}
|
|
|
|
int release(AppState *s) {
|
|
#ifdef PICO
|
|
xSemaphoreGive(s->lock);
|
|
return 0;
|
|
#else
|
|
return pthread_mutex_unlock(&s->lock);
|
|
#endif
|
|
}
|
|
|
|
int cancel_task(AppState *s) {
|
|
debug("stopping task...");
|
|
#ifdef PICO
|
|
if (s->task != NULL) {
|
|
vTaskDelete(*s->task);
|
|
free(s->task);
|
|
gpio_set_state(GPIOS[2], false);
|
|
return 0;
|
|
}
|
|
#else
|
|
if (s->task != NULL) {
|
|
if (pthread_cancel(*s->task) != 0) {
|
|
error("unable to cancel the thread task");
|
|
return -1;
|
|
}
|
|
|
|
if (pthread_join(*s->task, NULL) != 0) {
|
|
error("unable to wait for finished task");
|
|
return -1;
|
|
}
|
|
free(s->task);
|
|
s->task = NULL;
|
|
}
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
|
|
int launch_task(AppState *s, FnJob f) {
|
|
debug("starting app task...");
|
|
#ifdef PICO
|
|
TaskHandle_t* task = malloc(sizeof(TaskHandle_t));
|
|
if (task == NULL) {
|
|
error("unable allocate memory for the app task");
|
|
return -1;
|
|
}
|
|
|
|
BaseType_t res =
|
|
xTaskCreate(f, "task", configMINIMAL_STACK_SIZE,
|
|
NULL, configMAX_PRIORITIES - 1U, task);
|
|
|
|
if (res != pdPASS) {
|
|
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) {
|
|
error("unable to allocate memory for task thread");
|
|
return -1;
|
|
}
|
|
|
|
if (pthread_create(task, NULL, f, s) != 0) {
|
|
error("thread task creation failed");
|
|
return -1;
|
|
}
|
|
|
|
s->task = task;
|
|
#endif
|
|
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;
|
|
bool has_proceed = false;
|
|
|
|
for (;;) {
|
|
if (!gpio_get_input(GPIOS[1])) {
|
|
#ifdef PICO
|
|
vTaskDelay(pdMS_TO_TICKS(BUTTON_BUFFETING_SLEEP_DURATION_MS));
|
|
#else
|
|
_sleep_ms(BUTTON_BUFFETING_SLEEP_DURATION_MS);
|
|
#endif
|
|
if(!gpio_get_input(GPIOS[1]) && !has_proceed) {
|
|
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)
|
|
fatal(stop_app_fallback, "unable to release app mutex");
|
|
gpio_set_state(GPIOS[0], false);
|
|
has_proceed = true;
|
|
continue;
|
|
}
|
|
|
|
s->action = START;
|
|
|
|
if (launch_task(s, params->f) != 0)
|
|
fatal(stop_app_fallback, "unable to launch app task");
|
|
|
|
if (release(s) != 0)
|
|
fatal(stop_app_fallback, "unable to release app mutex");
|
|
|
|
gpio_set_state(GPIOS[0], true);
|
|
has_proceed = true;
|
|
}
|
|
continue;
|
|
}
|
|
has_proceed = false;
|
|
}
|
|
}
|
|
|
|
#ifdef PICO
|
|
void vApplicationStackOverflowHook(TaskHandle_t pxTask, char *pcTaskName) {
|
|
fatal(stop_app_fallback, "a task stack overflow, please fix it");
|
|
}
|
|
#endif |