ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_dma.h File Reference

Generic DMA transfer substrate (DMAC engine). More...

#include <stdint.h>
#include "ra8_dmac.h"
#include "ra8_elc_regs.h"
#include "ra8_err.h"
Include dependency graph for ra8_dma.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ra8_dma_request_t
 Descriptor for a single DMA transfer. More...

Typedefs

typedef void(* ra8_dma_complete_fn_t) (void *ctx)
 Caller-supplied completion callback.

Enumerations

enum  ra8_dma_channel_count_t : uint8_t { k_ra8_dma_channel_count = 8U }
 Number of channels the DMAC backend exposes. More...
enum  ra8_dma_invalid_channel_t : uint8_t { k_ra8_dma_channel_none = 0xFFU }
 Sentinel for "no channel allocated". More...

Functions

ra8_err_t ra8_dma_init (void)
 Initialise the DMA substrate.
ra8_err_t ra8_dma_deinit (void)
 Release the DMA substrate.
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.
ra8_err_t ra8_dma_release (uint8_t channel)
 Stop a channel and return it to the free pool.
ra8_err_t ra8_dma_channel_is_busy (uint8_t channel, bool *out_busy)
 Query the allocation state of a channel.
void ra8_dma_dispatch_complete (uint8_t channel)
 Dispatch a transfer-end completion callback for one channel.

Detailed Description

Generic DMA transfer substrate (DMAC engine).

Tag
[Ring 3 / HAL] {World: S}

Ring 3 / HAL substrate. Sits on top of ra8_dmac and exposes a driver-friendly API that hides free-channel allocation and completion-interrupt wiring behind a single ra8_dma_request call.

Drivers call ra8_dma_request with a descriptor that says "I want bytes moved from A to B when ELC event E fires". The substrate:

  1. Picks a free DMAC channel (0..7) from an internal pool.
  2. Programmes DMSAR / DMDAR / DMCRA / DMTMD / DMAMD on the selected channel.
  3. Routes the ELC trigger to the channel via ra8_isr.
  4. Registers the caller's completion handler, if any, in the dispatch table so the Cortex-M85 vector-table trampoline can invoke it on the DMAC transfer-end interrupt.
  5. Returns the channel number so the caller can cancel.

ra8_dma_release tears a channel down: stops the channel, unregisters the completion interrupt, and returns the channel to the free pool.

The DTC has its own lifecycle + request model (install a vector table, enable, let activation events drive transfers); callers that need DTC semantics use ra8_dtc_* directly rather than going through this substrate.

Threading

Single-threaded init context only. Completion callbacks run in ISR context and must not call back into ra8_dma_request.

Definition in file ra8_dma.h.

Typedef Documentation

◆ ra8_dma_complete_fn_t

typedef void(* ra8_dma_complete_fn_t) (void *ctx)

Caller-supplied completion callback.

Parameters
[in]ctxContext pointer recorded at request time.
Note
Invoked from ISR context. Must return quickly and must not take any ra8_dma / ra8_mstp locks.

Definition at line 88 of file ra8_dma.h.

Enumeration Type Documentation

◆ ra8_dma_channel_count_t

enum ra8_dma_channel_count_t : uint8_t

Number of channels the DMAC backend exposes.

Enumerator
k_ra8_dma_channel_count 

RA8 DMA channel count.

Definition at line 67 of file ra8_dma.h.

◆ ra8_dma_invalid_channel_t

enum ra8_dma_invalid_channel_t : uint8_t

Sentinel for "no channel allocated".

Enumerator
k_ra8_dma_channel_none 

RA8 DMA channel none.

Definition at line 75 of file ra8_dma.h.

Function Documentation

◆ ra8_dma_channel_is_busy()

ra8_err_t ra8_dma_channel_is_busy ( uint8_t channel,
bool * out_busy )
nodiscard

Query the allocation state of a channel.

Diagnostic accessor used by unit tests to verify the allocator state. Returns true if the channel is currently in use.

Parameters
[in]channelChannel number 0..k_ra8_dma_channel_count - 1.
[out]out_busyOn success, true if allocated.
Returns
ra8_err_t error code.
Return values
k_ra8_okQuery successful.
k_ra8_err_null_ptrout_busy NULL.
k_ra8_err_invalid_argchannel out of range.
Precondition
out_busy is non-NULL.
Postcondition
No hardware state is modified.
Note
Thread safety: not thread-safe.
Since
0.1.0

Definition at line 428 of file ra8_dma.c.

References k_ra8_dma_channel_count, k_ra8_err_invalid_arg, k_ra8_ok, RA8_CHECK_NULL_PTR, s_channels, and s_tag.

◆ ra8_dma_deinit()

ra8_err_t ra8_dma_deinit ( void )
nodiscard

Release the DMA substrate.

Stops every in-use channel, then drops the MSTP reference. Used by tests; production code rarely tears this down.

Returns
ra8_err_t error code.
Return values
k_ra8_okSubstrate torn down.
k_ra8_err_hw_errorra8_mstp_disable underflow.
Precondition
IRQs masked or single-threaded init context.
Postcondition
Every ra8_dma channel is free.
DMAC MSTP reference decremented.
Note
Thread safety: not thread-safe.
Since
0.1.0

Release the DMA substrate.

Stops every in-use channel via ra8_dmac_stop(), clears the dispatch table, and releases the MSTPA22 reference (HUM Ch 11.2.6, p 443). After this returns ra8_dma_request() rejects with k_ra8_err_not_initialized.

Returns
ra8_err_t error code.
Return values
k_ra8_okAll channels stopped and MSTP released.
k_ra8_err_hw_errorUnderlying ra8_mstp_disable() failed.
Precondition
ra8_dma_init() previously succeeded.
No outstanding interrupt expected from any channel.
Postcondition
All channels report in_use == false.
Driver re-enters uninitialized state.
Note
Not thread-safe; call once during system shutdown.
Since
0.1.0

Definition at line 257 of file ra8_dma.c.

References k_ra8_dma_channel_count, k_ra8_err_hw_error, k_ra8_mstp_dmac0_dtc0, k_ra8_ok, ra8_dmac_stop(), ra8_log_error_val, ra8_mstp_disable(), s_channels, s_initialized, and s_tag.

◆ ra8_dma_dispatch_complete()

void ra8_dma_dispatch_complete ( uint8_t channel)

Dispatch a transfer-end completion callback for one channel.

Called from the DMAC IRQ trampoline when a channel finishes. Looks up the caller-supplied on_complete and invokes it with the stored context. Tests can call this function directly to simulate DMA completion without running real hardware.

Parameters
[in]channelChannel whose completion just fired.
Precondition
Called from ISR context or (for tests) from a direct test helper such as ra8_fake_dma_complete.
ra8_dma_init() previously succeeded.
Postcondition
On exit, the stored completion callback has been invoked exactly once (if non-NULL).
No state change if channel is out of range.
Note
Thread safety: re-entrant in the sense that the handler itself may enable nested interrupts; the dispatcher does not take any locks.
Since
0.1.0

Dispatch a transfer-end completion callback for one channel.

Looks up the stashed callback / context for channel and invokes the callback if non-NULL. Called from the DMAC IRQ trampoline (or from a unit-test driver in off-target mode). Out-of-range channels are silently ignored.

Parameters
[in]channelChannel whose completion just fired.
Precondition
ra8_dma_init() previously succeeded.
Called from ISR context or a test driver.
Postcondition
Registered callback invoked at most once with the stored context.
No state mutated by the dispatch itself.
Note
Thread safety: ISR context only; not re-entrant per channel.
Since
0.1.0

Definition at line 458 of file ra8_dma.c.

References k_ra8_dma_channel_count, and s_channels.

◆ ra8_dma_init()

ra8_err_t ra8_dma_init ( void )
nodiscard

Initialise the DMA substrate.

Requests MSTPCRA.MSTPA22 via ra8_mstp_enable(k_ra8_mstp_dmac0_dtc0) (so the DMAC is clocked), zeroes the internal channel-allocation table, and returns. Does NOT programme any channel. Callers follow with ra8_dma_request() to kick off actual transfers.

Returns
ra8_err_t error code.
Return values
k_ra8_okSubstrate ready.
k_ra8_err_hw_init_failedra8_mstp_enable failed.
Precondition
ra8_mstp_init() has been called (or this is a first request against a fresh ref-count table).
IRQs masked or single-threaded init context.
Postcondition
The ra8_dma channel table is all-free.
DMAC bus clock is on.
Note
Thread safety: not thread-safe.
Since
0.1.0

Initialise the DMA substrate.

Enables MSTPA22 (shared with DTC0, HUM Ch 11.2.6 "MSTPCRA : Module Stop Control Register A", p 443) and clears every entry in the channel-allocation / dispatch table. After this returns ra8_dma_request() may allocate channels.

Returns
ra8_err_t error code.
Return values
k_ra8_okChannel table reset and MSTP gate opened.
k_ra8_err_hw_init_failedUnderlying ra8_mstp_enable() failed.
Precondition
ra8_mstp_init() previously succeeded.
Single-threaded init context (or IRQs masked).
Postcondition
All channels report in_use == false.
DMAC0 + DTC0 MSTP reference held by this driver.
Note
Not thread-safe; call once during system init.
Since
0.1.0

Definition at line 215 of file ra8_dma.c.

References k_ra8_dma_channel_count, k_ra8_err_hw_init_failed, k_ra8_mstp_dmac0_dtc0, k_ra8_ok, ra8_log_error_val, ra8_log_info, ra8_mstp_enable(), s_channels, s_initialized, and s_tag.

Referenced by internal_setup_or_halt(), and ra8_nsc_periph_init().

◆ ra8_dma_release()

ra8_err_t ra8_dma_release ( uint8_t channel)
nodiscard

Stop a channel and return it to the free pool.

Parameters
[in]channelChannel number returned by ra8_dma_request.
Returns
ra8_err_t error code.
Return values
k_ra8_okChannel released.
k_ra8_err_invalid_argchannel out of range.
k_ra8_err_invalid_stateChannel was not allocated.
Precondition
IRQs masked or single-threaded init context.
Caller previously called ra8_dma_request for channel.
Postcondition
Channel is stopped and marked free.
Any registered completion handler is unregistered.
Note
Thread safety: not thread-safe.
Since
0.1.0

Stop a channel and return it to the free pool.

Calls ra8_dmac_stop() to disable the channel at the hardware level, then clears the dispatch entry. The MSTP reference held by the substrate root is preserved – only ra8_dma_deinit() releases it.

Parameters
[in]channelChannel previously returned by ra8_dma_request().
Returns
ra8_err_t error code.
Return values
k_ra8_okChannel released.
k_ra8_err_invalid_argchannel >= k_ra8_dma_channel_count.
k_ra8_err_invalid_stateChannel was not in use.
k_ra8_err_hw_errorra8_dmac_stop() failed.
Precondition
ra8_dma_init() previously succeeded.
Caller has accepted any pending IRQs may still latch.
Postcondition
Channel slot reports in_use == false.
DMAC channel is disabled at the register level.
Note
Not thread-safe; pair with IRQ masking.
Since
0.1.0

Definition at line 370 of file ra8_dma.c.

References k_ra8_dma_channel_count, k_ra8_err_hw_error, k_ra8_err_invalid_arg, k_ra8_err_invalid_state, k_ra8_ok, ra8_dmac_stop(), ra8_log_error_val, s_channels, and s_tag.

Referenced by internal_run_one().

◆ ra8_dma_request()

ra8_err_t ra8_dma_request ( const ra8_dma_request_t * req,
uint8_t * out_channel )
nodiscard

Allocate a DMAC channel, programme it, and start the trigger wiring.

Parameters
[in]reqTransfer descriptor. engine must be k_ra8_dma_engine_dmac.
[out]out_channelOn success, the allocated DMAC channel number in the range [0, k_ra8_dma_channel_count).
Returns
ra8_err_t error code.
Return values
k_ra8_okTransfer programmed and armed.
k_ra8_err_null_ptrreq or out_channel NULL.
k_ra8_err_invalid_argengine unsupported, count zero, or width out of range.
k_ra8_err_no_memAll DMAC channels in use.
k_ra8_err_hw_errorUnderlying ra8_dmac_start failed.
Precondition
ra8_dma_init() has been called.
IRQs masked or single-threaded init context.
Postcondition
On success, the DMAC channel is running.
On success, the ELC trigger is wired (if trigger is not k_ra8_elc_event_none).
*out_channel holds a valid channel number on success.
Note
Thread safety: not thread-safe.
See also
ra8_dma_release
Since
0.1.0

Allocate a DMAC channel, programme it, and start the trigger wiring.

Validates *req, finds a free channel via internal_find_free(), packs a ra8_dmac_config_t and calls ra8_dmac_start(). On success the channel index is written through out_channel and the caller-supplied completion callback is stashed for later dispatch.

Parameters
[in]reqTransfer descriptor (non-NULL).
[out]out_channelAllocated channel index (non-NULL).
Returns
ra8_err_t error code.
Return values
k_ra8_okChannel allocated and DMAC armed.
k_ra8_err_invalid_argreq malformed.
k_ra8_err_not_initializedra8_dma_init() was not called.
k_ra8_err_no_memNo free channel.
k_ra8_err_hw_errorra8_dmac_start() failed.
Precondition
ra8_dma_init() previously succeeded.
req != NULL and out_channel != NULL.
Postcondition
On success *out_channel references an in-use channel.
On failure no channel is allocated and no DMAC register changed.
Note
Not thread-safe; pair with IRQ masking.
Since
0.1.0

Definition at line 308 of file ra8_dma.c.

References ra8_dma_request_t::ctx, internal_find_free(), internal_pack_dmac_cfg(), internal_validate_request(), k_ra8_dma_channel_none, k_ra8_err_hw_error, k_ra8_err_no_mem, k_ra8_err_not_initialized, k_ra8_ok, ra8_dma_request_t::on_complete, RA8_CHECK_NULL_PTR, ra8_dmac_start(), ra8_log_error, ra8_log_error_val, s_channels, s_initialized, and s_tag.

Referenced by ra8_gpt_read_dma(), ra8_gpt_write_dma(), ra8_sci_read_dma(), ra8_sci_write_dma(), ra8_spi_read_dma(), and ra8_spi_write_dma().