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

The IOmcu's half of the link: answer polls, and fail safe when they stop. More...

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "link_msg.h"
#include "link_pages.h"

Go to the source code of this file.

Data Structures

 One page, as the IOmcu sees it. More...
 The IOmcu's end of the link: pages, the silence watchdog and the arm latch. More...

Macros

#define LINK_DEV_SILENCE_MS   200u
 Silence after which the IOmcu fills failsafe values on its own authority.

Functions

void link_dev_init (link_dev_t *d, const link_page_t *pages, uint8_t page_count, void *ctx, uint32_t now_ms)
 Start with no request heard, out of failsafe and with the arm latch set: the first ARM after a start needs a CLEAR ahead of it.
bool link_dev_dispatch (link_dev_t *d, const link_msg_t *req, link_msg_t *reply, uint32_t now_ms)
 Decide what to answer, without deciding how to carry it: which page, whether the range fits, whether the write is accepted, and what a NACK (negative acknowledge) says.
bool link_dev_apply (const link_dev_t *d, const link_msg_t *req, link_msg_t *reply)
 What link_dev_dispatch() answers, without touching the silence watchdog: the same page lookup, range check, read, write and refusals.
bool link_dev_tick (link_dev_t *d, uint32_t now_ms)
 Advance the silence watchdog.
void link_dev_clear_failsafe (link_dev_t *d, uint32_t now_ms)
 Leave failsafe and release the arm latch.
void link_dev_latch_arm (link_dev_t *d)
 Set the arm latch: a cause other than link silence took the outputs down, and the ARM the host goes on writing does not bring them back.
bool link_dev_arm_latched (const link_dev_t *d)
 Whether a write of ARM is refused until the host writes CLEAR.

Detailed Description

The IOmcu's half of the link: answer polls, and fail safe when they stop.

Pure C with the clock passed in as a millisecond count. No timers, no FreeRTOS, no pico-sdk, so both watchdogs are driven through their transitions on the host, including across the 32-bit wrap at 49.7 days.

SPDX-License-Identifier: MIT

Macro Definition Documentation

◆ LINK_DEV_SILENCE_MS

#define LINK_DEV_SILENCE_MS   200u

Silence after which the IOmcu fills failsafe values on its own authority.

The ratio follows ArduPilot's IOMCU (I/O microcontroller): the IOmcu gives up after 200ms and the host escalates after 1s, so the processor holding the outputs is the more suspicious of the two.

Function Documentation

◆ link_dev_apply()

bool link_dev_apply ( const link_dev_t * d,
const link_msg_t * req,
link_msg_t * reply )

What link_dev_dispatch() answers, without touching the silence watchdog: the same page lookup, range check, read, write and refusals.

For a caller on this end that is not the link, such as the bench console (page_console.h): a request from there proves nothing about the panel, so it must not hold the failsafe off.

False only on a null argument.

Parameters
dThe link state.
reqThe request to answer.
replyReceives the answer.
Returns
true when a reply was built, false on a null argument.

◆ link_dev_arm_latched()

bool link_dev_arm_latched ( const link_dev_t * d)

Whether a write of ARM is refused until the host writes CLEAR.

Parameters
dThe link state; NULL counts as latched.
Returns
true while the latch is set.

◆ link_dev_clear_failsafe()

void link_dev_clear_failsafe ( link_dev_t * d,
uint32_t now_ms )

Leave failsafe and release the arm latch.

Not exposed as "the link came back": recovery of the wire is not consent to spin a propeller, so the host asks for this by writing LINK_CLEAR_MAGIC to the control page.

Parameters
dThe link state.
now_msThe current time, in ms; restarts the silence watchdog.

◆ link_dev_dispatch()

bool link_dev_dispatch ( link_dev_t * d,
const link_msg_t * req,
link_msg_t * reply,
uint32_t now_ms )

Decide what to answer, without deciding how to carry it: which page, whether the range fits, whether the write is accepted, and what a NACK (negative acknowledge) says.

No transport is visible from here.

False only on a null argument. Every request produces exactly one reply, refusals included: silence means an IOmcu that is not there, and must not also mean a declined request.

Parameters
dThe link state.
reqThe request received.
replyReceives the answer: DATA, ACK or NACK.
now_msThe current time, in ms; restarts the silence watchdog.
Returns
true when a reply was built, false on a null argument.

◆ link_dev_init()

void link_dev_init ( link_dev_t * d,
const link_page_t * pages,
uint8_t page_count,
void * ctx,
uint32_t now_ms )

Start with no request heard, out of failsafe and with the arm latch set: the first ARM after a start needs a CLEAR ahead of it.

Parameters
dThe link state to set up.
pagesThe page table; kept, not copied.
page_countEntries in pages.
ctxPassed to every page callback.
now_msThe current time, in ms.

◆ link_dev_latch_arm()

void link_dev_latch_arm ( link_dev_t * d)

Set the arm latch: a cause other than link silence took the outputs down, and the ARM the host goes on writing does not bring them back.

Leaves failsafe as it is.

Parameters
dThe link state.

◆ link_dev_tick()

bool link_dev_tick ( link_dev_t * d,
uint32_t now_ms )

Advance the silence watchdog.

Returns true on the edge where failsafe fires, so the caller can drop the outputs once rather than every tick. The edge sets the arm latch too.

Parameters
dThe link state.
now_msThe current time, in ms.
Returns
true only on the tick where failsafe fires.