ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_dma.c
Go to the documentation of this file.
1
18
19#include "ra8_dma.h"
20
21#include <stdint.h>
22
23#include "ra8_attributes.h"
24#include "ra8_check.h"
25#include "ra8_dmac.h"
26#include "ra8_err.h"
27#include "ra8_log.h"
28#include "ra8_mstp.h"
29#include "ra8_mstp_regs.h"
30
31static const char* s_tag = "DMA";
32
33/* =============================================================================
34 * State
35 * =============================================================================
36 */
37
47
60
61#ifdef RA8_OFF_TARGET
75static ra8_dma_request_t s_fake_requests[k_ra8_dma_channel_count];
76#endif
77
83static bool s_initialized = false;
84
85/* =============================================================================
86 * Internal helpers
87 * =============================================================================
88 */
89
114{
115 for (uint8_t ch = 0U; ch < k_ra8_dma_channel_count; ++ch) {
116 if (!s_channels[ch].in_use) {
117 return ch;
118 }
119 }
121}
122
145 ra8_dmac_config_t* out_cfg)
146{
147 out_cfg->src = (uint32_t)req->src_addr;
148 out_cfg->dst = (uint32_t)req->dst_addr;
149 out_cfg->count = req->count;
150 out_cfg->width = req->width;
151 out_cfg->src_inc = req->src_inc;
152 out_cfg->dst_inc = req->dst_inc;
153}
154
179{
180 if (req->count == 0U) {
182 }
183 if ((uint8_t)req->width > k_ra8_dmac_width_word) {
185 }
186 return k_ra8_ok;
187}
188
189/* =============================================================================
190 * Public API
191 * =============================================================================
192 */
193
216{
217 ra8_log_info(s_tag, "ra8_dma_init");
218
219 /* HUM Ch 11.2.6 "MSTPCRA : Module Stop Control Register A", p 443
220 * -- DMAC0 + DTC0 share MSTPA22. */
222 if (mst_err != k_ra8_ok) {
223 ra8_log_error_val(s_tag, "mstp enable failed", (uint32_t)mst_err);
225 }
226
227 for (uint8_t ch = 0U; ch < k_ra8_dma_channel_count; ++ch) {
228 s_channels[ch].on_complete = nullptr;
229 s_channels[ch].ctx = nullptr;
230 s_channels[ch].in_use = false;
231 }
232 s_initialized = true;
233 return k_ra8_ok;
234}
235
258{
259 /* Tear down every in-use channel before releasing the MSTP
260 * reference so no pending transfer can wedge the DMAC block. */
261 for (uint8_t ch = 0U; ch < k_ra8_dma_channel_count; ++ch) {
262 if (s_channels[ch].in_use) {
263 /* Ignore dmac_stop errors -- the goal is to get every
264 * channel into a safe state before releasing MSTP. */
265 (void)ra8_dmac_stop(ch);
266 s_channels[ch].on_complete = nullptr;
267 s_channels[ch].ctx = nullptr;
268 s_channels[ch].in_use = false;
269 }
270 }
271
273 if (mst_err != k_ra8_ok) {
274 ra8_log_error_val(s_tag, "mstp disable failed", (uint32_t)mst_err);
275 return k_ra8_err_hw_error;
276 }
277 s_initialized = false;
278 return k_ra8_ok;
279}
280
308ra8_err_t ra8_dma_request(const ra8_dma_request_t* req, uint8_t* out_channel)
309{
310 RA8_CHECK_NULL_PTR(req, s_tag, "request must not be NULL");
311 RA8_CHECK_NULL_PTR(out_channel, s_tag, "out_channel must not be NULL");
312 if (!s_initialized) {
314 }
315
316 const ra8_err_t verr = internal_validate_request(req);
317 if (verr != k_ra8_ok) {
318 return verr;
319 }
320
321 const uint8_t ch = internal_find_free();
322 if (ch == k_ra8_dma_channel_none) {
323 ra8_log_error(s_tag, "no free channel");
324 return k_ra8_err_no_mem;
325 }
326
327 ra8_dmac_config_t cfg = {};
328 internal_pack_dmac_cfg(req, &cfg);
329
330 const ra8_err_t derr = ra8_dmac_start(ch, &cfg);
331 if (derr != k_ra8_ok) {
332 ra8_log_error_val(s_tag, "dmac_start failed", (uint32_t)derr);
333 return k_ra8_err_hw_error;
334 }
335
336 s_channels[ch].on_complete = req->on_complete;
337 s_channels[ch].ctx = req->ctx;
338 s_channels[ch].in_use = true;
339#ifdef RA8_OFF_TARGET
340 s_fake_requests[ch] = *req;
341#endif
342 *out_channel = ch;
343 return k_ra8_ok;
344}
345
371{
372 if (channel >= k_ra8_dma_channel_count) {
374 }
375 if (!s_channels[channel].in_use) {
377 }
378
379 /* ra8_dmac_stop itself drops one MSTP reference -- the bit
380 * stays cleared because ra8_dma_init holds the root reference. */
381 const ra8_err_t stop_err = ra8_dmac_stop(channel);
382 if (stop_err != k_ra8_ok) {
383 ra8_log_error_val(s_tag, "dmac_stop failed", (uint32_t)stop_err);
384 return k_ra8_err_hw_error;
385 }
386
387 s_channels[channel].on_complete = nullptr;
388 s_channels[channel].ctx = nullptr;
389 s_channels[channel].in_use = false;
390 return k_ra8_ok;
391}
392
393#ifdef RA8_OFF_TARGET
416const ra8_dma_request_t* ra8_dma_fake_peek_request(uint8_t channel)
417{
418 if (channel >= k_ra8_dma_channel_count) {
419 return nullptr;
420 }
421 if (!s_channels[channel].in_use) {
422 return nullptr;
423 }
424 return &s_fake_requests[channel];
425}
426#endif
427
428ra8_err_t ra8_dma_channel_is_busy(uint8_t channel, bool* out_busy)
429{
430 RA8_CHECK_NULL_PTR(out_busy, s_tag, "out_busy must not be NULL");
431 if (channel >= k_ra8_dma_channel_count) {
433 }
434 *out_busy = s_channels[channel].in_use;
435 return k_ra8_ok;
436}
437
458void ra8_dma_dispatch_complete(uint8_t channel)
459{
460 if (channel >= k_ra8_dma_channel_count) {
461 return;
462 }
463 const ra8_dma_complete_fn_t cb = s_channels[channel].on_complete;
464 void* const ctx = s_channels[channel].ctx;
465 if (cb != nullptr) {
466 cb(ctx);
467 }
468}
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#define RA8_ISR_SAFE
The function is callable from interrupt context.
#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
static bool s_initialized
True once display_init has succeeded.
ra8_err_t ra8_dma_channel_is_busy(uint8_t channel, bool *out_busy)
Query the allocation state of a channel.
Definition ra8_dma.c:428
static ra8_err_t internal_validate_request(const ra8_dma_request_t *req)
Validate a request descriptor before touching hardware.
Definition ra8_dma.c:178
static ra8_dma_channel_state_t s_channels[k_ra8_dma_channel_count]
Channel allocation + dispatch table.
Definition ra8_dma.c:59
ra8_err_t ra8_dma_init(void)
Bring up the generic DMA substrate.
Definition ra8_dma.c:215
ra8_err_t ra8_dma_release(uint8_t channel)
Release a previously allocated channel.
Definition ra8_dma.c:370
ra8_err_t ra8_dma_deinit(void)
Tear down the generic DMA substrate.
Definition ra8_dma.c:257
static void internal_pack_dmac_cfg(const ra8_dma_request_t *req, ra8_dmac_config_t *out_cfg)
Copy a high-level ra8_dma_request_t into the lower-level ra8_dmac_config_t the DMAC driver expects.
Definition ra8_dma.c:144
void ra8_dma_dispatch_complete(uint8_t channel)
Fire the per-channel completion callback.
Definition ra8_dma.c:458
ra8_err_t ra8_dma_request(const ra8_dma_request_t *req, uint8_t *out_channel)
Allocate a channel and arm a DMAC transfer.
Definition ra8_dma.c:308
static uint8_t internal_find_free(void)
Find the first free channel.
Definition ra8_dma.c:113
Generic DMA transfer substrate (DMAC engine).
@ k_ra8_dma_channel_none
RA8 DMA channel none.
Definition ra8_dma.h:76
@ k_ra8_dma_channel_count
RA8 DMA channel count.
Definition ra8_dma.h:68
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_word
32-bit transfers (DMTMD.SZ = 10b).
Definition ra8_dmac.h:53
ra8_err_t ra8_dmac_stop(uint8_t channel)
Disable a DMAC0 channel and drop its MSTP reference.
Definition ra8_dmac.c:432
ra8_err_t ra8_dmac_start(uint8_t channel, const ra8_dmac_config_t *cfg)
Programme and enable a DMAC0 channel.
Definition ra8_dmac.c:398
Error Code Definitions for ra8-firmware.
@ k_ra8_err_hw_init_failed
Hardware peripheral failed to initialise.
Definition ra8_err.h:290
@ k_ra8_err_no_mem
Static buffer exhausted (no dynamic memory on this project).
Definition ra8_err.h:142
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_err_invalid_state
Module in wrong state for requested operation.
Definition ra8_err.h:161
@ k_ra8_err_not_initialized
Module not initialized – _init() not yet called successfully.
Definition ra8_err.h:235
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_hw_error
Generic hardware fault detected (error flag set, fault interrupt).
Definition ra8_err.h:310
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Lightweight Logging Interface for ra8-firmware.
#define ra8_log_error_val(tag, message, value)
RA8 log error val.
Definition ra8_log.h:337
#define ra8_log_info(tag, message)
RA8 log info.
Definition ra8_log.h:364
#define ra8_log_error(tag, message)
RA8 log error.
Definition ra8_log.h:335
Ref-counted Module Stop Control wrapper for the RA8D2.
ra8_err_t ra8_mstp_enable(ra8_mstp_t id)
Reference-counted "ungate this peripheral" request.
Definition ra8_mstp.c:343
ra8_err_t ra8_mstp_disable(ra8_mstp_t id)
Reference-counted "gate this peripheral" request.
Definition ra8_mstp.c:382
Module Stop Control (MSTP) register layout for the Renesas RA8D2.
@ k_ra8_mstp_dmac0_dtc0
MSTPA22 DMAC0+DTC0 (shared).
Per-channel dispatch-table entry.
Definition ra8_dma.c:42
void * ctx
Stored context.
Definition ra8_dma.c:44
ra8_dma_complete_fn_t on_complete
Callback or NULL.
Definition ra8_dma.c:43
bool in_use
True while allocated.
Definition ra8_dma.c:45
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
DMAC channel configuration.
Definition ra8_dmac.h:121
uint16_t count
Transfer count (DMCRA low).
Definition ra8_dmac.h:124
uint32_t src
Source address (DMSAR).
Definition ra8_dmac.h:122
bool dst_inc
true: DM = increment, else fixed.
Definition ra8_dmac.h:127
bool src_inc
true: SM = increment, else fixed.
Definition ra8_dmac.h:126
uint32_t dst
Destination address (DMDAR).
Definition ra8_dmac.h:123
ra8_dmac_width_t width
Transfer element width.
Definition ra8_dmac.h:125