From ecd6c1d5d6669d2ffbaf80942e5fa30caf987a4a Mon Sep 17 00:00:00 2001 From: abody Date: Tue, 1 Oct 2019 14:49:10 +0200 Subject: [PATCH] usart_handler: DMA based memory copy --- .cproject | 588 ++++++++++++++---------------------------- Inc/stm32f4xx_it.h | 1 + Src/dma.c | 47 +++- Src/stm32f4xx_it.c | 15 ++ app/application.c | 21 +- app/config.h | 9 + app/diag.h | 1 + app/stats.h | 2 + f407ve_hs_uart.ioc | 23 +- lib/console_handler.c | 4 - lib/memcpy_dma.c | 39 +++ lib/memcpy_dma.h | 20 ++ lib/usart_handler.c | 5 +- 13 files changed, 367 insertions(+), 408 deletions(-) create mode 100644 lib/memcpy_dma.c create mode 100644 lib/memcpy_dma.h diff --git a/.cproject b/.cproject index 861f716..435280f 100644 --- a/.cproject +++ b/.cproject @@ -1,394 +1,200 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Inc/stm32f4xx_it.h b/Inc/stm32f4xx_it.h index 4006de1..4a2cc55 100644 --- a/Inc/stm32f4xx_it.h +++ b/Inc/stm32f4xx_it.h @@ -69,6 +69,7 @@ void USART3_IRQHandler(void); void DMA1_Stream7_IRQHandler(void); void UART4_IRQHandler(void); void UART5_IRQHandler(void); +void DMA2_Stream0_IRQHandler(void); void DMA2_Stream1_IRQHandler(void); void DMA2_Stream2_IRQHandler(void); void DMA2_Stream4_IRQHandler(void); diff --git a/Src/dma.c b/Src/dma.c index 36bfb25..0a70083 100644 --- a/Src/dma.c +++ b/Src/dma.c @@ -61,13 +61,13 @@ void MX_DMA_Init(void) LL_DMA_SetPeriphIncMode(DMA2, LL_DMA_STREAM_4, LL_DMA_PERIPH_INCREMENT); /* Set memory increment mode */ - LL_DMA_SetMemoryIncMode(DMA2, LL_DMA_STREAM_4, LL_DMA_MEMORY_INCREMENT); + LL_DMA_SetMemoryIncMode(DMA2, LL_DMA_STREAM_4, LL_DMA_MEMORY_NOINCREMENT); /* Set peripheral data width */ - LL_DMA_SetPeriphSize(DMA2, LL_DMA_STREAM_4, LL_DMA_PDATAALIGN_BYTE); + LL_DMA_SetPeriphSize(DMA2, LL_DMA_STREAM_4, LL_DMA_PDATAALIGN_WORD); /* Set memory data width */ - LL_DMA_SetMemorySize(DMA2, LL_DMA_STREAM_4, LL_DMA_MDATAALIGN_BYTE); + LL_DMA_SetMemorySize(DMA2, LL_DMA_STREAM_4, LL_DMA_MDATAALIGN_WORD); /* Enable FIFO mode */ LL_DMA_EnableFifoMode(DMA2, LL_DMA_STREAM_4); @@ -81,6 +81,44 @@ void MX_DMA_Init(void) /* Set peripheral burst size */ LL_DMA_SetPeriphBurstxfer(DMA2, LL_DMA_STREAM_4, LL_DMA_PBURST_SINGLE); + /* Configure DMA request MEMTOMEM_DMA2_Stream0 */ + + /* Select channel */ + LL_DMA_SetChannelSelection(DMA2, LL_DMA_STREAM_0, LL_DMA_CHANNEL_0); + + /* Set transfer direction */ + LL_DMA_SetDataTransferDirection(DMA2, LL_DMA_STREAM_0, LL_DMA_DIRECTION_MEMORY_TO_MEMORY); + + /* Set priority level */ + LL_DMA_SetStreamPriorityLevel(DMA2, LL_DMA_STREAM_0, LL_DMA_PRIORITY_LOW); + + /* Set DMA mode */ + LL_DMA_SetMode(DMA2, LL_DMA_STREAM_0, LL_DMA_MODE_NORMAL); + + /* Set peripheral increment mode */ + LL_DMA_SetPeriphIncMode(DMA2, LL_DMA_STREAM_0, LL_DMA_PERIPH_INCREMENT); + + /* Set memory increment mode */ + LL_DMA_SetMemoryIncMode(DMA2, LL_DMA_STREAM_0, LL_DMA_MEMORY_INCREMENT); + + /* Set peripheral data width */ + LL_DMA_SetPeriphSize(DMA2, LL_DMA_STREAM_0, LL_DMA_PDATAALIGN_WORD); + + /* Set memory data width */ + LL_DMA_SetMemorySize(DMA2, LL_DMA_STREAM_0, LL_DMA_MDATAALIGN_WORD); + + /* Enable FIFO mode */ + LL_DMA_EnableFifoMode(DMA2, LL_DMA_STREAM_0); + + /* Set FIFO threshold */ + LL_DMA_SetFIFOThreshold(DMA2, LL_DMA_STREAM_0, LL_DMA_FIFOTHRESHOLD_FULL); + + /* Set memory burst size */ + LL_DMA_SetMemoryBurstxfer(DMA2, LL_DMA_STREAM_0, LL_DMA_MBURST_SINGLE); + + /* Set peripheral burst size */ + LL_DMA_SetPeriphBurstxfer(DMA2, LL_DMA_STREAM_0, LL_DMA_PBURST_SINGLE); + /* DMA interrupt init */ /* DMA1_Stream0_IRQn interrupt configuration */ NVIC_SetPriority(DMA1_Stream0_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); @@ -106,6 +144,9 @@ void MX_DMA_Init(void) /* DMA1_Stream7_IRQn interrupt configuration */ NVIC_SetPriority(DMA1_Stream7_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); NVIC_EnableIRQ(DMA1_Stream7_IRQn); + /* DMA2_Stream0_IRQn interrupt configuration */ + NVIC_SetPriority(DMA2_Stream0_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); + NVIC_EnableIRQ(DMA2_Stream0_IRQn); /* DMA2_Stream1_IRQn interrupt configuration */ NVIC_SetPriority(DMA2_Stream1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); NVIC_EnableIRQ(DMA2_Stream1_IRQn); diff --git a/Src/stm32f4xx_it.c b/Src/stm32f4xx_it.c index 7b47321..dc33684 100644 --- a/Src/stm32f4xx_it.c +++ b/Src/stm32f4xx_it.c @@ -26,6 +26,7 @@ #include "usart_handler.h" #include "crc_handler.h" #include "console_handler.h" +#include "memcpy_dma.h" #include "globals.h" #include "diag.h" @@ -380,6 +381,20 @@ void UART5_IRQHandler(void) /* USER CODE END UART5_IRQn 1 */ } +/** + * @brief This function handles DMA2 stream0 global interrupt. + */ +void DMA2_Stream0_IRQHandler(void) +{ + /* USER CODE BEGIN DMA2_Stream0_IRQn 0 */ + HandleMemcpyDmaIrq(); + /* USER CODE END DMA2_Stream0_IRQn 0 */ + + /* USER CODE BEGIN DMA2_Stream0_IRQn 1 */ + + /* USER CODE END DMA2_Stream0_IRQn 1 */ +} + /** * @brief This function handles DMA2 stream1 global interrupt. */ diff --git a/app/application.c b/app/application.c index 35f6ecd..6c4c1d9 100644 --- a/app/application.c +++ b/app/application.c @@ -1,4 +1,5 @@ #include +#include #include "application.h" #include "globals.h" #include "strutil.h" @@ -6,6 +7,7 @@ #include "usart_handler.h" #include "crc_handler.h" #include "console_handler.h" +#include "memcpy_dma.h" #define PACKAGE_DELAY_MS 0 #define STATS_DELAY_MS 1000 @@ -21,7 +23,9 @@ void MainLoop() { - static uint8_t const text2Send[] = "------------------------------------------------\r\n| Megszentsegtelenithetetlensegeskedeseitekert |\r\n------------------------------------------------\r\n"; + uint8_t const text2Send[] __attribute__((aligned(4))) = + "Megszentsegtelenithetetlensegeskedeseitekert\r\n" + "--------------------------------------------\r\n\0\0\0"; struct initdata_t { USART_TypeDef* uart; @@ -40,6 +44,14 @@ void MainLoop() uint32_t prevSentTick = 0; uint8_t statId = 0; + uint32_t tmp = sizeof(text2Send) - 1; + uint32_t randmask = 0x80000000; + do + if(randmask & tmp) + break; + while((randmask = randmask >> 1)); + randmask -= 1; + for(uint16_t idx = 0; idx < sizeof(g_uartStatuses) / sizeof(g_uartStatuses[0]); ++idx) { struct initdata_t const *id = &initdata[idx]; InitUartStatus(&g_uartStatuses[idx], id->uart, id->dma, id->stream_rx, id->stream_tx, @@ -49,9 +61,10 @@ void MainLoop() InitCrcStatus(&g_crcStatus, DMA2, LL_DMA_STREAM_4); - InitDmaInfo(&g_ConsoleTxDmaInfo, DMA1, LL_DMA_STREAM_4); + InitDmaInfo(&g_ConsoleTxDmaInfo, CONSOLE_DMA_ENGINE, CONSOLE_TX_DMA_STREAM); LL_DMA_EnableIT_TC(g_ConsoleTxDmaInfo.dma, g_ConsoleTxDmaInfo.stream); - LL_DMA_EnableIT_TE(g_ConsoleTxDmaInfo.dma, g_ConsoleTxDmaInfo.stream); + + InitMemcpyDma(MEMCPY_DMA_ENGINE, MEMCPY_DMA_STREAM); lastStatsTick = HAL_GetTick(); @@ -66,7 +79,7 @@ void MainLoop() for(uint16_t idx = 0; idx < sizeof(g_uartStatuses) / sizeof(g_uartStatuses[0]); ++idx) { if(!g_uartStatuses[idx].txBuffer.busy && send) { - PostPacket(&g_uartStatuses[idx], NULL, sizeof(text2Send) -1, &g_crcStatus); + PostPacket(&g_uartStatuses[idx], text2Send, sizeof(text2Send) - 1 - (rand() & randmask), &g_crcStatus); } for(uint16_t rIdx = 0; rIdx < 2; ++rIdx) if(g_uartStatuses[idx].rxBuffers[rIdx].busy || g_uartStatuses[idx].rxBuffers[rIdx].error) diff --git a/app/config.h b/app/config.h index 257e585..092426c 100644 --- a/app/config.h +++ b/app/config.h @@ -16,4 +16,13 @@ #define USART5_OFFSET 3 #define USART6_OFFSET 4 +#define CONSOLE_DMA_ENGINE DMA1 +#define CONSOLE_TX_DMA_STREAM LL_DMA_STREAM_4 + +#define CRC_DMA_ENGINE DMA2 +#define CRC_DMA_STREAM LL_DMA_STREAM_4 + +#define MEMCPY_DMA_ENGINE DMA2 +#define MEMCPY_DMA_STREAM LL_DMA_STREAM_0 + #endif /* CONFIG_H_ */ diff --git a/app/diag.h b/app/diag.h index 258ff82..8a72935 100644 --- a/app/diag.h +++ b/app/diag.h @@ -21,6 +21,7 @@ if(x) { \ #define DIAG_CRC_CALC_END() LL_GPIO_ResetOutputPin(DIAG0_GPIO_Port, DIAG0_Pin)//; LL_GPIO_TogglePin(DIAG3_GPIO_Port, DIAG3_Pin) #define DIAG_INTERRUPT_IN() LL_GPIO_SetOutputPin(DIAG1_GPIO_Port, DIAG1_Pin) #define DIAG_INTERRUPT_OUT() LL_GPIO_ResetOutputPin(DIAG1_GPIO_Port, DIAG1_Pin) +#define DIAG_ERROR_EVENT() LL_GPIO_TogglePin(DIAG2_GPIO_Port, DIAG2_Pin) #else // _ENABLE_DIAG diff --git a/app/stats.h b/app/stats.h index cf4c69d..29f1b5c 100644 --- a/app/stats.h +++ b/app/stats.h @@ -7,6 +7,7 @@ #ifndef STATS_H_ #define STATS_H_ +#include "diag.h" #ifndef DIAG_ERROR_EVENT # define DIAG_ERROR_EVENT() @@ -41,6 +42,7 @@ static inline void StatsIncPayloadError(STATS *s, uint32_t pep1, uint32_t pep2) s->pep2 = pep2; } static inline void StatsIncDmaError(STATS *s) { + DIAG_ERROR_EVENT(); ++s->dmaError; } static inline void StatsIncRcvd(STATS *s) { diff --git a/f407ve_hs_uart.ioc b/f407ve_hs_uart.ioc index 625c7ec..a33b79d 100644 --- a/f407ve_hs_uart.ioc +++ b/f407ve_hs_uart.ioc @@ -4,19 +4,33 @@ Dma.MEMTOMEM.12.FIFOMode=DMA_FIFOMODE_ENABLE Dma.MEMTOMEM.12.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL Dma.MEMTOMEM.12.Instance=DMA2_Stream4 Dma.MEMTOMEM.12.MemBurst=DMA_MBURST_SINGLE -Dma.MEMTOMEM.12.MemDataAlignment=DMA_MDATAALIGN_BYTE -Dma.MEMTOMEM.12.MemInc=DMA_MINC_ENABLE +Dma.MEMTOMEM.12.MemDataAlignment=DMA_MDATAALIGN_WORD +Dma.MEMTOMEM.12.MemInc=DMA_MINC_DISABLE Dma.MEMTOMEM.12.Mode=DMA_NORMAL Dma.MEMTOMEM.12.PeriphBurst=DMA_PBURST_SINGLE -Dma.MEMTOMEM.12.PeriphDataAlignment=DMA_PDATAALIGN_BYTE +Dma.MEMTOMEM.12.PeriphDataAlignment=DMA_PDATAALIGN_WORD Dma.MEMTOMEM.12.PeriphInc=DMA_PINC_ENABLE Dma.MEMTOMEM.12.Priority=DMA_PRIORITY_LOW Dma.MEMTOMEM.12.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode,FIFOThreshold,MemBurst,PeriphBurst +Dma.MEMTOMEM.13.Direction=DMA_MEMORY_TO_MEMORY +Dma.MEMTOMEM.13.FIFOMode=DMA_FIFOMODE_ENABLE +Dma.MEMTOMEM.13.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL +Dma.MEMTOMEM.13.Instance=DMA2_Stream0 +Dma.MEMTOMEM.13.MemBurst=DMA_MBURST_SINGLE +Dma.MEMTOMEM.13.MemDataAlignment=DMA_MDATAALIGN_WORD +Dma.MEMTOMEM.13.MemInc=DMA_MINC_ENABLE +Dma.MEMTOMEM.13.Mode=DMA_NORMAL +Dma.MEMTOMEM.13.PeriphBurst=DMA_PBURST_SINGLE +Dma.MEMTOMEM.13.PeriphDataAlignment=DMA_PDATAALIGN_WORD +Dma.MEMTOMEM.13.PeriphInc=DMA_PINC_ENABLE +Dma.MEMTOMEM.13.Priority=DMA_PRIORITY_LOW +Dma.MEMTOMEM.13.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode,FIFOThreshold,MemBurst,PeriphBurst Dma.Request0=UART4_RX Dma.Request1=UART4_TX Dma.Request10=USART6_RX Dma.Request11=USART6_TX Dma.Request12=MEMTOMEM +Dma.Request13=MEMTOMEM Dma.Request2=USART3_RX Dma.Request3=USART3_TX Dma.Request4=UART5_RX @@ -25,7 +39,7 @@ Dma.Request6=USART2_RX Dma.Request7=USART2_TX Dma.Request8=USART1_RX Dma.Request9=USART1_TX -Dma.RequestsNb=13 +Dma.RequestsNb=14 Dma.UART4_RX.0.Direction=DMA_PERIPH_TO_MEMORY Dma.UART4_RX.0.FIFOMode=DMA_FIFOMODE_DISABLE Dma.UART4_RX.0.Instance=DMA1_Stream2 @@ -209,6 +223,7 @@ NVIC.DMA1_Stream4_IRQn=true\:0\:0\:false\:false\:true\:false\:true NVIC.DMA1_Stream5_IRQn=true\:0\:0\:false\:false\:true\:false\:true NVIC.DMA1_Stream6_IRQn=true\:0\:0\:false\:false\:true\:false\:true NVIC.DMA1_Stream7_IRQn=true\:0\:0\:false\:false\:true\:false\:true +NVIC.DMA2_Stream0_IRQn=true\:0\:0\:false\:false\:true\:true\:true NVIC.DMA2_Stream1_IRQn=true\:0\:0\:false\:false\:true\:false\:true NVIC.DMA2_Stream2_IRQn=true\:0\:0\:false\:false\:true\:false\:true NVIC.DMA2_Stream4_IRQn=true\:0\:0\:false\:false\:true\:true\:true diff --git a/lib/console_handler.c b/lib/console_handler.c index 41aced6..29f5f7a 100644 --- a/lib/console_handler.c +++ b/lib/console_handler.c @@ -16,10 +16,6 @@ void HandleConsoleUsartTxDmaIrq(DMAINFO *info, USART_TypeDef *usart) // debug us LL_USART_EnableIT_TC(usart); LL_DMA_DisableStream(info->dma, info->stream); } - else if(*info->isReg & info->htMask) - *info->ifcReg = info->htMask; - else if(*info->isReg & info->teMask) - *info->ifcReg = info->teMask; } void HandleConsoleUsartIrq(USART_TypeDef *usart) diff --git a/lib/memcpy_dma.c b/lib/memcpy_dma.c new file mode 100644 index 0000000..35770f8 --- /dev/null +++ b/lib/memcpy_dma.c @@ -0,0 +1,39 @@ +/* + * memcpy_dma.c + * + * Created on: Oct 1, 2019 + * Author: abody + */ +#include "memcpy_dma.h" +#include "dma_helper.h" + +volatile uint8_t g_memcpyDmaBusy = 0; + +static DMAINFO g_memcpyDmaInfo; + +void InitMemcpyDma(DMA_TypeDef *dma, uint32_t stream) +{ + InitDmaInfo(&g_memcpyDmaInfo, dma, stream); + LL_DMA_EnableIT_TC(dma, stream); +} + +void * MemcpyDma(void *dst, void const *src, size_t length) +{ + LL_DMA_SetM2MSrcAddress(g_memcpyDmaInfo.dma, g_memcpyDmaInfo.stream, (uint32_t)src); + LL_DMA_SetM2MDstAddress(g_memcpyDmaInfo.dma, g_memcpyDmaInfo.stream, (uint32_t)dst); + LL_DMA_SetDataLength(g_memcpyDmaInfo.dma, g_memcpyDmaInfo.stream, (length+3)/4 ); + g_memcpyDmaBusy = 1; + //DIAG_CRC_CALC_START(); + LL_DMA_EnableStream(g_memcpyDmaInfo.dma, g_memcpyDmaInfo.stream); + while(g_memcpyDmaBusy); + return dst; +} + +void HandleMemcpyDmaIrq() +{ + if(*g_memcpyDmaInfo.isReg & g_memcpyDmaInfo.tcMask) { // DMA transfer complete + *g_memcpyDmaInfo.ifcReg = g_memcpyDmaInfo.tcMask; + LL_DMA_DisableStream(g_memcpyDmaInfo.dma, g_memcpyDmaInfo.stream); + g_memcpyDmaBusy = 0; + } +} diff --git a/lib/memcpy_dma.h b/lib/memcpy_dma.h new file mode 100644 index 0000000..9eab257 --- /dev/null +++ b/lib/memcpy_dma.h @@ -0,0 +1,20 @@ +/* + * memcpy_dma.h + * + * Created on: Oct 1, 2019 + * Author: abody + */ + +#ifndef MEMCPY_DMA_H_ +#define MEMCPY_DMA_H_ + +#include +#include "dma.h" +//#include "dma_helper.h" +//extern DMAINFO g_memcpyDmaInfo; + +void InitMemcpyDma(DMA_TypeDef *dma, uint32_t stream); +void * MemcpyDma(void *dst, void const *src, size_t length); +void HandleMemcpyDmaIrq(); + +#endif /* MEMCPY_DMA_H_ */ diff --git a/lib/usart_handler.c b/lib/usart_handler.c index 594edc3..ea27003 100644 --- a/lib/usart_handler.c +++ b/lib/usart_handler.c @@ -11,6 +11,7 @@ #include "usart_handler.h" #include "dma_helper.h" #include "crc_handler.h" +#include "memcpy_dma.h" #ifndef DIAG_RX_BUFFER_SWITCH # define DIAG_RX_BUFFER_SWITCH(x) @@ -73,7 +74,7 @@ uint8_t PostPacket(UARTSTATUS *status, uint8_t const *payload, uint16_t length, BuildHeader(&status->txBuffer, status->txSerial++, length); uint16_t payloadLength = (length+3) & 0xfffc; // round up to 4 if(payload) - memcpy(status->txBuffer.packet.payload, payload, length); + MemcpyDma(status->txBuffer.packet.payload, payload, length); status->txBuffer.requestedLength = sizeof(UARTPACKETHEADER) + payloadLength + sizeof(uint32_t); // +4 for the hash status->txBuffer.busy = 1; status->txBuffer.error = 0; @@ -118,7 +119,7 @@ void ConsumePacket(UARTSTATUS *status, uint8_t packetIndex, struct crcstatus_t * void SetupTransmit(USART_TypeDef *uart, DMA_TypeDef* dma, uint32_t stream, void *buffer, uint32_t length) { - LL_DMA_ConfigAddresses(dma, stream, (uint32_t)buffer, LL_USART_DMA_GetRegAddr(uart),LL_DMA_DIRECTION_MEMORY_TO_PERIPH); + LL_DMA_ConfigAddresses(dma, stream, (uint32_t)buffer, LL_USART_DMA_GetRegAddr(uart), LL_DMA_DIRECTION_MEMORY_TO_PERIPH); LL_DMA_SetDataLength(dma, stream, length); LL_USART_EnableDMAReq_TX(uart); LL_DMA_EnableStream(dma, stream);