|
rcbench
Servo and ESC test bench: panel, IOmcu and shared C
|
The IOmcu application. More...
#include <stdio.h>#include <string.h>#include "pico/stdlib.h"#include "iomcu.h"#include "iomcu_pins.h"#include "bench_state.h"#include "dshot.h"#include "flash_gate.h"#include "out_bind.h"#include "rcbench_version.h"#include "out_stage.h"#include "outputs_pages.h"#include "pd_uart.h"#include "sense_limit.h"#include "sense_map.h"#include "tone_core1.h"#include "update_hw.h"#include "xl2515.h"#include "sense_trace_hw.h"#include "console_hw.h"Macros | |
| #define | IOMCU_SAY console_hw_say |
| This file's report lines. | |
Functions | |
| static bool | sense_capture_open (void) |
| Whether the page holds a capture that has not finished. | |
| static void | sample (void) |
| Takes one 50Hz sample of the bench readings and publishes them. | |
| static void | outputs_off (void) |
| The failsafe edge: disarm the one bank every output goes through, then bring the pages into line with it so what the panel reads back is what the bank holds. | |
| static bool | flash_busy (void) |
| Whether flash may not be written now: flash_gate_busy(), host-tested, with this end's four inputs. | |
| int | main (void) |
| Boots the IOmcu, then runs the main loop. | |
Variables | |
| iomcu_state_t | s_state |
| What iomcu.h declares and describes. | |
| servo_page_t | s_servo |
| The SERVO page: the PWM target's frame rate and the sweep. | |
| supply_page_t | s_supply |
| pdmini_t | s_pd |
| bool | s_pd_open |
| uint8_t | s_pd_rate |
| bool | s_supply_unsaved |
| Wiring taken and not yet in flash: no ON until it is, so a restart in the run finds the wiring that drives the module and can switch it off. | |
| bool | s_supply_attach |
| New wiring taken, the UART to attach once it is saved. | |
| sense_page_t | s_sense |
| The SENSE and SERVO_SENSE pages: the current monitors' set-up, kept, and the pins it holds. | |
| tone_page_t | s_tone |
| The TONE page: the phase tap's set-up, kept, and the beeps core 1 hears on it. | |
| sense_snap_t | s_sense_snap |
| Core 1's last snapshot. | |
| sense_cmd_t | s_sense_cmd |
| uint16_t | s_run_gen |
| Moves on each edge of the bank into driving: core 1 starts the run's peaks and the INA228's totals on it. | |
| bool | s_edge_set |
| The capture's PWM edge, stamped by outputs_hw for capture order s_edge_gen. | |
| uint16_t | s_edge_gen |
| uint64_t | s_edge_us |
| uint64_t | s_base_reserved |
| What the board and this application hold, before the supply and the sensor bus take their pins. | |
| prog_port_t | s_prog |
| The PROG page: the programming ports, outputs of their own kind with their own pins (shared/outputs/prog_port.h). | |
| kst_port_t | s_kst |
| The KST page: the wire protocol for KST and Chaservo servos on a programming port (shared/outputs/kst_port.h) and the wire driver the port's pin is handed to (protocols/kst/rp2350). | |
| kst_line_t | s_kst_line |
| hitec_port_t | s_hitec |
| The HITEC page: raw transactions of the Hitec wire on a programming port (shared/outputs/hitec_port.h) and the wire driver the port's pin is handed to (protocols/hitec/rp2350). | |
| hitec_line_t | s_hitec_line |
| link_dev_t | s_dev |
| outputs_t | s_outputs |
| Every output, behind one set of rules. | |
| heartbeat_mon_t | s_beat |
| The panel's safety line, as judged in firmware. | |
| uint32_t | s_frames |
| Requests this end has answered, published on the STATUS page. | |
| uint32_t | s_refused |
| CAN frames received and refused since power-up, published on the STATUS page (LINK_ST_REFUSED_LO and _HI). | |
| uint32_t | s_now_ms |
| The pass's clock, used by everything the pass reaches – including the page callbacks, which run inside can_service() and have no now of their own. | |
| static bool | s_pass_driving |
| The bank was driving on the last pass: the edge into driving moves s_run_gen. | |
| static bool | s_kst_armed |
| The bank was asked to drive on the last pass: its falling edge stops a session. | |
| static const link_page_t | k_pages [] |
| The link pages this application serves. A page with a NULL write handler is read-only. | |
| static bench_state_t | s_bench |
| The numbers, and only the ones something measured. | |
| static bool | s_was_driving |
| The peaks belong to a run, and a run starts when the bank arms. | |
The IOmcu application.
Answers polls and never transmits unsolicited: every transmission here follows a decoded request.
The power path is not written. This application runs on core 0 and holds the wire, the failsafe and the output bank; iomcu.h lists the files it is cut into. The output protocols are out_pwm.c and the drivers in protocols/ppm and protocols/dshot, behind outputs_hw.c. Core 1 reads the current monitors on their I2C bus (sense_core1.c) and nothing else; core 0 gives it its orders and publishes what it reads.
Nothing here models a reading. A number this end publishes came off a wire or a sensor, and a quantity nothing measures is left at zero with its valid bit clear. The panel models when no IOmcu answers at all, which is the only case where a modelled number cannot be mistaken for a measured one.
SPDX-License-Identifier: MIT
| #define IOMCU_SAY console_hw_say |
This file's report lines.
The bench console build sends them through the console's output: none lands inside a console line that leaves in pieces, and none waits for the host. Every other build prints them, and printf() waits for the host for up to 500 ms (PICO_STDIO_USB_STDOUT_TIMEOUT_US).
|
static |
Whether flash may not be written now: flash_gate_busy(), host-tested, with this end's four inputs.
A function of its own because update_hw_init() takes one. The PD mini is asked only while it is open.
| int main | ( | void | ) |
Boots the IOmcu, then runs the main loop.
|
static |
Whether the page holds a capture that has not finished.
| heartbeat_mon_t s_beat |
The panel's safety line, as judged in firmware.
The control page consults it before it arms; see heartbeat_init() in iomcu_can.c.
|
static |
The numbers, and only the ones something measured.
Speed, and the ESC's own voltage, current and temperature, come from a bidirectional DShot ESC (electronic speed controller) answering on its own signal line. Voltage, current, power, their peaks, charge and energy come from the INA228 instead while it is enabled and answering (LINK_BN_SENSED, sense_page_bench()), and the ESC's two then stay on the SENSE page. A quantity nothing measured is zero with its valid bit clear, and the panel draws that field empty.
LINK_BN_SIMULATED is never set here. An IOmcu that is answering is reporting what it can see; the panel models only when nothing answers at all, and marks that itself.
| hitec_port_t s_hitec |
The HITEC page: raw transactions of the Hitec wire on a programming port (shared/outputs/hitec_port.h) and the wire driver the port's pin is handed to (protocols/hitec/rp2350).
A port is free, the KST page's or this page's, never two of them. Not kept: a restart finds the port free.
| kst_port_t s_kst |
The KST page: the wire protocol for KST and Chaservo servos on a programming port (shared/outputs/kst_port.h) and the wire driver the port's pin is handed to (protocols/kst/rp2350).
Not kept: a restart finds the port in PWM (pulse-width modulation) with no session.
| uint32_t s_now_ms |
The pass's clock, used by everything the pass reaches – including the page callbacks, which run inside can_service() and have no now of their own.
Read at the top of the loop and once more before its tail, and nowhere else. The second read is there because two things in a pass can stop this core for longer than a pass lasts: a flash window, and a printf to a USB host. See the loop for why that matters to what is measured after them.
Every timeout in this application is a wrap-safe unsigned subtraction of two timestamps. A second reading of the clock inside a pass can be a millisecond ahead of the pass's own, and a stamp ahead of the now it is later compared against subtracts to 4,294,967,295ms – past every timeout there is. A CHANNELS write stamped that way reads as stale in the same pass and is put back to rest; a save stamped that way skips the settle and the quiet-bus wait and takes its flash window inside the request burst it was meant to wait out.
| outputs_t s_outputs |
Every output, behind one set of rules.
The pages above are the wire format; the rules (arming, clamping, slew and the silence timeout) live in shared/outputs and nowhere else, so this end and the panel cannot answer them differently.
The output pages address bank channels 0..LINK_OUT_CHANNELS-1 directly. The throttle lives above that range, so the control page commands it without colliding with a CHANNELS-page write, and a motor command keeps the control page's priority on the wire.
| uint8_t s_pd_rate |
the rate it runs at, 0..6
| prog_port_t s_prog |
The PROG page: the programming ports, outputs of their own kind with their own pins (shared/outputs/prog_port.h).
Pin, slew, endpoints and function are kept; the pulse's switch and the tester's target are not.
| uint32_t s_refused |
CAN frames received and refused since power-up, published on the STATUS page (LINK_ST_REFUSED_LO and _HI).
Counted in two places, both shared code: a receive buffer with no frame the link carries in it (mcp2515_recv_next()) and a frame link_can_decode() refuses (link_can_decode_counted()). Wraps at 2^32.
| sense_page_t s_sense |
The SENSE and SERVO_SENSE pages: the current monitors' set-up, kept, and the pins it holds.
Core 1 reads the parts (sense_core1.h); this core gives it its orders and publishes what it hands back.
| sense_snap_t s_sense_snap |
Core 1's last snapshot.
The pins it said it still holds are the page's (sense_page_held()): a bus moved or closed keeps its old pins from the outputs until core 1 has let them go, about 1ms.
| servo_page_t s_servo |
The SERVO page: the PWM target's frame rate and the sweep.
Not kept.
| iomcu_state_t s_state |
What iomcu.h declares and describes.
The register images of the pages in iomcu_state_t.
What iomcu.h declares and describes.
| tone_page_t s_tone |
The TONE page: the phase tap's set-up, kept, and the beeps core 1 hears on it.
Core 0 owns the PIO state machine and the DMA ring (tone_cap.c in protocols/phase_tap/rp2350); core 1 reads and detects (tone_core1.c).
|
static |
The peaks belong to a run, and a run starts when the bank arms.
They are kept on this end because it has the fast samples and the panel sees one poll in fifty of them, so only this end can see the peak at all. Holding them since boot instead would report a maximum from a motor that was taken off the bench two runs ago.