ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_etha_stats.c
Go to the documentation of this file.
1
27
28#include <stdint.h>
29
30#include "ra8_attributes.h"
31#include "ra8_check.h"
32#include "ra8_err.h"
33#include "ra8_etha.h"
34#include "ra8_etha_internal.h"
35#include "ra8_etha_regs.h"
36#include "ra8_log.h"
37
48static const char* s_tag = "ETHA";
49
60
81static inline bool internal_ring_args_ok(uint16_t num_tx, uint16_t num_rx, uint16_t buffer_size)
82{
83 return (num_tx >= k_ra8_etha_ring_count_min) && (num_tx <= k_ra8_etha_ring_count_max) &&
84 (num_rx >= k_ra8_etha_ring_count_min) && (num_rx <= k_ra8_etha_ring_count_max) &&
85 (buffer_size >= k_ra8_etha_ring_buf_min) && (buffer_size <= k_ra8_etha_ring_buf_max);
86}
87
107static inline uint32_t internal_sat_add_u32(uint32_t base, uint32_t inc)
108{
109 if (inc > (UINT32_MAX - base)) {
110 return UINT32_MAX;
111 }
112 return base + inc;
113}
114
116 uint16_t num_tx,
117 uint16_t num_rx,
118 uint16_t buffer_size)
119{
120 if (!internal_port_ok(channel)) {
121 ra8_log_error(s_tag, "etha_descriptor_ring_init: channel out of range");
123 }
124 if (!internal_ring_args_ok(num_tx, num_rx, buffer_size)) {
125 ra8_log_error(s_tag, "etha_descriptor_ring_init: ring args out of range");
127 }
128 s_etha_slots[(uint8_t)channel].stats.ring_tx = num_tx;
129 s_etha_slots[(uint8_t)channel].stats.ring_rx = num_rx;
130 s_etha_slots[(uint8_t)channel].stats.ring_buf = buffer_size;
131
132 /* Clamp every per-class TX queue depth to num_tx so the hardware
133 * never schedules a class deeper than the host-side ring can hold.
134 * EATDQDC is 11 bits (k_ra8_etha_mask_dqd = 0x7FF = 2047). */
135 uint16_t depth = num_tx;
136 if ((uint32_t)depth > k_ra8_etha_mask_dqd) {
137 depth = (uint16_t)k_ra8_etha_mask_dqd;
138 }
139 volatile r_etha_regs_t* reg = ra8_etha(channel);
140 for (uint8_t i = 0U; i < k_ra8_etha_tc_count; ++i) {
141 /* HUM Ch 32.3.2.7 "EATDQDCq" p 1636 */
142 reg->EATDQDC[i] = (uint32_t)depth & k_ra8_etha_mask_dqd;
143 }
144 return k_ra8_ok;
145}
146
148{
149 RA8_CHECK_NULL_PTR(out_stats, s_tag, "etha_get_stats: out_stats null");
150 if (!internal_port_ok(channel)) {
151 ra8_log_error(s_tag, "etha_get_stats: channel out of range");
153 }
154 *out_stats = s_etha_slots[(uint8_t)channel].stats;
155 return k_ra8_ok;
156}
157
159 uint32_t tx_ok,
160 uint32_t tx_err,
161 uint32_t rx_ok,
162 uint32_t rx_err,
163 uint32_t rx_drop)
164{
165 if (!internal_port_ok(channel)) {
166 ra8_log_error(s_tag, "etha_account_traffic: channel out of range");
168 }
169 ra8_etha_port_stats_t* st = &s_etha_slots[(uint8_t)channel].stats;
170 st->tx_ok = internal_sat_add_u32(st->tx_ok, tx_ok);
171 st->tx_err = internal_sat_add_u32(st->tx_err, tx_err);
172 st->rx_ok = internal_sat_add_u32(st->rx_ok, rx_ok);
173 st->rx_err = internal_sat_add_u32(st->rx_err, rx_err);
174 st->rx_drop = internal_sat_add_u32(st->rx_drop, rx_drop);
175 return k_ra8_ok;
176}
177
200{
201 enum : uint32_t { k_ra8_etha_mode_spin = 200000U };
202 /* HUM Ch 32.3.1.1 "EAMC : Mode Command Register" p 1631 +
203 * HUM Ch 32.3.1.2 "EAMS : Mode Status Register" p 1631 */
204 volatile r_etha_regs_t* reg = ra8_etha(channel);
205 reg->EAMC = (uint32_t)k_ra8_etha_opc_operation;
206 for (uint32_t i = 0U; i < (uint32_t)k_ra8_etha_mode_spin; ++i) {
207 if ((reg->EAMS & k_ra8_etha_mask_ops) == (uint32_t)k_ra8_etha_opc_operation) {
208 return k_ra8_ok;
209 }
210 }
211 ra8_log_error(s_tag, "etha_to_operation: EAMS never reached OPERATION");
213}
214
216 const ra8_etha_phy_open_t* phy,
217 ra8_rmac_phy_link_t* out_link)
218{
219 RA8_CHECK_NULL_PTR(phy, s_tag, "etha_open: phy null");
220 RA8_CHECK_NULL_PTR(out_link, s_tag, "etha_open: out_link null");
221 if (!internal_port_ok(channel)) {
222 ra8_log_error(s_tag, "etha_open: channel out of range");
224 }
225 /* Map ETHA channel index 1:1 onto the corresponding RMAC port. */
226 const ra8_rmac_port_t rmac_port = (ra8_rmac_port_t)(uint8_t)channel;
227
228 const ra8_err_t op_err = internal_etha_to_operation(channel);
229 if (op_err != k_ra8_ok) {
230 return op_err;
231 }
232
233 /* Each PHY step below is an MDIO transaction pair (drain + post-wait)
234 * polling the RMAC MPSM register. On the host unit-test build those
235 * waits consult the ra8_fake_mmio seam, so each error leg is reached by
236 * failing the matching MPSM wait-loop (fail_wait / fail_nth_wait). */
237 ra8_err_t err = ra8_rmac_phy_reset(rmac_port, phy->phy_addr);
238 if (err != k_ra8_ok) {
239 ra8_log_error(s_tag, "etha_open: phy_reset");
240 return err;
241 }
242 err = ra8_rmac_phy_set_advertise(rmac_port, phy->phy_addr, phy->advertise);
243 if (err != k_ra8_ok) {
244 ra8_log_error(s_tag, "etha_open: set_advertise");
245 return err;
246 }
247 err = ra8_rmac_phy_auto_neg_start(rmac_port, phy->phy_addr);
248 if (err != k_ra8_ok) {
249 ra8_log_error(s_tag, "etha_open: auto_neg_start");
250 return err;
251 }
252 return ra8_rmac_phy_auto_neg_wait(rmac_port, phy->phy_addr, phy->timeout_ms, out_link);
253}
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_CHECK_NULL_PTR(ptr, tag, message)
Reject nullptr pointer, returning k_ra8_err_null_ptr.
Definition ra8_check.h:243
Error Code Definitions for ra8-firmware.
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_err_hw_timeout
Hardware timed out waiting for a flag or handshake.
Definition ra8_err.h:304
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
ra8_etha_slot_t s_etha_slots[k_ra8_etha_port_count]
Per-port handler table; index = ra8_etha_port_t.
Definition ra8_etha.c:117
Per-port Ethernet Agent (ETHA) driver – HUM Ch 32 (p 1627-1702).
Cross-TU shared surface for the ra8_etha driver split.
static bool internal_port_ok(ra8_etha_port_t port)
Range-check a port argument.
Ethernet Agent (ETHA) per-port register layout for the RA8D2.
ra8_etha_port_t
ETHA port index (m = 0, 1).
@ k_ra8_etha_tc_count
Number of traffic classes per port.
@ k_ra8_etha_opc_operation
Enter OPERATION mode.
static volatile r_etha_regs_t * ra8_etha(ra8_etha_port_t port)
Compile-time offset and size insurance for r_etha_regs_t.
@ k_ra8_etha_mask_dqd
EATDQDCq.DQD[10:0].
@ k_ra8_etha_mask_ops
EAMS.OPS[1:0].
static bool internal_ring_args_ok(uint16_t num_tx, uint16_t num_rx, uint16_t buffer_size)
Validate descriptor-ring sizing.
ra8_err_t ra8_etha_account_traffic(ra8_etha_port_t channel, uint32_t tx_ok, uint32_t tx_err, uint32_t rx_ok, uint32_t rx_err, uint32_t rx_drop)
Increment the per-port TX OK / TX err / RX OK / RX err / drop counters.
ra8_etha_ring_limits_t
Bound checks for ra8_etha_descriptor_ring_init arguments.
@ k_ra8_etha_ring_buf_min
IEEE 802.3 minimum frame.
@ k_ra8_etha_ring_buf_max
14-bit frame-size field cap.
@ k_ra8_etha_ring_count_max
Maximum descriptor ring depth.
@ k_ra8_etha_ring_count_min
Minimum descriptor ring depth.
static ra8_err_t internal_etha_to_operation(ra8_etha_port_t channel)
Transition ETHA channel into OPERATION and wait for EAMS.
ra8_err_t ra8_etha_open(ra8_etha_port_t channel, const ra8_etha_phy_open_t *phy, ra8_rmac_phy_link_t *out_link)
Bring an ETHA port + its off-chip PHY up to OPERATION mode.
ra8_err_t ra8_etha_descriptor_ring_init(ra8_etha_port_t channel, uint16_t num_tx, uint16_t num_rx, uint16_t buffer_size)
Configure the per-port descriptor-ring sizing.
static uint32_t internal_sat_add_u32(uint32_t base, uint32_t inc)
Saturating-add helper for the per-port traffic counters.
ra8_err_t ra8_etha_get_stats(ra8_etha_port_t channel, ra8_etha_port_stats_t *out_stats)
Snapshot the per-port software-maintained traffic counters.
Lightweight Logging Interface for ra8-firmware.
#define ra8_log_error(tag, message)
RA8 log error.
Definition ra8_log.h:335
ra8_err_t ra8_rmac_phy_set_advertise(ra8_rmac_port_t port, uint8_t phy_addr, uint16_t capabilities)
Program the off-chip PHY's auto-negotiation advertisement.
ra8_err_t ra8_rmac_phy_auto_neg_start(ra8_rmac_port_t port, uint8_t phy_addr)
Kick off (or restart) auto-negotiation on the off-chip PHY.
ra8_err_t ra8_rmac_phy_reset(ra8_rmac_port_t port, uint8_t phy_addr)
Software-reset an off-chip PHY via Clause-22 MDIO.
ra8_err_t ra8_rmac_phy_auto_neg_wait(ra8_rmac_port_t port, uint8_t phy_addr, uint32_t timeout_ms, ra8_rmac_phy_link_t *out_link)
Block (with a bounded poll) until the PHY reports AN_COMPLETE.
ra8_rmac_port_t
RMAC port index (m = 0, 1).
Full ETHA per-port register window (HUM Ch 32, FSP R_ETHA0_Type).
volatile uint32_t EAMC
+0x0000 Mode command.
volatile uint32_t EATDQDC[8]
+0x0060..0x007F Per-class queue depth.
volatile uint32_t EAMS
+0x0004 Mode status.
PHY auto-negotiation parameters for ra8_etha_open.
uint32_t timeout_ms
Auto-neg wait timeout (0 = internal cap).
uint16_t advertise
OR of ra8_rmac_phy_advert_t bits.
uint8_t phy_addr
MDIO address of the off-chip PHY (0..31).
Per-port runtime traffic counters maintained by ra8_etha.
uint32_t tx_ok
Frames transmitted successfully.
uint32_t rx_drop
Frames dropped due to ring overflow.
uint32_t tx_err
Frames that failed to transmit.
uint32_t rx_ok
Frames received successfully.
uint32_t rx_err
Frames received with PHY/MAC/FCS error.