|
rcbench
Servo and ESC test bench: panel, IOmcu and shared C
|
The page protocol over CAN (Controller Area Network). More...
Go to the source code of this file.
Data Structures | |
| struct | link_can_frame_t |
| One CAN frame: its identifier and up to 8 payload bytes. More... | |
Macros | |
| #define | LINK_CAN_PRIO_SHIFT 26 |
| The 29-bit extended identifier, most significant field first: | |
| #define | LINK_CAN_OP_SHIFT 22 |
| #define | LINK_CAN_PAGE_SHIFT 14 |
| #define | LINK_CAN_OFFSET_SHIFT 6 |
| #define | LINK_CAN_COUNT_SHIFT 0 |
| #define | LINK_CAN_PRIO_MASK 0x7u |
| Masks of the fields of the 29-bit CAN identifier, after shifting. | |
| #define | LINK_CAN_OP_MASK 0xFu |
| #define | LINK_CAN_PAGE_MASK 0xFFu |
| #define | LINK_CAN_OFFSET_MASK 0xFFu |
| #define | LINK_CAN_COUNT_MASK 0x3Fu |
| #define | LINK_CAN_REGS_PER_FRAME 4 |
| Registers that fit one 8-byte payload. | |
| #define | LINK_CAN_MAX_FRAMES (LINK_MAX_REGS / LINK_CAN_REGS_PER_FRAME) |
| Frames a full page takes: 32 registers, four to a frame. | |
Enumerations | |
| enum | link_can_prio_t { LINK_CAN_PRIO_CONTROL = 0 , LINK_CAN_PRIO_NORMAL = 1 , LINK_CAN_PRIO_BULK = 2 } |
| Arbitration classes. More... | |
Functions | |
| link_can_prio_t | link_can_priority (uint8_t page, uint8_t op) |
| The arbitration class a page and op belong to. | |
| uint32_t | link_can_id (link_can_prio_t prio, uint8_t op, uint8_t page, uint8_t offset, uint8_t count) |
| Build a 29-bit identifier from its fields. | |
| void | link_can_id_split (uint32_t id, link_can_prio_t *prio, uint8_t *op, uint8_t *page, uint8_t *offset, uint8_t *count) |
| Split an identifier back into its fields. | |
| size_t | link_can_encode (const link_msg_t *msg, link_can_frame_t *out, size_t cap) |
| Render a message as one or more CAN frames. | |
| bool | link_can_decode (const link_can_frame_t *f, link_msg_t *out) |
| Turn one received frame back into a message carrying up to four registers. | |
| bool | link_can_decode_counted (const link_can_frame_t *f, link_msg_t *out, uint32_t *refused) |
| link_can_decode(), and a count of the frames it refuses. | |
The page protocol over CAN (Controller Area Network).
link_msg_t (an op, a page, an offset, a count and up to a page of registers) carries no transport. This file maps it onto CAN frames.
Three properties of the mapping:
CAN arbitrates by identifier, lowest wins, so priority is a property of the address: a write to the control page wins arbitration against telemetry already in flight, on the wire, with no software involved at either end.
SPDX-License-Identifier: MIT
| #define LINK_CAN_PRIO_SHIFT 26 |
The 29-bit extended identifier, most significant field first:
28..26 priority 3 bits lower wins arbitration 25..22 op 4 bits a link_op_t 21..14 page 8 bits the page map 13..6 offset 8 bits first register this frame carries 5..0 count 6 bits registers this frame is about, 0..32
Exactly 29 bits: the whole extended identifier.
| enum link_can_prio_t |
| bool link_can_decode | ( | const link_can_frame_t * | f, |
| link_msg_t * | out ) |
Turn one received frame back into a message carrying up to four registers.
False if the identifier describes something impossible: an unknown op, a count past the end of a page, a payload that disagrees with the count. The layer above accumulates the parts into the transfer it asked for, because only it knows what it asked.
| f | The received frame. |
| out | Receives the message. |
| bool link_can_decode_counted | ( | const link_can_frame_t * | f, |
| link_msg_t * | out, | ||
| uint32_t * | refused ) |
link_can_decode(), and a count of the frames it refuses.
A refused frame adds 1 to refused, modulo 2^32; NULL counts nothing. A NULL frame or message is not a frame received and is not counted. The IOmcu publishes the count on the STATUS page (LINK_ST_REFUSED_LO and _HI, protocol 4.21).
| f | The received frame. |
| out | Receives the message. |
| refused | Refused-frame counter; may be NULL. |
| size_t link_can_encode | ( | const link_msg_t * | msg, |
| link_can_frame_t * | out, | ||
| size_t | cap ) |
Render a message as one or more CAN frames.
Returns how many were written, or 0 if the message is malformed or would not fit. A READ carries no registers and is always one frame.
| msg | The message to render. |
| out | Receives the frames. |
| cap | Number of frames out can hold. |
| uint32_t link_can_id | ( | link_can_prio_t | prio, |
| uint8_t | op, | ||
| uint8_t | page, | ||
| uint8_t | offset, | ||
| uint8_t | count ) |
Build a 29-bit identifier from its fields.
Each field is masked to its width before it is shifted into place.
| prio | The arbitration class. |
| op | The op, a link_op_t; masked to 4 bits. |
| page | The page number; masked to 8 bits. |
| offset | First register the frame carries; masked to 8 bits. |
| count | Registers the frame is about; masked to 6 bits, 0..63. |
| void link_can_id_split | ( | uint32_t | id, |
| link_can_prio_t * | prio, | ||
| uint8_t * | op, | ||
| uint8_t * | page, | ||
| uint8_t * | offset, | ||
| uint8_t * | count ) |
Split an identifier back into its fields.
Any pointer may be NULL.
| id | The 29-bit identifier. |
| prio | Receives the arbitration class; may be NULL. |
| op | Receives the op; may be NULL. |
| page | Receives the page number; may be NULL. |
| offset | Receives the first register; may be NULL. |
| count | Receives the register count; may be NULL. |
| link_can_prio_t link_can_priority | ( | uint8_t | page, |
| uint8_t | op ) |
The arbitration class a page and op belong to.
Derived rather than chosen per call site, so a new page cannot be added at the wrong priority. The control, limits, failsafe and supply pages stop a bench – the supply's OFF switches off a powered load – and everything that touches them outranks everything else, their own acknowledgements included.
| page | The page number. |
| op | The op, a link_op_t. |