|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
ETHA time-aware shaper (TAS / 802.1Qbv) flows – HUM Ch 32.4.2. More...
#include <stdint.h>#include "ra8_attributes.h"#include "ra8_check.h"#include "ra8_err.h"#include "ra8_etha.h"#include "ra8_etha_internal.h"#include "ra8_etha_regs.h"#include "ra8_hw_err.h"#include "ra8_log.h"Go to the source code of this file.
Enumerations | |
| enum | ra8_etha_tas_poll_t : uint32_t { k_ra8_etha_tas_learn_spins = 100000U , k_ra8_etha_tas_ram_spins = 100000U } |
| Spin budgets for the two TAS flows that wait on hardware. More... | |
| enum | ra8_etha_tas_word_t : uint32_t { k_ra8_etha_tas_word_mask = 0xFFFFFFFFUL } |
| Word-width mask used when splitting the 64-bit cycle start time. More... | |
Functions | |
| static ra8_err_t | internal_tas_learn_entry (volatile r_etha_regs_t *reg, uint8_t address, const ra8_etha_tas_entry_t *entry) |
| Learn one entry into the TAS RAM and wait for it to land. | |
| static ra8_err_t | internal_tas_validate (const ra8_etha_tas_queue_t *queues) |
| Reject a schedule hardware could not hold before any of it is written. | |
| static ra8_err_t | internal_tas_learn_all (volatile r_etha_regs_t *reg, const ra8_etha_tas_queue_t *queues, uint8_t base) |
| Learn every queue's entries, laid out in queue order from base. | |
| ra8_err_t | ra8_etha_tas_ram_reset (ra8_etha_port_t port) |
| Reset the TAS RAM and wait for it to report ready. | |
| static void | internal_tas_program_timing (volatile r_etha_regs_t *reg, const ra8_etha_tas_queue_t *queues, uint8_t initial_gate_states, uint32_t cycle_time_ns, uint64_t start_time) |
| Write the schedule's sizing and timing registers. | |
| ra8_err_t | ra8_etha_set_tas_schedule (ra8_etha_port_t port, const ra8_etha_tas_queue_t *queues, uint8_t initial_gate_states, uint32_t cycle_time_ns, uint64_t start_time) |
| Programme the time-aware shaper (TAS / 802.1Qbv) gate lists. | |
| ra8_err_t | ra8_etha_read_tas_entry (ra8_etha_port_t port, uint8_t address, ra8_etha_tas_entry_t *out) |
| Read one TAS RAM entry back out of hardware. | |
| ra8_err_t | ra8_etha_enable_tas (ra8_etha_port_t port, uint8_t enable) |
| Enable or disable the TAS scheduler (main switch). | |
Variables | |
| static const char * | s_tag = "ETHA" |
| Logger tag used by every TAS call in this translation unit. | |
ETHA time-aware shaper (TAS / 802.1Qbv) flows – HUM Ch 32.4.2.
The TAS half of the ETHA driver, split out of ra8_etha.c because it is the only part of the block that is a multi-step hardware FLOW rather than a set of independent register writes. Three of the manual's flows are implemented here verbatim:
What was here before returned k_ra8_ok while programming the wrong things into the right registers (#539). EATASGL0.TASGAL[7:0] is the TAS RAM ENTRY ADDRESS – "Configures the address in which the TAS entry is learned" (HUM Ch 32.3.5.13 p 1652) – and it was receiving the gate state, so every learn iteration targeted an address derived from a gate bitmask and the entry index was never written at all. EATASGL1 bit 28 is TASGSL, the entry's gate state (Ch 32.3.5.14 p 1652), and it was receiving an unrelated "cut-through" flag. The mandatory per-queue entry counts (EATASENCi) were never written, and EATASGLR.GL – which hardware raises on every EATASGL1 write and lowers when the learn lands – was never polled, so the writes raced each other.
Nothing detected any of that, because all five shaper calls returned success from argument validation alone and no caller ever read hardware back. ra8_etha_read_tas_entry exists so that is no longer true.
Definition in file ra8_etha_tas.c.
| enum ra8_etha_tas_poll_t : uint32_t |
Spin budgets for the two TAS flows that wait on hardware.
Both waits are for an on-chip RAM operation that completes in a handful of ETHA clocks, so the budget only has to be large enough that a healthy part never reaches it and small enough that a wedged part is reported rather than hanging the caller forever.
| Enumerator | |
|---|---|
| k_ra8_etha_tas_learn_spins | EATASGLR.GL / EATASGRR.GR budget. |
| k_ra8_etha_tas_ram_spins | EATASRIRM.TASRR budget. |
Definition at line 76 of file ra8_etha_tas.c.
| enum ra8_etha_tas_word_t : uint32_t |
Word-width mask used when splitting the 64-bit cycle start time.
EATASCSTC0 and EATASCSTC1 together hold one 64-bit start time as two 32-bit halves, so the split needs a named 32-bit mask rather than a bare literal.
| Enumerator | |
|---|---|
| k_ra8_etha_tas_word_mask | All 32 bits of one register. |
Definition at line 91 of file ra8_etha_tas.c.
|
static |
Learn every queue's entries, laid out in queue order from base.
The per-queue blocks are contiguous and start at the address hardware nominated in EATASC.TASCA, so queue 0's block begins at base and each subsequent queue begins where the previous one ended.
| [in] | reg | MMIO pointer to the port's ETHA window. |
| [in] | queues | Per-queue gate lists, k_ra8_etha_tc_count of them. |
| [in] | base | TAS RAM address the first entry is written to. |
| k_ra8_ok | Every entry was learned. |
| k_ra8_err_hw_timeout | A learn never completed; nothing committed. |
Definition at line 223 of file ra8_etha_tas.c.
References ra8_etha_tas_queue_t::count, internal_tas_learn_entry(), k_ra8_etha_mask_tas_gal, k_ra8_etha_tas_entries_max, k_ra8_etha_tc_count, k_ra8_ok, and RA8_LOOP_BOUND.
Referenced by ra8_etha_set_tas_schedule().
|
static |
Learn one entry into the TAS RAM and wait for it to land.
HUM Figure 32.14 (Ch 32.4.2.12 "TAS Entry i Learn Flow" p 1677): set EATASGL0 to the entry address, write EATASGL1, then read EATASGLR until GL is 0. Writing EATASGL1 is what raises GL, so the poll must follow that write and not precede it.
| [in] | reg | MMIO pointer to the port's ETHA window. |
| [in] | address | TAS RAM entry address for this entry. |
| [in] | entry | Gate state and gate time to store. |
| k_ra8_ok | Hardware lowered EATASGLR.GL. |
| k_ra8_err_hw_timeout | GL stayed high for the whole budget. |
Definition at line 121 of file ra8_etha_tas.c.
References r_etha_regs_t::EATASGL0, r_etha_regs_t::EATASGL1, r_etha_regs_t::EATASGLR, ra8_etha_tas_entry_t::gate_open, ra8_etha_tas_entry_t::gate_time_ns, k_ra8_etha_eatasgl1_tasgsl_pos, k_ra8_etha_eatasglr_gl_pos, k_ra8_etha_mask_tas_gal, k_ra8_etha_mask_tas_gtl, k_ra8_etha_tas_learn_spins, k_ra8_ok, ra8_hw_wait_flag_clear32(), ra8_log_error, and s_tag.
Referenced by internal_tas_learn_all().
|
static |
Write the schedule's sizing and timing registers.
Steps 3 and 4 of HUM Figure 32.11: each queue's entry count to its own EATASENCi, the per-queue initial gate states to EATASIGSC, and the cycle start / cycle time to EATASCSTC0, EATASCSTC1 and EATASCTC. Split out of ra8_etha_set_tas_schedule so that function stays inside the statement budget; it is one contiguous block of the manual's flow with no decisions of its own.
| [in] | reg | MMIO pointer to the port's ETHA window. |
| [in] | queues | Per-queue gate lists, one per traffic class. |
| [in] | initial_gate_states | EATASIGSC bitmap, bit q per queue q. |
| [in] | cycle_time_ns | Value for EATASCTC. |
| [in] | start_time | 64-bit cycle start, split across CSTC0/CSTC1. |
Definition at line 292 of file ra8_etha_tas.c.
References r_etha_regs_t::EATASCSTC0, r_etha_regs_t::EATASCSTC1, r_etha_regs_t::EATASCTC, r_etha_regs_t::EATASENC, r_etha_regs_t::EATASIGSC, k_ra8_etha_mask_aen, k_ra8_etha_mask_tas_igs, k_ra8_etha_tas_word_mask, k_ra8_etha_tc_count, and RA8_LOOP_BOUND.
Referenced by ra8_etha_set_tas_schedule().
|
static |
Reject a schedule hardware could not hold before any of it is written.
Validates the whole request up front so a rejected schedule leaves the previously active one running: once the first EATASENCi write lands there is no way back. Checks the per-queue pointer contract, the TASGTL[27:0] width of every gate time, and the TAS RAM capacity limit from HUM Ch 32.3.5.3 (p 1647).
| [in] | queues | Per-queue gate lists, k_ra8_etha_tc_count of them. |
| k_ra8_ok | Schedule is programmable as given. |
| k_ra8_err_null_ptr | A non-empty queue has a nullptr entry list. |
| k_ra8_err_invalid_arg | Capacity or gate-time width exceeded. |
Definition at line 172 of file ra8_etha_tas.c.
References ra8_etha_tas_queue_t::count, k_ra8_err_invalid_arg, k_ra8_etha_mask_tas_gtl, k_ra8_etha_tas_entries_max, k_ra8_etha_tc_count, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_log_error, RA8_LOOP_BOUND, and s_tag.
Referenced by ra8_etha_set_tas_schedule().
|
nodiscard |
Enable or disable the TAS scheduler (main switch).
| [in] | port | Port identifier. |
| [in] | enable | Non-zero -> set EATASC.TASE; zero -> clear. |
| k_ra8_ok | EATASC.TASE updated. |
| k_ra8_err_invalid_arg | port out of range. |
Definition at line 389 of file ra8_etha_tas.c.
References r_etha_regs_t::EATASC, internal_port_ok(), k_ra8_err_invalid_arg, k_ra8_etha_eatasc_tase_pos, k_ra8_ok, ra8_etha(), ra8_log_error, and s_tag.
Referenced by tsn_program_tas().
|
nodiscard |
Read one TAS RAM entry back out of hardware.
The TAS entry read flow of HUM Figure 32.15 (Ch 32.4.2.13 "TAS Entry i Read Flow" p 1678): write the address to EATASGR.TASGAR, poll until EATASGRR.GR clears, then take TASGSR and TASGTR[27:0].
This is the read-back that lets a caller assert something real. Without it, the only available evidence that a schedule was programmed is that the programming calls returned k_ra8_ok – which they also did while the driver was writing gate states into the entry-address register.
| [in] | port | Port identifier. |
| [in] | address | TAS RAM entry address (0..k_ra8_etha_tas_addr_max). |
| [out] | out | Entry read back from that address. |
| k_ra8_ok | *out holds the entry at address. |
| k_ra8_err_null_ptr | out is nullptr. |
| k_ra8_err_invalid_arg | port out of range. |
| k_ra8_err_hw_timeout | EATASGRR.GR never cleared within budget. |
Definition at line 361 of file ra8_etha_tas.c.
References r_etha_regs_t::EATASGR, r_etha_regs_t::EATASGRR, ra8_etha_tas_entry_t::gate_open, ra8_etha_tas_entry_t::gate_time_ns, internal_port_ok(), k_ra8_err_invalid_arg, k_ra8_etha_eatasgrr_gr_pos, k_ra8_etha_eatasgrr_tasgsr_pos, k_ra8_etha_mask_tas_gal, k_ra8_etha_mask_tas_gtl, k_ra8_etha_tas_learn_spins, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_etha(), ra8_hw_wait_flag_clear32(), ra8_log_error, and s_tag.
Referenced by tsn_tas_entry_matches().
|
nodiscard |
Programme the time-aware shaper (TAS / 802.1Qbv) gate lists.
Implements the TAS setting flow of HUM Figure 32.11 (Ch 32.4.2.9 "TAS Setting Flow" p 1675-1676) exactly:
queues is indexed by descriptor queue because the TAS RAM is partitioned per queue rather than holding one interleaved list: the entry blocks are laid out in queue order from EATASC.TASCA upward, and an entry's single GS bit belongs to the queue whose block holds it.
| [in] | port | Port identifier. |
| [in] | queues | Per-queue gate lists; k_ra8_etha_tc_count elements. |
| [in] | initial_gate_states | EATASIGSC bitmap – bit q is queue q's gate state at schedule start (HUM Ch 32.3.5.2 p 1647). |
| [in] | cycle_time_ns | Total cycle time, written verbatim to EATASCTC. |
| [in] | start_time | Absolute cycle-start time on the gPTP time base; low word to EATASCSTC0, high word to EATASCSTC1. |
| k_ra8_ok | TAS programmed and committed. |
| k_ra8_err_null_ptr | queues is nullptr, or a queue declares a non-zero count with a nullptr entry list. |
| k_ra8_err_invalid_arg | port out of range, the total entry count exceeds k_ra8_etha_tas_entries_max, or a gate time does not fit TASGTL[27:0]. |
| k_ra8_err_busy | EATASC.TASCI is set; the port cannot accept a configuration change right now. |
| k_ra8_err_hw_timeout | EATASGLR.GL never cleared after a learn. |
Definition at line 313 of file ra8_etha_tas.c.
References r_etha_regs_t::EATASC, internal_port_ok(), internal_tas_learn_all(), internal_tas_program_timing(), internal_tas_validate(), k_ra8_err_busy, k_ra8_err_invalid_arg, k_ra8_etha_eatasc_tasca_pos, k_ra8_etha_eatasc_tascc_pos, k_ra8_etha_eatasc_tasci_pos, k_ra8_etha_eatasc_tase_pos, k_ra8_etha_mask_tas_gal, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_etha(), ra8_log_error, and s_tag.
Referenced by tsn_program_tas().
|
nodiscard |
Reset the TAS RAM and wait for it to report ready.
The TAS RAM reset flow of HUM Figure 32.8 (Ch 32.4.2.6 "TAS RAM Reset Flow" p 1667): write 1 to EATASRIRM.TASRIOG, then poll until EATASRIRM.TASRR reads 1. Hardware clears TASRIOG itself when the initialisation completes. Entries learned before a reset do not survive it, so this runs once during bring-up, ahead of any schedule.
| [in] | port | Port identifier. |
| k_ra8_ok | TAS RAM initialised; EATASRIRM.TASRR reads 1. |
| k_ra8_err_invalid_arg | port out of range. |
| k_ra8_err_hw_timeout | TASRR never asserted within budget. |
Definition at line 244 of file ra8_etha_tas.c.
References r_etha_regs_t::EATASRIRM, internal_port_ok(), k_ra8_err_invalid_arg, k_ra8_etha_eatasrirm_tasriog_pos, k_ra8_etha_eatasrirm_tasrr_pos, k_ra8_etha_tas_ram_spins, k_ra8_ok, ra8_etha(), ra8_hw_wait_flag_set32(), ra8_log_error, and s_tag.
Referenced by tsn_program_tas().
|
static |
Logger tag used by every TAS call in this translation unit.
TU-local read-only logger tag, matching the string the other two ETHA translation units use so a log reader sees one subsystem.
Definition at line 62 of file ra8_etha_tas.c.