rcbench
Servo and ESC test bench: panel, IOmcu and shared C
Loading...
Searching...
No Matches
main.c File Reference

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.

Detailed Description

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

Macro Definition Documentation

◆ IOMCU_SAY

#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).

Function Documentation

◆ flash_busy()

bool flash_busy ( void )
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.

Returns
True while a flash write must wait.

◆ main()

int main ( void )

Boots the IOmcu, then runs the main loop.

Returns
Does not return.

◆ sense_capture_open()

bool sense_capture_open ( void )
static

Whether the page holds a capture that has not finished.

Returns
True while the capture is armed, waiting for a move, or moving.

Variable Documentation

◆ 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.

◆ s_bench

bench_state_t s_bench
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.

◆ s_hitec

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.

◆ s_kst

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.

◆ s_now_ms

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.

◆ s_outputs

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.

◆ s_pd_rate

uint8_t s_pd_rate

the rate it runs at, 0..6

◆ s_prog

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.

◆ s_refused

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.

◆ s_sense

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.

◆ s_sense_snap

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.

◆ s_servo

servo_page_t s_servo

The SERVO page: the PWM target's frame rate and the sweep.

Not kept.

◆ s_state

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.

◆ s_tone

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).

◆ s_was_driving

bool s_was_driving
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.