From a479b4a43a5d4dcaf9f9f5498637b145884b9b71 Mon Sep 17 00:00:00 2001 From: Ayoub Farah Date: Tue, 3 Mar 2026 17:15:23 +0100 Subject: [PATCH 1/5] Patch for solving communications errors when using serial monitor --- .../zephyr/src/Rs485.cpp | 34 +++++++++++++++++++ .../owntech_communication/zephyr/src/Rs485.h | 7 ++++ .../zephyr/src/Rs485Communication.cpp | 5 +++ .../zephyr/src/Rs485Communication.h | 5 +++ .../src/uninterruptible_synchronous_task.cpp | 9 +++++ 5 files changed, 60 insertions(+) diff --git a/zephyr/modules/owntech_communication/zephyr/src/Rs485.cpp b/zephyr/modules/owntech_communication/zephyr/src/Rs485.cpp index 6888f02c..e0db0c2b 100644 --- a/zephyr/modules/owntech_communication/zephyr/src/Rs485.cpp +++ b/zephyr/modules/owntech_communication/zephyr/src/Rs485.cpp @@ -171,6 +171,7 @@ void serial_init(void) uart_configure(uart_dev, &uart_cfg); LL_USART_ConfigAsyncMode(USART3); + LL_USART_EnableOverrunDetect(USART3); /* Enable DMA request*/ LL_USART_EnableDMAReq_TX(USART3); @@ -376,3 +377,36 @@ void serial_start() { LL_USART_Enable(USART3); } + +/** + * This function is used to recover the RX DMA if an overrun error occurs. + * It checks if the overrun error flag is set, and if so, it clears the overrun state and + * re-arms the RX DMA channel to continue receiving data. + * See https://github.com/owntech-foundation/MMC/issues/6 + */ +int8_t reinitialize_rx_dma_if_overrun() +{ + if (LL_USART_IsActiveFlag_ORE(USART3) == 0U) + { + return -1; + } + + /* Clear UART RX overrun state first. */ + LL_USART_RequestRxDataFlush(USART3); + LL_USART_ClearFlag_ORE(USART3); + + /* Re-arm circular RX DMA from the beginning */ + LL_DMA_DisableChannel(DMA_USART, LL_DMA_CHANNEL_RX); + LL_DMA_ClearFlag_TC7(DMA_USART); + LL_DMA_ClearFlag_HT7(DMA_USART); + LL_DMA_ClearFlag_TE7(DMA_USART); + LL_DMA_SetMemoryAddress(DMA_USART, + LL_DMA_CHANNEL_RX, + (uint32_t)(rx_usart_val)); + LL_DMA_SetDataLength(DMA_USART, LL_DMA_CHANNEL_RX, dma_buffer_size); + LL_DMA_EnableIT_TC(DMA_USART, LL_DMA_CHANNEL_RX); + LL_DMA_DisableIT_HT(DMA_USART, LL_DMA_CHANNEL_RX); + LL_DMA_EnableChannel(DMA_USART, LL_DMA_CHANNEL_RX); + + return 0; +} \ No newline at end of file diff --git a/zephyr/modules/owntech_communication/zephyr/src/Rs485.h b/zephyr/modules/owntech_communication/zephyr/src/Rs485.h index 399ce8c6..585b9009 100644 --- a/zephyr/modules/owntech_communication/zephyr/src/Rs485.h +++ b/zephyr/modules/owntech_communication/zephyr/src/Rs485.h @@ -128,4 +128,11 @@ void serial_stop(); */ void serial_start(); +/** + * @brief Reinitialize RX DMA if an overrun error occurs. + * + * @return 0 if the overrun error was handled and RX DMA reinitialized, -1 otherwise. + */ +int8_t reinitialize_rx_dma_if_overrun(); + #endif /* RS485_H_ */ diff --git a/zephyr/modules/owntech_communication/zephyr/src/Rs485Communication.cpp b/zephyr/modules/owntech_communication/zephyr/src/Rs485Communication.cpp index 55be55d8..7ccb1e53 100644 --- a/zephyr/modules/owntech_communication/zephyr/src/Rs485Communication.cpp +++ b/zephyr/modules/owntech_communication/zephyr/src/Rs485Communication.cpp @@ -94,3 +94,8 @@ void Rs485Communication::turnOffCommunication() { serial_stop(); } + +int8_t Rs485Communication::reinitializeRxDmaIfOverrun() +{ + return reinitialize_rx_dma_if_overrun(); +} \ No newline at end of file diff --git a/zephyr/modules/owntech_communication/zephyr/src/Rs485Communication.h b/zephyr/modules/owntech_communication/zephyr/src/Rs485Communication.h index a5f01dc6..3ed994e4 100644 --- a/zephyr/modules/owntech_communication/zephyr/src/Rs485Communication.h +++ b/zephyr/modules/owntech_communication/zephyr/src/Rs485Communication.h @@ -116,6 +116,11 @@ class Rs485Communication * @brief Turn off the RS485 */ void turnOffCommunication(); + + /** + * @brief Reinitialize RX DMA if an overrun error occurs. + */ + int8_t reinitializeRxDmaIfOverrun(); }; #endif /* CONFIG_OWNTECH_COMMUNICATION_ENABLE_RS485 */ diff --git a/zephyr/modules/owntech_task_api/zephyr/src/uninterruptible_synchronous_task.cpp b/zephyr/modules/owntech_task_api/zephyr/src/uninterruptible_synchronous_task.cpp index 0d6bf8a5..4c54356d 100644 --- a/zephyr/modules/owntech_task_api/zephyr/src/uninterruptible_synchronous_task.cpp +++ b/zephyr/modules/owntech_task_api/zephyr/src/uninterruptible_synchronous_task.cpp @@ -32,6 +32,10 @@ #include "hrtim.h" #include "SpinAPI.h" +#ifdef CONFIG_OWNTECH_COMMUNICATION +#include "CommunicationAPI.h" +#endif + #ifdef CONFIG_OWNTECH_SAFETY_API #include "safety_internal.h" #include "SafetyAPI.h" @@ -106,6 +110,11 @@ void thread_error(void *, void *, void *) void user_task_proxy() { + +#ifdef CONFIG_OWNTECH_COMMUNICATION +communication.rs485.reinitializeRxDmaIfOverrun(); +#endif + #ifdef CONFIG_OWNTECH_SAFETY_API if (safety_task() != 0) safety_alert = true; From 00f1c754b12677429239e7d57c3ce4a29b14e4f3 Mon Sep 17 00:00:00 2001 From: Ayoub Farah Date: Wed, 4 Mar 2026 12:13:34 +0100 Subject: [PATCH 2/5] adding a warning log --- .../src/uninterruptible_synchronous_task.cpp | 46 +++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/zephyr/modules/owntech_task_api/zephyr/src/uninterruptible_synchronous_task.cpp b/zephyr/modules/owntech_task_api/zephyr/src/uninterruptible_synchronous_task.cpp index 4c54356d..c17fd747 100644 --- a/zephyr/modules/owntech_task_api/zephyr/src/uninterruptible_synchronous_task.cpp +++ b/zephyr/modules/owntech_task_api/zephyr/src/uninterruptible_synchronous_task.cpp @@ -27,6 +27,10 @@ /* Current module */ #include "scheduling_common.h" +/* Zephyr */ +#include +#include + /* OwnTech Power API */ #include "timer.h" #include "hrtim.h" @@ -39,6 +43,13 @@ #ifdef CONFIG_OWNTECH_SAFETY_API #include "safety_internal.h" #include "SafetyAPI.h" +#endif + +#if defined(CONFIG_OWNTECH_SAFETY_API) || \ + (defined(CONFIG_OWNTECH_COMMUNICATION) && \ + defined(CONFIG_OWNTECH_COMMUNICATION_ENABLE_RS485)) + +LOG_MODULE_REGISTER(owntech_task_api, LOG_LEVEL_INF); /* Size of stack area used by error thread */ #define STACKSIZE 512 @@ -72,15 +83,26 @@ static bool do_data_dispatch = false; static uint32_t task_period = 0; /* Safety */ +#ifdef CONFIG_OWNTECH_SAFETY_API static bool safety_alert = false; +#endif + +#if defined(CONFIG_OWNTECH_COMMUNICATION) && \ + defined(CONFIG_OWNTECH_COMMUNICATION_ENABLE_RS485) +static atomic_t rs485_overrun_pending = ATOMIC_INIT(0); +static atomic_t rs485_overrun_count = ATOMIC_INIT(0); +#endif /* Private API */ -#ifdef CONFIG_OWNTECH_SAFETY_API +#if defined(CONFIG_OWNTECH_SAFETY_API) || \ + (defined(CONFIG_OWNTECH_COMMUNICATION) && \ + defined(CONFIG_OWNTECH_COMMUNICATION_ENABLE_RS485)) void thread_error(void *, void *, void *) { while (1) { +#ifdef CONFIG_OWNTECH_SAFETY_API if (safety_alert) { printk("SAFETY ERROR : reset the MCU \n"); @@ -102,6 +124,19 @@ void thread_error(void *, void *, void *) #endif } +#endif + +#if defined(CONFIG_OWNTECH_COMMUNICATION) && \ + defined(CONFIG_OWNTECH_COMMUNICATION_ENABLE_RS485) + if (atomic_cas(&rs485_overrun_pending, 1, 0)) + { + uint32_t overrun_count = (uint32_t)atomic_get(&rs485_overrun_count); + + LOG_WRN("RS485 RX overrun detected: RX DMA reinitialized (event #%u). " + "One frame may be lost because RX callback is paused during overrun.", + (unsigned int)overrun_count); + } +#endif k_msleep(200); } @@ -111,8 +146,13 @@ void thread_error(void *, void *, void *) void user_task_proxy() { -#ifdef CONFIG_OWNTECH_COMMUNICATION -communication.rs485.reinitializeRxDmaIfOverrun(); +#if defined(CONFIG_OWNTECH_COMMUNICATION) && \ + defined(CONFIG_OWNTECH_COMMUNICATION_ENABLE_RS485) + if (communication.rs485.reinitializeRxDmaIfOverrun() == 0) + { + atomic_inc(&rs485_overrun_count); + atomic_set(&rs485_overrun_pending, 1); + } #endif #ifdef CONFIG_OWNTECH_SAFETY_API From 1193ff205c45181441b4e26c2e662a3f236396aa Mon Sep 17 00:00:00 2001 From: Ayoub Farah Date: Wed, 4 Mar 2026 13:13:04 +0100 Subject: [PATCH 3/5] first step toward replacing with zzephyr rtos driver --- .../zephyr/src/Rs485.cpp | 54 +++++++++++++++++-- 1 file changed, 50 insertions(+), 4 deletions(-) diff --git a/zephyr/modules/owntech_communication/zephyr/src/Rs485.cpp b/zephyr/modules/owntech_communication/zephyr/src/Rs485.cpp index e0db0c2b..2a493af4 100644 --- a/zephyr/modules/owntech_communication/zephyr/src/Rs485.cpp +++ b/zephyr/modules/owntech_communication/zephyr/src/Rs485.cpp @@ -31,6 +31,7 @@ /* Zephyr drivers */ #include #include +#include /* Header */ #include "Rs485.h" @@ -107,9 +108,16 @@ static void _dma_callback_tx(const struct device *dev, } /** - * DMA callback RX clear reception flag, then call user functions + * RX handler body shared by: + * - direct ZLI IRQ path (primary path) + * - Zephyr DMA callback path (fallback/safety path) + * + * Note: there is only one hardware IRQ line for this DMA channel. + * In nominal behavior, IRQ 17 is handled by _dma_callback_rx_direct(). + * The Zephyr callback exists to keep dma_config() ownership/tracking valid + * and as a fallback if IRQ routing is changed later. */ -static void _dma_callback_rx() +static void _dma_callback_rx_common() { /* Clear transmission complete flag */ LL_DMA_ClearFlag_TC7(DMA_USART); @@ -119,6 +127,34 @@ static void _dma_callback_rx() } } +/** + * DMA callback RX direct ISR (ZLI path). + */ +ISR_DIRECT_DECLARE(_dma_callback_rx_direct) +{ + _dma_callback_rx_common(); + + /* No scheduling decision from this ISR path */ + return 0; +} + +/** + * DMA callback RX wrapper for Zephyr DMA driver API. + * This path is not expected in nominal ZLI configuration. + */ +static void _dma_callback_rx_zephyr(const struct device *dev, + void *user_data, + uint32_t channel, + int status) +{ + ARG_UNUSED(dev); + ARG_UNUSED(user_data); + ARG_UNUSED(channel); + ARG_UNUSED(status); + + _dma_callback_rx_common(); +} + /* Public functions */ @@ -298,6 +334,7 @@ void dma_channel_init_tx() void dma_channel_init_rx() { /* Configure DMA */ + struct dma_config dma_config_s = {0}; LL_DMA_InitTypeDef DMA_InitStruct = {0}; /* Initialization of DMA */ @@ -312,7 +349,16 @@ void dma_channel_init_rx() DMA_InitStruct.PeriphRequest = LL_DMAMUX_REQ_USART3_RX; DMA_InitStruct.NbData = dma_buffer_size; - IRQ_DIRECT_CONNECT(17, 0, _dma_callback_rx, IRQ_ZERO_LATENCY); + /* + * Register RX channel usage in Zephyr DMA driver. + * This does not create a second hardware interrupt path by itself. + */ + dma_config_s.dma_callback = _dma_callback_rx_zephyr; + dma_config_s.linked_channel = STM32_DMA_HAL_OVERRIDE; + dma_config(dma1, ZEPHYR_DMA_CHANNEL_RX, &dma_config_s); + + /* Bind DMA1 channel IRQ line (17) to the direct zero-latency ISR. */ + IRQ_DIRECT_CONNECT(17, 0, _dma_callback_rx_direct, IRQ_ZERO_LATENCY); irq_enable(17); /* Disabling channel for initial set-up */ @@ -409,4 +455,4 @@ int8_t reinitialize_rx_dma_if_overrun() LL_DMA_EnableChannel(DMA_USART, LL_DMA_CHANNEL_RX); return 0; -} \ No newline at end of file +} From ff3defcd3e41606b98e967bd1d8284679d533ad6 Mon Sep 17 00:00:00 2001 From: Ayoub Farah Date: Wed, 4 Mar 2026 16:55:48 +0100 Subject: [PATCH 4/5] Replacing with full zephyr driver for RX --- .../zephyr/src/Rs485.cpp | 122 ++++++++---------- 1 file changed, 55 insertions(+), 67 deletions(-) diff --git a/zephyr/modules/owntech_communication/zephyr/src/Rs485.cpp b/zephyr/modules/owntech_communication/zephyr/src/Rs485.cpp index 2a493af4..849d657b 100644 --- a/zephyr/modules/owntech_communication/zephyr/src/Rs485.cpp +++ b/zephyr/modules/owntech_communication/zephyr/src/Rs485.cpp @@ -108,31 +108,29 @@ static void _dma_callback_tx(const struct device *dev, } /** - * RX handler body shared by: - * - direct ZLI IRQ path (primary path) - * - Zephyr DMA callback path (fallback/safety path) - * - * Note: there is only one hardware IRQ line for this DMA channel. - * In nominal behavior, IRQ 17 is handled by _dma_callback_rx_direct(). - * The Zephyr callback exists to keep dma_config() ownership/tracking valid - * and as a fallback if IRQ routing is changed later. + * DMA callback RX direct ISR (ZLI path). + * With cyclic DMA configured through Zephyr, both HT and TC IRQs can be + * raised. We clear HT and only trigger user callback on TC. */ -static void _dma_callback_rx_common() +ISR_DIRECT_DECLARE(_dma_callback_rx_direct) { - /* Clear transmission complete flag */ - LL_DMA_ClearFlag_TC7(DMA_USART); + bool is_half_transfer = (LL_DMA_IsActiveFlag_HT7(DMA_USART) != 0U); + bool is_transfer_complete = (LL_DMA_IsActiveFlag_TC7(DMA_USART) != 0U); - if(user_fnc != NULL){ - user_fnc(); + if (is_half_transfer) + { + LL_DMA_ClearFlag_HT7(DMA_USART); } -} -/** - * DMA callback RX direct ISR (ZLI path). - */ -ISR_DIRECT_DECLARE(_dma_callback_rx_direct) -{ - _dma_callback_rx_common(); + if (is_transfer_complete) + { + LL_DMA_ClearFlag_TC7(DMA_USART); + + if (user_fnc != NULL) + { + user_fnc(); + } + } /* No scheduling decision from this ISR path */ return 0; @@ -140,7 +138,10 @@ ISR_DIRECT_DECLARE(_dma_callback_rx_direct) /** * DMA callback RX wrapper for Zephyr DMA driver API. - * This path is not expected in nominal ZLI configuration. + * If IRQ_DIRECT_CONNECT is used for Zephyr DMA RX channel, + * this callback will not be used and the direct ZLI ISR will + * be triggered instead. Otherwise, this callback will be used + * and will call the user function on transfer complete. */ static void _dma_callback_rx_zephyr(const struct device *dev, void *user_data, @@ -150,9 +151,14 @@ static void _dma_callback_rx_zephyr(const struct device *dev, ARG_UNUSED(dev); ARG_UNUSED(user_data); ARG_UNUSED(channel); - ARG_UNUSED(status); - _dma_callback_rx_common(); + if (status == DMA_STATUS_COMPLETE) + { + if (user_fnc != NULL) + { + user_fnc(); + } + } } /* Public functions */ @@ -333,58 +339,40 @@ void dma_channel_init_tx() */ void dma_channel_init_rx() { - /* Configure DMA */ + struct dma_block_config dma_block_config_s = {0}; struct dma_config dma_config_s = {0}; - LL_DMA_InitTypeDef DMA_InitStruct = {0}; - - /* Initialization of DMA */ - DMA_InitStruct.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY; - DMA_InitStruct.PeriphOrM2MSrcAddress = (uint32_t)(&(USART3->RDR)); - DMA_InitStruct.MemoryOrM2MDstAddress = (uint32_t)(rx_usart_val); - DMA_InitStruct.Mode = LL_DMA_MODE_CIRCULAR; - DMA_InitStruct.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_BYTE; - DMA_InitStruct.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_BYTE; - DMA_InitStruct.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; - DMA_InitStruct.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; - DMA_InitStruct.PeriphRequest = LL_DMAMUX_REQ_USART3_RX; - DMA_InitStruct.NbData = dma_buffer_size; - /* - * Register RX channel usage in Zephyr DMA driver. - * This does not create a second hardware interrupt path by itself. - */ + /* Circular peripheral-to-memory transfer configuration */ + dma_block_config_s.source_address = (uint32_t)(&(USART3->RDR)); + dma_block_config_s.dest_address = (uint32_t)(rx_usart_val); + dma_block_config_s.block_size = dma_buffer_size; + dma_block_config_s.source_addr_adj = DMA_ADDR_ADJ_NO_CHANGE; + dma_block_config_s.dest_addr_adj = DMA_ADDR_ADJ_INCREMENT; + dma_block_config_s.source_reload_en = 1; + dma_block_config_s.dest_reload_en = 1; + + dma_config_s.dma_slot = LL_DMAMUX_REQ_USART3_RX; + dma_config_s.channel_direction = PERIPHERAL_TO_MEMORY; + dma_config_s.channel_priority = 3; + dma_config_s.source_data_size = 1; + dma_config_s.dest_data_size = 1; + dma_config_s.source_burst_length = 1; + dma_config_s.dest_burst_length = 1; + dma_config_s.block_count = 1; + dma_config_s.head_block = &dma_block_config_s; dma_config_s.dma_callback = _dma_callback_rx_zephyr; - dma_config_s.linked_channel = STM32_DMA_HAL_OVERRIDE; - dma_config(dma1, ZEPHYR_DMA_CHANNEL_RX, &dma_config_s); + + if (dma_config(dma1, ZEPHYR_DMA_CHANNEL_RX, &dma_config_s) != 0) + { + return; + } /* Bind DMA1 channel IRQ line (17) to the direct zero-latency ISR. */ IRQ_DIRECT_CONNECT(17, 0, _dma_callback_rx_direct, IRQ_ZERO_LATENCY); irq_enable(17); - /* Disabling channel for initial set-up */ - LL_DMA_DisableChannel(DMA_USART, LL_DMA_CHANNEL_RX); - - /* Initialize DMA */ - - /* DMA data size */ - LL_DMA_SetDataLength(DMA_USART, LL_DMA_CHANNEL_RX, dma_buffer_size); - /* DMA channel priority */ - LL_DMA_SetChannelPriorityLevel(DMA_USART, - LL_DMA_CHANNEL_RX, - LL_DMA_PRIORITY_VERYHIGH); - - LL_DMA_Init(DMA_USART, LL_DMA_CHANNEL_RX, &DMA_InitStruct); - - /* Clearing flag */ - LL_DMA_ClearFlag_TC7(DMA_USART); - LL_DMA_ClearFlag_HT7(DMA_USART); - - /* Enabling channel */ - LL_DMA_EnableChannel(DMA_USART, LL_DMA_CHANNEL_RX); - /* Enable transfer complete interruption */ - LL_DMA_EnableIT_TC(DMA_USART, LL_DMA_CHANNEL_RX); - /* Disable half-transfer interruption */ - LL_DMA_DisableIT_HT(DMA_USART, LL_DMA_CHANNEL_RX); + /* Start RX DMA channel through Zephyr API */ + dma_start(dma1, ZEPHYR_DMA_CHANNEL_RX); } From f0366a09b57338f4864513d79fbfd10cbda95e1a Mon Sep 17 00:00:00 2001 From: Ayoub Farah Date: Wed, 4 Mar 2026 17:06:39 +0100 Subject: [PATCH 5/5] adding zephyr drivers for TX --- .../zephyr/src/Rs485.cpp | 92 +++++++------------ 1 file changed, 34 insertions(+), 58 deletions(-) diff --git a/zephyr/modules/owntech_communication/zephyr/src/Rs485.cpp b/zephyr/modules/owntech_communication/zephyr/src/Rs485.cpp index 849d657b..148439a0 100644 --- a/zephyr/modules/owntech_communication/zephyr/src/Rs485.cpp +++ b/zephyr/modules/owntech_communication/zephyr/src/Rs485.cpp @@ -90,21 +90,20 @@ static dma_callbackRXfunc_t user_fnc = NULL; /* Private functions */ /** - * DMA callback TX clear transmission flag, and disabled DMA channel TX. + * DMA callback TX: called by Zephyr DMA driver on transfer completion. */ static void _dma_callback_tx(const struct device *dev, void *user_data, uint32_t channel, int status) { - /* Disable DMA channel after sending datas */ - LL_DMA_DisableChannel(DMA_USART, LL_DMA_CHANNEL_TX); + ARG_UNUSED(dev); + ARG_UNUSED(user_data); + ARG_UNUSED(channel); + ARG_UNUSED(status); LL_USART_ClearFlag_TXFE(USART3); - /* Clear transmission complete flag USART */ LL_USART_ClearFlag_TC(USART3); - /* Clear transmission complete dma channel TX */ - LL_DMA_ClearFlag_TC6(DMA_USART); } /** @@ -286,51 +285,30 @@ void oversamp_set(usart_oversampling_t oversampling) */ void dma_channel_init_tx() { - /* Configure DMA */ + struct dma_block_config dma_block_config_s = {0}; struct dma_config dma_config_s = {0}; - LL_DMA_InitTypeDef DMA_InitStruct = {0}; - - /* Callback function set-up */ - dma_config_s.dma_callback = _dma_callback_tx; - /* HAL override */ - dma_config_s.linked_channel = STM32_DMA_HAL_OVERRIDE; - - /* DMA configuration with LL drivers */ - DMA_InitStruct.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH; - DMA_InitStruct.PeriphOrM2MSrcAddress = (uint32_t)(&(USART3->TDR)); - DMA_InitStruct.MemoryOrM2MDstAddress = (uint32_t)(tx_usart_val); - DMA_InitStruct.Mode = LL_DMA_MODE_NORMAL; - DMA_InitStruct.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_BYTE; - DMA_InitStruct.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_BYTE; - DMA_InitStruct.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; - DMA_InitStruct.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; - DMA_InitStruct.PeriphRequest = LL_DMAMUX_REQ_USART3_TX; - DMA_InitStruct.NbData = dma_buffer_size; - - /* Indicates callback function to zephyr driver */ - dma_config(dma1, ZEPHYR_DMA_CHANNEL_TX, &dma_config_s); - /* Disabling channel for initial set-up */ - LL_DMA_DisableChannel(DMA_USART, LL_DMA_CHANNEL_TX); - - /* Initialize DMA */ - - /* DMA data size */ - LL_DMA_SetDataLength(DMA_USART, LL_DMA_CHANNEL_TX, dma_buffer_size); - /* DMA channel priority */ - LL_DMA_SetChannelPriorityLevel(DMA_USART, - LL_DMA_CHANNEL_TX, - LL_DMA_PRIORITY_VERYHIGH); - LL_DMA_Init(DMA_USART, LL_DMA_CHANNEL_TX, &DMA_InitStruct); + /* Memory-to-peripheral transfer configuration (TX buffer -> USART TDR). */ + dma_block_config_s.source_address = (uint32_t)(tx_usart_val); + dma_block_config_s.dest_address = (uint32_t)(&(USART3->TDR)); + dma_block_config_s.block_size = dma_buffer_size; + dma_block_config_s.source_addr_adj = DMA_ADDR_ADJ_INCREMENT; + dma_block_config_s.dest_addr_adj = DMA_ADDR_ADJ_NO_CHANGE; + dma_block_config_s.source_reload_en = 0; + dma_block_config_s.dest_reload_en = 0; - /* Clearing flags */ - LL_DMA_ClearFlag_TC6(DMA_USART); - LL_DMA_ClearFlag_HT6(DMA_USART); + dma_config_s.dma_slot = LL_DMAMUX_REQ_USART3_TX; + dma_config_s.channel_direction = MEMORY_TO_PERIPHERAL; + dma_config_s.channel_priority = 3; + dma_config_s.source_data_size = 1; + dma_config_s.dest_data_size = 1; + dma_config_s.source_burst_length = 1; + dma_config_s.dest_burst_length = 1; + dma_config_s.block_count = 1; + dma_config_s.head_block = &dma_block_config_s; + dma_config_s.dma_callback = _dma_callback_tx; - /* Enable transfer complete interruption */ - LL_DMA_EnableIT_TC(DMA_USART, LL_DMA_CHANNEL_TX); - /* Disable half-transfer interruption */ - LL_DMA_DisableIT_HT(DMA_USART, LL_DMA_CHANNEL_TX); + dma_config(dma1, ZEPHYR_DMA_CHANNEL_TX, &dma_config_s); } @@ -382,18 +360,16 @@ void dma_channel_init_rx() */ void serial_tx_on() { - /* Making sure the flag is cleared before transmission */ - LL_DMA_ClearFlag_TC6(DMA_USART); - /* Disable channel to reload TX buffer */ - LL_DMA_DisableChannel(DMA_USART, LL_DMA_CHANNEL_TX); - /* Reloading TX buffer */ - LL_DMA_SetMemoryAddress(DMA_USART, - LL_DMA_CHANNEL_TX, - (uint32_t)(tx_usart_val)); + if (dma_reload(dma1, + ZEPHYR_DMA_CHANNEL_TX, + (uint32_t)(tx_usart_val), + (uint32_t)(&(USART3->TDR)), + dma_buffer_size) != 0) + { + return; + } - LL_DMA_SetDataLength(DMA_USART, LL_DMA_CHANNEL_TX, dma_buffer_size); - /* Re-enable the channel */ - LL_DMA_EnableChannel(DMA_USART, LL_DMA_CHANNEL_TX); + dma_start(dma1, ZEPHYR_DMA_CHANNEL_TX); } /**