Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ All parameters are in the `[dmuart]` section:
| `instance` | integer | 1 | UART instance number (1-8) |
| `rx_ring_size` | integer | 256 | Capacity of the RX ring buffer, in bytes (0 disables it) |
| `rx_ring_wait_mode` | string | "some_data" | RX ring read-wait behavior: "none" (return immediately), "some_data" (wait for at least one byte), "all_data" (wait for the full requested length) |
| `rx_dma` | integer | 1 | Receive by DMA when the port can (STM32F7); 0: by interrupt. For a platform whose DMA does not serve the UART, e.g. an emulator |

### Receiving by DMA (STM32F7)

Expand Down
14 changes: 14 additions & 0 deletions include/dmuart_port.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,18 @@ dmod_dmuart_port_api(1.0, int, _remove_interrupt_handler,
dmod_dmuart_port_api(1.0, int, _set_rx_ring,
( dmuart_instance_t instance, dm_sw_ring_t ring ) );

/* --- Receiving by DMA --- */

/**
* @brief Allow (or forbid) receiving by DMA for the next set_rx_ring()
*
* A port that can receive by DMA does so by default. Forbidding it makes the
* instance receive by interrupt - for a platform whose DMA does not serve the
* UART (e.g. an emulator). Call it before dmuart_port_set_rx_ring().
* Ports without DMA receive do nothing.
*
* @return 0 on success, negative on an invalid instance
*/
dmod_dmuart_port_api(1.0, int, _set_rx_dma, ( dmuart_instance_t instance, bool enabled ) );

#endif // DMUART_PORT_H
3 changes: 3 additions & 0 deletions src/dmuart.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ struct dmdrvi_context
dm_sw_ring_t rx_ring; /**< Software ring buffer for received bytes */
uint32_t rx_ring_size; /**< Capacity of the RX ring buffer (from config) */
dm_sw_ring_flags_t rx_ring_wait_flags; /**< RX ring read-wait behavior (from config) */
bool rx_dma; /**< Receive by DMA when the port can (from config) */
char *tty_path; /**< Absolute dmdevfs path announced to dmtty (NULL = not announced) */
};

Expand Down Expand Up @@ -272,6 +273,7 @@ static int read_config_parameters(dmdrvi_context_t context, dmini_context_t conf
context->rx_ring_size = (uint32_t)dmini_get_int(config, section, "rx_ring_size", 256);
context->rx_ring_wait_flags = string_to_rx_ring_wait_flags(
dmini_get_string(config, section, "rx_ring_wait_mode", "some_data"));
context->rx_dma = dmini_get_int(config, section, "rx_dma", 1) != 0;

return check_config_parameters(&context->config);
}
Expand Down Expand Up @@ -466,6 +468,7 @@ dmod_dmdrvi_dif_api_declaration(2.0, dmuart, dmdrvi_context_t, _create, ( dmini_
}
else
{
(void)dmuart_port_set_rx_dma(context->config.instance, context->rx_dma);
dmuart_port_set_rx_ring(context->config.instance, context->rx_ring);
}
}
Expand Down
6 changes: 6 additions & 0 deletions src/port/stm32f4/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,12 @@ dmod_dmuart_port_api_declaration(1.0, int, _set_rx_ring,
return 0;
}

dmod_dmuart_port_api_declaration(1.0, int, _set_rx_dma, ( dmuart_instance_t instance, bool enabled ))
{
(void)enabled; /* (receives by interrupt only) */
return validate_instance(instance);
}

/* ---- ISR handlers ---- */

/* Upper bound on bytes drained from DR per ISR entry. DR itself holds only
Expand Down
11 changes: 10 additions & 1 deletion src/port/stm32f7/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ typedef struct
} rx_dma_t;

static rx_dma_t rx_dma[STM32F7_UART_MAX_INSTANCES];
static bool rx_dma_forbidden[STM32F7_UART_MAX_INSTANCES]; /* receive by interrupt (dmuart_port_set_rx_dma()) */

/* NVIC IRQ numbers for STM32F7 UART instances (must match DMOD_IRQ_HANDLER list below) */
static const uint32_t uart_irqn[STM32F7_UART_MAX_INSTANCES] = {
Expand Down Expand Up @@ -193,6 +194,7 @@ int dmod_init(const Dmod_Config_t *Config)
irq_user_ptrs[i] = NULL;
rx_rings[i] = NULL;
memset(&rx_dma[i], 0, sizeof(rx_dma[i]));
rx_dma_forbidden[i] = false;
}
return 0;
}
Expand Down Expand Up @@ -771,11 +773,18 @@ dmod_dmuart_port_api_declaration(1.0, int, _set_rx_ring,
if (ring == NULL)
rx_dma_stop(instance);
rx_rings[instance - 1] = ring;
if (ring != NULL)
if (ring != NULL && !rx_dma_forbidden[instance - 1])
(void)rx_dma_start(instance); /* (no stream: by interrupt) */
return 0;
}

dmod_dmuart_port_api_declaration(1.0, int, _set_rx_dma, ( dmuart_instance_t instance, bool enabled ))
{
if (validate_instance(instance) != 0) return -1;
rx_dma_forbidden[instance - 1] = !enabled;
return 0;
}

/* ---- ISR handlers ---- */

/* Upper bound on bytes drained from RDR per ISR entry. RDR itself holds only
Expand Down
Loading