USART2 DMA RX/TX works

- Rx/Tx handler in usart2_dma.*
- CubeMX: USART and DMA init
- DMA CH2: Tx
- DMA CH3: Rx
- DMA Port0 for periph transfer
- DMA Port1 for mem transfer
- Continuous Rx handling via DMA pointer (no INT, no TC flag)
- Tx: collect data into tx buf or send immediately
master
unicod 4 weeks ago
parent b8802c266f
commit 9b1029a5e1

@ -0,0 +1,16 @@
#ifndef __USART2_IT_H__
#define __USART2_IT_H__
#include <stdint.h>
#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

@ -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__

@ -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_Init(void (*)(const uint8_t* data, uint16_t len));
extern void Usart3_DMA_Task(); extern void Usart3_DMA_Task();
extern void Usart3_PutByte(uint8_t d); extern uint8_t Usart3_TxBufWrite(const void* src, size_t n, uint8_t flush);
extern void Usart3_PutData(const void* src, uint16_t n);
extern int16_t Usart3_GetByte(void);
#endif #endif

@ -26,6 +26,7 @@
#include "disp7seg.h" #include "disp7seg.h"
#include "printf.h" #include "printf.h"
#include "usart2_dma.h"
#include "usart3_dma.h" #include "usart3_dma.h"
#include "uart5_it.h" #include "uart5_it.h"
@ -49,6 +50,7 @@
/* Private variables ---------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/
LL_DMA_LinkNodeTypeDef Node_GPDMA1_Channel3;
LL_DMA_LinkNodeTypeDef Node_GPDMA1_Channel1; LL_DMA_LinkNodeTypeDef Node_GPDMA1_Channel1;
/* USER CODE BEGIN PV */ /* USER CODE BEGIN PV */
@ -69,7 +71,6 @@ static void MX_UART5_Init(void);
static void MX_USART2_UART_Init(void); static void MX_USART2_UART_Init(void);
/* USER CODE BEGIN PFP */ /* USER CODE BEGIN PFP */
uint8_t Usart3_TxBufWrite(const void* src, size_t n, uint8_t start);
/* USER CODE END PFP */ /* 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) { void ProcessUsart3RxData(const uint8_t* data, uint16_t len) {
printf("USART3 RX(%u): ", len);
for (uint16_t i = 0; i < len; i++) { for (uint16_t i = 0; i < len; i++) {
printf("%c", data[i]); printf("%c", data[i]);
} }
printf("\n");
Delay_us(500); // simulate long processing time
} }
/* USER CODE END 0 */ /* USER CODE END 0 */
@ -171,6 +183,7 @@ int main(void)
DispPutDigit(3, ' ', 0); DispPutDigit(3, ' ', 0);
ShiftReg_Update(); ShiftReg_Update();
Usart2_DMA_Init(ProcessUsart2RxData);
Usart3_DMA_Init(ProcessUsart3RxData); Usart3_DMA_Init(ProcessUsart3RxData);
Uart5_Init(); Uart5_Init();
printf("Hello printf\n"); printf("Hello printf\n");
@ -195,6 +208,8 @@ int main(void)
char s[256]; 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); 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 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; static uint32_t Tick100msRef = 0;
@ -210,6 +225,7 @@ int main(void)
DispPutDigit(0, c, 0); DispPutDigit(0, c, 0);
} }
Usart2_DMA_Task(); // handle USART2 DMA rx/tx
Usart3_DMA_Task(); // handle USART3 DMA rx/tx Usart3_DMA_Task(); // handle USART3 DMA rx/tx
@ -317,6 +333,8 @@ static void MX_GPDMA1_Init(void)
/* GPDMA1 interrupt Init */ /* GPDMA1 interrupt Init */
NVIC_SetPriority(GPDMA1_Channel0_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); 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_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 */ /* USER CODE BEGIN GPDMA1_Init 1 */
@ -498,11 +516,22 @@ static void MX_USART2_UART_Init(void)
/* USER CODE BEGIN USART2_Init 0 */ /* 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 */ /* USER CODE END USART2_Init 0 */
LL_USART_InitTypeDef USART_InitStruct = {0}; LL_USART_InitTypeDef USART_InitStruct = {0};
LL_GPIO_InitTypeDef GPIO_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); 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; GPIO_InitStruct.Alternate = LL_GPIO_AF_7;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct); 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 */ /* 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 */ /* USER CODE END USART2_Init 1 */
USART_InitStruct.PrescalerValue = LL_USART_PRESCALER_DIV1; USART_InitStruct.PrescalerValue = LL_USART_PRESCALER_DIV1;
USART_InitStruct.BaudRate = 115200; USART_InitStruct.BaudRate = 115200;

@ -0,0 +1,238 @@
/***************************************************************************//**
* @file usart2_dma.c
* @brief UART with DMA
*//****************************************************************************/
//------------------------------C library---------------------------------------
#include <stddef.h>
#include <stdint.h>
#include <string.h>
//----------------------------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
}

@ -8,18 +8,29 @@ CAD.provider=Component Search Engine
CORTEX_M33_NS.userName=CORTEX_M33 CORTEX_M33_NS.userName=CORTEX_M33
File.Version=6 File.Version=6
GPDMA1.CIRCULARMODE_GPDMACH1=ENABLE GPDMA1.CIRCULARMODE_GPDMACH1=ENABLE
GPDMA1.CIRCULARMODE_GPDMACH3=ENABLE
GPDMA1.DESTINC_GPDMACH1=DMA_DINC_INCREMENTED GPDMA1.DESTINC_GPDMACH1=DMA_DINC_INCREMENTED
GPDMA1.DESTINC_GPDMACH3=DMA_DINC_INCREMENTED
GPDMA1.DIRECTION_GPDMACH0=DMA_MEMORY_TO_PERIPH GPDMA1.DIRECTION_GPDMACH0=DMA_MEMORY_TO_PERIPH
GPDMA1.DIRECTION_GPDMACH2=DMA_MEMORY_TO_PERIPH
GPDMA1.IPHANDLE_GPDMACH0-SIMPLEREQUEST_GPDMACH0=__NULL GPDMA1.IPHANDLE_GPDMACH0-SIMPLEREQUEST_GPDMACH0=__NULL
GPDMA1.IPHANDLE_GPDMACH1-SIMPLEREQUEST_GPDMACH1=__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_GPDMACH1=DMA_LINK_ALLOCATED_PORT1
GPDMA1.LINKALLOCATEDPORT_CIRCULAR_GPDMACH3=DMA_LINK_ALLOCATED_PORT1
GPDMA1.REQUEST_GPDMACH0=GPDMA1_REQUEST_USART3_TX GPDMA1.REQUEST_GPDMACH0=GPDMA1_REQUEST_USART3_TX
GPDMA1.REQUEST_GPDMACH1=GPDMA1_REQUEST_USART3_RX 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_GPDMACH0=DMA_SINC_INCREMENTED
GPDMA1.SRCINC_GPDMACH2=DMA_SINC_INCREMENTED
GPDMA1.TRANSFERALLOCATEDPORTDEST_GPDMACH1=DMA_DEST_ALLOCATED_PORT1 GPDMA1.TRANSFERALLOCATEDPORTDEST_GPDMACH1=DMA_DEST_ALLOCATED_PORT1
GPDMA1.TRANSFERALLOCATEDPORTDEST_GPDMACH3=DMA_DEST_ALLOCATED_PORT1
GPDMA1.TRANSFERALLOCATEDPORTSRC_GPDMACH0=DMA_SRC_ALLOCATED_PORT1 GPDMA1.TRANSFERALLOCATEDPORTSRC_GPDMACH0=DMA_SRC_ALLOCATED_PORT1
GPDMA1.TRANSFERALLOCATEDPORTSRC_GPDMACH1=DMA_SRC_ALLOCATED_PORT0 GPDMA1.TRANSFERALLOCATEDPORTSRC_GPDMACH1=DMA_SRC_ALLOCATED_PORT0
GPDMA1.TRANSFERALLOCATEDPORTSRC_GPDMACH2=DMA_SRC_ALLOCATED_PORT1
GPDMA1.TRANSFEREVENTMODE_LL_CIRCULAR_GPDMACH1=DMA_TCEM_BLOCK_TRANSFER GPDMA1.TRANSFEREVENTMODE_LL_CIRCULAR_GPDMACH1=DMA_TCEM_BLOCK_TRANSFER
GPIO.groupedBy=Group By Peripherals GPIO.groupedBy=Group By Peripherals
KeepUserPlacement=false KeepUserPlacement=false
@ -87,15 +98,17 @@ Mcu.Pin15=PB8
Mcu.Pin16=VP_CORTEX_M33_NS_VS_Hclk Mcu.Pin16=VP_CORTEX_M33_NS_VS_Hclk
Mcu.Pin17=VP_GPDMA1_VS_GPDMACH0 Mcu.Pin17=VP_GPDMA1_VS_GPDMACH0
Mcu.Pin18=VP_GPDMA1_VS_GPDMACH1 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.Pin2=PH0-OSC_IN(PH0)
Mcu.Pin20=VP_PWR_VS_SECSignals Mcu.Pin20=VP_GPDMA1_VS_GPDMACH3
Mcu.Pin21=VP_PWR_VS_LPOM Mcu.Pin21=VP_ICACHE_VS_ICACHE
Mcu.Pin22=VP_SYS_VS_Systick Mcu.Pin22=VP_PWR_VS_SECSignals
Mcu.Pin23=VP_TIM2_VS_ClockSourceINT Mcu.Pin23=VP_PWR_VS_LPOM
Mcu.Pin24=VP_TIM5_VS_ClockSourceINT Mcu.Pin24=VP_SYS_VS_Systick
Mcu.Pin25=VP_BOOTPATH_VS_BOOTPATH Mcu.Pin25=VP_TIM2_VS_ClockSourceINT
Mcu.Pin26=VP_MEMORYMAP_VS_MEMORYMAP 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.Pin3=PH1-OSC_OUT(PH1)
Mcu.Pin4=PA1 Mcu.Pin4=PA1
Mcu.Pin5=PA2 Mcu.Pin5=PA2
@ -103,7 +116,7 @@ Mcu.Pin6=PA3
Mcu.Pin7=PB1 Mcu.Pin7=PB1
Mcu.Pin8=PB10 Mcu.Pin8=PB10
Mcu.Pin9=PB14 Mcu.Pin9=PB14
Mcu.PinsNb=27 Mcu.PinsNb=29
Mcu.ThirdPartyNb=0 Mcu.ThirdPartyNb=0
Mcu.UserConstants= Mcu.UserConstants=
Mcu.UserName=STM32H533RETx Mcu.UserName=STM32H533RETx
@ -114,6 +127,8 @@ NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.ForceEnableDMAVector=true NVIC.ForceEnableDMAVector=true
NVIC.GPDMA1_Channel0_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false 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_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.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.MemoryManagement_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 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_GPDMACH0.Signal=GPDMA1_VS_GPDMACH0
VP_GPDMA1_VS_GPDMACH1.Mode=SIMPLEREQUEST_GPDMACH1 VP_GPDMA1_VS_GPDMACH1.Mode=SIMPLEREQUEST_GPDMACH1
VP_GPDMA1_VS_GPDMACH1.Signal=GPDMA1_VS_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.Mode=DefaultMode
VP_ICACHE_VS_ICACHE.Signal=ICACHE_VS_ICACHE VP_ICACHE_VS_ICACHE.Signal=ICACHE_VS_ICACHE
VP_MEMORYMAP_VS_MEMORYMAP.Mode=CurAppReg VP_MEMORYMAP_VS_MEMORYMAP.Mode=CurAppReg

Loading…
Cancel
Save