Astra MCU SDK Peripheral Driver Library
Loading...
Searching...
No Matches

Topics

 Enumerated Types
 Enumerated types for DMIC driver.
 Data Structures
 Data structures for DMIC driver.
 General Functions
 General functions for DMIC driver.

Detailed Description

Maximum number of DMIC channels supported by this API.

The DMIC block is a high-performance digital microphone interface subsystem designed to capture and process audio signals from integrated microphone elements. Each DMIC instance can be configured to support various sample rates, decimation ratios, and gain settings for flexible audio acquisition across different application scenarios.

The driver exposes a unified configuration interface while supporting both polling-based and interrupt-driven audio capture. Internally the driver supports FIFO and DMA data paths depending on hardware capability.

Applications can retrieve audio samples using either:

  • Blocking (synchronous) read model
  • Non-blocking streaming model using callbacks

This allows the same driver to be used for simple applications as well as high-throughput real-time audio processing pipelines.

Features:

  • Digital microphone interface with configurable sample rates
  • Programmable decimation (16x, 32x, 64x)
  • Adjustable microphone gain control (-3 dB to +3 dB)
  • Programmable boost levels (0 dB to 24 dB)
  • Input phase alignment control
  • DMA or FIFO based audio data transfer
  • Circular buffer streaming support
  • Interrupt support for overflow and transfer events
  • Blocking and non-blocking data retrieval modes
  • Multiple DMIC instances with independent operation
Note
The DMIC driver supports two data retrieval models:

Blocking (Polling) Mode

  • Application explicitly calls dmic_read
  • The API blocks until audio data becomes available or timeout occurs
  • Suitable for simple applications or RTOS threads dedicated to audio capture

Non-Blocking (Interrupt / Callback) Mode

  • Application registers a callback using dmic_register_callback
  • The driver invokes the callback when DMA or FIFO transfer events occur
  • Audio data is processed asynchronously
  • Suitable for real-time streaming pipelines
Warning
DMIC channels require proper initialization sequencing and clock configuration before audio data can be reliably captured. Changing gain, boost, or decimation settings while the DMIC is actively capturing may result in audio artifacts or data loss. Software should always stop capture using dmic_stop before reconfiguration.

Configuration Considerations

Typical initialization sequence:

  1. Call dmic_init to initialize the DMIC instance.
  2. Configure I/O settings using dmic_configure_io.
  3. Configure channels using dmic_config_channel.
  4. Register callback using dmic_register_callback (optional for async mode).
  5. Enable the interface using dmic_enable.
  6. Configure data path using dmic_config_data_path.
  7. Start capture using dmic_start.

After starting capture, applications may use either blocking or non-blocking data retrieval models.

Blocking Data Retrieval

In blocking mode the application periodically calls dmic_read to retrieve captured audio data. The function waits until a buffer becomes available or the timeout expires.

Typical flow:

  1. Start capture using dmic_start
  2. Call ::dmic_read(instance, buf, timeout)
  3. Process returned audio samples
  4. Repeat until capture stops
/* Blocking read: waits until data is available or timeout expires. */
.channel = DMIC_EXAMPLE_CHANNEL,
.buffer = g_dmic_read_buf,
.buffer_size = sizeof(g_dmic_read_buf),
.offset_bytes = 0U,
.available_bytes = 0U
};
dmic_status_en rc = dmic_read(DMIC_EXAMPLE_INSTANCE, &read_ctx, DMIC_TIMEOUT_MS);
if (rc == DMIC_OK && read_ctx.available_bytes > 0U) {
/* Process read_ctx.buffer + read_ctx.offset_bytes for read_ctx.available_bytes bytes. */
}

This model is recommended for:

  • Simple audio capture applications
  • RTOS tasks dedicated to audio processing
  • Systems where a dedicated audio thread polls for buffers

Non-Blocking Streaming Mode

In non-blocking mode the driver uses interrupts to notify the application when audio data becomes available. The application registers a callback using dmic_register_callback.

When a DMA period or FIFO threshold is reached the driver invokes the callback with offset and size information describing the available data.

Typical flow:

  1. Register callback using dmic_register_callback
  2. Start capture using dmic_start
  3. Process audio data inside callback or signal a worker task
/* Non-blocking streaming: register callback, then poll/query without blocking. */
dmic_data_path_config_t dma_path_cfg = {
.channel = DMIC_EXAMPLE_CHANNEL,
.transfer_mode = DMIC_TRANSFER_MODE_DMA,
.cfg.dma = {
.buffer = g_dmic_dma_ring,
.buffer_bytes = DMIC_RING_BYTES,
.period_bytes = DMIC_PERIOD_BYTES,
.frame_bytes = DMIC_FRAME_BYTES
}
};
.channel = DMIC_EXAMPLE_CHANNEL,
.buffer = g_dmic_dma_ring, /* In DMA mode, must match configured ring buffer. */
.buffer_size = DMIC_RING_BYTES,
.offset_bytes = 0U,
.available_bytes = 0U
};
dmic_config_data_path(DMIC_EXAMPLE_INSTANCE, &dma_path_cfg);
dmic_register_callback(DMIC_EXAMPLE_INSTANCE, dmic_audio_cb, NULL);
dmic_start(DMIC_EXAMPLE_INSTANCE);
rc = dmic_read_nonblocking(DMIC_EXAMPLE_INSTANCE, &nb_ctx);
if (rc == DMIC_OK && nb_ctx.available_bytes > 0U) {
/* Consume nb_ctx.available_bytes from g_dmic_dma_ring + nb_ctx.offset_bytes. */
}

This model is recommended for:

  • Continuous audio streaming
  • Real-time DSP processing
  • Voice activity detection pipelines
  • Multi-microphone audio processing

dmic_audio_capture

Starts and stops audio capture from the microphone.

Audio data is transferred using either:

  • DMA circular buffer (preferred for streaming)
  • FIFO data path (low-latency hardware access)
/* Configure and start DMIC capture (FIFO path shown). */
dmic_io_config_t io_cfg = {
.fs_Hz = DMIC_SAMPLE_RATE_HZ,
.pdm_clk_Hz = DMIC_PDM_CLK_HZ,
.polarity_reversal = false,
.channel_swap = false,
};
.hpf_cutoff_freq = 0U,
.enable = true,
.enable_low_power = false,
.enable_ll_filter = false,
.enable_hpf = false,
.enable_iir = false
};
.channel = DMIC_EXAMPLE_CHANNEL,
.transfer_mode = DMIC_TRANSFER_MODE_FIFO,
.cfg.fifo = {
.enable = true,
.threshold = 64U,
.int_almost_full_enable = true,
.int_full_enable = true,
.int_overflow_enable = true
}
};
dmic_init(DMIC_EXAMPLE_INSTANCE);
dmic_configure_io(DMIC_EXAMPLE_INSTANCE, &io_cfg);
dmic_config_channel(DMIC_EXAMPLE_INSTANCE, DMIC_EXAMPLE_CHANNEL, &ch_cfg);
dmic_set_channel_gain(DMIC_EXAMPLE_INSTANCE, DMIC_EXAMPLE_CHANNEL, DMIC_GAIN_0DB);
dmic_set_channel_boost(DMIC_EXAMPLE_INSTANCE, DMIC_EXAMPLE_CHANNEL, DMIC_BOOST_0DB);
dmic_config_data_path(DMIC_EXAMPLE_INSTANCE, &path_cfg);
dmic_enable(DMIC_EXAMPLE_INSTANCE);
dmic_start(DMIC_EXAMPLE_INSTANCE);
/* Stop and disable DMIC capture. */
dmic_stop(DMIC_EXAMPLE_INSTANCE);
dmic_disable(DMIC_EXAMPLE_INSTANCE);

dmic_data_transfer

In DMA mode, the application provides a DMA-capable circular ring buffer through dmic_dma_config_t.buffer. The driver programs DMA to write directly into this buffer and maintains read/write period tracking. Data becomes available periodically based on the configured transfer size or FIFO threshold.

Applications retrieve data using:

  • dmic_read (blocking mode)
  • callback notifications (non-blocking mode)

This architecture allows continuous audio capture while avoiding data loss when the application processes buffers promptly.

dmic_interrupt_management

The interrupt API supports enabling and monitoring interrupt sources such as:

  • Almost-full FIFO
  • Full FIFO
  • Overflow detection

These interrupts are primarily used internally by the driver for streaming and buffer management but may also be enabled by advanced applications.

/* Enable DMIC interrupt sources used for FIFO status/overflow signaling. */
dmic_enable_interrupts(DMIC_EXAMPLE_INSTANCE,
/* Example software status checks updated from callback/ISR path. */
if (g_dmic_data_ready) {
g_dmic_data_ready = false;
}
if (g_dmic_overflow) {
g_dmic_overflow = false;
}
if (g_dmic_error) {
g_dmic_error = false;
}
/* Interrupt acknowledge is backend-specific; driver ISR typically performs ACK. */
dmic_isr(DMIC_EXAMPLE_INSTANCE);

DMA Circular Buffer Model

When operating in DMA mode, the DMIC driver uses a circular buffer model to continuously capture audio data from the microphone without requiring the application to reconfigure the hardware after each transfer.

The DMA buffer is divided into fixed-size segments called periods. The size of the circular buffer and the transfer period are configured through the DMIC data-path API. The total buffer size must be an integer multiple of the period size. The required relationship is: buffer_bytes % period_bytes == 0. period_bytes should be greater than or equal to frame_bytes. The required relationship is: period_bytes % frame_bytes == 0. For PCM layouts, frame_bytes should match active_channel_count * 4 bytes.

Example buffer layout:

|---------------- Circular DMA Buffer ----------------|
| Period 0 | Period 1 | Period 2 | Period 3 | ... |

The total buffer size is defined by buffer_bytes, while each transfer segment is defined by period_bytes.

buffer_bytes = N * period_bytes

The DMA engine continuously writes microphone samples into the circular buffer. When one period of data is captured, a DMA interrupt occurs and the driver marks the period as available for the application.

Current implementation note:

  • DMA read APIs are DMA-backed blocking capture using the configured user DMA ring buffer.
  • In DMA mode, the buffer passed to dmic_read/dmic_read_nonblocking must reference the configured DMA ring buffer (zero-copy contract).
  • DMA teardown is deferred to non-callback API context (for example stop/disable/next transfer setup); DMA callback context only signals completion/error and requests deferred cleanup.
  • DMA memory/alignment requirements:
    • buffer_bytes, period_bytes, and frame_bytes must be non-zero.
    • buffer_bytes >= period_bytes and buffer_bytes % period_bytes == 0.
    • period_bytes >= frame_bytes and period_bytes % frame_bytes == 0.
    • frame_bytes must be a multiple of 4 bytes (32-bit sample containers).
    • If cfg.dma.buffer is provided, it must be DMA-capable and 64-byte aligned.
  • Descriptor/ring constraints:
    • period_bytes / 4 must not exceed backend DMA max words per transfer.
    • Period count (buffer_bytes / period_bytes) must be within backend descriptor limits.
    • When using the internal fallback ring (cfg.dma.buffer == NULL), total ring size is bounded by backend internal-ring limits.

DMA buffer alignment and maximum supported buffer size are backend/platform dependent. Cache coherency and cache maintenance requirements are outside the scope of this API and must be handled by platform integration. DMA-capable memory alignment may be required by the platform DMA engine. DMA buffer memory is application-owned and must remain valid until dmic_stop completes. DMA mode operates as a zero-copy transfer model; no copy is performed between the DMA ring buffer and application memory.

dmic_read Unblocking Behavior

The dmic_read API retrieves audio samples from the internal circular buffer.

In DMA mode, dmic_read unblocks once per completed period, not when the entire buffer becomes full. This ensures predictable latency and continuous streaming behavior.

For example:

sample_rate = 16000 Hz
frame_bytes = 4 bytes
period_bytes = 320 bytes
frames_per_period = 320 / 4 = 80 frames
period_time = 160 / 16000 = 10 ms

In this configuration the dmic_read call becomes ready approximately every 10 ms when a new period of audio data is available.

This behavior allows applications to process audio data in predictable intervals while maintaining low latency. In DMA mode, each successful dmic_read returns at most one completed DMA period.

Sample container rule:

In the current implementation, all FIFO/DMA transfers use 32-bit memory words.
For 16-bit and 24-bit sample formats, samples are stored in 32-bit containers.
Therefore buffer_size, period_bytes, and frame_bytes must be calculated using
a 4-byte container size per sample.

DMA Internal Operation

Internally the driver maintains read and write indices within the circular buffer:

DMA write pointer ---> advancing as samples arrive
CPU read pointer ---> advancing as application consumes data
|------ circular buffer ------|
^read_idx ^write_idx

Each DMA interrupt advances the write pointer by period_bytes. The dmic_read function advances the read pointer after returning the captured audio samples to the application. When write_idx reaches the end of the ring buffer, it wraps to the start. The same wrap behavior applies to read_idx after data consumption.

If the application does not read data quickly enough and the write pointer overtakes the read pointer, unread DMA periods may be overwritten, an overflow condition is raised, and the driver reports DMIC_EVENT_OVERFLOW / DMIC_ERROR_OVERFLOW. Capture is backend-dependent and may continue after overflow notification.

FIFO Data Path Model

Some hardware configurations support a FIFO-based data path instead of DMA. In this mode, audio samples are pushed into an internal hardware FIFO before being read by the CPU.

The FIFO generates interrupts based on configured threshold levels:

  • Almost-full interrupt – FIFO level reaches the configured threshold
  • Full interrupt – FIFO becomes completely full
  • Overflow interrupt – FIFO data is lost due to lack of servicing

The FIFO threshold unit is hardware FIFO words (0-511), not PCM frames. One FIFO word may not equal one interleaved audio frame. FIFO word width may vary by hardware packing/format configuration. The FIFO threshold controls when the application should retrieve samples from the FIFO. FIFO mode copies FIFO register data into the application-provided output buffer.

Example FIFO layout:

Microphone Samples ---> [ DMIC FIFO ]
| s0 |
| s1 |
| s2 |
| s3 |
| ... |

When the FIFO level reaches the configured threshold, the hardware raises an interrupt and the driver signals that audio data is ready.

FIFO Configuration Example

Example configuration where the FIFO threshold is set to 64 FIFO words (typically 64 samples for mono 16-bit capture):

dmic_fifo_config_t fifo_cfg = {
.enable = true,
.threshold = 64,
.int_almost_full_enable = true,
.int_full_enable = true,
.int_overflow_enable = true
};
.channel = DMIC_CH_0,
.transfer_mode = DMIC_TRANSFER_MODE_FIFO,
.cfg.fifo = fifo_cfg
};
dmic_config_data_path(instance, &path);
struct dmic_data_path_config_s dmic_data_path_config_t
Unified DMIC data-path configuration.
struct dmic_fifo_config_s dmic_fifo_config_t
DMIC RX FIFO configuration structure.
@ DMIC_TRANSFER_MODE_FIFO
Definition dmic.h:683
dmic_status_en dmic_config_data_path(dmic_instance_en instance, const dmic_data_path_config_t *cfg)

In this configuration the FIFO generates an interrupt whenever 64 samples are accumulated in the hardware buffer (word/sample mapping is hardware-format dependent).

FIFO Blocking Mode Example

In blocking mode the application periodically calls dmic_read to retrieve samples from the FIFO.

int32_t timeout_ms = 100;
buf.channel = DMIC_CH_0;
buf.buffer = audio_buffer;
buf.buffer_size = sizeof(audio_buffer);
while (capture_active)
{
dmic_read(instance, &buf, timeout_ms);
process_audio(buf.buffer, buf.available_bytes / 4U);
}
struct dmic_buffer_context_s dmic_buffer_context_t
DMIC buffer context structure.
dmic_status_en dmic_read(dmic_instance_en instance, dmic_buffer_context_t *buf, int32_t timeout)
uint8_t * buffer
Definition dmic.h:809
uint32_t buffer_size
Definition dmic.h:810
uint8_t channel
Definition dmic.h:808
uint32_t available_bytes
Definition dmic.h:812

The dmic_read call blocks until the FIFO threshold condition occurs or sufficient data becomes available.

FIFO Interrupt Mode Example

In interrupt-driven operation the application registers a callback and processes audio data whenever the FIFO threshold interrupt occurs.

static void audio_cb(dmic_instance_en inst,
uint8_t channel,
uint32_t offset,
uint32_t size,
void *user)
{
if (event == DMIC_EVENT_ALMOST_FULL)
{
buf.channel = channel;
buf.buffer = audio_buffer;
buf.buffer_size = sizeof(audio_buffer);
dmic_read_nonblocking(inst, &buf);
process_audio(buf.buffer + buf.offset_bytes,
buf.available_bytes / 4U);
}
}
dmic_register_callback(instance, audio_cb, NULL);
dmic_start(instance);
dmic_instance_en
DMIC instances for CM52.
Definition sl2610_cm52.h:619
dmic_event_en
DMIC event notifications.
Definition dmic.h:574
@ DMIC_EVENT_ALMOST_FULL
Definition dmic.h:579
dmic_status_en dmic_register_callback(dmic_instance_en instance, dmic_event_cb_t event_cb, void *user_data)
dmic_status_en dmic_start(dmic_instance_en instance)
dmic_status_en dmic_read_nonblocking(dmic_instance_en instance, dmic_buffer_context_t *buf)
uint32_t offset_bytes
Definition dmic.h:811

dmic_read_nonblocking returns immediately. If data is available, buf is populated with currently available data metadata/content; otherwise it returns DMIC_OK with available_bytes set to 0 if no data is currently available. In callback mode, transfer-ready notification is typically DMIC_EVENT_READ_COMPLETE. Some backends may additionally report raw FIFO level events (for example DMIC_EVENT_ALMOST_FULL). Raw FIFO events such as DMIC_EVENT_ALMOST_FULL and DMIC_EVENT_FULL are only reported if enabled through dmic_enable_interrupts. In DMA mode, transfer-ready callback notification is reported using DMIC_EVENT_READ_COMPLETE.

FIFO Latency Considerations

FIFO threshold configuration determines the latency and interrupt frequency.

Example:

sample_rate = 16000 Hz
threshold = 64 samples
interrupt_interval = 64 / 16000
~= 4 ms

Lower thresholds reduce latency but increase interrupt load. Higher thresholds reduce CPU interrupts but increase buffering latency.

Applications should choose FIFO thresholds based on real-time processing requirements and CPU availability.

Blocking vs Non-Blocking Operation

The DMIC driver supports both blocking and non-blocking data retrieval models.

Blocking Mode

The application calls dmic_read and waits until the requested amount of audio data becomes available or the timeout expires. Timeout semantics:

  • timeout < 0 waits indefinitely.
  • timeout > 0 waits up to the specified timeout.
  • timeout == 0 performs a non-blocking query.

Typical flow:

dmic_start(instance);
while (capture_active) {
dmic_read(instance, &buffer, timeout);
process_audio(buffer);
}

Non-Blocking Mode

In non-blocking mode the application registers a callback using dmic_register_callback. The driver invokes the callback when DMA periods or FIFO thresholds are reached.

Typical flow:

dmic_register_callback(instance, audio_cb, user_ctx);
dmic_start(instance);
// audio_cb() processes data asynchronously

This model is recommended for continuous streaming pipelines and real-time audio processing where low latency and deterministic scheduling are required.

For a given DMIC instance, avoid mixing blocking and callback-driven streaming paths concurrently unless backend behavior explicitly supports it. Recommended policy: use one data-retrieval mode per instance at a time.

Thread-safety: unless otherwise documented by the platform integration, concurrent dmic_read/dmic_read_nonblocking calls on the same instance from multiple threads are not guaranteed to be thread-safe.

Callback execution context is backend-dependent and may be ISR context or a deferred worker context; callback handlers should be written accordingly.

/******************************************************************************* Enumerations