Compare commits
13
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce9d729027 | ||
|
|
06acd84928 | ||
|
|
cfd047a0ac | ||
|
|
a3830a58cb | ||
|
|
3785f07189 | ||
|
|
37b772218b | ||
|
|
8f7db974fa | ||
|
|
02d226b949 | ||
|
|
d71e28c85d | ||
|
|
adff1d963b | ||
|
|
d84116c45b | ||
|
|
1ade64b2b2 | ||
|
|
20535ceb14 |
@@ -1,4 +1,4 @@
|
||||
idf_component_register(SRCS "app_machine.c"
|
||||
INCLUDE_DIRS "include"
|
||||
REQUIRES ui_cmd app_process
|
||||
PRIV_REQUIRES hal_motor hal_temp hal_audio)
|
||||
PRIV_REQUIRES hal_motor hal_temp hal_audio freertos)
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
|
||||
#include "app_machine.h"
|
||||
#include "app_process.h"
|
||||
#include "hal_motor.h"
|
||||
@@ -5,6 +8,7 @@
|
||||
#include "hal_audio.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define AGITATE_RPM 60u
|
||||
|
||||
@@ -16,20 +20,13 @@ static uint32_t s_deadline_ms;
|
||||
static bool s_have_deadline;
|
||||
static bool s_resume_pending;
|
||||
static bool s_auto_advance;
|
||||
static ui_evt_t s_q[UI_EVT_QUEUE_LEN];
|
||||
static uint8_t s_q_head;
|
||||
static uint8_t s_q_tail;
|
||||
static uint8_t s_q_count;
|
||||
static QueueHandle_t s_evtq;
|
||||
|
||||
static void emit(ui_evt_t ev)
|
||||
{
|
||||
if (s_q_count == UI_EVT_QUEUE_LEN) {
|
||||
s_q_head = (uint8_t)((s_q_head + 1u) % UI_EVT_QUEUE_LEN);
|
||||
s_q_count--;
|
||||
if (s_evtq != NULL) {
|
||||
xQueueSend(s_evtq, &ev, 0);
|
||||
}
|
||||
s_q[s_q_tail] = ev;
|
||||
s_q_tail = (uint8_t)((s_q_tail + 1u) % UI_EVT_QUEUE_LEN);
|
||||
s_q_count++;
|
||||
}
|
||||
|
||||
static void fill_common(ui_evt_t *ev)
|
||||
@@ -122,14 +119,13 @@ static void enter_armed(void)
|
||||
emit_id(EVT_STEP_ARMED);
|
||||
}
|
||||
|
||||
static void start_running(uint32_t now_ms)
|
||||
static void start_running(void)
|
||||
{
|
||||
const process_def_t *p = app_process_get(s_proc);
|
||||
uint16_t t_s = app_process_time_s(s_proc, s_step);
|
||||
s_remaining_ms = (uint32_t)t_s * 1000u;
|
||||
s_deadline_ms = now_ms + s_remaining_ms;
|
||||
s_have_deadline = true;
|
||||
s_resume_pending = false;
|
||||
s_have_deadline = false;
|
||||
s_resume_pending = true;
|
||||
|
||||
if (t_s == 0 || p == NULL) {
|
||||
hal_motor_enable(false);
|
||||
@@ -198,10 +194,14 @@ void app_machine_init(void)
|
||||
s_deadline_ms = 0;
|
||||
s_have_deadline = false;
|
||||
s_resume_pending = false;
|
||||
s_auto_advance = false;
|
||||
s_q_head = 0;
|
||||
s_q_tail = 0;
|
||||
s_q_count = 0;
|
||||
s_auto_advance = true;
|
||||
|
||||
if (s_evtq == NULL) {
|
||||
s_evtq = xQueueCreate(UI_EVT_QUEUE_LEN, sizeof(ui_evt_t));
|
||||
} else {
|
||||
xQueueReset(s_evtq);
|
||||
}
|
||||
|
||||
app_process_init();
|
||||
hal_motor_init();
|
||||
hal_temp_init();
|
||||
@@ -230,13 +230,13 @@ uint32_t app_machine_remaining_ms(void)
|
||||
|
||||
int app_machine_last_event(ui_evt_t *out)
|
||||
{
|
||||
if (s_q_count == 0 || out == NULL) {
|
||||
if (s_evtq == NULL || out == NULL) {
|
||||
return 0;
|
||||
}
|
||||
*out = s_q[s_q_head];
|
||||
s_q_head = (uint8_t)((s_q_head + 1u) % UI_EVT_QUEUE_LEN);
|
||||
s_q_count--;
|
||||
return 1;
|
||||
if (xQueueReceive(s_evtq, out, 0) == pdTRUE) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void app_machine_on_temp(float c, bool ok)
|
||||
@@ -336,7 +336,7 @@ void app_machine_handle_cmd(const ui_cmd_t *cmd)
|
||||
enter_armed();
|
||||
} else if (s_state == ST_ARMED) {
|
||||
apply_step_index(cmd->step_index);
|
||||
start_running(0);
|
||||
start_running();
|
||||
} else if (s_state == ST_COMPLETE) {
|
||||
arm_or_next_from_complete();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
set(srcs)
|
||||
set(priv_inc)
|
||||
set(priv_req driver)
|
||||
set(priv_req driver esp_timer)
|
||||
|
||||
if(IDF_TARGET STREQUAL "esp32")
|
||||
list(APPEND srcs hal_temp.c)
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_timer.h"
|
||||
|
||||
#include "onewire_bus.h"
|
||||
#include "board.h"
|
||||
@@ -18,10 +17,24 @@
|
||||
|
||||
static const char *TAG = "temp";
|
||||
|
||||
#define TEMP_CONV_MS 750
|
||||
|
||||
typedef enum {
|
||||
T_START,
|
||||
T_WAIT,
|
||||
} temp_state_t;
|
||||
|
||||
static onewire_bus_handle_t s_bus;
|
||||
static bool s_inited;
|
||||
static float s_last_c;
|
||||
static bool s_last_ok;
|
||||
static temp_state_t s_state = T_START;
|
||||
static uint32_t s_deadline_ms;
|
||||
|
||||
static uint32_t now_ms(void)
|
||||
{
|
||||
return (uint32_t)(esp_timer_get_time() / 1000ULL);
|
||||
}
|
||||
|
||||
static bool scratch_valid(const uint8_t *sp)
|
||||
{
|
||||
@@ -45,38 +58,55 @@ void hal_temp_tick(void)
|
||||
{
|
||||
if (s_bus == NULL) {
|
||||
s_last_ok = false;
|
||||
vTaskDelay(pdMS_TO_TICKS(750));
|
||||
return;
|
||||
}
|
||||
uint32_t now = now_ms();
|
||||
if (s_state == T_START) {
|
||||
if (now < s_deadline_ms) {
|
||||
return;
|
||||
}
|
||||
if (onewire_bus_reset(s_bus) != ESP_OK) {
|
||||
s_last_ok = false;
|
||||
s_deadline_ms = now + TEMP_CONV_MS;
|
||||
return;
|
||||
}
|
||||
uint8_t conv[2] = {CMD_SKIP_ROM, CMD_CONVERT_T};
|
||||
if (onewire_bus_write_bytes(s_bus, conv, 2) != ESP_OK) {
|
||||
s_last_ok = false;
|
||||
s_deadline_ms = now + TEMP_CONV_MS;
|
||||
return;
|
||||
}
|
||||
s_deadline_ms = now + TEMP_CONV_MS;
|
||||
s_state = T_WAIT;
|
||||
return;
|
||||
}
|
||||
/* T_WAIT */
|
||||
if (now < s_deadline_ms) {
|
||||
return;
|
||||
}
|
||||
s_state = T_START;
|
||||
s_deadline_ms = now;
|
||||
if (onewire_bus_reset(s_bus) != ESP_OK) {
|
||||
s_last_ok = false;
|
||||
vTaskDelay(pdMS_TO_TICKS(750));
|
||||
return;
|
||||
}
|
||||
uint8_t conv[2] = {CMD_SKIP_ROM, CMD_CONVERT_T};
|
||||
if (onewire_bus_write_bytes(s_bus, conv, 2) != ESP_OK) {
|
||||
s_last_ok = false;
|
||||
vTaskDelay(pdMS_TO_TICKS(750));
|
||||
return;
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(750));
|
||||
if (onewire_bus_reset(s_bus) != ESP_OK) {
|
||||
s_last_ok = false;
|
||||
s_deadline_ms = now + TEMP_CONV_MS;
|
||||
return;
|
||||
}
|
||||
uint8_t rd[2] = {CMD_SKIP_ROM, CMD_READ_SCRATCH};
|
||||
if (onewire_bus_write_bytes(s_bus, rd, 2) != ESP_OK) {
|
||||
s_last_ok = false;
|
||||
s_deadline_ms = now + TEMP_CONV_MS;
|
||||
return;
|
||||
}
|
||||
uint8_t sp[9];
|
||||
memset(sp, 0, sizeof(sp));
|
||||
if (onewire_bus_read_bytes(s_bus, sp, sizeof(sp)) != ESP_OK) {
|
||||
s_last_ok = false;
|
||||
s_deadline_ms = now + TEMP_CONV_MS;
|
||||
return;
|
||||
}
|
||||
if (!scratch_valid(sp)) {
|
||||
s_last_ok = false;
|
||||
s_deadline_ms = now + TEMP_CONV_MS;
|
||||
return;
|
||||
}
|
||||
int16_t raw = (int16_t)((uint16_t)sp[0] | ((uint16_t)sp[1] << 8));
|
||||
|
||||
@@ -42,10 +42,10 @@ The branch was cut with uncommitted `components/app_machine/app_machine.c` chang
|
||||
| ID | File | Session goal | STATUS |
|
||||
| --- | --- | --- | --- |
|
||||
| A00 | `audit/A00-docs.md` | Land audit doc + megaplan + phase files | DONE |
|
||||
| A01 | `audit/A01-machine-timing-queue.md` | Deadline fix + FreeRTOS event queue + host queue shim | TODO |
|
||||
| A02 | `audit/A02-auto-advance.md` | Restore auto-arm after step complete + test rework | TODO |
|
||||
| A03 | `audit/A03-task-wdt.md` | Explicit TWDT init/reconfigure + `add()` failure logging | TODO |
|
||||
| A04 | `audit/A04-temp-nonblocking.md` | OPTIONAL: non-blocking DS18B20 conversion | TODO |
|
||||
| A01 | `audit/A01-machine-timing-queue.md` | Deadline fix + FreeRTOS event queue + host queue shim | DONE |
|
||||
| A02 | `audit/A02-auto-advance.md` | Restore auto-arm after step complete + test rework | DONE |
|
||||
| A03 | `audit/A03-task-wdt.md` | Explicit TWDT init/reconfigure + `add()` failure logging | DONE |
|
||||
| A04 | `audit/A04-temp-nonblocking.md` | OPTIONAL: non-blocking DS18B20 conversion | DONE |
|
||||
|
||||
## Dependency
|
||||
|
||||
|
||||
@@ -52,6 +52,8 @@ P07 Notes: custom NV3041A QSPI + GT911; shared app_ui text grid + colour softkey
|
||||
|
||||
P08 Notes: LEDC audio; RMT STEP + GPIO DIR/EN; onewire_bus DS18B20 +0.4; GPIO keypad; IDF I2C 2004. Arduino-as-component removed. third_party trees unlinked. host ctest green. idf.py not run here (no IDF_PATH). hw unflashed.
|
||||
|
||||
AUDIT A02 Notes: supersedes the frozen `auto_advance` default-false constraint — `s_auto_advance = true` restores the legacy auto-ARM chain (audit item 3, owner-approved); auto-ARM only, never auto-run.
|
||||
|
||||
## Dependency
|
||||
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# A01 — app_machine deadline fix + FreeRTOS event queue + host queue shim
|
||||
|
||||
STATUS: TODO
|
||||
STATUS: DONE
|
||||
DEPENDS: A00
|
||||
|
||||
**READ:** this file, `docs/megaplans/AUDIT-MEGAPLAN.md`, `docs/audit_remediation_plan.md` items 1–2, `components/app_machine/app_machine.c`, `tests/host/CMakeLists.txt`
|
||||
@@ -37,8 +37,8 @@ All green. Firmware builds run in CI on push.
|
||||
Stage hunks per concern (`git add -p` or re-apply in order) — the dirty file combines all three changes plus the A02 flag.
|
||||
|
||||
**DoD checkboxes:**
|
||||
- [ ] `start_running` takes no `now_ms`; deadline set on the first `RUNNING` tick.
|
||||
- [ ] `emit`/`app_machine_last_event` go through `s_evtq`; `app_machine_init` creates or resets the queue.
|
||||
- [ ] `s_auto_advance` still `false`.
|
||||
- [ ] Host ctest green with zero test changes.
|
||||
- [ ] STATUS → DONE here and in the megaplan table.
|
||||
- [x] `start_running` takes no `now_ms`; deadline set on the first `RUNNING` tick.
|
||||
- [x] `emit`/`app_machine_last_event` go through `s_evtq`; `app_machine_init` creates or resets the queue.
|
||||
- [x] `s_auto_advance` still `false`.
|
||||
- [x] Host ctest green with zero test changes.
|
||||
- [x] STATUS → DONE here and in the megaplan table.
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
# A02 — restore auto-advance (auto-arm next step after complete)
|
||||
|
||||
STATUS: TODO
|
||||
STATUS: DONE
|
||||
DEPENDS: A01
|
||||
Notes: `stop_disables_motor_and_resume` final assertion updated to `ST_ARMED` — the "unchanged" list cannot hold once auto-advance is on (resume-to-complete auto-arms step 1).
|
||||
|
||||
**READ:** this file, `docs/megaplans/AUDIT-MEGAPLAN.md`, `docs/audit_remediation_plan.md` item 3, `docs/CURRENT_STATE.md` §Runtime behaviour, `components/app_machine/app_machine.c`, `tests/host/test_machine.c`
|
||||
|
||||
@@ -34,9 +35,9 @@ All green, including the new `auto_advance_last_step_goes_idle`. Firmware builds
|
||||
2. `Update machine tests for auto-advance`
|
||||
|
||||
**DoD checkboxes:**
|
||||
- [ ] `s_auto_advance = true`; auto-ARM only, never auto-run.
|
||||
- [ ] Last step completes → `ST_IDLE` + `EVT_PROCESS_IDLE`.
|
||||
- [ ] `ST_COMPLETE` + `CMD_STOP` branch retained.
|
||||
- [ ] REFACTOR-MEGAPLAN supersede note added.
|
||||
- [ ] Host ctest green.
|
||||
- [ ] STATUS → DONE here and in the megaplan table.
|
||||
- [x] `s_auto_advance = true`; auto-ARM only, never auto-run.
|
||||
- [x] Last step completes → `ST_IDLE` + `EVT_PROCESS_IDLE`.
|
||||
- [x] `ST_COMPLETE` + `CMD_STOP` branch retained.
|
||||
- [x] REFACTOR-MEGAPLAN supersede note added.
|
||||
- [x] Host ctest green.
|
||||
- [x] STATUS → DONE here and in the megaplan table.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# A03 — explicit task watchdog setup in app_main
|
||||
|
||||
STATUS: TODO
|
||||
STATUS: DONE
|
||||
DEPENDS: A00 (independent of A01/A02 — `main/main.c` only)
|
||||
|
||||
**READ:** this file, `docs/megaplans/AUDIT-MEGAPLAN.md`, `docs/audit_remediation_plan.md` item 4, `main/main.c`, `sdkconfig.defaults`
|
||||
@@ -53,8 +53,8 @@ cmake -S tests/host -B build/host && cmake --build build/host && ctest --test-di
|
||||
1. `Make task watchdog setup explicit in app_main`
|
||||
|
||||
**DoD checkboxes:**
|
||||
- [ ] init-or-reconfigure runs before task creation.
|
||||
- [ ] `esp_task_wdt_add` failures are logged in all four tasks.
|
||||
- [ ] Effective config unchanged: 10 s timeout, CPU0 idle watched, no panic.
|
||||
- [ ] Both CI firmware builds green.
|
||||
- [ ] STATUS → DONE here and in the megaplan table.
|
||||
- [x] init-or-reconfigure runs before task creation.
|
||||
- [x] `esp_task_wdt_add` failures are logged in all four tasks.
|
||||
- [x] Effective config unchanged: 10 s timeout, CPU0 idle watched, no panic.
|
||||
- [x] Both CI firmware builds green.
|
||||
- [x] STATUS → DONE here and in the megaplan table.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# A04 — (OPTIONAL) non-blocking DS18B20 conversion in hal_temp
|
||||
|
||||
STATUS: TODO (OPTIONAL — may be deferred indefinitely; if skipped, A03's explicit WDT setup already covers the constraint)
|
||||
STATUS: DONE
|
||||
DEPENDS: A03 (shares `temp_task` in `main/main.c`)
|
||||
|
||||
**READ:** this file, `docs/megaplans/AUDIT-MEGAPLAN.md`, `docs/audit_remediation_plan.md` item 5, `components/hal_temp/hal_temp.c`, `main/main.c`
|
||||
@@ -30,8 +30,8 @@ plus CI firmware builds for both targets.
|
||||
1. `Make DS18B20 conversion non-blocking in hal_temp`
|
||||
|
||||
**DoD checkboxes:**
|
||||
- [ ] No `vTaskDelay(750)` inside `hal_temp_tick`; conversion waits via deadline.
|
||||
- [ ] `temp_task` always blocks (explicit 100 ms delay).
|
||||
- [ ] `TEMP_OFFSET`, CRC, and read semantics unchanged.
|
||||
- [ ] Host ctest green; both CI firmware builds green.
|
||||
- [ ] STATUS → DONE here and in the megaplan table (or noted `SKIPPED` with reason).
|
||||
- [x] No `vTaskDelay(750)` inside `hal_temp_tick`; conversion waits via deadline.
|
||||
- [x] `temp_task` always blocks (explicit 100 ms delay).
|
||||
- [x] `TEMP_OFFSET`, CRC, and read semantics unchanged.
|
||||
- [x] Host ctest green; both CI firmware builds green.
|
||||
- [x] STATUS → DONE here and in the megaplan table (or noted `SKIPPED` with reason).
|
||||
|
||||
+45
-4
@@ -97,7 +97,10 @@ static void map_and_post_key(char key)
|
||||
static void input_task(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
esp_task_wdt_add(NULL);
|
||||
esp_err_t werr = esp_task_wdt_add(NULL);
|
||||
if (werr != ESP_OK) {
|
||||
ESP_LOGW(TAG, "input wdt add failed: %s", esp_err_to_name(werr));
|
||||
}
|
||||
const TickType_t period = pdMS_TO_TICKS(40); /* 25 Hz */
|
||||
for (;;) {
|
||||
ui_raw_key_t raw;
|
||||
@@ -119,7 +122,10 @@ static void input_task(void *arg)
|
||||
static void machine_task(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
esp_task_wdt_add(NULL);
|
||||
esp_err_t werr = esp_task_wdt_add(NULL);
|
||||
if (werr != ESP_OK) {
|
||||
ESP_LOGW(TAG, "machine wdt add failed: %s", esp_err_to_name(werr));
|
||||
}
|
||||
const TickType_t period = pdMS_TO_TICKS(20); /* 50 Hz */
|
||||
for (;;) {
|
||||
ui_cmd_t cmd;
|
||||
@@ -136,7 +142,10 @@ static void machine_task(void *arg)
|
||||
static void ui_task(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
esp_task_wdt_add(NULL);
|
||||
esp_err_t werr = esp_task_wdt_add(NULL);
|
||||
if (werr != ESP_OK) {
|
||||
ESP_LOGW(TAG, "ui wdt add failed: %s", esp_err_to_name(werr));
|
||||
}
|
||||
|
||||
hal_display_clear();
|
||||
hal_display_text(0, 0, "AUTOFILM");
|
||||
@@ -164,13 +173,17 @@ static void ui_task(void *arg)
|
||||
static void temp_task(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
esp_task_wdt_add(NULL);
|
||||
esp_err_t werr = esp_task_wdt_add(NULL);
|
||||
if (werr != ESP_OK) {
|
||||
ESP_LOGW(TAG, "temp wdt add failed: %s", esp_err_to_name(werr));
|
||||
}
|
||||
for (;;) {
|
||||
hal_temp_tick();
|
||||
float c = 0.0f;
|
||||
bool ok = (hal_temp_read_c(&c) == ESP_OK);
|
||||
app_machine_on_temp(ok ? c : 0.0f, ok);
|
||||
esp_task_wdt_reset();
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -205,6 +218,34 @@ void app_main(void)
|
||||
|
||||
s_cmdq = xQueueCreate(UI_CMD_QUEUE_LEN, sizeof(ui_cmd_t));
|
||||
|
||||
#if CONFIG_ESP_TASK_WDT_EN
|
||||
esp_task_wdt_config_t wdt_cfg = {
|
||||
.timeout_ms = CONFIG_ESP_TASK_WDT_TIMEOUT_S * 1000,
|
||||
.idle_core_mask =
|
||||
#if CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0
|
||||
(1u << 0)
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
#if CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1
|
||||
| (1u << 1)
|
||||
#endif
|
||||
,
|
||||
#if CONFIG_ESP_TASK_WDT_PANIC
|
||||
.trigger_panic = true,
|
||||
#else
|
||||
.trigger_panic = false,
|
||||
#endif
|
||||
};
|
||||
esp_err_t wdt_err = esp_task_wdt_init(&wdt_cfg);
|
||||
if (wdt_err == ESP_ERR_INVALID_STATE) {
|
||||
wdt_err = esp_task_wdt_reconfigure(&wdt_cfg); /* already auto-initialised */
|
||||
}
|
||||
if (wdt_err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "task wdt setup: %s", esp_err_to_name(wdt_err));
|
||||
}
|
||||
#endif
|
||||
|
||||
xTaskCreate(temp_task, "temp", 4096, NULL, 2, NULL);
|
||||
xTaskCreate(input_task, "input", 3072, NULL, 8, NULL);
|
||||
xTaskCreate(machine_task, "machine", 4096, NULL, 6, NULL);
|
||||
|
||||
@@ -37,6 +37,7 @@ add_executable(test_machine
|
||||
stubs/hal_motor.c
|
||||
stubs/hal_temp.c
|
||||
stubs/hal_audio.c
|
||||
freertos/queue.c
|
||||
)
|
||||
|
||||
target_include_directories(test_machine PRIVATE ${HOST_INCLUDES})
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
typedef uint32_t TickType_t;
|
||||
|
||||
#define pdFALSE ((BaseType_t)0)
|
||||
#define pdTRUE ((BaseType_t)1)
|
||||
#define pdPASS pdTRUE
|
||||
#define pdFAIL pdFALSE
|
||||
|
||||
#define pdMS_TO_TICKS(xTimeInMs) ((TickType_t)(xTimeInMs))
|
||||
@@ -0,0 +1,72 @@
|
||||
#include "freertos/queue.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct QueueDefinition {
|
||||
UBaseType_t len;
|
||||
UBaseType_t item_size;
|
||||
UBaseType_t head;
|
||||
UBaseType_t tail;
|
||||
UBaseType_t count;
|
||||
uint8_t *storage;
|
||||
};
|
||||
|
||||
QueueHandle_t xQueueCreate(UBaseType_t uxQueueLength, UBaseType_t uxItemSize)
|
||||
{
|
||||
struct QueueDefinition *q = calloc(1, sizeof(*q));
|
||||
if (q == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
q->storage = malloc((size_t)uxQueueLength * uxItemSize);
|
||||
if (q->storage == NULL) {
|
||||
free(q);
|
||||
return NULL;
|
||||
}
|
||||
q->len = uxQueueLength;
|
||||
q->item_size = uxItemSize;
|
||||
return q;
|
||||
}
|
||||
|
||||
BaseType_t xQueueSend(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait)
|
||||
{
|
||||
(void)xTicksToWait;
|
||||
if (xQueue == NULL || pvItemToQueue == NULL) {
|
||||
return pdFALSE;
|
||||
}
|
||||
if (xQueue->count == xQueue->len) {
|
||||
return pdFALSE;
|
||||
}
|
||||
memcpy(xQueue->storage + (size_t)xQueue->tail * xQueue->item_size,
|
||||
pvItemToQueue, xQueue->item_size);
|
||||
xQueue->tail = (xQueue->tail + 1u) % xQueue->len;
|
||||
xQueue->count++;
|
||||
return pdTRUE;
|
||||
}
|
||||
|
||||
BaseType_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait)
|
||||
{
|
||||
(void)xTicksToWait;
|
||||
if (xQueue == NULL || pvBuffer == NULL) {
|
||||
return pdFALSE;
|
||||
}
|
||||
if (xQueue->count == 0u) {
|
||||
return pdFALSE;
|
||||
}
|
||||
memcpy(pvBuffer, xQueue->storage + (size_t)xQueue->head * xQueue->item_size,
|
||||
xQueue->item_size);
|
||||
xQueue->head = (xQueue->head + 1u) % xQueue->len;
|
||||
xQueue->count--;
|
||||
return pdTRUE;
|
||||
}
|
||||
|
||||
BaseType_t xQueueReset(QueueHandle_t xQueue)
|
||||
{
|
||||
if (xQueue == NULL) {
|
||||
return pdFALSE;
|
||||
}
|
||||
xQueue->head = 0;
|
||||
xQueue->tail = 0;
|
||||
xQueue->count = 0;
|
||||
return pdTRUE;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
|
||||
struct QueueDefinition;
|
||||
typedef struct QueueDefinition *QueueHandle_t;
|
||||
|
||||
QueueHandle_t xQueueCreate(UBaseType_t uxQueueLength, UBaseType_t uxItemSize);
|
||||
BaseType_t xQueueSend(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait);
|
||||
BaseType_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait);
|
||||
BaseType_t xQueueReset(QueueHandle_t xQueue);
|
||||
+17
-17
@@ -145,12 +145,10 @@ static void arm_start_complete_custom_10s(void)
|
||||
app_machine_tick(9999);
|
||||
expect_int((int)app_machine_state(), ST_RUNNING, "custom tick9999");
|
||||
app_machine_tick(10000);
|
||||
expect_int((int)app_machine_state(), ST_COMPLETE, "custom complete");
|
||||
expect_int((int)app_machine_state(), ST_ARMED, "custom auto-armed next");
|
||||
expect_int((int)app_machine_step_index(), 1, "custom auto-advance step");
|
||||
expect_int(stub_motor_enabled ? 1 : 0, 0, "custom motor off complete");
|
||||
expect_int(stub_alarm_count >= 1 ? 1 : 0, 1, "custom alarm");
|
||||
/* default auto_advance false */
|
||||
app_machine_tick(10001);
|
||||
expect_int((int)app_machine_state(), ST_COMPLETE, "auto_advance stays complete");
|
||||
}
|
||||
|
||||
static void stop_disables_motor_and_resume(void)
|
||||
@@ -182,7 +180,7 @@ static void stop_disables_motor_and_resume(void)
|
||||
expect_int(stub_beep_count >= beeps + 1 ? 1 : 0, 1, "resume beep");
|
||||
app_machine_tick(1000);
|
||||
app_machine_tick(1000 + rem);
|
||||
expect_int((int)app_machine_state(), ST_COMPLETE, "resume then complete");
|
||||
expect_int((int)app_machine_state(), ST_ARMED, "resume then auto-armed");
|
||||
}
|
||||
|
||||
static void return_from_stopped(void)
|
||||
@@ -208,23 +206,23 @@ static void return_from_stopped(void)
|
||||
expect_int((int)app_process_get(PROC_CUSTOM)->steps[0].time_s, 10, "const still 10");
|
||||
}
|
||||
|
||||
static void stop_during_complete_cancels_alarm(void)
|
||||
static void auto_advance_last_step_goes_idle(void)
|
||||
{
|
||||
app_machine_init();
|
||||
ui_cmd_t c = cmd_select(PROC_CUSTOM);
|
||||
app_machine_handle_cmd(&c);
|
||||
ui_cmd_t arm = cmd_arm(0);
|
||||
ui_cmd_t arm = cmd_arm(3);
|
||||
app_machine_handle_cmd(&arm);
|
||||
ui_cmd_t start = cmd_start(0);
|
||||
ui_cmd_t start = cmd_start(3);
|
||||
app_machine_handle_cmd(&start);
|
||||
app_machine_tick(0);
|
||||
app_machine_tick(10000);
|
||||
expect_int((int)app_machine_state(), ST_COMPLETE, "complete before stop");
|
||||
int cancels = stub_alarm_cancel_count;
|
||||
ui_cmd_t stop = cmd_id(CMD_STOP);
|
||||
app_machine_handle_cmd(&stop);
|
||||
expect_int((int)app_machine_state(), ST_STEP_SELECT, "stop from complete");
|
||||
expect_int(stub_alarm_cancel_count >= cancels + 1 ? 1 : 0, 1, "alarm cancel");
|
||||
expect_int((int)app_machine_state(), ST_IDLE, "last step goes idle");
|
||||
ui_evt_id_t ids[8];
|
||||
int n = pop_ids(ids, 8);
|
||||
if (!has_id(ids, n, EVT_PROCESS_IDLE)) {
|
||||
fail("last step idle event");
|
||||
}
|
||||
}
|
||||
|
||||
static void ecn2_remjet_zero_time(void)
|
||||
@@ -246,7 +244,8 @@ static void ecn2_remjet_zero_time(void)
|
||||
expect_int(stub_motor_enabled ? 1 : 0, 0, "remjet no enable");
|
||||
expect_int(stub_agitate_start_count, starts, "remjet no agitate");
|
||||
app_machine_tick(0);
|
||||
expect_int((int)app_machine_state(), ST_COMPLETE, "remjet complete next tick");
|
||||
expect_int((int)app_machine_state(), ST_ARMED, "remjet auto-armed next");
|
||||
expect_int((int)app_machine_step_index(), 2, "remjet auto-advance step");
|
||||
}
|
||||
|
||||
static void stop_ignored_meaningless_in_idle(void)
|
||||
@@ -275,7 +274,8 @@ static void c41_clock(void)
|
||||
app_machine_tick(179999);
|
||||
expect_int((int)app_machine_state(), ST_RUNNING, "c41 tick179999");
|
||||
app_machine_tick(180000);
|
||||
expect_int((int)app_machine_state(), ST_COMPLETE, "c41 tick180000");
|
||||
expect_int((int)app_machine_state(), ST_ARMED, "c41 auto-armed next");
|
||||
expect_int((int)app_machine_step_index(), 1, "c41 auto-advance step");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
@@ -285,7 +285,7 @@ int main(void)
|
||||
arm_start_complete_custom_10s();
|
||||
stop_disables_motor_and_resume();
|
||||
return_from_stopped();
|
||||
stop_during_complete_cancels_alarm();
|
||||
auto_advance_last_step_goes_idle();
|
||||
ecn2_remjet_zero_time();
|
||||
stop_ignored_meaningless_in_idle();
|
||||
c41_clock();
|
||||
|
||||
Reference in New Issue
Block a user