|
rcbench
Servo and ESC test bench: panel, IOmcu and shared C
|
The panel's half of the throttle's pulse endpoints, Idle pulse and Full pulse, on the CHAN_CFG (0x23) link page: when a debt is paid, what each outcome of paying it leaves, and whether a switch to ARMED may go on. More...
#include <stdatomic.h>#include <stdbool.h>#include <stdint.h>Go to the source code of this file.
Data Structures | |
| struct | endpoints_debt_t |
| The debt. More... | |
Macros | |
| #define | ENDPOINTS_SETTLE_MS 300u |
| An edit rests this long before the pair is written. | |
Enumerations | |
| enum | endpoints_next_t { ENDPOINTS_PAID = 0 , ENDPOINTS_WAIT_DISARM , ENDPOINTS_WAIT_SETTLE , ENDPOINTS_PAY } |
| What the debt asks of this pass, endpoints_next(). More... | |
| enum | endpoints_outcome_t { ENDPOINTS_NO_ANSWER = 0 , ENDPOINTS_READ_REFUSED , ENDPOINTS_ORDER , ENDPOINTS_HELD , ENDPOINTS_TAKEN , ENDPOINTS_WRITE_REFUSED , ENDPOINTS_DIFFERS } |
| How paying a debt went. More... | |
| enum | endpoints_block_t { ENDPOINTS_BLOCK_NONE = 0 , ENDPOINTS_BLOCK_OWED , ENDPOINTS_BLOCK_UNKNOWN , ENDPOINTS_BLOCK_ORDER , ENDPOINTS_BLOCK_REFUSED , ENDPOINTS_BLOCK_DIFFERS } |
| Why a switch to ARMED is refused for the pair, endpoints_block(). More... | |
Functions | |
| endpoints_next_t | endpoints_next (bool owed, bool far_disarmed, uint32_t edit_ms, uint32_t now_ms) |
What a debt asks of a pass at now_ms. | |
| bool | endpoints_page_holds (const uint16_t *page, uint16_t min_us, uint16_t max_us) |
Whether every throttle channel of a CHAN_CFG page page (LINK_CC_COUNT registers) holds min_us and max_us. | |
| bool | endpoints_owed_after (endpoints_outcome_t outcome) |
Whether the debt stands after an attempt that ended in outcome: true only for ENDPOINTS_NO_ANSWER, and for a value outside the enum. | |
| void | endpoints_publish (endpoints_debt_t *d, uint16_t min_us, uint16_t max_us, uint32_t now_ms) |
An edit of Idle pulse or Full pulse at now_ms, from any task: the pair, then the time, then the flag, so a payment that sees the flag sees the pair and the rest it starts from. | |
| void | endpoints_link_up (endpoints_debt_t *d) |
| A link-up edge: the pair is owed again and the far end held disarmed until it is paid. | |
| bool | endpoints_owed (const endpoints_debt_t *d) |
| Whether a pair is owed: true refuses a switch to ARMED with the link up. | |
| void | endpoints_recheck (endpoints_debt_t *d) |
| A binding was written: the throttle channels may have moved, so the pair is owed again, due at the next poll once its edit has rested. | |
| endpoints_block_t | endpoints_block (const endpoints_debt_t *d) |
| Why a switch to ARMED with the link up is refused for the pair: ENDPOINTS_BLOCK_OWED while owed, else what the last answered payment left. | |
| bool | endpoints_blocked (const endpoints_debt_t *d) |
| endpoints_block() is not ENDPOINTS_BLOCK_NONE. | |
| bool | endpoints_held (const endpoints_debt_t *d) |
| Whether the far end is held disarmed for the debt. | |
| uint16_t | endpoints_min (const endpoints_debt_t *d) |
| The pair as last published, in us; 0 for NULL. | |
| uint16_t | endpoints_max (const endpoints_debt_t *d) |
| The Full pulse as last published, in us; 0 for NULL. | |
| endpoints_next_t | endpoints_take (endpoints_debt_t *d, bool far_disarmed, uint32_t now_ms) |
| The debt at a poll, on the control task: what endpoints_next() finds. | |
| void | endpoints_paid (endpoints_debt_t *d, endpoints_outcome_t outcome) |
The end of a payment endpoints_take() handed out: owed again on a missing answer, the hold and the block kept with it; otherwise paid, the hold ended, and the block set from outcome – none for ENDPOINTS_HELD and ENDPOINTS_TAKEN. | |
The panel's half of the throttle's pulse endpoints, Idle pulse and Full pulse, on the CHAN_CFG (0x23) link page: when a debt is paid, what each outcome of paying it leaves, and whether a switch to ARMED may go on.
An edit of either setting, a link-up edge and the panel's start owe the IOmcu the pair. The debt is paid at a poll whose control write put ARM = 0 at the IOmcu and was acknowledged, once ENDPOINTS_SETTLE_MS (300ms) have passed since the last edit: a key held on + or - steps the value every few hundred milliseconds, and each write of CHAN_CFG is a flash save at the IOmcu. Paying it reads the page, puts the pair on the throttle channels and writes the page when it differs.
The IOmcu applies a CHAN_CFG write to its outputs before it acknowledges it, and the acknowledgement carries what it stored. A read that already holds the pair, or an ACK whose stored throttle channels hold it, is the pair in force; a read or a write nobody answered leaves the debt owed.
Any other answer ends the debt and blocks the switch to ARMED (endpoints_block()): the read refused, Idle pulse not below Full pulse, the write refused, or an ACK whose throttle channels hold another pair. The same request refused once is refused every time, so the debt is not sent again by itself. A new edit, a new binding (endpoints_recheck()) or a link-up edge, an IOmcu restart or update included, owes the pair again, and the payment that follows decides afresh.
The frame that switches to ARMED carries no CHAN_CFG. While the pair is not in force – owed or blocked – with the link up, a switch to ARMED is refused (arming_hs_facts_t.endpoints_blocked): one that went on would run the throttle on whatever range the IOmcu holds.
The debt crosses two tasks: the settings screen publishes an edit (endpoints_publish()) and the control task, which owns the link, pays it (endpoints_service()) and asks it before a switch to ARMED (endpoints_owed()). The pair and the time travel in atomics beside the flag, the pair in one word, min in the high half, so a payment never pairs one edit's minimum with another's maximum.
No link of its own: the caller's pay function makes the exchanges and reports how they went.
SPDX-License-Identifier: MIT
| enum endpoints_block_t |
Why a switch to ARMED is refused for the pair, endpoints_block().
| enum endpoints_next_t |
What the debt asks of this pass, endpoints_next().
| enum endpoints_outcome_t |
How paying a debt went.
| endpoints_block_t endpoints_block | ( | const endpoints_debt_t * | d | ) |
Why a switch to ARMED with the link up is refused for the pair: ENDPOINTS_BLOCK_OWED while owed, else what the last answered payment left.
ENDPOINTS_BLOCK_NONE for NULL.
| d | The debt to read. |
| bool endpoints_blocked | ( | const endpoints_debt_t * | d | ) |
endpoints_block() is not ENDPOINTS_BLOCK_NONE.
| d | The debt to read. |
| bool endpoints_held | ( | const endpoints_debt_t * | d | ) |
Whether the far end is held disarmed for the debt.
False for NULL.
| d | The debt to read. |
| void endpoints_link_up | ( | endpoints_debt_t * | d | ) |
A link-up edge: the pair is owed again and the far end held disarmed until it is paid.
Control task only.
| d | The debt to update. |
| uint16_t endpoints_max | ( | const endpoints_debt_t * | d | ) |
The Full pulse as last published, in us; 0 for NULL.
| d | The debt to read. |
| uint16_t endpoints_min | ( | const endpoints_debt_t * | d | ) |
The pair as last published, in us; 0 for NULL.
| d | The debt to read. |
| endpoints_next_t endpoints_next | ( | bool | owed, |
| bool | far_disarmed, | ||
| uint32_t | edit_ms, | ||
| uint32_t | now_ms ) |
What a debt asks of a pass at now_ms.
owed: a pair is owed. far_disarmed: the control write of this pass put ARM = 0 at the far end and was acknowledged. edit_ms: the time of the last edit.
Due once now_ms - edit_ms, taken modulo 2^32, reaches ENDPOINTS_SETTLE_MS: 299ms after an edit waits, 300ms pays.
| owed | true while a pair is owed. |
| far_disarmed | true when the control write of this pass put ARM = 0 at the far end and it was acknowledged. |
| edit_ms | The time of the last edit, in ms. |
| now_ms | The time of this pass, in ms. |
| bool endpoints_owed | ( | const endpoints_debt_t * | d | ) |
Whether a pair is owed: true refuses a switch to ARMED with the link up.
False for NULL.
| d | The debt to read. |
| bool endpoints_owed_after | ( | endpoints_outcome_t | outcome | ) |
Whether the debt stands after an attempt that ended in outcome: true only for ENDPOINTS_NO_ANSWER, and for a value outside the enum.
| outcome | The outcome of the attempt. |
| bool endpoints_page_holds | ( | const uint16_t * | page, |
| uint16_t | min_us, | ||
| uint16_t | max_us ) |
Whether every throttle channel of a CHAN_CFG page page (LINK_CC_COUNT registers) holds min_us and max_us.
A page with no throttle channel holds any pair. False for NULL.
| page | The CHAN_CFG page, LINK_CC_COUNT registers. |
| min_us | The Idle pulse, in us. |
| max_us | The Full pulse, in us. |
| void endpoints_paid | ( | endpoints_debt_t * | d, |
| endpoints_outcome_t | outcome ) |
The end of a payment endpoints_take() handed out: owed again on a missing answer, the hold and the block kept with it; otherwise paid, the hold ended, and the block set from outcome – none for ENDPOINTS_HELD and ENDPOINTS_TAKEN.
| d | The debt, or NULL. |
| outcome | The result of the payment. |
| void endpoints_publish | ( | endpoints_debt_t * | d, |
| uint16_t | min_us, | ||
| uint16_t | max_us, | ||
| uint32_t | now_ms ) |
An edit of Idle pulse or Full pulse at now_ms, from any task: the pair, then the time, then the flag, so a payment that sees the flag sees the pair and the rest it starts from.
| d | The debt to update. |
| min_us | The Idle pulse, in us. |
| max_us | The Full pulse, in us. |
| now_ms | The time of the edit, in ms. |
| void endpoints_recheck | ( | endpoints_debt_t * | d | ) |
A binding was written: the throttle channels may have moved, so the pair is owed again, due at the next poll once its edit has rested.
Control task only.
| d | The debt to update. |
| endpoints_next_t endpoints_take | ( | endpoints_debt_t * | d, |
| bool | far_disarmed, | ||
| uint32_t | now_ms ) |
The debt at a poll, on the control task: what endpoints_next() finds.
On ENDPOINTS_PAY the flag has been taken, and the caller pays the pair endpoints_min() and endpoints_max() read now and ends the payment with endpoints_paid(). The flag is taken before the exchanges and given back by a missing answer, so an edit published while they run stays owed. A switch to ARMED asks endpoints_owed() on the same task, so never between the taking and the outcome.
On ENDPOINTS_PAID the hold ends. A NULL d changes nothing and returns ENDPOINTS_WAIT_DISARM.
| d | The debt, or NULL. |
| far_disarmed | true when the far end is disarmed. |
| now_ms | The time of the poll, in ms. |