diff --git a/Core/Inc/usart2_dma.h b/Core/Inc/usart2_dma.h new file mode 100644 index 0000000..fee957a --- /dev/null +++ b/Core/Inc/usart2_dma.h @@ -0,0 +1,16 @@ +#ifndef __USART2_IT_H__ +#define __USART2_IT_H__ + +#include +#include "usart2_dma_cfg.h" + + +extern uint8_t Usart2RxDmaBuf[USART2_RXDMA_BUF_SIZE]; + +extern void Usart2_DMA_Init(void (*)(const uint8_t* data, uint16_t len)); +extern void Usart2_DMA_Task(); +extern uint8_t Usart2_TxBufWrite(const void* src, size_t n, uint8_t flush); + + +#endif + diff --git a/Core/Inc/usart2_dma_cfg.h b/Core/Inc/usart2_dma_cfg.h new file mode 100644 index 0000000..3b6bbf2 --- /dev/null +++ b/Core/Inc/usart2_dma_cfg.h @@ -0,0 +1,15 @@ +#ifndef __USART2_IT_CFG_H__ +#define __USART2_IT_CFG_H__ + +#include "stm32h5xx_ll_dma.h" + + +#define USART2_RXDMA_BUF_SIZE 2048 +#define USART2_TXDMA_BUF_SIZE 2048 + +#define USART2_GPDMA GPDMA1 +#define USART2_DMA_TX_CHANNEL LL_DMA_CHANNEL_2 +#define USART2_DMA_RX_CHANNEL LL_DMA_CHANNEL_3 + + +#endif // __USART2_CFG_H__ diff --git a/Core/Inc/usart3_dma.h b/Core/Inc/usart3_dma.h index b07b4d3..da40346 100644 --- a/Core/Inc/usart3_dma.h +++ b/Core/Inc/usart3_dma.h @@ -9,9 +9,7 @@ extern uint8_t Usart3RxDmaBuf[USART3_RXDMA_BUF_SIZE]; extern void Usart3_DMA_Init(void (*)(const uint8_t* data, uint16_t len)); extern void Usart3_DMA_Task(); -extern void Usart3_PutByte(uint8_t d); -extern void Usart3_PutData(const void* src, uint16_t n); -extern int16_t Usart3_GetByte(void); +extern uint8_t Usart3_TxBufWrite(const void* src, size_t n, uint8_t flush); #endif diff --git a/Core/Src/main.c b/Core/Src/main.c index ebcd904..c5a4b29 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -26,6 +26,7 @@ #include "disp7seg.h" #include "printf.h" +#include "usart2_dma.h" #include "usart3_dma.h" #include "uart5_it.h" @@ -49,6 +50,7 @@ /* Private variables ---------------------------------------------------------*/ +LL_DMA_LinkNodeTypeDef Node_GPDMA1_Channel3; LL_DMA_LinkNodeTypeDef Node_GPDMA1_Channel1; /* USER CODE BEGIN PV */ @@ -69,7 +71,6 @@ static void MX_UART5_Init(void); static void MX_USART2_UART_Init(void); /* USER CODE BEGIN PFP */ -uint8_t Usart3_TxBufWrite(const void* src, size_t n, uint8_t start); /* USER CODE END PFP */ @@ -102,11 +103,22 @@ void uart_putc (void* p, char c) { } +void ProcessUsart2RxData(const uint8_t* data, uint16_t len) { + printf("USART2 RX(%u): ", len); + for (uint16_t i = 0; i < len; i++) { + printf("%c", data[i]); + } + printf("\n"); + Delay_us(500); // simulate long processing time +} void ProcessUsart3RxData(const uint8_t* data, uint16_t len) { + printf("USART3 RX(%u): ", len); for (uint16_t i = 0; i < len; i++) { printf("%c", data[i]); } + printf("\n"); + Delay_us(500); // simulate long processing time } /* USER CODE END 0 */ @@ -171,6 +183,7 @@ int main(void) DispPutDigit(3, ' ', 0); ShiftReg_Update(); + Usart2_DMA_Init(ProcessUsart2RxData); Usart3_DMA_Init(ProcessUsart3RxData); Uart5_Init(); printf("Hello printf\n"); @@ -195,6 +208,8 @@ int main(void) char s[256]; sprintf(s, "%u: Hello DMA World! This is a long message to test the double buffering mechanism of USART3 Tx DMA.\n", cnt); Usart3_TxBufWrite(s, strlen(s), cnt&0x04); // write data and request flush + sprintf(s, "%u: Message from USART2 DMA.\n", cnt); + Usart2_TxBufWrite(s, strlen(s), !(cnt&0x04)); } static uint32_t Tick100msRef = 0; @@ -210,6 +225,7 @@ int main(void) DispPutDigit(0, c, 0); } + Usart2_DMA_Task(); // handle USART2 DMA rx/tx Usart3_DMA_Task(); // handle USART3 DMA rx/tx @@ -317,6 +333,8 @@ static void MX_GPDMA1_Init(void) /* GPDMA1 interrupt Init */ NVIC_SetPriority(GPDMA1_Channel0_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); NVIC_SetPriority(GPDMA1_Channel1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); + NVIC_SetPriority(GPDMA1_Channel2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); + NVIC_SetPriority(GPDMA1_Channel3_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); /* USER CODE BEGIN GPDMA1_Init 1 */ @@ -498,11 +516,22 @@ static void MX_USART2_UART_Init(void) /* USER CODE BEGIN USART2_Init 0 */ + // WARNING + // Remove the second redefinition of NodeConfig after Cube MX code generation. + LL_DMA_InitNodeTypeDef NodeConfig = {0}; + + NodeConfig.SrcAddress = (uint32_t)LL_USART_DMA_GetRegAddr(USART2, LL_USART_DMA_REG_DATA_RECEIVE); + NodeConfig.DestAddress = (uint32_t)&Usart2RxDmaBuf; + NodeConfig.BlkDataLength = ARRAY_COUNT(Usart2RxDmaBuf); + + /* USER CODE END USART2_Init 0 */ LL_USART_InitTypeDef USART_InitStruct = {0}; LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + LL_DMA_InitLinkedListTypeDef DMA_InitLinkedListStruct = {0}; + LL_DMA_InitTypeDef DMA_InitStruct = {0}; LL_RCC_SetUSARTClockSource(LL_RCC_USART2_CLKSOURCE_PCLK1); @@ -523,8 +552,83 @@ static void MX_USART2_UART_Init(void) GPIO_InitStruct.Alternate = LL_GPIO_AF_7; LL_GPIO_Init(GPIOA, &GPIO_InitStruct); + /* USART2 DMA Init */ + + /* GPDMA1_REQUEST_USART2_RX Init */ + NodeConfig.DestAllocatedPort = LL_DMA_DEST_ALLOCATED_PORT1; + NodeConfig.DestHWordExchange = LL_DMA_DEST_HALFWORD_PRESERVE; + NodeConfig.DestByteExchange = LL_DMA_DEST_BYTE_PRESERVE; + NodeConfig.DestBurstLength = 1; + NodeConfig.DestIncMode = LL_DMA_DEST_INCREMENT; + NodeConfig.DestDataWidth = LL_DMA_DEST_DATAWIDTH_BYTE; + NodeConfig.SrcAllocatedPort = LL_DMA_SRC_ALLOCATED_PORT0; + NodeConfig.SrcByteExchange = LL_DMA_SRC_BYTE_PRESERVE; + NodeConfig.DataAlignment = LL_DMA_DATA_ALIGN_ZEROPADD; + NodeConfig.SrcBurstLength = 1; + NodeConfig.SrcIncMode = LL_DMA_SRC_FIXED; + NodeConfig.SrcDataWidth = LL_DMA_SRC_DATAWIDTH_BYTE; + NodeConfig.TransferEventMode = LL_DMA_TCEM_BLK_TRANSFER; + NodeConfig.Mode = LL_DMA_NORMAL; + NodeConfig.TriggerPolarity = LL_DMA_TRIG_POLARITY_MASKED; + NodeConfig.BlkHWRequest = LL_DMA_HWREQUEST_SINGLEBURST; + NodeConfig.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY; + NodeConfig.Request = LL_GPDMA1_REQUEST_USART2_RX; + NodeConfig.UpdateRegisters = (LL_DMA_UPDATE_CTR1 | LL_DMA_UPDATE_CTR2 | LL_DMA_UPDATE_CBR1 | LL_DMA_UPDATE_CSAR | LL_DMA_UPDATE_CDAR | LL_DMA_UPDATE_CTR3 | LL_DMA_UPDATE_CBR2 | LL_DMA_UPDATE_CLLR); + NodeConfig.NodeType = LL_DMA_GPDMA_LINEAR_NODE; + LL_DMA_CreateLinkNode(&NodeConfig, &Node_GPDMA1_Channel3); + + LL_DMA_ConnectLinkNode(&Node_GPDMA1_Channel3, LL_DMA_CLLR_OFFSET5, &Node_GPDMA1_Channel3, LL_DMA_CLLR_OFFSET5); + + /* Next function call is commented because it will not compile as is. The Node structure address has to be cast to an unsigned int (uint32_t)pNode_DMAxCHy */ + /* + + */ + LL_DMA_SetLinkedListBaseAddr(GPDMA1, LL_DMA_CHANNEL_3, (uint32_t)&Node_GPDMA1_Channel3); + + DMA_InitLinkedListStruct.Priority = LL_DMA_LOW_PRIORITY_LOW_WEIGHT; + DMA_InitLinkedListStruct.LinkStepMode = LL_DMA_LSM_FULL_EXECUTION; + DMA_InitLinkedListStruct.LinkAllocatedPort = LL_DMA_LINK_ALLOCATED_PORT1; + DMA_InitLinkedListStruct.TransferEventMode = LL_DMA_TCEM_BLK_TRANSFER; + LL_DMA_List_Init(GPDMA1, LL_DMA_CHANNEL_3, &DMA_InitLinkedListStruct); + + /* GPDMA1_REQUEST_USART2_TX Init */ + DMA_InitStruct.SrcAddress = 0x00000000U; + DMA_InitStruct.DestAddress = 0x00000000U; + DMA_InitStruct.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH; + DMA_InitStruct.BlkHWRequest = LL_DMA_HWREQUEST_SINGLEBURST; + DMA_InitStruct.DataAlignment = LL_DMA_DATA_ALIGN_ZEROPADD; + DMA_InitStruct.SrcBurstLength = 1; + DMA_InitStruct.DestBurstLength = 1; + DMA_InitStruct.SrcDataWidth = LL_DMA_SRC_DATAWIDTH_BYTE; + DMA_InitStruct.DestDataWidth = LL_DMA_DEST_DATAWIDTH_BYTE; + DMA_InitStruct.SrcIncMode = LL_DMA_SRC_INCREMENT; + DMA_InitStruct.DestIncMode = LL_DMA_DEST_FIXED; + DMA_InitStruct.Priority = LL_DMA_LOW_PRIORITY_LOW_WEIGHT; + DMA_InitStruct.BlkDataLength = 0x00000000U; + DMA_InitStruct.TriggerMode = LL_DMA_TRIGM_BLK_TRANSFER; + DMA_InitStruct.TriggerPolarity = LL_DMA_TRIG_POLARITY_MASKED; + DMA_InitStruct.TriggerSelection = 0x00000000U; + DMA_InitStruct.Request = LL_GPDMA1_REQUEST_USART2_TX; + DMA_InitStruct.TransferEventMode = LL_DMA_TCEM_BLK_TRANSFER; + DMA_InitStruct.Mode = LL_DMA_NORMAL; + DMA_InitStruct.SrcAllocatedPort = LL_DMA_SRC_ALLOCATED_PORT1; + DMA_InitStruct.DestAllocatedPort = LL_DMA_DEST_ALLOCATED_PORT0; + DMA_InitStruct.LinkAllocatedPort = LL_DMA_LINK_ALLOCATED_PORT1; + DMA_InitStruct.LinkStepMode = LL_DMA_LSM_FULL_EXECUTION; + DMA_InitStruct.LinkedListBaseAddr = 0x00000000U; + DMA_InitStruct.LinkedListAddrOffset = 0x00000000U; + LL_DMA_Init(GPDMA1, LL_DMA_CHANNEL_2, &DMA_InitStruct); + /* USER CODE BEGIN USART2_Init 1 */ + LL_DMA_ConfigLinkUpdate(GPDMA1, LL_DMA_CHANNEL_3, LL_DMA_UPDATE_CTR1 | LL_DMA_UPDATE_CTR2 |LL_DMA_UPDATE_CBR1 | LL_DMA_UPDATE_CSAR | LL_DMA_UPDATE_CDAR | LL_DMA_UPDATE_CLLR, (uint32_t)&Node_GPDMA1_Channel3); + LL_DMA_EnableChannel(GPDMA1, LL_DMA_CHANNEL_3); + LL_DMA_SetLinkedListAddrOffset(GPDMA1, LL_DMA_CHANNEL_3, LL_DMA_CLLR_OFFSET5); + LL_USART_EnableDMAReq_RX(USART2); + + LL_DMA_SetDestAddress(GPDMA1, LL_DMA_CHANNEL_2, LL_USART_DMA_GetRegAddr(USART2, LL_USART_DMA_REG_DATA_TRANSMIT)); + LL_USART_EnableDMAReq_TX(USART2); + /* USER CODE END USART2_Init 1 */ USART_InitStruct.PrescalerValue = LL_USART_PRESCALER_DIV1; USART_InitStruct.BaudRate = 115200; diff --git a/Core/Src/usart2_dma.c b/Core/Src/usart2_dma.c new file mode 100644 index 0000000..6d1e5f8 --- /dev/null +++ b/Core/Src/usart2_dma.c @@ -0,0 +1,238 @@ +/***************************************************************************//** +* @file usart2_dma.c +* @brief UART with DMA +*//****************************************************************************/ + +//------------------------------C library--------------------------------------- +#include +#include +#include +//----------------------------user includes------------------------------------- +#include "usart2_dma.h" +//------------------------------------------------------------------------------ + + + + +/* Private typedefs ----------------------------------------------------------*/ + +typedef struct { + uint8_t BufA[USART2_TXDMA_BUF_SIZE]; + uint8_t BufB[USART2_TXDMA_BUF_SIZE]; + int DataCntA; // data count in BufA + int DataCntB; // data count in BufB + int BufSelTx; // -1:none, 0:A, 1:B + int BufSelWr; // 0:A, 1:B + uint8_t FlushA; + uint8_t FlushB; +} Usart2TxBuf_t; + +typedef void (*FuncProcData)(const uint8_t* data, uint16_t len); + + + +/* Private macros ------------------------------------------------------------*/ + +#define ARRAY_COUNT(arr) (sizeof(arr) / sizeof((arr)[0])) + + +/* Private variables ---------------------------------------------------------*/ +uint8_t Usart2RxDmaBuf[USART2_RXDMA_BUF_SIZE] = {0}; +Usart2TxBuf_t Usart2TxDmaBuf = { {0},{0}, 0, 0, -1, 0 }; + +static FuncProcData ProcRxData = NULL; // function to process received data, set by Usart2_DMA_Init + + +/* Public variables ----------------------------------------------------------*/ + + +/* Functions -----------------------------------------------------------------*/ + + +/***************************************************************************//** +* @brief USART2 init +*//****************************************************************************/ +void Usart2_DMA_Init(void (*procRxData)(const uint8_t* data, uint16_t len)) { + ProcRxData = procRxData; + // USART and DMA initialization code should be generated by Cube MX +} + +/***************************************************************************//** +* @brief USART2 Rx/Tx DMA task, to be called periodically in main loop +*//****************************************************************************/ +void Usart2_DMA_Task() { + // Handle received data from USART2 DMA + static uint32_t LastNDTR = USART2_RXDMA_BUF_SIZE; + static uint32_t WritePos = 0U; + uint32_t curNDTR = LL_DMA_GetBlkDataLength(USART2_GPDMA, USART2_DMA_RX_CHANNEL); + uint32_t newBytes; + if (curNDTR <= LastNDTR) { // no Wrap-Around + newBytes = LastNDTR - curNDTR; + }else { // NDTR is bigger than before: Wrap-Around occurred + newBytes = LastNDTR + (USART2_RXDMA_BUF_SIZE - curNDTR); + } + if (newBytes > 0U) { + uint32_t startPos = WritePos; // start of new data + uint32_t endPos = (WritePos + newBytes) % USART2_RXDMA_BUF_SIZE; // end of new data + if (startPos < endPos) { // no Wrap-Around + ProcRxData(&Usart2RxDmaBuf[startPos], newBytes); + } else { // first: to buffer end, second: from buffer begin + uint32_t part1 = USART2_RXDMA_BUF_SIZE - startPos; + ProcRxData(&Usart2RxDmaBuf[startPos], part1); + + uint32_t part2 = newBytes - part1; + ProcRxData(&Usart2RxDmaBuf[0], part2); + } + // Store new Write Position and NDTR + WritePos = endPos; // next start position for write + LastNDTR = curNDTR; // NTDR value for next cycle + } + + // Handle USART2 Tx DMA transfer complete + if (LL_DMA_IsActiveFlag_TC(USART2_GPDMA, USART2_DMA_TX_CHANNEL)) { + LL_DMA_ClearFlag_TC(USART2_GPDMA, USART2_DMA_TX_CHANNEL); + Usart2TxBuf_t* d = &Usart2TxDmaBuf; + switch (d->BufSelTx) { + case 0: { // transfer from BufA completed + d->BufSelTx = -1; // no transfer ongoing + d->DataCntA = 0; // reset BufA data count + if (d->FlushB) { // flush requested for BufB + // start transfer from BufB + LL_DMA_ClearFlag_TC(USART2_GPDMA, USART2_DMA_TX_CHANNEL); + LL_DMA_SetSrcAddress(USART2_GPDMA, USART2_DMA_TX_CHANNEL, (uint32_t)d->BufB); + LL_DMA_SetBlkDataLength(USART2_GPDMA, USART2_DMA_TX_CHANNEL, d->DataCntB); + LL_DMA_EnableChannel(USART2_GPDMA, USART2_DMA_TX_CHANNEL); + d->BufSelTx = 1; // mark transfer from BufB ongoing + d->BufSelWr = 0; // switch write to BufA + d->FlushB = 0; // clear flush request + } + }break; + case 1: { // transfer from BufB completed + d->BufSelTx = -1; // no transfer ongoing + d->DataCntB = 0; // reset BufB data count + if (d->FlushA) { // flush requested for BufA + // start transfer from BufA + LL_DMA_ClearFlag_TC(USART2_GPDMA, USART2_DMA_TX_CHANNEL); + LL_DMA_SetSrcAddress(USART2_GPDMA, USART2_DMA_TX_CHANNEL, (uint32_t)d->BufA); + LL_DMA_SetBlkDataLength(USART2_GPDMA, USART2_DMA_TX_CHANNEL, d->DataCntA); + LL_DMA_EnableChannel(USART2_GPDMA, USART2_DMA_TX_CHANNEL); + d->BufSelTx = 0; // mark transfer from BufA ongoing + d->BufSelWr = 1; // switch write to BufB + d->FlushA = 0; // clear flush request + } + }break; + } + } +} + +/***************************************************************************//** +* @brief Write data to USART2 Tx buffer, and optionally start DMA transfer if flush is requested +* @param src: data to write +* @param n: count of data +* @param flush: if non-zero, request to start DMA transfer after writing data +*//****************************************************************************/ +uint8_t Usart2_TxBufWrite(const void* src, size_t n, uint8_t flush) { + Usart2TxBuf_t* d = &Usart2TxDmaBuf; + switch (d->BufSelWr) { + case 0: { // BufA selected for write + int newpos = d->DataCntA + n; + if (newpos <= 2 * USART2_TXDMA_BUF_SIZE) { // enough space in the entire buffer + if (d->BufSelTx == 1 && newpos > USART2_TXDMA_BUF_SIZE) { + // transfer from BufB ongoing and BufA overflow + return 4; // overflow: skip data + } + memcpy(&d->BufA[d->DataCntA], src, n); + if (newpos > USART2_TXDMA_BUF_SIZE) { // BufA full + d->DataCntA = USART2_TXDMA_BUF_SIZE; // BufA full + // start transfer from BufA + LL_DMA_ClearFlag_TC(USART2_GPDMA, USART2_DMA_TX_CHANNEL); + LL_DMA_SetSrcAddress(USART2_GPDMA, USART2_DMA_TX_CHANNEL, (uint32_t)d->BufA); + LL_DMA_SetBlkDataLength(USART2_GPDMA, USART2_DMA_TX_CHANNEL, d->DataCntA); + LL_DMA_EnableChannel(USART2_GPDMA, USART2_DMA_TX_CHANNEL); + d->BufSelTx = 0; // mark transfer from BufA ongoing + d->BufSelWr = 1; // switch write to BufB + d->DataCntB = newpos - USART2_TXDMA_BUF_SIZE; // adjust BufB write position + if (flush) { + // BufA flush already started + d->FlushB = 1; // mark BufB flush requested + } + }else { // BufA not full yet + d->DataCntA = newpos; + if (flush) { + if (d->BufSelTx == -1) { // flush requested and no transfer ongoing + // start transfer from BufA + LL_DMA_ClearFlag_TC(USART2_GPDMA, USART2_DMA_TX_CHANNEL); + LL_DMA_SetSrcAddress(USART2_GPDMA, USART2_DMA_TX_CHANNEL, (uint32_t)d->BufA); + LL_DMA_SetBlkDataLength(USART2_GPDMA, USART2_DMA_TX_CHANNEL, d->DataCntA); + LL_DMA_EnableChannel(USART2_GPDMA, USART2_DMA_TX_CHANNEL); + d->BufSelTx = 0; // mark transfer from BufA ongoing + d->BufSelWr = 1; // switch write to BufB + }else { + d->FlushA = 1; // mark BufA flush requested + } + } + } + }else { // not enough space in the entire buffer + return 1; // overflow: skip data + } + }break; + case 1: { // BufB selected for write + int newpos = d->DataCntB + n; + if (newpos <= USART2_TXDMA_BUF_SIZE) { // enough space in BufB + memcpy(&d->BufB[d->DataCntB], src, n); + d->DataCntB = newpos; + if (flush) { + if (d->BufSelTx == -1) { // flush requested and no transfer ongoing + // start transfer from BufB + LL_DMA_ClearFlag_TC(USART2_GPDMA, USART2_DMA_TX_CHANNEL); + LL_DMA_SetSrcAddress(USART2_GPDMA, USART2_DMA_TX_CHANNEL, (uint32_t)d->BufB); + LL_DMA_SetBlkDataLength(USART2_GPDMA, USART2_DMA_TX_CHANNEL, d->DataCntB); + LL_DMA_EnableChannel(USART2_GPDMA, USART2_DMA_TX_CHANNEL); + d->BufSelTx = 1; // mark transfer from BufB ongoing + d->BufSelWr = 0; // switch write to BufA + }else { + d->FlushB = 1; // mark BufB flush requested + } + } + }else { // not enough space in BufB + // try to flush BufB if possible + if (d->BufSelTx == -1) { // no transfer ongoing + // start transfer from BufB + LL_DMA_ClearFlag_TC(USART2_GPDMA, USART2_DMA_TX_CHANNEL); + LL_DMA_SetSrcAddress(USART2_GPDMA, USART2_DMA_TX_CHANNEL, (uint32_t)d->BufB); + LL_DMA_SetBlkDataLength(USART2_GPDMA, USART2_DMA_TX_CHANNEL, d->DataCntB); + LL_DMA_EnableChannel(USART2_GPDMA, USART2_DMA_TX_CHANNEL); + d->BufSelTx = 1; // mark transfer from BufB ongoing + d->BufSelWr = 0; // switch write to BufA + } + if (d->BufSelTx != 0) { // BufA ready to write (not being transmitted) + d->BufSelWr = 0; // switch write to BufA + if (n <= USART2_TXDMA_BUF_SIZE) { // enough space in BufA + memcpy(d->BufA, src, n); + d->DataCntA = n; + if (flush) { // flush requested + if (d->BufSelTx == -1) { // no transfer ongoing + // start transfer from BufA + LL_DMA_ClearFlag_TC(USART2_GPDMA, USART2_DMA_TX_CHANNEL); + LL_DMA_SetSrcAddress(USART2_GPDMA, USART2_DMA_TX_CHANNEL, (uint32_t)d->BufA); + LL_DMA_SetBlkDataLength(USART2_GPDMA, USART2_DMA_TX_CHANNEL, d->DataCntA); + LL_DMA_EnableChannel(USART2_GPDMA, USART2_DMA_TX_CHANNEL); + d->BufSelTx = 0; // mark transfer from BufA ongoing + d->BufSelWr = 1; // switch write to BufB + }else { // transfer ongoing + d->FlushA = 1; // mark BufA flush requested + } + } + }else { + return 2; // overflow: skip data + } + }else { + return 3; // overflow: skip data + } + } + }break; + } + return 0; // no error +} + + diff --git a/DigitalAudioH533.ioc b/DigitalAudioH533.ioc index 506c239..dc26f8d 100644 --- a/DigitalAudioH533.ioc +++ b/DigitalAudioH533.ioc @@ -8,18 +8,29 @@ CAD.provider=Component Search Engine CORTEX_M33_NS.userName=CORTEX_M33 File.Version=6 GPDMA1.CIRCULARMODE_GPDMACH1=ENABLE +GPDMA1.CIRCULARMODE_GPDMACH3=ENABLE GPDMA1.DESTINC_GPDMACH1=DMA_DINC_INCREMENTED +GPDMA1.DESTINC_GPDMACH3=DMA_DINC_INCREMENTED GPDMA1.DIRECTION_GPDMACH0=DMA_MEMORY_TO_PERIPH +GPDMA1.DIRECTION_GPDMACH2=DMA_MEMORY_TO_PERIPH GPDMA1.IPHANDLE_GPDMACH0-SIMPLEREQUEST_GPDMACH0=__NULL GPDMA1.IPHANDLE_GPDMACH1-SIMPLEREQUEST_GPDMACH1=__NULL -GPDMA1.IPParameters=IPHANDLE_GPDMACH0-SIMPLEREQUEST_GPDMACH0,REQUEST_GPDMACH0,CIRCULARMODE_GPDMACH1,LINKALLOCATEDPORT_CIRCULAR_GPDMACH1,IPHANDLE_GPDMACH1-SIMPLEREQUEST_GPDMACH1,REQUEST_GPDMACH1,TRANSFERALLOCATEDPORTDEST_GPDMACH1,TRANSFEREVENTMODE_LL_CIRCULAR_GPDMACH1,DIRECTION_GPDMACH0,SRCINC_GPDMACH0,DESTINC_GPDMACH1,TRANSFERALLOCATEDPORTSRC_GPDMACH1,TRANSFERALLOCATEDPORTSRC_GPDMACH0 +GPDMA1.IPHANDLE_GPDMACH2-SIMPLEREQUEST_GPDMACH2=__NULL +GPDMA1.IPHANDLE_GPDMACH3-SIMPLEREQUEST_GPDMACH3=__NULL +GPDMA1.IPParameters=REQUEST_GPDMACH0,CIRCULARMODE_GPDMACH1,LINKALLOCATEDPORT_CIRCULAR_GPDMACH1,REQUEST_GPDMACH1,TRANSFERALLOCATEDPORTDEST_GPDMACH1,TRANSFEREVENTMODE_LL_CIRCULAR_GPDMACH1,DIRECTION_GPDMACH0,SRCINC_GPDMACH0,DESTINC_GPDMACH1,TRANSFERALLOCATEDPORTSRC_GPDMACH1,TRANSFERALLOCATEDPORTSRC_GPDMACH0,REQUEST_GPDMACH2,DIRECTION_GPDMACH2,SRCINC_GPDMACH2,TRANSFERALLOCATEDPORTSRC_GPDMACH2,IPHANDLE_GPDMACH2-SIMPLEREQUEST_GPDMACH2,IPHANDLE_GPDMACH1-SIMPLEREQUEST_GPDMACH1,IPHANDLE_GPDMACH0-SIMPLEREQUEST_GPDMACH0,CIRCULARMODE_GPDMACH3,LINKALLOCATEDPORT_CIRCULAR_GPDMACH3,IPHANDLE_GPDMACH3-SIMPLEREQUEST_GPDMACH3,REQUEST_GPDMACH3,DESTINC_GPDMACH3,TRANSFERALLOCATEDPORTDEST_GPDMACH3 GPDMA1.LINKALLOCATEDPORT_CIRCULAR_GPDMACH1=DMA_LINK_ALLOCATED_PORT1 +GPDMA1.LINKALLOCATEDPORT_CIRCULAR_GPDMACH3=DMA_LINK_ALLOCATED_PORT1 GPDMA1.REQUEST_GPDMACH0=GPDMA1_REQUEST_USART3_TX GPDMA1.REQUEST_GPDMACH1=GPDMA1_REQUEST_USART3_RX +GPDMA1.REQUEST_GPDMACH2=GPDMA1_REQUEST_USART2_TX +GPDMA1.REQUEST_GPDMACH3=GPDMA1_REQUEST_USART2_RX GPDMA1.SRCINC_GPDMACH0=DMA_SINC_INCREMENTED +GPDMA1.SRCINC_GPDMACH2=DMA_SINC_INCREMENTED GPDMA1.TRANSFERALLOCATEDPORTDEST_GPDMACH1=DMA_DEST_ALLOCATED_PORT1 +GPDMA1.TRANSFERALLOCATEDPORTDEST_GPDMACH3=DMA_DEST_ALLOCATED_PORT1 GPDMA1.TRANSFERALLOCATEDPORTSRC_GPDMACH0=DMA_SRC_ALLOCATED_PORT1 GPDMA1.TRANSFERALLOCATEDPORTSRC_GPDMACH1=DMA_SRC_ALLOCATED_PORT0 +GPDMA1.TRANSFERALLOCATEDPORTSRC_GPDMACH2=DMA_SRC_ALLOCATED_PORT1 GPDMA1.TRANSFEREVENTMODE_LL_CIRCULAR_GPDMACH1=DMA_TCEM_BLOCK_TRANSFER GPIO.groupedBy=Group By Peripherals KeepUserPlacement=false @@ -87,15 +98,17 @@ Mcu.Pin15=PB8 Mcu.Pin16=VP_CORTEX_M33_NS_VS_Hclk Mcu.Pin17=VP_GPDMA1_VS_GPDMACH0 Mcu.Pin18=VP_GPDMA1_VS_GPDMACH1 -Mcu.Pin19=VP_ICACHE_VS_ICACHE +Mcu.Pin19=VP_GPDMA1_VS_GPDMACH2 Mcu.Pin2=PH0-OSC_IN(PH0) -Mcu.Pin20=VP_PWR_VS_SECSignals -Mcu.Pin21=VP_PWR_VS_LPOM -Mcu.Pin22=VP_SYS_VS_Systick -Mcu.Pin23=VP_TIM2_VS_ClockSourceINT -Mcu.Pin24=VP_TIM5_VS_ClockSourceINT -Mcu.Pin25=VP_BOOTPATH_VS_BOOTPATH -Mcu.Pin26=VP_MEMORYMAP_VS_MEMORYMAP +Mcu.Pin20=VP_GPDMA1_VS_GPDMACH3 +Mcu.Pin21=VP_ICACHE_VS_ICACHE +Mcu.Pin22=VP_PWR_VS_SECSignals +Mcu.Pin23=VP_PWR_VS_LPOM +Mcu.Pin24=VP_SYS_VS_Systick +Mcu.Pin25=VP_TIM2_VS_ClockSourceINT +Mcu.Pin26=VP_TIM5_VS_ClockSourceINT +Mcu.Pin27=VP_BOOTPATH_VS_BOOTPATH +Mcu.Pin28=VP_MEMORYMAP_VS_MEMORYMAP Mcu.Pin3=PH1-OSC_OUT(PH1) Mcu.Pin4=PA1 Mcu.Pin5=PA2 @@ -103,7 +116,7 @@ Mcu.Pin6=PA3 Mcu.Pin7=PB1 Mcu.Pin8=PB10 Mcu.Pin9=PB14 -Mcu.PinsNb=27 +Mcu.PinsNb=29 Mcu.ThirdPartyNb=0 Mcu.UserConstants= Mcu.UserName=STM32H533RETx @@ -114,6 +127,8 @@ NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false NVIC.ForceEnableDMAVector=true NVIC.GPDMA1_Channel0_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false NVIC.GPDMA1_Channel1_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false +NVIC.GPDMA1_Channel2_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false +NVIC.GPDMA1_Channel3_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false @@ -319,6 +334,10 @@ VP_GPDMA1_VS_GPDMACH0.Mode=SIMPLEREQUEST_GPDMACH0 VP_GPDMA1_VS_GPDMACH0.Signal=GPDMA1_VS_GPDMACH0 VP_GPDMA1_VS_GPDMACH1.Mode=SIMPLEREQUEST_GPDMACH1 VP_GPDMA1_VS_GPDMACH1.Signal=GPDMA1_VS_GPDMACH1 +VP_GPDMA1_VS_GPDMACH2.Mode=SIMPLEREQUEST_GPDMACH2 +VP_GPDMA1_VS_GPDMACH2.Signal=GPDMA1_VS_GPDMACH2 +VP_GPDMA1_VS_GPDMACH3.Mode=SIMPLEREQUEST_GPDMACH3 +VP_GPDMA1_VS_GPDMACH3.Signal=GPDMA1_VS_GPDMACH3 VP_ICACHE_VS_ICACHE.Mode=DefaultMode VP_ICACHE_VS_ICACHE.Signal=ICACHE_VS_ICACHE VP_MEMORYMAP_VS_MEMORYMAP.Mode=CurAppReg