ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_spi_b_dma.c
Go to the documentation of this file.
1
33
34#include <stdint.h>
35
36#include "ra8_attributes.h"
37#include "ra8_cache.h"
38#include "ra8_check.h"
39#include "ra8_dma.h"
40#include "ra8_dmac.h"
41#include "ra8_err.h"
42#include "ra8_spi.h"
43#include "ra8_spi_regs.h"
44
45static const char* s_tag = "SPI_B";
46
71RA8_INTERNAL static ra8_err_t internal_dma_args_ok(uint8_t channel, uint16_t len)
72{
73 ra8_err_t err = k_ra8_ok;
74 if (channel >= k_ra8_spi_b_channel_count) {
76 }
77 if (len == 0U) {
79 }
80 return err;
81}
82
83/* =============================================================================
84 * DMA TX / RX
85 * =============================================================================
86 */
87
113
125
149RA8_INTERNAL static uint32_t internal_round_up_to_cache_line(uint32_t bytes)
150{
151 if (bytes == 0U) {
152 return 0U;
153 }
154 const uint32_t line = ra8_cache_dcache_line_bytes();
155 if (line == 0U) { /* GCOVR_EXCL_BR_LINE -- cache line size fixed nonzero by architecture */
156 return bytes; /* GCOVR_EXCL_LINE -- cache line size fixed nonzero by architecture */
157 }
158 return (bytes + (line - 1U)) & ~(line - 1U);
159}
160
186{
188 if (rxc == nullptr) { /* GCOVR_EXCL_BR_LINE -- callback set by internal caller, never null */
189 return; /* GCOVR_EXCL_LINE -- callback set by internal caller, never null */
190 }
192 if (rxc->user_on_complete != nullptr) {
193 rxc->user_on_complete(rxc->user_ctx);
194 }
195}
196
198 const uint8_t* data,
199 uint16_t len,
200 ra8_dma_complete_fn_t on_complete,
201 void* ctx,
202 uint8_t* out_dma_channel)
203{
204 RA8_CHECK_NULL_PTR(data, s_tag, "spi_write_dma: data");
205 RA8_CHECK_NULL_PTR(out_dma_channel, s_tag, "spi_write_dma: out_dma_channel");
206 const ra8_err_t args_ok = internal_dma_args_ok(channel, len);
207 if (args_ok != k_ra8_ok) {
208 return args_ok;
209 }
210 volatile r_spi_regs_t* reg = ra8_spi(channel);
211 if (reg == nullptr) { /* GCOVR_EXCL_BR_LINE -- internal caller proves reg non-null */
212 return k_ra8_err_invalid_arg; /* GCOVR_EXCL_LINE -- internal caller proves reg non-null */
213 }
214 /* Cache coherency: the SPI DMA reads CPU-written 'data' straight from
215 * memory, so flush any dirty lines covering it before the engine starts.
216 * No-op when the D-cache is disabled. */
218 /* Byte-wide DMA writes target the low byte of SPDR; wider-frame
219 * streaming is a future wave. */
220 /* HUM Ch 43.2.2 "SPDR : SPI Data Register" p 2881 */
221 ra8_dma_request_t req = {};
222 req.src_addr = (uintptr_t)data;
223 req.dst_addr = (uintptr_t)&reg->SPDR;
224 req.count = len;
226 req.src_inc = true;
227 req.dst_inc = false;
228 req.trigger = (ra8_elc_event_t)0;
229 req.on_complete = on_complete;
230 req.ctx = ctx;
231 return ra8_dma_request(&req, out_dma_channel);
232}
233
235 uint8_t* out_buf,
236 uint16_t len,
237 ra8_dma_complete_fn_t on_complete,
238 void* ctx,
239 uint8_t* out_dma_channel)
240{
241 RA8_CHECK_NULL_PTR(out_buf, s_tag, "spi_read_dma: out_buf");
242 RA8_CHECK_NULL_PTR(out_dma_channel, s_tag, "spi_read_dma: out_dma_channel");
243 const ra8_err_t args_ok = internal_dma_args_ok(channel, len);
244 if (args_ok != k_ra8_ok) {
245 return args_ok;
246 }
247 volatile r_spi_regs_t* reg = ra8_spi(channel);
248 if (reg == nullptr) { /* GCOVR_EXCL_BR_LINE -- internal caller proves reg non-null */
249 return k_ra8_err_invalid_arg; /* GCOVR_EXCL_LINE -- internal caller proves reg non-null */
250 }
251 /* Cache coherency: the RX DMA writes out_buf straight to memory. Wrap the
252 * caller's completion so the CPU invalidates those lines once the transfer
253 * is known-complete -- before it (or the caller's callback) reads them.
254 * The wrapper is the only known-complete hook in this asynchronous path
255 * (ra8_dma_request returns immediately; completion fires from the DMAC
256 * transfer-end ISR). No-op when the D-cache is disabled. */
257 ra8_spi_dma_rx_ctx_t* rxc = &s_spi_dma_rx_ctx[channel];
258 rxc->rx_buf = out_buf;
259 rxc->rx_len = len;
260 rxc->user_on_complete = on_complete;
261 rxc->user_ctx = ctx;
262
263 /* HUM Ch 43.2.2 "SPDR : SPI Data Register" p 2881 */
264 ra8_dma_request_t req = {};
265 req.src_addr = (uintptr_t)&reg->SPDR;
266 req.dst_addr = (uintptr_t)out_buf;
267 req.count = len;
269 req.src_inc = false;
270 req.dst_inc = true;
271 req.trigger = (ra8_elc_event_t)0;
273 req.ctx = rxc;
274 return ra8_dma_request(&req, out_dma_channel);
275}
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).
Cortex-M85 L1 cache maintenance, enable/disable, and I-cache invalidate.
ra8_err_t ra8_cache_dcache_invalidate_by_addr(const void *addr, uint32_t size)
Invalidate (drop) the D-cache lines covering a byte range.
Definition ra8_cache.c:185
uint32_t ra8_cache_dcache_line_bytes(void)
Smallest Cortex-M85 D-cache line size, in bytes.
Definition ra8_cache.c:97
ra8_err_t ra8_cache_dcache_clean_by_addr(const void *addr, uint32_t size)
Clean (write back) the D-cache lines covering a byte range.
Definition ra8_cache.c:180
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
Generic DMA transfer substrate (DMAC engine).
ra8_err_t ra8_dma_request(const ra8_dma_request_t *req, uint8_t *out_channel)
Allocate a DMAC channel, programme it, and start the trigger wiring.
Definition ra8_dma.c:308
void(* ra8_dma_complete_fn_t)(void *ctx)
Caller-supplied completion callback.
Definition ra8_dma.h:88
8-channel DMA controller (DMAC0) driver
@ k_ra8_dmac_width_byte
8-bit transfers (DMTMD.SZ = 00b).
Definition ra8_dmac.h:51
ra8_elc_event_t
Partial list of ELC events (populate as drivers need them).
Error Code Definitions for ra8-firmware.
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ 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
SPI_B controller driver (RA8D2 Type-B SPI peripheral).
static ra8_err_t internal_dma_args_ok(uint8_t channel, uint16_t len)
Report whether a DMA entry point's channel index and length are usable.
static ra8_spi_dma_rx_ctx_t s_spi_dma_rx_ctx[k_ra8_spi_b_channel_count]
Per-channel RX-DMA completion bridge, indexed by SPI channel.
static uint32_t internal_round_up_to_cache_line(uint32_t bytes)
Round a byte count up to a whole number of D-cache lines.
ra8_err_t ra8_spi_read_dma(uint8_t channel, uint8_t *out_buf, uint16_t len, ra8_dma_complete_fn_t on_complete, void *ctx, uint8_t *out_dma_channel)
Kick off a DMA-backed RX transfer on an SPI channel.
static void internal_spi_dma_rx_complete(void *ctx)
RX-DMA transfer-end wrapper: invalidate the buffer, then chain.
ra8_err_t ra8_spi_write_dma(uint8_t channel, const uint8_t *data, uint16_t len, ra8_dma_complete_fn_t on_complete, void *ctx, uint8_t *out_dma_channel)
Kick off a DMA-backed TX transfer on an SPI channel.
SPI_B register layout for the Renesas RA8D2.
static volatile r_spi_regs_t * ra8_spi(uint8_t channel)
Get pointer to SPI_B channel channel (0..1).
@ k_ra8_spi_b_channel_count
SPI0 + SPI1.
SPI_B register-window mirror (matches FSP R_SPI_B0_Type, 0x70 bytes).
volatile uint32_t SPDR
+0x00 SPI Data Register.
Descriptor for a single DMA transfer.
Definition ra8_dma.h:115
ra8_dma_complete_fn_t on_complete
On complete.
Definition ra8_dma.h:123
uintptr_t dst_addr
Dst address.
Definition ra8_dma.h:117
bool dst_inc
Dst inc.
Definition ra8_dma.h:121
ra8_dmac_width_t width
Width.
Definition ra8_dma.h:119
bool src_inc
Src inc.
Definition ra8_dma.h:120
uint16_t count
Count.
Definition ra8_dma.h:118
uintptr_t src_addr
Src address.
Definition ra8_dma.h:116
void * ctx
Ctx.
Definition ra8_dma.h:124
ra8_elc_event_t trigger
Trigger.
Definition ra8_dma.h:122
Driver-owned completion context for an RX DMA, used to bridge the cache-invalidate step onto the call...
void * rx_buf
Caller RX buffer to invalidate.
uint16_t rx_len
RX byte count (pre-rounding).
ra8_dma_complete_fn_t user_on_complete
Caller callback (may be NULL).
void * user_ctx
Caller callback context.