STM32F051 UART Tx with DMA
Hi there,
I'm working on an STM32F051 with Standard Peripheral Libraries.
I using the UART to communicate with a PC and actually evrything work with Interrupts.
To get best perfomance, I started to implemnet DMA trasnfert.
For the RX, I use the DMA in circular mode and the reception works very well.
After that I started to implements Uart Tx with DMA but I have some question about that.
I use a circular buffer for the reception with two index:
- RRp: Read Pointer: this is the address where the DMA start to transfer the data.
- RWp: Write Ponter: this is the address where the application writes the data to send.
My concern is how to handle the circular buffer.
In detail how to specify every time where get the data and how many data send.
It seems that I can specify the source buffer and the data length only during the DMA Channel initialization.
This is my DMA initialization:
uint8_t dmaConfigId;
DMA_InitTypeDef DMA_InitStructure;
dmaConfigId = UartConfig[uartId].dmaConfigId;
/** DMA Clock Enable */
RCC_AHBPeriphClockCmd( DmaConfiguration[dmaConfigId].dmaClock, ENABLE );
/** Deinitialize DMA Channels */
DMA_DeInit( DmaConfiguration[dmaConfigId].rxDmaChannel );
DMA_DeInit( DmaConfiguration[dmaConfigId].txDmaChannel );
/** DMA Channel Common Configuration */
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
/** Usart Rx DMA Channel Configuration - Circular Mode */
DMA_InitStructure.DMA_BufferSize = UartConfig[uartId].RxSize;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)UartConfig[uartId].Rx;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
DMA_InitStructure.DMA_PeripheralBaseAddr = DmaConfiguration[dmaConfigId].peripheralRxRegister;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_Init( DmaConfiguration[dmaConfigId].rxDmaChannel, &DMA_InitStructure );
/** Usart Tx DMA Channel Configuration - Normal Mode */
DMA_InitStructure.DMA_BufferSize = UartConfig[uartId].TxSize;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)UartConfig[uartId].Tx;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
DMA_InitStructure.DMA_PeripheralBaseAddr = DmaConfiguration[dmaConfigId].peripheralTxRegister;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_Init( DmaConfiguration[dmaConfigId].txDmaChannel, &DMA_InitStructure );
/** Enable the USARTx Rx and Rx requests */
USART_DMACmd( UartConfig[uartId].USARTx, (USART_DMAReq_Rx | USART_DMAReq_Tx), ENABLE );
/**
* Enable DMA Interrupts
*
* Non è necessario attivare gli interrupt in ricezione del DMA
* perchè il trasferimento DMA avviene in automatico con la USART
*/
/** Abilitazione dell'interrupt di Transfer Complete in trasmissione */
DMA_ITConfig( DmaConfiguration[dmaConfigId].txDmaChannel, DMA_IT_TC, ENABLE );
/** NVIC Init */
NVIC_Initialize( DmaConfiguration[dmaConfigId].txIrq, 0 );
/** UART Rx - Enable DMA Channel */
DMA_Cmd( DmaConfiguration[dmaConfigId].rxDmaChannel, ENABLE );The UART2_TX_DMA_IT_TC is rised correctly, and into this ISR, I should stard another DMA trasnfer if more data are added to my buffer.
The problem is that I don't know how to specify size and buffer address before start a new DMA transfer.
These are the DMA function the I can use:
/* Function used to set the DMA configuration to the default reset state ******/
void DMA_DeInit(DMA_Channel_TypeDef* DMAy_Channelx);
/* Initialization and Configuration functions *********************************/
void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct);
void DMA_StructInit(DMA_InitTypeDef* DMA_InitStruct);
void DMA_Cmd(DMA_Channel_TypeDef* DMAy_Channelx, FunctionalState NewState);
/* Data Counter functions******************************************************/
void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t DataNumber);
uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx);
/* Interrupts and flags management functions **********************************/
void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, uint32_t DMA_IT, FunctionalState NewState);
FlagStatus DMA_GetFlagStatus(uint32_t DMA_FLAG);
void DMA_ClearFlag(uint32_t DMA_FLAG);
ITStatus DMA_GetITStatus(uint32_t DMA_IT);
void DMA_ClearITPendingBit(uint32_t DMA_IT);Thanks in advance fot the help
