|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
LIN (Local Interconnect Network) commander + responder driver on SCI_B. More...
Go to the source code of this file.
Data Structures | |
| struct | ra8_sci_lin_cfg_t |
| Configuration descriptor for ra8_sci_lin_init. More... | |
Enumerations | |
| enum | ra8_sci_lin_limits_t : uint8_t { k_ra8_sci_lin_id_max = 0x3FU } |
| Public range limits for the LIN frame identifier. More... | |
| enum | ra8_sci_lin_timer_clk_t : uint8_t { k_ra8_sci_lin_clk_div4 = 1U , k_ra8_sci_lin_clk_div16 = 2U , k_ra8_sci_lin_clk_div64 = 3U } |
| Break-field timer clock divider (maps to SCI_B XCR0.TCSS[1:0]). More... | |
| enum | ra8_sci_lin_role_t : uint8_t { k_ra8_sci_lin_role_commander = 0U , k_ra8_sci_lin_role_responder = 1U } |
| Selects whether the channel drives (commander) or detects (responder) the LIN frame header. More... | |
| enum | ra8_sci_lin_checksum_mode_t : uint8_t { k_ra8_sci_lin_checksum_classic = 0U , k_ra8_sci_lin_checksum_enhanced = 1U } |
| Selector for the classic vs. More... | |
Functions | |
| ra8_err_t | ra8_sci_lin_init (uint8_t channel, const ra8_sci_lin_cfg_t *cfg) |
| Configure an SCI_B channel for a LIN role (commander or responder). | |
| ra8_err_t | ra8_sci_lin_send_break (uint8_t channel) |
| Emit a LIN break field on the channel's TXD line. | |
| ra8_err_t | ra8_sci_lin_send_header (uint8_t channel, uint8_t id) |
| Transmit a full LIN header: break + SYNC (0x55) + PID. | |
| ra8_err_t | ra8_sci_lin_break_detected (uint8_t channel, bool *out_detected) |
| Report whether the responder's break-field detector has fired. | |
| ra8_err_t | ra8_sci_lin_wait_break (uint8_t channel) |
| Block until the responder detects a break field (XSR0.BFDF set). | |
| ra8_err_t | ra8_sci_lin_clear_status (uint8_t channel) |
| Clear the Simple-LIN status latches (XSR0) via XFCLR. | |
| ra8_err_t | ra8_sci_lin_send_response (uint8_t channel, ra8_sci_lin_checksum_mode_t mode, uint8_t pid, const uint8_t *data, uint8_t len) |
| Publish a LIN response: data bytes followed by the checksum. | |
| ra8_err_t | ra8_sci_lin_read_response (uint8_t channel, uint8_t *out_data, uint8_t len, uint8_t *out_checksum) |
| Read a LIN response: len data bytes plus one checksum byte. | |
| ra8_err_t | ra8_sci_lin_check_header (uint8_t sync, uint8_t pid, uint8_t *out_id, bool *out_valid) |
| Validate a received LIN header: SYNC byte + protected identifier. | |
| ra8_err_t | ra8_sci_lin_check_response (ra8_sci_lin_checksum_mode_t mode, uint8_t pid, const uint8_t *data, uint8_t len, uint8_t received, bool *out_valid) |
| Verify a received LIN response checksum against the data field. | |
| uint8_t | ra8_sci_lin_pid (uint8_t id) |
| Compute the LIN protected identifier (PID) from a frame id. | |
| ra8_err_t | ra8_sci_lin_checksum (ra8_sci_lin_checksum_mode_t mode, uint8_t pid, const uint8_t *data, uint8_t len, uint8_t *out_checksum) |
| Compute a classic or enhanced LIN checksum over a data field. | |
LIN (Local Interconnect Network) commander + responder driver on SCI_B.
LIN is a single-wire, single-commander serial protocol layered on top of a standard UART. The commander node drives every frame header; it emits a BREAK field (at least 13 dominant bit-times), a SYNC byte (0x55), and a protected identifier (PID = a 6-bit frame id plus two parity bits). The header is then followed by a response phase – data bytes and a checksum – published by whichever node the frame id assigns as the transmitter (commander or responder).
This driver implements both LIN roles on the SCI_B Simple-LIN sub-mode:
This driver targets the SCI_B Simple-LIN sub-mode (HUM Ch 38.11 "Simple LIN Mode", p 2338; register-level break generation via XCR0/XCR1/XCR2 and detection via XSR0/XSR1/XFCLR). It builds on the async-UART bring-up in ra8_sci.h: ra8_sci_lin_init configures the baud / framing through the base UART path and then switches CCR3.MOD to Simple LIN and programs the role-specific break-field timer / detector.
This header includes ra8_sci.h one-directionally for the base configuration type (ra8_sci_cfg_t). ra8_sci.h does NOT include this header back; consumers that need the LIN API include ra8_sci_lin.h directly.
Lifecycle:
Commander frame generation:
Responder frame detection:
Response (data) phase, either role:
Pure helpers:
Definition in file ra8_sci_lin.h.
| enum ra8_sci_lin_checksum_mode_t : uint8_t |
Selector for the classic vs.
enhanced LIN checksum.
Classic (LIN 1.x) sums only the data bytes; enhanced (LIN 2.x) folds the protected identifier into the sum as well. Both then take the inverted modulo-255 sum.
| Enumerator | |
|---|---|
| k_ra8_sci_lin_checksum_classic | LIN 1.x: sum of data bytes only. |
| k_ra8_sci_lin_checksum_enhanced | LIN 2.x: sum of PID + data bytes. |
Definition at line 144 of file ra8_sci_lin.h.
| enum ra8_sci_lin_limits_t : uint8_t |
Public range limits for the LIN frame identifier.
The LIN protected identifier carries a 6-bit frame id, so the largest legal value passed to ra8_sci_lin_send_header is 0x3F (63).
| Enumerator | |
|---|---|
| k_ra8_sci_lin_id_max | Highest legal 6-bit LIN frame id. |
Definition at line 99 of file ra8_sci_lin.h.
| enum ra8_sci_lin_role_t : uint8_t |
Selects whether the channel drives (commander) or detects (responder) the LIN frame header.
A LIN bus has exactly one commander that generates every frame header (break + sync + PID) and any number of responders that detect it. The two roles program different Simple-LIN control bits at init: the commander arms the break-field output timer (XCR1.TCST is pulsed per frame), while the responder arms Start-Frame detection (XCR1.SDST) plus bit-rate measurement (XCR1.BMEN) so the hardware flags an inbound break in XSR0.BFDF and measures the sync field into XSR1.TCNT.
| Enumerator | |
|---|---|
| k_ra8_sci_lin_role_commander | Generate the header (bus controller). |
| k_ra8_sci_lin_role_responder | Detect the header (subordinate node). |
Definition at line 131 of file ra8_sci_lin.h.
| enum ra8_sci_lin_timer_clk_t : uint8_t |
Break-field timer clock divider (maps to SCI_B XCR0.TCSS[1:0]).
Selects the divider applied to the Simple-LIN module timer clock (TCLK) that times the break field. The enumerator values equal the on-chip XCR0.TCSS encodings (HUM Ch 38.2.14, p 2221), so no translation table is needed.
| Enumerator | |
|---|---|
| k_ra8_sci_lin_clk_div4 | Break timer clock = TCLK / 4. |
| k_ra8_sci_lin_clk_div16 | Break timer clock = TCLK / 16. |
| k_ra8_sci_lin_clk_div64 | Break timer clock = TCLK / 64. |
Definition at line 112 of file ra8_sci_lin.h.
|
nodiscard |
Report whether the responder's break-field detector has fired.
Reads XSR0.BFDF once (non-blocking) and writes its state to *out_detected. On a responder channel the Simple-LIN Start-Frame detector sets BFDF when it sees a dominant span at least as long as the configured break-field length; the flag stays set until cleared through ra8_sci_lin_clear_status. Reads no data and modifies no hardware.
| [in] | channel | SCI channel number (0..9). |
| [out] | out_detected | Receives true if XSR0.BFDF is set, else false. |
| k_ra8_ok | Flag state written to *out_detected. |
| k_ra8_err_null_ptr | out_detected is NULL or channel out of range. |
Definition at line 367 of file ra8_sci_lin.c.
References k_ra8_ok, k_ra8_sci_xsr0_bit_bfdf, RA8_CHECK_NULL_PTR, ra8_sci(), s_tag, and r_sci_regs_t::XSR0.
|
nodiscard |
Validate a received LIN header: SYNC byte + protected identifier.
A responder accepts a header only when BOTH the SYNC field equals 0x55 AND the received PID's parity bits match the parity recomputed from its low 6 bits. This pure predicate performs exactly that compound check, writing the extracted 6-bit frame id to *out_id and the accept decision to *out_valid. Pure: touches no hardware register.
| [in] | sync | The received SYNC field byte (must be 0x55). |
| [in] | pid | The received protected-identifier byte. |
| [out] | out_id | Receives the low 6 bits of pid (the frame id). |
| [out] | out_valid | Receives true iff SYNC == 0x55 and PID parity is OK. |
| k_ra8_ok | Decision written to *out_valid / *out_id. |
| k_ra8_err_null_ptr | out_id or out_valid is NULL. |
Definition at line 494 of file ra8_sci_lin.c.
References k_ra8_ok, k_ra8_sci_lin_id_mask, k_ra8_sci_lin_sync_byte, RA8_CHECK_NULL_PTR, ra8_sci_lin_pid(), and s_tag.
|
nodiscard |
Verify a received LIN response checksum against the data field.
Recomputes the classic or enhanced checksum over data (and pid for the enhanced mode) with ra8_sci_lin_checksum and compares it to the received checksum byte, writing the match result to *out_valid. Pure: touches no hardware register. Pair with ra8_sci_lin_read_response to validate an inbound response.
| [in] | mode | Classic (data only) or enhanced (PID + data). |
| [in] | pid | Protected identifier, folded in for enhanced mode. |
| [in] | data | Data-field byte buffer; non-NULL when len > 0. |
| [in] | len | Number of data bytes (0..8). |
| [in] | received | The checksum byte received on the wire. |
| [out] | out_valid | Receives true iff the recomputed checksum matches. |
| k_ra8_ok | Decision written to *out_valid. |
| k_ra8_err_null_ptr | out_valid is NULL, or data NULL with len > 0. |
| k_ra8_err_invalid_arg | mode is not a defined checksum mode. |
Definition at line 509 of file ra8_sci_lin.c.
References k_ra8_ok, RA8_CHECK_NULL_PTR, RA8_RETURN_ON_ERROR, ra8_sci_lin_checksum(), and s_tag.
|
nodiscard |
Compute a classic or enhanced LIN checksum over a data field.
Sums the data bytes (and, for k_ra8_sci_lin_checksum_enhanced, the protected identifier pid) into an accumulator, folds the carry bits back into the low byte to form the modulo-255 sum, and returns the one's complement of that sum. Pure: touches no hardware register.
| [in] | mode | Classic (data only) or enhanced (PID + data). |
| [in] | pid | Protected identifier, folded in only when mode == k_ra8_sci_lin_checksum_enhanced. |
| [in] | data | Data-field byte buffer; may be NULL only when len == 0. |
| [in] | len | Number of data bytes (0..8 for standard LIN). |
| [out] | out_checksum | Receives the 8-bit checksum on success. |
| k_ra8_ok | Checksum computed. |
| k_ra8_err_null_ptr | out_checksum is NULL, or data is NULL while len > 0. |
| k_ra8_err_invalid_arg | mode is not a defined checksum mode. |
Definition at line 465 of file ra8_sci_lin.c.
References internal_lin_fold_complement(), k_ra8_err_invalid_arg, k_ra8_err_null_ptr, k_ra8_ok, k_ra8_sci_lin_checksum_enhanced, RA8_CHECK_NULL_PTR, and s_tag.
Referenced by ra8_sci_lin_check_response(), and ra8_sci_lin_send_response().
|
nodiscard |
Clear the Simple-LIN status latches (XSR0) via XFCLR.
Writes the clear-all-LIN mask to XFCLR, which clears every W1C XSR0 latch (BFDF, AEDF, COF, bus-conflict, and the control-field match flags). A responder calls this after consuming one frame's break / sync detection so the detector is armed clean for the next header.
| [in] | channel | SCI channel number (0..9). |
| k_ra8_ok | LIN status latches cleared. |
| k_ra8_err_null_ptr | channel out of range. |
Definition at line 391 of file ra8_sci_lin.c.
References k_ra8_ok, k_ra8_sci_xfclr_default, RA8_CHECK_NULL_PTR, ra8_sci(), s_tag, and r_sci_regs_t::XFCLR.
|
nodiscard |
Configure an SCI_B channel for a LIN role (commander or responder).
First brings the channel up as an async UART (ra8_sci_init with cfg->uart: MSTP gate, baud, framing, TE/RE). It then drops CCR0, switches CCR3.MOD to Simple LIN (110b) while preserving the framing bits the base init programmed, programs the break-field timer clock (XCR0.TCSS) and break-field enable (XCR0.BFE), sets the break-field length (XCR2.BFLW), and re-enables CCR0.TE + CCR0.RE. The XCR1 program depends on cfg->role: a commander leaves XCR1 idle (TCST is pulsed per frame by ra8_sci_lin_send_break); a responder sets XCR1.SDST (Start-Frame detection) and XCR1.BMEN (bit-rate measurement) so the hardware flags an inbound break in XSR0.BFDF (HUM Ch 38.11.2 p 2341).
| [in] | channel | SCI channel number (0..9). |
| [in] | cfg | Non-NULL LIN configuration descriptor. |
| k_ra8_ok | Channel configured for the requested role. |
| k_ra8_err_null_ptr | cfg was NULL or channel out of range. |
| k_ra8_err_invalid_arg | role undefined, timer_clk not a defined divider, or break_field_len exceeds 0xFFFE. |
| k_ra8_err_hw_init_failed | The underlying ra8_sci_init failed. |
Definition at line 306 of file ra8_sci_lin.c.
References ra8_sci_lin_cfg_t::break_field_len, internal_lin_program_mode(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_sci_lin_clk_div4, k_ra8_sci_lin_clk_div64, k_ra8_sci_lin_role_responder, k_ra8_sci_xcr2_bflw_max, RA8_CHECK_NULL_PTR, ra8_log_info_val, RA8_RETURN_ON_ERROR, ra8_sci(), ra8_sci_init(), ra8_sci_lin_cfg_t::role, s_tag, ra8_sci_lin_cfg_t::timer_clk, and ra8_sci_lin_cfg_t::uart.
Referenced by lin_hil_setup_or_halt().
|
nodiscard |
Compute the LIN protected identifier (PID) from a frame id.
The PID packs the 6-bit frame id in bits 0..5 plus two parity bits: P0 = ID0 ^ ID1 ^ ID2 ^ ID4 in bit 6, and P1 = NOT(ID1 ^ ID3 ^ ID4 ^ ID5) in bit 7 (LIN 2.x parity). Any caller bits above bit 5 are masked off before the parity is computed, so the function is total. Pure: touches no hardware register.
| [in] | id | LIN frame identifier; only the low 6 bits are significant. |
Definition at line 446 of file ra8_sci_lin.c.
References k_ra8_sci_lin_bit_mask, k_ra8_sci_lin_id_bit0, k_ra8_sci_lin_id_bit1, k_ra8_sci_lin_id_bit2, k_ra8_sci_lin_id_bit3, k_ra8_sci_lin_id_bit4, k_ra8_sci_lin_id_bit5, k_ra8_sci_lin_id_mask, k_ra8_sci_lin_pid_p0_shift, and k_ra8_sci_lin_pid_p1_shift.
Referenced by lin_hil_send_frame(), ra8_sci_lin_check_header(), and ra8_sci_lin_send_header().
|
nodiscard |
Read a LIN response: len data bytes plus one checksum byte.
Drains len data bytes into out_data and the trailing checksum byte into *out_checksum, each via ra8_sci_putc_polling's receive peer ra8_sci_getc_polling. This is a thin I/O primitive: it does NOT validate the checksum – the caller passes out_data / *out_checksum to ra8_sci_lin_check_response to verify. Used by the receiving node of a frame (the subscriber).
| [in] | channel | SCI channel number (0..9). |
| [out] | out_data | Buffer receiving len data bytes. |
| [in] | len | Number of data bytes to read (1..8). |
| [out] | out_checksum | Receives the trailing checksum byte. |
| k_ra8_ok | len data bytes + checksum read. |
| k_ra8_err_null_ptr | channel out of range, or out_data / out_checksum is NULL. |
| k_ra8_err_invalid_arg | len is 0 or > 8. |
| k_ra8_err_hw_timeout | An RDRF poll timed out mid-frame. |
Definition at line 428 of file ra8_sci_lin.c.
References internal_lin_rx_buf(), k_ra8_err_invalid_arg, k_ra8_sci_lin_data_max, RA8_CHECK_NULL_PTR, RA8_RETURN_ON_ERROR, ra8_sci(), ra8_sci_getc_polling(), and s_tag.
|
nodiscard |
Emit a LIN break field on the channel's TXD line.
Writes 1 to XCR1.TCST, which starts the hardware break-field timer; the SCI_B holds TXD dominant for the (BFLW + 1) x timer-clock period set at init and self-clears TCST when the field completes. The call then blocks (bounded spin) until TCST reads back clear. On the host (RA8_OFF_TARGET) the timer drain is not modelled, so the wait returns success immediately.
| [in] | channel | SCI channel number (0..9). |
| k_ra8_ok | Break field emitted (or fake stub). |
| k_ra8_err_null_ptr | channel out of range. |
| k_ra8_err_hw_timeout | TCST did not self-clear within the budget. |
Definition at line 332 of file ra8_sci_lin.c.
References internal_lin_wait_break_done(), k_ra8_sci_xcr1_bit_tcst, RA8_CHECK_NULL_PTR, ra8_sci(), s_tag, and r_sci_regs_t::XCR1.
Referenced by ra8_sci_lin_send_header().
|
nodiscard |
Transmit a full LIN header: break + SYNC (0x55) + PID.
Emits the break field (ra8_sci_lin_send_break), then sends the SYNC byte 0x55 and the protected identifier as two ordinary UART frames via ra8_sci_putc_polling. The PID is computed from id with ra8_sci_lin_pid (6-bit id plus the two LIN parity bits).
| [in] | channel | SCI channel number (0..9). |
| [in] | id | 6-bit LIN frame identifier (0..63). |
| k_ra8_ok | Header transmitted. |
| k_ra8_err_null_ptr | channel out of range. |
| k_ra8_err_invalid_arg | id exceeds 63. |
| k_ra8_err_hw_timeout | A TDRE poll or the break wait timed out. |
Definition at line 344 of file ra8_sci_lin.c.
References k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_sci_lin_id_max, k_ra8_sci_lin_sync_byte, RA8_CHECK_NULL_PTR, RA8_RETURN_ON_ERROR, ra8_sci(), ra8_sci_lin_pid(), ra8_sci_lin_send_break(), ra8_sci_putc_polling(), and s_tag.
Referenced by lin_hil_send_frame().
|
nodiscard |
Publish a LIN response: data bytes followed by the checksum.
Computes the classic or enhanced checksum over data (folding pid in for the enhanced mode) via ra8_sci_lin_checksum, then clocks the len data bytes and the checksum byte out as ordinary UART frames with ra8_sci_putc_polling. Used by the transmitting node of a frame: the commander for a commander-to-responder frame, or a responder for a responder-to-commander frame. The caller must already have sent (as commander) or detected (as responder) the header.
| [in] | channel | SCI channel number (0..9). |
| [in] | mode | Classic (data only) or enhanced (PID + data) checksum. |
| [in] | pid | Protected identifier, folded into the enhanced sum. |
| [in] | data | Data-field byte buffer; non-NULL when len > 0. |
| [in] | len | Number of data bytes (1..8 for standard LIN). |
| k_ra8_ok | Data + checksum clocked out. |
| k_ra8_err_null_ptr | channel out of range, or data NULL with len > 0. |
| k_ra8_err_invalid_arg | mode undefined or len is 0 or > 8. |
| k_ra8_err_hw_timeout | A TDRE poll timed out mid-frame. |
Definition at line 401 of file ra8_sci_lin.c.
References internal_lin_tx_buf(), k_ra8_err_invalid_arg, k_ra8_sci_lin_data_max, RA8_CHECK_NULL_PTR, RA8_RETURN_ON_ERROR, ra8_sci(), ra8_sci_lin_checksum(), ra8_sci_putc_polling(), and s_tag.
Referenced by lin_hil_send_frame().
|
nodiscard |
Block until the responder detects a break field (XSR0.BFDF set).
Spins on XSR0.BFDF with a bounded budget; returns as soon as the break field is detected. On the host (RA8_OFF_TARGET) the poll runs against the programmable MMIO seam, so a test pre-stages BFDF or arms a timeout. Does not clear the flag – call ra8_sci_lin_clear_status before waiting for the next frame.
| [in] | channel | SCI channel number (0..9). |
| k_ra8_ok | A break field was detected within the budget. |
| k_ra8_err_null_ptr | channel out of range. |
| k_ra8_err_hw_timeout | No break field detected within the budget. |
Definition at line 379 of file ra8_sci_lin.c.
References k_ra8_hw_budget_long, k_ra8_sci_xsr0_bit_bfdf, RA8_CHECK_NULL_PTR, ra8_hw_wait_flag_set32(), ra8_sci(), s_tag, and r_sci_regs_t::XSR0.