From 8e9ae1b6b2454043187a62ceb2aa6a532238d998 Mon Sep 17 00:00:00 2001 From: Mario Goebbels Date: Thu, 18 Jan 2018 00:28:57 +0100 Subject: [PATCH 1/6] pios_usart,F4: Add DMA transfer capability. --- flight/PiOS/STM32/inc/pios_usart_priv.h | 18 ++ flight/PiOS/STM32F4xx/pios_usart.c | 208 ++++++++++++++++++++++-- 2 files changed, 211 insertions(+), 15 deletions(-) diff --git a/flight/PiOS/STM32/inc/pios_usart_priv.h b/flight/PiOS/STM32/inc/pios_usart_priv.h index 1b9c9c0715..185875168a 100644 --- a/flight/PiOS/STM32/inc/pios_usart_priv.h +++ b/flight/PiOS/STM32/inc/pios_usart_priv.h @@ -36,12 +36,25 @@ extern const struct pios_com_driver pios_usart_com_driver; +#if defined(STM32F4XX) +struct pios_usart_dma_cfg { + DMA_Stream_TypeDef *stream; + DMA_InitTypeDef init; + uint32_t tcif; + NVIC_InitTypeDef irq; +}; +#endif + struct pios_usart_cfg { USART_TypeDef *regs; uint32_t remap; /* GPIO_Remap_* */ struct stm32_gpio rx; struct stm32_gpio tx; struct stm32_irq irq; +#if defined(STM32F4XX) + struct pios_usart_dma_cfg *dma_send; + struct pios_usart_dma_cfg *dma_recv; +#endif }; struct pios_usart_params { @@ -55,6 +68,11 @@ struct pios_usart_params { extern int32_t PIOS_USART_Init(uintptr_t * usart_id, const struct pios_usart_cfg * cfg, struct pios_usart_params * params); extern const struct pios_usart_cfg * PIOS_USART_GetConfig(uintptr_t usart_id); +#if defined(STM32F4XX) +extern void PIOS_USART_dma_irq_tx_handler(const struct pios_usart_cfg *cfg); +extern void PIOS_USART_dma_irq_rx_handler(const struct pios_usart_cfg *cfg); +#endif + #endif /* PIOS_USART_PRIV_H */ /** diff --git a/flight/PiOS/STM32F4xx/pios_usart.c b/flight/PiOS/STM32F4xx/pios_usart.c index adee4a8e64..43fde117be 100644 --- a/flight/PiOS/STM32F4xx/pios_usart.c +++ b/flight/PiOS/STM32F4xx/pios_usart.c @@ -39,6 +39,10 @@ #include +/* DMA buffer sizes. */ +#define PIOS_USART_DMA_SEND_BUFFER_SZ 64 +#define PIOS_USART_DMA_RECV_BUFFER_SZ 64 + /* Provide a COM driver */ static void PIOS_USART_ChangeBaud(uintptr_t usart_id, uint32_t baud); static void PIOS_USART_RegisterRxCallback(uintptr_t usart_id, pios_com_callback rx_in_cb, uintptr_t context); @@ -66,6 +70,8 @@ struct pios_usart_dev { uintptr_t rx_in_context; pios_com_callback tx_out_cb; uintptr_t tx_out_context; + uint32_t dma_send_buffer; + uint32_t dma_recv_buffer; }; static bool PIOS_USART_validate(struct pios_usart_dev * usart_dev) @@ -215,13 +221,50 @@ int32_t PIOS_USART_Init(uintptr_t * usart_id, const struct pios_usart_cfg * cfg, break; } NVIC_Init((NVIC_InitTypeDef *)&(usart_dev->cfg->irq.init)); - USART_ITConfig(usart_dev->cfg->regs, USART_IT_RXNE, ENABLE); - USART_ITConfig(usart_dev->cfg->regs, USART_IT_TXE, ENABLE); // FIXME XXX Clear / reset uart here - sends NUL char else + /* Check DMA transmit configuration and prepare DMA. */ + if (cfg->dma_send) { + usart_dev->dma_send_buffer = (uint32_t)PIOS_malloc(PIOS_USART_DMA_SEND_BUFFER_SZ); + + if (usart_dev->dma_send_buffer) { + DMA_DeInit(cfg->dma_send->stream); + DMA_Init(cfg->dma_send->stream, &cfg->dma_send->init); + NVIC_Init(&cfg->dma_send->irq); + } + } + + /* Check DMA receive configuration, and setup and start DMA. */ + if (cfg->dma_recv) { + usart_dev->dma_recv_buffer = (uint32_t)PIOS_malloc(PIOS_USART_DMA_RECV_BUFFER_SZ); + + if (usart_dev->dma_recv_buffer) { + DMA_DeInit(cfg->dma_recv->stream); + DMA_Init(cfg->dma_recv->stream, &cfg->dma_recv->init); + NVIC_Init(&cfg->dma_recv->irq); + + USART_ITConfig(cfg->regs, USART_IT_IDLE, ENABLE); + + /* Start DMA here already. */ + DMA_ITConfig(cfg->dma_recv->stream, DMA_IT_TC, ENABLE); + DMA_MemoryTargetConfig(cfg->dma_recv->stream, usart_dev->dma_recv_buffer, DMA_Memory_0); + DMA_SetCurrDataCounter(cfg->dma_recv->stream, PIOS_USART_DMA_RECV_BUFFER_SZ); + + USART_DMACmd(cfg->regs, USART_DMAReq_Rx, ENABLE); + DMA_Cmd(cfg->dma_recv->stream, ENABLE); + } + } + + if (!usart_dev->dma_recv_buffer) { + /* If DMA isn't in-use or we failed to allocate the buffer, use RXNE interrupt for data. */ + USART_ITConfig(cfg->regs, USART_IT_RXNE, ENABLE); + } + + USART_ITConfig(cfg->regs, USART_IT_TXE, ENABLE); + /* Enable USART */ - USART_Cmd(usart_dev->cfg->regs, ENABLE); + USART_Cmd(cfg->regs, ENABLE); return(0); @@ -244,8 +287,10 @@ static void PIOS_USART_TxStart(uintptr_t usart_id, uint16_t tx_bytes_avail) bool valid = PIOS_USART_validate(usart_dev); PIOS_Assert(valid); - - USART_ITConfig(usart_dev->cfg->regs, USART_IT_TXE, ENABLE); + + if (!usart_dev->dma_send_buffer || DMA_GetCmdStatus(usart_dev->cfg->dma_send->stream) == DISABLE) { + USART_ITConfig(usart_dev->cfg->regs, USART_IT_TXE, ENABLE); + } } /** @@ -325,23 +370,64 @@ static void PIOS_USART_generic_irq_handler(uintptr_t usart_id) (void) (usart_dev->rx_in_cb)(usart_dev->rx_in_context, &byte, 1, NULL, &rx_need_yield); } } + + if (sr & USART_SR_IDLE) { + /* If line goes idle, trigger DMA IRQ for data processing. */ + DMA_Cmd(usart_dev->cfg->dma_recv->stream, DISABLE); + while (DMA_GetCmdStatus(usart_dev->cfg->dma_recv->stream) == ENABLE) ; + } /* Check if TXE flag is set */ bool tx_need_yield = false; if (sr & USART_SR_TXE) { if (usart_dev->tx_out_cb) { - uint8_t b; - uint16_t bytes_to_send; - - bytes_to_send = (usart_dev->tx_out_cb)(usart_dev->tx_out_context, &b, 1, NULL, &tx_need_yield); - - if (bytes_to_send > 0) { - /* Send the byte we've been given */ - usart_dev->cfg->regs->DR = b; + + if (usart_dev->dma_send_buffer) { + /* Here's how it goes: + + TXE interrupt triggers, because USART has nothing to do. If there's more than 1 byte to send, + the TXE IRQ gets disabled and a single DMA transfer gets triggered. When that transfer is done, + it'll reenable TXE IRQ, to repeat this whole thing. */ + + if (DMA_GetCmdStatus(usart_dev->cfg->dma_send->stream) == ENABLE) { + /* If we get here while DMA is enabled, for whatever reason, GTFO. + Also, re-disable TXE. */ + USART_ITConfig(usart_dev->cfg->regs, USART_IT_TXE, DISABLE); + return; + } + + uint16_t bytes_to_send = (usart_dev->tx_out_cb)(usart_dev->tx_out_context, (uint8_t*)usart_dev->dma_send_buffer, + PIOS_USART_DMA_SEND_BUFFER_SZ, NULL, &tx_need_yield); + + if (bytes_to_send > 1) { + USART_ITConfig(usart_dev->cfg->regs, USART_IT_TXE, DISABLE); + + DMA_MemoryTargetConfig(usart_dev->cfg->dma_send->stream, usart_dev->dma_send_buffer, DMA_Memory_0); + DMA_SetCurrDataCounter(usart_dev->cfg->dma_send->stream, bytes_to_send); + DMA_ITConfig(usart_dev->cfg->dma_send->stream, DMA_IT_TC, ENABLE); + + USART_DMACmd(usart_dev->cfg->regs, USART_DMAReq_Tx, ENABLE); + DMA_Cmd(usart_dev->cfg->dma_send->stream, ENABLE); + } else if (bytes_to_send == 1) { + /* Don't use DMA for single byte. */ + usart_dev->cfg->regs->DR = *((uint8_t*)usart_dev->dma_send_buffer); + } else { + USART_ITConfig(usart_dev->cfg->regs, USART_IT_TXE, DISABLE); + } } else { - /* No bytes to send, disable TXE interrupt */ - USART_ITConfig(usart_dev->cfg->regs, USART_IT_TXE, DISABLE); + /* Send byte-by-byte. */ + uint8_t byte; + uint16_t bytes_to_send = (usart_dev->tx_out_cb)(usart_dev->tx_out_context, &byte, 1, NULL, &tx_need_yield); + + if (bytes_to_send > 0) { + /* Send the byte we've been given */ + usart_dev->cfg->regs->DR = byte; + } else { + /* No bytes to send, disable TXE interrupt */ + USART_ITConfig(usart_dev->cfg->regs, USART_IT_TXE, DISABLE); + } } + /* if (usart_dev->dma_send_buffer) */ } else { /* No bytes to send, disable TXE interrupt */ USART_ITConfig(usart_dev->cfg->regs, USART_IT_TXE, DISABLE); @@ -349,6 +435,98 @@ static void PIOS_USART_generic_irq_handler(uintptr_t usart_id) } } +static uintptr_t PIOS_USART_GetDevice(const struct pios_usart_cfg *cfg) +{ + PIOS_Assert(cfg); + + switch((uint32_t)cfg->regs) { + case (uint32_t)USART1: + return PIOS_USART_1_id; + case (uint32_t)USART2: + return PIOS_USART_2_id; + case (uint32_t)USART3: + return PIOS_USART_3_id; + case (uint32_t)UART4: + return PIOS_USART_4_id; + case (uint32_t)UART5: + return PIOS_USART_5_id; + case (uint32_t)USART6: + return PIOS_USART_6_id; + default: + return 0; + } +} + +void PIOS_USART_dma_irq_tx_handler(const struct pios_usart_cfg *cfg) +{ + PIOS_IRQ_Prologue(); + + struct pios_usart_dev *usart_dev = (struct pios_usart_dev*)PIOS_USART_GetDevice(cfg); + if (!usart_dev) + goto get_out; + + struct pios_usart_dma_cfg *dmacfg = usart_dev->cfg->dma_send; + PIOS_Assert(dmacfg); + + if (DMA_GetFlagStatus(dmacfg->stream, dmacfg->tcif) == SET) { + /* TX handler*/ + USART_DMACmd(usart_dev->cfg->regs, USART_DMAReq_Tx, DISABLE); + + DMA_Cmd(dmacfg->stream, DISABLE); + while (DMA_GetCmdStatus(dmacfg->stream) == ENABLE) ; + + DMA_ITConfig(dmacfg->stream, DMA_IT_TC, DISABLE); + DMA_ClearITPendingBit(dmacfg->stream, dmacfg->tcif); + DMA_ClearFlag(dmacfg->stream, dmacfg->tcif); + + /* Re-enable TXE interrupt, which kicks off the next data transfer, if there's stuff. */ + USART_ITConfig(usart_dev->cfg->regs, USART_IT_TXE, ENABLE); + } + +get_out: + PIOS_IRQ_Epilogue(); +} + +void PIOS_USART_dma_irq_rx_handler(const struct pios_usart_cfg *cfg) +{ + PIOS_IRQ_Prologue(); + + struct pios_usart_dev *usart_dev = (struct pios_usart_dev*)PIOS_USART_GetDevice(cfg); + if (!usart_dev) + goto get_out; + + struct pios_usart_dma_cfg *dmacfg = usart_dev->cfg->dma_recv; + PIOS_Assert(dmacfg); + + /* RX handler*/ + if (DMA_GetFlagStatus(dmacfg->stream, dmacfg->tcif) == SET) { + + DMA_Cmd(dmacfg->stream, DISABLE); + while (DMA_GetCmdStatus(dmacfg->stream) == ENABLE) ; + + /* Need to figure out how much data was captured either way, because USART idle stops the DMA + causing this to trigger, too.*/ + uint32_t data_read = PIOS_USART_DMA_RECV_BUFFER_SZ - DMA_GetCurrDataCounter(dmacfg->stream); + + if (usart_dev->rx_in_cb && data_read > 0) { + bool rx_need_yield = false; + (usart_dev->rx_in_cb)(usart_dev->rx_in_context, (uint8_t*)usart_dev->dma_recv_buffer, data_read, + NULL, &rx_need_yield); + } + + DMA_ClearITPendingBit(dmacfg->stream, dmacfg->tcif); + DMA_ClearFlag(dmacfg->stream, dmacfg->tcif); + + /* Restart DMA. */ + DMA_MemoryTargetConfig(dmacfg->stream, usart_dev->dma_recv_buffer, DMA_Memory_0); + DMA_SetCurrDataCounter(dmacfg->stream, PIOS_USART_DMA_RECV_BUFFER_SZ); + DMA_Cmd(dmacfg->stream, ENABLE); + } + +get_out: + PIOS_IRQ_Epilogue(); +} + #endif /** From 7f2c57f54d04245949ac00e037b8234f7116bbf0 Mon Sep 17 00:00:00 2001 From: Mario Goebbels Date: Thu, 18 Jan 2018 00:29:36 +0100 Subject: [PATCH 2/6] seppuku: DMA on USART6 test/demo config. --- .../seppuku/board-info/board_hw_defs.c | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/flight/targets/seppuku/board-info/board_hw_defs.c b/flight/targets/seppuku/board-info/board_hw_defs.c index d7b61b2ae3..6f18378e05 100644 --- a/flight/targets/seppuku/board-info/board_hw_defs.c +++ b/flight/targets/seppuku/board-info/board_hw_defs.c @@ -661,6 +661,60 @@ static const struct pios_usart_cfg pios_uart4_cfg = { }, }; +/* + USART6 DMA config. +*/ +static struct pios_usart_dma_cfg pios_usart6_dma_rx_cfg = { + .stream = DMA2_Stream2, + .tcif = DMA_FLAG_TCIF2, + .init = { + /* Could probably thin out some of these, that are defined to zero anyway. */ + .DMA_Channel = DMA_Channel_5, + .DMA_PeripheralBaseAddr = (uint32_t)&USART6->DR, + .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte, + .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte, + .DMA_MemoryInc = DMA_MemoryInc_Enable, + .DMA_PeripheralInc = DMA_PeripheralInc_Disable, + .DMA_DIR = DMA_DIR_PeripheralToMemory, + .DMA_Mode = DMA_Mode_Normal, + .DMA_Priority = DMA_Priority_High, + .DMA_MemoryBurst = DMA_MemoryBurst_Single, + .DMA_PeripheralBurst = DMA_PeripheralBurst_Single, + .DMA_FIFOMode = DMA_FIFOMode_Disable, + }, + .irq = { + .NVIC_IRQChannel = DMA2_Stream2_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_LOW, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + } +}; +static struct pios_usart_dma_cfg pios_usart6_dma_tx_cfg = { + .stream = DMA2_Stream7, + .tcif = DMA_FLAG_TCIF7, + .init = { + /* Could probably thin out some of these, that are defined to zero anyway. */ + .DMA_Channel = DMA_Channel_5, + .DMA_PeripheralBaseAddr = (uint32_t)&USART6->DR, + .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte, + .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte, + .DMA_MemoryInc = DMA_MemoryInc_Enable, + .DMA_PeripheralInc = DMA_PeripheralInc_Disable, + .DMA_DIR = DMA_DIR_MemoryToPeripheral, + .DMA_Mode = DMA_Mode_Normal, + .DMA_Priority = DMA_Priority_High, + .DMA_MemoryBurst = DMA_MemoryBurst_Single, + .DMA_PeripheralBurst = DMA_PeripheralBurst_Single, + .DMA_FIFOMode = DMA_FIFOMode_Disable, + }, + .irq = { + .NVIC_IRQChannel = DMA2_Stream7_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_LOW, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + } +}; + static const struct pios_usart_cfg pios_usart6_cfg = { .regs = USART6, .remap = GPIO_AF_USART6, @@ -694,8 +748,19 @@ static const struct pios_usart_cfg pios_usart6_cfg = { }, .pin_source = GPIO_PinSource6, }, + .dma_recv = &pios_usart6_dma_rx_cfg, + .dma_send = &pios_usart6_dma_tx_cfg }; +void DMA2_Stream2_IRQHandler(void) +{ + PIOS_USART_dma_irq_rx_handler(&pios_usart6_cfg); +} +void DMA2_Stream7_IRQHandler(void) +{ + PIOS_USART_dma_irq_tx_handler(&pios_usart6_cfg); +} + #endif /* PIOS_INCLUDE_USART */ #if defined(PIOS_INCLUDE_COM) From 7410022203bdf828d12ceb889742179e3cd49fb0 Mon Sep 17 00:00:00 2001 From: Mario Goebbels Date: Tue, 1 May 2018 19:18:18 +0200 Subject: [PATCH 3/6] pios_usart: Declare USART specific DMA RX/TX handlers to call. --- flight/PiOS/STM32/inc/pios_usart_priv.h | 21 +++- flight/PiOS/STM32F4xx/pios_usart.c | 127 ++++++++++++++++-------- 2 files changed, 107 insertions(+), 41 deletions(-) diff --git a/flight/PiOS/STM32/inc/pios_usart_priv.h b/flight/PiOS/STM32/inc/pios_usart_priv.h index 185875168a..4134ef4e82 100644 --- a/flight/PiOS/STM32/inc/pios_usart_priv.h +++ b/flight/PiOS/STM32/inc/pios_usart_priv.h @@ -69,8 +69,25 @@ extern int32_t PIOS_USART_Init(uintptr_t * usart_id, const struct pios_usart_cfg extern const struct pios_usart_cfg * PIOS_USART_GetConfig(uintptr_t usart_id); #if defined(STM32F4XX) -extern void PIOS_USART_dma_irq_tx_handler(const struct pios_usart_cfg *cfg); -extern void PIOS_USART_dma_irq_rx_handler(const struct pios_usart_cfg *cfg); + +extern void PIOS_USART_1_dmarx_irq_handler(void); +extern void PIOS_USART_1_dmatx_irq_handler(void); + +extern void PIOS_USART_2_dmarx_irq_handler(void); +extern void PIOS_USART_2_dmatx_irq_handler(void); + +extern void PIOS_USART_3_dmarx_irq_handler(void); +extern void PIOS_USART_3_dmatx_irq_handler(void); + +extern void PIOS_USART_4_dmarx_irq_handler(void); +extern void PIOS_USART_4_dmatx_irq_handler(void); + +extern void PIOS_USART_5_dmarx_irq_handler(void); +extern void PIOS_USART_5_dmatx_irq_handler(void); + +extern void PIOS_USART_6_dmarx_irq_handler(void); +extern void PIOS_USART_6_dmatx_irq_handler(void); + #endif #endif /* PIOS_USART_PRIV_H */ diff --git a/flight/PiOS/STM32F4xx/pios_usart.c b/flight/PiOS/STM32F4xx/pios_usart.c index 43fde117be..b175f448ad 100644 --- a/flight/PiOS/STM32F4xx/pios_usart.c +++ b/flight/PiOS/STM32F4xx/pios_usart.c @@ -153,6 +153,7 @@ static void PIOS_USART_6_irq_handler (void) PIOS_IRQ_Epilogue(); } + /** * Initialise a single USART device */ @@ -435,42 +436,20 @@ static void PIOS_USART_generic_irq_handler(uintptr_t usart_id) } } -static uintptr_t PIOS_USART_GetDevice(const struct pios_usart_cfg *cfg) -{ - PIOS_Assert(cfg); - - switch((uint32_t)cfg->regs) { - case (uint32_t)USART1: - return PIOS_USART_1_id; - case (uint32_t)USART2: - return PIOS_USART_2_id; - case (uint32_t)USART3: - return PIOS_USART_3_id; - case (uint32_t)UART4: - return PIOS_USART_4_id; - case (uint32_t)UART5: - return PIOS_USART_5_id; - case (uint32_t)USART6: - return PIOS_USART_6_id; - default: - return 0; - } -} - -void PIOS_USART_dma_irq_tx_handler(const struct pios_usart_cfg *cfg) +void PIOS_USART_dma_irq_tx_handler(uintptr_t usart_id) { - PIOS_IRQ_Prologue(); - - struct pios_usart_dev *usart_dev = (struct pios_usart_dev*)PIOS_USART_GetDevice(cfg); + struct pios_usart_dev *usart_dev = (struct pios_usart_dev*)usart_id; if (!usart_dev) - goto get_out; + return; - struct pios_usart_dma_cfg *dmacfg = usart_dev->cfg->dma_send; + const struct pios_usart_cfg *cfg = usart_dev->cfg; + + struct pios_usart_dma_cfg *dmacfg = cfg->dma_send; PIOS_Assert(dmacfg); if (DMA_GetFlagStatus(dmacfg->stream, dmacfg->tcif) == SET) { /* TX handler*/ - USART_DMACmd(usart_dev->cfg->regs, USART_DMAReq_Tx, DISABLE); + USART_DMACmd(cfg->regs, USART_DMAReq_Tx, DISABLE); DMA_Cmd(dmacfg->stream, DISABLE); while (DMA_GetCmdStatus(dmacfg->stream) == ENABLE) ; @@ -480,20 +459,15 @@ void PIOS_USART_dma_irq_tx_handler(const struct pios_usart_cfg *cfg) DMA_ClearFlag(dmacfg->stream, dmacfg->tcif); /* Re-enable TXE interrupt, which kicks off the next data transfer, if there's stuff. */ - USART_ITConfig(usart_dev->cfg->regs, USART_IT_TXE, ENABLE); + USART_ITConfig(cfg->regs, USART_IT_TXE, ENABLE); } - -get_out: - PIOS_IRQ_Epilogue(); } -void PIOS_USART_dma_irq_rx_handler(const struct pios_usart_cfg *cfg) +void PIOS_USART_dma_irq_rx_handler(uintptr_t usart_id) { - PIOS_IRQ_Prologue(); - - struct pios_usart_dev *usart_dev = (struct pios_usart_dev*)PIOS_USART_GetDevice(cfg); + struct pios_usart_dev *usart_dev = (struct pios_usart_dev*)usart_id; if (!usart_dev) - goto get_out; + return; struct pios_usart_dma_cfg *dmacfg = usart_dev->cfg->dma_recv; PIOS_Assert(dmacfg); @@ -522,8 +496,83 @@ void PIOS_USART_dma_irq_rx_handler(const struct pios_usart_cfg *cfg) DMA_SetCurrDataCounter(dmacfg->stream, PIOS_USART_DMA_RECV_BUFFER_SZ); DMA_Cmd(dmacfg->stream, ENABLE); } +} -get_out: +void PIOS_USART_1_dmarx_irq_handler(void) +{ + PIOS_IRQ_Prologue(); + PIOS_USART_dma_irq_rx_handler(PIOS_USART_1_id); + PIOS_IRQ_Epilogue(); +} +void PIOS_USART_1_dmatx_irq_handler(void) +{ + PIOS_IRQ_Prologue(); + PIOS_USART_dma_irq_tx_handler(PIOS_USART_1_id); + PIOS_IRQ_Epilogue(); +} + +void PIOS_USART_2_dmarx_irq_handler(void) +{ + PIOS_IRQ_Prologue(); + PIOS_USART_dma_irq_rx_handler(PIOS_USART_2_id); + PIOS_IRQ_Epilogue(); +} +void PIOS_USART_2_dmatx_irq_handler(void) +{ + PIOS_IRQ_Prologue(); + PIOS_USART_dma_irq_tx_handler(PIOS_USART_2_id); + PIOS_IRQ_Epilogue(); +} + +void PIOS_USART_3_dmarx_irq_handler(void) +{ + PIOS_IRQ_Prologue(); + PIOS_USART_dma_irq_rx_handler(PIOS_USART_3_id); + PIOS_IRQ_Epilogue(); +} +void PIOS_USART_3_dmatx_irq_handler(void) +{ + PIOS_IRQ_Prologue(); + PIOS_USART_dma_irq_tx_handler(PIOS_USART_3_id); + PIOS_IRQ_Epilogue(); +} + +void PIOS_USART_4_dmarx_irq_handler(void) +{ + PIOS_IRQ_Prologue(); + PIOS_USART_dma_irq_rx_handler(PIOS_USART_4_id); + PIOS_IRQ_Epilogue(); +} +void PIOS_USART_4_dmatx_irq_handler(void) +{ + PIOS_IRQ_Prologue(); + PIOS_USART_dma_irq_tx_handler(PIOS_USART_4_id); + PIOS_IRQ_Epilogue(); +} + +void PIOS_USART_5_dmarx_irq_handler(void) +{ + PIOS_IRQ_Prologue(); + PIOS_USART_dma_irq_rx_handler(PIOS_USART_5_id); + PIOS_IRQ_Epilogue(); +} +void PIOS_USART_5_dmatx_irq_handler(void) +{ + PIOS_IRQ_Prologue(); + PIOS_USART_dma_irq_tx_handler(PIOS_USART_5_id); + PIOS_IRQ_Epilogue(); +} + +void PIOS_USART_6_dmarx_irq_handler(void) +{ + PIOS_IRQ_Prologue(); + PIOS_USART_dma_irq_rx_handler(PIOS_USART_6_id); + PIOS_IRQ_Epilogue(); +} +void PIOS_USART_6_dmatx_irq_handler(void) +{ + PIOS_IRQ_Prologue(); + PIOS_USART_dma_irq_tx_handler(PIOS_USART_6_id); PIOS_IRQ_Epilogue(); } From d87b816924254d414f110f6aafd39dbf7c6d1017 Mon Sep 17 00:00:00 2001 From: Mario Goebbels Date: Tue, 1 May 2018 19:18:49 +0200 Subject: [PATCH 4/6] seppuku: Change handler stuff --- flight/targets/seppuku/board-info/board_hw_defs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flight/targets/seppuku/board-info/board_hw_defs.c b/flight/targets/seppuku/board-info/board_hw_defs.c index 6f18378e05..b6bd9438a0 100644 --- a/flight/targets/seppuku/board-info/board_hw_defs.c +++ b/flight/targets/seppuku/board-info/board_hw_defs.c @@ -754,11 +754,11 @@ static const struct pios_usart_cfg pios_usart6_cfg = { void DMA2_Stream2_IRQHandler(void) { - PIOS_USART_dma_irq_rx_handler(&pios_usart6_cfg); + PIOS_USART_6_dmarx_irq_handler(); } void DMA2_Stream7_IRQHandler(void) { - PIOS_USART_dma_irq_tx_handler(&pios_usart6_cfg); + PIOS_USART_6_dmatx_irq_handler(); } #endif /* PIOS_INCLUDE_USART */ From 56c7dafca2ca0475405d10bf54ad8e730b438a32 Mon Sep 17 00:00:00 2001 From: Mario Goebbels Date: Tue, 1 May 2018 19:32:41 +0200 Subject: [PATCH 5/6] pios_usart: Add flag field and DMA hint. --- flight/PiOS/STM32/inc/pios_usart_priv.h | 4 ++++ flight/PiOS/STM32F4xx/pios_usart.c | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/flight/PiOS/STM32/inc/pios_usart_priv.h b/flight/PiOS/STM32/inc/pios_usart_priv.h index 4134ef4e82..bc93ad2ea6 100644 --- a/flight/PiOS/STM32/inc/pios_usart_priv.h +++ b/flight/PiOS/STM32/inc/pios_usart_priv.h @@ -34,6 +34,9 @@ #include #include "pios_usart.h" +#define PIOS_USART_ALLOW_RECEIVE_DMA 0x1 +#define PIOS_USART_ALLOW_TRANSMIT_DMA 0x2 + extern const struct pios_com_driver pios_usart_com_driver; #if defined(STM32F4XX) @@ -63,6 +66,7 @@ struct pios_usart_params { bool tx_invert; bool rxtx_swap; bool single_wire; + uint8_t flags; }; extern int32_t PIOS_USART_Init(uintptr_t * usart_id, const struct pios_usart_cfg * cfg, struct pios_usart_params * params); diff --git a/flight/PiOS/STM32F4xx/pios_usart.c b/flight/PiOS/STM32F4xx/pios_usart.c index b175f448ad..ba3669074a 100644 --- a/flight/PiOS/STM32F4xx/pios_usart.c +++ b/flight/PiOS/STM32F4xx/pios_usart.c @@ -226,7 +226,7 @@ int32_t PIOS_USART_Init(uintptr_t * usart_id, const struct pios_usart_cfg * cfg, // FIXME XXX Clear / reset uart here - sends NUL char else /* Check DMA transmit configuration and prepare DMA. */ - if (cfg->dma_send) { + if (cfg->dma_send && (params->flags & PIOS_USART_ALLOW_TRANSMIT_DMA)) { usart_dev->dma_send_buffer = (uint32_t)PIOS_malloc(PIOS_USART_DMA_SEND_BUFFER_SZ); if (usart_dev->dma_send_buffer) { @@ -237,7 +237,7 @@ int32_t PIOS_USART_Init(uintptr_t * usart_id, const struct pios_usart_cfg * cfg, } /* Check DMA receive configuration, and setup and start DMA. */ - if (cfg->dma_recv) { + if (cfg->dma_recv && (params->flags & PIOS_USART_ALLOW_RECEIVE_DMA)) { usart_dev->dma_recv_buffer = (uint32_t)PIOS_malloc(PIOS_USART_DMA_RECV_BUFFER_SZ); if (usart_dev->dma_recv_buffer) { From 35d6ff94adc8ab2be862d0b54becca410a820c21 Mon Sep 17 00:00:00 2001 From: Mario Goebbels Date: Tue, 1 May 2018 19:33:22 +0200 Subject: [PATCH 6/6] pios_hal: Allow USART DMA for OpenLog, S.Bus, SRXL, IBus and Crossfire. --- flight/PiOS/Common/pios_hal.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/flight/PiOS/Common/pios_hal.c b/flight/PiOS/Common/pios_hal.c index 6ba46eef4b..1002b4ba1d 100644 --- a/flight/PiOS/Common/pios_hal.c +++ b/flight/PiOS/Common/pios_hal.c @@ -813,6 +813,7 @@ void PIOS_HAL_ConfigurePort(HwSharedPortTypesOptions port_type, case HWSHARED_PORTTYPES_OPENLOG: #if defined(PIOS_INCLUDE_OPENLOG) + usart_port_params.flags = PIOS_USART_ALLOW_TRANSMIT_DMA; PIOS_HAL_ConfigureCom(usart_port_cfg, &usart_port_params, 0, PIOS_COM_OPENLOG_TX_BUF_LEN, com_driver, &port_driver_id); target = &pios_com_openlog_logging_id; #endif /* PIOS_INCLUDE_OPENLOG */ @@ -874,6 +875,7 @@ void PIOS_HAL_ConfigurePort(HwSharedPortTypesOptions port_type, usart_port_params.init.USART_StopBits = USART_StopBits_2; usart_port_params.init.USART_HardwareFlowControl = USART_HardwareFlowControl_None; usart_port_params.init.USART_Mode = USART_Mode_Rx; + usart_port_params.flags = PIOS_USART_ALLOW_RECEIVE_DMA; if (port_type == HWSHARED_PORTTYPES_SBUS) usart_port_params.rx_invert = true; @@ -919,6 +921,7 @@ void PIOS_HAL_ConfigurePort(HwSharedPortTypesOptions port_type, usart_port_params.init.USART_StopBits = USART_StopBits_1; usart_port_params.init.USART_HardwareFlowControl = USART_HardwareFlowControl_None; usart_port_params.init.USART_Mode = USART_Mode_Rx; + usart_port_params.flags = PIOS_USART_ALLOW_RECEIVE_DMA; PIOS_HAL_ConfigureSRXL(usart_port_cfg, &usart_port_params, com_driver); } @@ -934,6 +937,7 @@ void PIOS_HAL_ConfigurePort(HwSharedPortTypesOptions port_type, usart_port_params.init.USART_StopBits = USART_StopBits_1; usart_port_params.init.USART_HardwareFlowControl = USART_HardwareFlowControl_None; usart_port_params.init.USART_Mode = USART_Mode_Rx; + usart_port_params.flags = PIOS_USART_ALLOW_RECEIVE_DMA; PIOS_HAL_ConfigureIBus(usart_port_cfg, &usart_port_params, com_driver); } @@ -949,6 +953,7 @@ void PIOS_HAL_ConfigurePort(HwSharedPortTypesOptions port_type, usart_port_params.init.USART_StopBits = USART_StopBits_1; usart_port_params.init.USART_HardwareFlowControl = USART_HardwareFlowControl_None; usart_port_params.init.USART_Mode = USART_Mode_Rx|USART_Mode_Tx; + usart_port_params.flags = PIOS_USART_ALLOW_RECEIVE_DMA | PIOS_USART_ALLOW_TRANSMIT_DMA; PIOS_HAL_ConfigureTbsCrossfire(usart_port_cfg, &usart_port_params, com_driver); PIOS_Modules_Enable(PIOS_MODULE_UAVOCROSSFIRETELEMETRY);