ProtoCore v0.0.2
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
powerlink.h
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file powerlink.h
6 * @brief Ethernet POWERLINK (EPSG) basic frame codec (PC_ENABLE_POWERLINK).
7 *
8 * Ethernet POWERLINK is the EPSG real-time managed-node bus over raw L2 (ethertype 0x88AB, on the
9 * shipped services/fieldbus/rawl2). The Managing Node (MN) runs an isochronous cycle: it multicasts a **SoC**
10 * (Start of Cycle), unicasts a **PReq** (Poll Request) to each Controlled Node (CN), each CN answers with
11 * a **PRes** (Poll Response) carrying its process data, then an **SoA** (Start of Async) opens the async
12 * phase. Every EPL basic frame is:
13 *
14 * [messageType : 1][destination node : 1][source node : 1][payload...]
15 *
16 * This builds and parses those frames (the four cyclic message types + the node addressing), so the MN
17 * schedules the cycle and a CN answers with its PRes process image. Pure, zero heap, no stdlib,
18 * host-testable; the raw-L2 transmit + the isochronous timing (the preempting-task model) are the device
19 * step.
20 */
21
22#ifndef PROTOCORE_POWERLINK_H
23#define PROTOCORE_POWERLINK_H
24
25#include "protocore_config.h"
26#include <stddef.h>
27#include <stdint.h>
28
29#if PC_ENABLE_POWERLINK
30
31/** @brief EPL message types (EPSG DS 301). */
32// POWERLINK message types + node ids: wire bytes, so integer constants in a namespacing struct.
33struct Epl
34{
35 static constexpr uint8_t EPL_MSG_SOC = 0x01; ///< Start of Cycle (MN -> all, multicast).
36 static constexpr uint8_t EPL_MSG_PREQ = 0x03; ///< Poll Request (MN -> CN, unicast).
37 static constexpr uint8_t EPL_MSG_PRES = 0x04; ///< Poll Response (CN -> all, multicast, carries process data).
38 static constexpr uint8_t EPL_MSG_SOA = 0x05; ///< Start of Async (MN -> all).
39 static constexpr uint8_t EPL_MSG_ASND = 0x06; ///< Async Send.
40 static constexpr uint8_t EPL_NODE_BROADCAST = 0xFF; ///< broadcast node id (SoC/SoA destination).
41 static constexpr uint8_t EPL_NODE_MN = 0xF0; ///< the Managing Node id (240).
42};
43
44/**
45 * @brief Build an EPL basic frame: [messageType][dest][source][payload...].
46 * @return the frame length (3 + payload_len), or 0 on overflow / bad args.
47 */
48size_t pc_epl_build(uint8_t msg_type, uint8_t dest, uint8_t source, const uint8_t *payload, size_t payload_len,
49 uint8_t *out, size_t cap);
50
51/** @brief Convenience: build an SoC (MN -> broadcast, no payload). */
52size_t pc_epl_soc(uint8_t source, uint8_t *out, size_t cap);
53
54/** @brief Convenience: build a PReq to a CN carrying its output process image. */
55size_t pc_epl_preq(uint8_t dest_cn, uint8_t source, const uint8_t *pdo, size_t pdo_len, uint8_t *out, size_t cap);
56
57/** @brief Convenience: build a PRes from a CN carrying its input process image (multicast). */
58size_t pc_epl_pres(uint8_t source_cn, const uint8_t *pdo, size_t pdo_len, uint8_t *out, size_t cap);
59
60/** @brief Convenience: build an SoA (MN -> broadcast) that opens the asynchronous phase. @p payload is the
61 * SoA field block (NMT status, requested service id / target, EPL version), or null for a bare invite. */
62size_t pc_epl_soa(uint8_t source, const uint8_t *payload, size_t payload_len, uint8_t *out, size_t cap);
63
64/** @brief Convenience: build an ASnd (asynchronous send) from @p source to @p dest. @p payload is the ASnd
65 * service block (service id + service data). ASnd may be unicast to a node or broadcast (0xFF). */
66size_t pc_epl_asnd(uint8_t dest, uint8_t source, const uint8_t *payload, size_t payload_len, uint8_t *out, size_t cap);
67
68/** @brief A parsed EPL basic frame (payload points into the input). */
69struct EplFrame
70{
71 uint8_t msg_type;
72 uint8_t dest;
73 uint8_t source;
74 const uint8_t *payload;
75 size_t payload_len;
76};
77
78/** @brief Parse an EPL basic frame. @return true if @p len >= 3 and the message type is known. */
79bool pc_epl_parse(const uint8_t *frame, size_t len, EplFrame *out);
80
81#endif // PC_ENABLE_POWERLINK
82#endif // PROTOCORE_POWERLINK_H
User-facing configuration for ProtoCore.