|
rcbench
Servo and ESC test bench: panel, IOmcu and shared C
|
The panel's Wi-Fi over esp_wifi, esp_http_server, esp_http_client and a UDP (user datagram protocol) socket for the mDNS name. More...
#include "wifi_access.h"#include <fcntl.h>#include <stdatomic.h>#include <stdio.h>#include <string.h>#include <strings.h>#include <unistd.h>#include "esp_crt_bundle.h"#include "esp_event.h"#include "esp_http_client.h"#include "esp_http_server.h"#include "esp_heap_caps.h"#include "esp_log.h"#include "esp_netif.h"#include "esp_random.h"#include "esp_timer.h"#include "esp_wifi.h"#include "freertos/FreeRTOS.h"#include "freertos/semphr.h"#include "freertos/task.h"#include "lwip/inet.h"#include "lwip/sockets.h"#include "nvs.h"#include "storage.h"#include "wa_mdns.h"#include "wa_page.h"#include "wa_send.h"#include "wifi_dns.h"#include "wifi_ntp.h"#include "wifi_radio.h"#include "wifi_req.h"#include "wifi_sock.h"#include "wa_text.h"#include "wa_walk.h"#include "wa_zip.h"#include "wall_clock.h"Data Structures | |
| struct | bufs_t |
| struct | http_ctx_t |
| struct | [struct].s |
| Driver state of the UART: the claimed machines and the pins. More... | |
Macros | |
| #define | NVS_NS "wifi" |
| #define | WORKER_STACK 6912u |
| Stack of the wifi_ctl task, in bytes, from internal RAM. The deepest call chain, the radio stop down to snprintf(), is 3744 bytes; 6912 leaves 2144 above tools/stack_check.py's 1024-byte margin. | |
| #define | MDNS_STACK 4096u |
| #define | HTTPD_STACK 8192u |
| #define | HTTPD_WAIT_S 5u |
| A receive or a send of the page's server waits this long at a time, s: esp_http_server's own default (HTTPD_DEFAULT_CONFIG()), written out. A request whose client goes quiet for it ends. | |
| #define | UPLOAD_WAITS 6u |
| Waits of HTTPD_WAIT_S an upload rides out: 30s quiet. | |
| #define | NET_PRIORITY 1u |
| #define | WORKER_PRIO 2u |
| #define | NET_CORE 0 |
| #define | IO_CHUNK 4096u |
| #define | SCAN_READ 24u |
| #define | FETCH_STACK 8192u |
| #define | FETCH_SLICE_MS 1000u |
| #define | FETCH_GRACE_MS 1500u |
| The radio goes off after this much, task ended or not, ms. A connection ends with the radio; a name lookup only when lwIP gives up on it, up to about 7s a DNS server, and the radio does not wait for that (wa_fetch_start_gate()). | |
| #define | FETCH_AGENT "rcbench-panel" |
| #define | DRAIN_MS 2000u |
| How long the worker waits for the event loop to pass the radio's last events at its stop (drain()), ms. | |
Functions | |
| ESP_EVENT_DEFINE_BASE (WA_DRAIN_EVENT) | |
| The worker's marker in the default event loop (drain()). | |
| static uint32_t | ms (void) |
| static void | lock (void) |
| static void | unlock (void) |
| static void | poke (void) |
| static uint32_t | rand32 (void *ctx) |
| static bool | nvs_conf_load (void *ctx, wa_conf_t *out) |
| static bool | nvs_conf_save (void *ctx, const wa_conf_t *c) |
| static bool | nvs_conf_erase (void *ctx) |
| static size_t | card_path (char *out, size_t cap, const char *rel) |
| static bool | card_stopped (void *ctx) |
| wa_fs_t.stopped(): a request under way ends now (s.abort). | |
| static void * | card_opendir (void *ctx, const char *path) |
| static int | card_readdir (void *ctx, void *dir, wa_dirent_t *out) |
| static void | card_closedir (void *ctx, void *dir) |
| static void * | card_open (void *ctx, const char *path) |
| static int32_t | card_read (void *ctx, void *file, uint8_t *dst, uint32_t len) |
| static void | card_close (void *ctx, void *file) |
| static bool | req_begin (void) |
| static void | req_end (void) |
| static bool | req_guard (httpd_req_t *r, wa_req_kind_t kind, esp_err_t *e) |
| wifi_req_guard() before anything else of a handler's. | |
| static wa_code_t | req_code (httpd_req_t *r) |
| static void | page_info (wa_page_info_t *pi) |
| static bool | sink_chunk (void *ctx, const void *data, size_t n) |
| static esp_err_t | send_page (httpd_req_t *r, bool code_form, bool wrong) |
| static esp_err_t | closed (httpd_req_t *r) |
| static esp_err_t | h_root (httpd_req_t *r) |
| static esp_err_t | h_code (httpd_req_t *r) |
| static esp_err_t | refused (httpd_req_t *r, const char *status) |
| static bool | upload_text (void *ctx, const void *data, size_t n) |
| static esp_err_t | answer_upload (httpd_req_t *r, fw_err_t e, const fw_image_info_t *info, bool same, bool cut) |
| static esp_err_t | h_update (httpd_req_t *r) |
| static wa_send_res_t | raw_send (httpd_req_t *r, const void *data, size_t n) |
| static wa_send_res_t | raw_head (httpd_req_t *r, uint64_t length, const char *name) |
| static esp_err_t | h_file (httpd_req_t *r) |
| static esp_err_t | h_zip (httpd_req_t *r) |
| GET /card.zip: the whole card as one ZIP archive, its length announced before the first byte. | |
| static esp_err_t | httpd_up (void) |
| static void | mdns_task (void *arg) |
| static esp_err_t | on_http (esp_http_client_event_t *e) |
| static void | h_close (void *ctx) |
| static bool | h_open (void *ctx, const char *url, uint32_t timeout_ms, bool api, wa_http_head_t *head, char *loc, size_t loc_cap) |
| static int32_t | h_read (void *ctx, uint8_t *dst, uint32_t n, uint32_t timeout_ms) |
| static uint32_t | f_now (void *ctx) |
| static bool | f_stopped (void *ctx) |
| static void | f_report (void *ctx, wa_phase_t ph, uint32_t done, uint32_t total) |
| static uint8_t * | f_alloc (void *ctx, uint32_t bytes) |
| static void | fetch_task (void *arg) |
| static bool | auth_refused (uint8_t reason) |
| static void | scan_start (uint32_t tok, unsigned run) |
Start the scan of tok, all channels, the driver's default times, while it is still the scan under way; a refusal ends the session WA_OFF_FAILED only while it still is. | |
| static void | on_scan_done (const wifi_event_sta_scan_done_t *d) |
| WIFI_EVENT_SCAN_DONE in a scan session: read the list of the scan under way, or start it again, or end the session. | |
| static void | on_event (void *arg, esp_event_base_t base, int32_t id, void *data) |
| static void | start_failed (const char *step, esp_err_t e) |
| static void | on_drain (void *arg, esp_event_base_t base, int32_t id, void *data) |
| The marker drain() posts: every event posted before it is handled. | |
| static void | drain (void) |
| Wait, DRAIN_MS at most, until the event loop has handled every event the radio posted before its stop. | |
| static bool | net_once (void) |
| static bool | fetch_wait (uint32_t wait_ms) |
| static void | radio_down (void) |
| Take the radio down: mDNS, the fetch, the page's server, the driver and the interface. | |
| static bool | radio_bring_up (wa_mode_t mode, const wa_t *w, const wa_conf_t *c) |
Bring the radio up in mode: the C6's link, the interface, the driver, the configuration and, in AP and JOIN, the page's server. | |
| static void | radio_hold (void) |
| Keep the radio up past its session's end for the clock's NTP answer (wifi_ntp.h): the page's requests under way and the mDNS name end now, the station and the interface stay until radio_down(). Logged once a radio. | |
| static void | worker (void *arg) |
| The task that owns the radio: compares what the session wants with what runs, and brings the radio up or down; a failed C6 link takes it down. A session that ended and lingers (wa_lingers()) keeps the radio while the clock's NTP request asks. | |
| esp_err_t | wifi_access_init (uint32_t slot, const fw_image_info_t *running) |
| void | wifi_access_set_german (bool de) |
| wa_off_t | wifi_access_start (wa_mode_t mode, wa_off_t gate) |
| void | wifi_access_close (wa_off_t why) |
Radio off for why; see wa_close(). | |
| bool | wifi_access_tick (wa_off_t gate, bool stop, bool may_write) |
Once a frame: the gate, STOP pressed since the last call, the time-outs; and a change to what is kept written when may_write. | |
| void | wifi_access_get (wifi_access_state_t *out) |
| bool | wifi_access_down (void) |
| Whether the radio is wholly off and no start of it is asked for; from any task, without the lock. | |
| void | wifi_access_end_linger (void) |
| The radio goes off without waiting for the clock's NTP answer: a session that ended and lingers (wa_lingers()) stops lingering; one that runs goes on. From any task, without the lock. | |
| bool | wifi_access_save_net (const char *ssid, const char *pass) |
| void | wifi_access_forget (void) |
| void | wifi_access_set_code (bool on) |
| void | wifi_access_discard (void) |
| bool | wifi_access_take (const uint8_t **img, uint32_t *bytes, fw_image_info_t *info) |
| void | wifi_access_release (void) |
| wa_got_t | wifi_access_fetch_start (wa_job_t job, fw_version_t want, wa_channel_t ch, wa_why_t gate) |
| void | wifi_access_fetch_tick (wa_why_t abort) |
| void | wifi_access_fetch_get (wa_fetch_t *out) |
| bool | wifi_access_home (char *ssid, size_t n) |
Variables | |
| static const char * | TAG = "wifi" |
| static struct | s |
| static bufs_t * | b |
| static const wa_store_t | k_store |
| static const wa_fs_t | k_card |
| static http_ctx_t | s_http |
| static const wa_http_t | k_http = { h_open, h_read, h_close, &s_http } |
The panel's Wi-Fi over esp_wifi, esp_http_server, esp_http_client and a UDP (user datagram protocol) socket for the mDNS name.
The radio under esp_wifi is the board's ESP32-C6 on SDIO, brought up by wifi_radio.h.
Three tasks touch the session: the UI loop (start, close, tick), the event loop (what the radio reports) and the HTTP server (requests). Everything they share is under one mutex, held for copies and counters only, never across a socket or a card read. A fourth task, the worker, owns bringing the radio up and down: it compares what the session wants with what runs and acts, so a stop that waits for a download to end never waits on the UI loop. A fifth, the fetch task, runs one job's requests to GitHub (wa_fetch.h) and ends with it.
SPDX-License-Identifier: MIT
|
static |
wa_fs_t.stopped(): a request under way ends now (s.abort).
| ctx | unused |
|
static |
Wait, DRAIN_MS at most, until the event loop has handled every event the radio posted before its stop.
Binds each scan's done report to its radio: the next radio's station start, which starts its scan (wa_scan_begin()), comes after the marker, so a done report of the radio taken down is never read as the next one's.
|
static |
GET /card.zip: the whole card as one ZIP archive, its length announced before the first byte.
| r | the request |
|
static |
The marker drain() posts: every event posted before it is handled.
| arg | Unused. |
| base | WA_DRAIN_EVENT. |
| id | Unused. |
| data | Unused. |
|
static |
WIFI_EVENT_SCAN_DONE in a scan session: read the list of the scan under way, or start it again, or end the session.
A done report with no scan of this session under way reads nothing: its list, if any, goes with the driver at the radio's stop. A failed scan, a list that cannot be read and a read that does not hold what the report counts each count as a failure (wa_scan_read_ok()), never as an empty list. The scan's token carries the report through the read, which runs without the lock.
| d | The event's data; NULL reads as a success that counts nothing. |
Bring the radio up in mode: the C6's link, the interface, the driver, the configuration and, in AP and JOIN, the page's server.
| mode | The session's mode. |
| w | The session, for the access point's password. |
| c | The kept home network, for JOIN and FETCH. |
|
static |
Take the radio down: mDNS, the fetch, the page's server, the driver and the interface.
The fetch task gets FETCH_GRACE_MS. One still in a name lookup after it is not waited for: the radio counts as down once the interface is gone, and the task ends when lwIP gives up on the lookup. It reads no state the radio's end frees, its report is dropped by the job's generation, and no job starts while it lives (wa_fetch_start_gate()). A lookup that a next session's station answers leads to one connection over it, whose result is dropped; f_stopped() ends the job before any further request.
After a failed C6 link, esp_wifi_stop() and esp_wifi_deinit() are not called: each is a request to the C6, which is held in reset then, and would end only at esp_hosted's response time-out, 5s each.
|
static |
wifi_req_guard() before anything else of a handler's.
| r | the request |
| kind | what it is |
| e | takes the handler's return on a refusal |
|
static |
Start the scan of tok, all channels, the driver's default times, while it is still the scan under way; a refusal ends the session WA_OFF_FAILED only while it still is.
Called with the lock not held, from the event loop: the request goes to the C6 and waits for its answer, and a session can end and another start meanwhile (wa_scan_begin()).
| tok | The scan's token. |
| run | The scan's number in the session, from 1. |
| void wifi_access_close | ( | wa_off_t | why | ) |
Radio off for why; see wa_close().
| why | The reason. |
| void wifi_access_discard | ( | void | ) |
Drop a received or staged image. Nothing while one is taken.
| bool wifi_access_down | ( | void | ) |
Whether the radio is wholly off and no start of it is asked for; from any task, without the lock.
A start asked for counts as up from the call on, a close until the station or access point is stopped and its interface is gone. A GitHub fetch task still in a name lookup then does not hold it up: it sends nothing while the radio stays off, and no fetch job starts before it ends.
| void wifi_access_fetch_get | ( | wa_fetch_t * | out | ) |
The job, as a copy.
| wa_got_t wifi_access_fetch_start | ( | wa_job_t | job, |
| fw_version_t | want, | ||
| wa_channel_t | ch, | ||
| wa_why_t | gate ) |
Start job (wa_fetch_start()) for release want (DOWNLOAD only) on channel ch (CHECK: which releases it looks at) unless gate says why not. WA_GOT_NONE: the radio comes up in WA_MODE_FETCH and the job runs; otherwise it has ended at once. A DOWNLOAD drops an image the page left staged first; while one is taken, or the last job's task has not ended yet, it is BLOCKED for BUSY. Refused on a session another screen runs: the caller starts no job while WI-FI is open.
| void wifi_access_fetch_tick | ( | wa_why_t | abort | ) |
Once a frame, after wifi_access_tick(): abort as wa_fetch_tick() takes it. Moves the job on, ends it, switches the radio off when it has ended, and starts the task that talks to GitHub once joined.
| void wifi_access_forget | ( | void | ) |
FORGET: no home network, the access code on.
| bool wifi_access_home | ( | char * | ssid, |
| size_t | n ) |
Whether a home network is kept, and its name into ssid of n bytes (empty for none).
| esp_err_t wifi_access_init | ( | uint32_t | slot, |
| const fw_image_info_t * | running ) |
Read the kept home network and set up the task. slot is the largest image taken, running the build that runs. The radio stays off. On a failure nothing is kept, and no other call of this file may be made: the panel runs without Wi-Fi until the next start.
| void wifi_access_release | ( | void | ) |
After a write that failed: the image is dropped.
| bool wifi_access_save_net | ( | const char * | ssid, |
| const char * | pass ) |
Keep a home network; false when wa_conf_set_net() refuses it.
| void wifi_access_set_german | ( | bool | de | ) |
The page's language.
Start in mode unless gate says why not; see wa_start().
| bool wifi_access_take | ( | const uint8_t ** | img, |
| uint32_t * | bytes, | ||
| fw_image_info_t * | info ) |
Take the staged image for the installer: it stays where it is, and nothing drops it, until wifi_access_release(). False when none waits.
| bool wifi_access_tick | ( | wa_off_t | gate, |
| bool | stop, | ||
| bool | may_write ) |
Once a frame: the gate, STOP pressed since the last call, the time-outs; and a change to what is kept written when may_write.
| gate | wa_gate()'s answer. |
| stop | STOP pressed since the last call. |
| may_write | Flash may be written now. |
|
static |
The task that owns the radio: compares what the session wants with what runs, and brings the radio up or down; a failed C6 link takes it down. A session that ended and lingers (wa_lingers()) keeps the radio while the clock's NTP request asks.
| arg | Unused. |
|
static |
|
static |