2012-06-25 06:38 AM
Hi,
I'm having an issue setting up a DMA to transfer data from a 2 element uint8_t array to UART5. The code works, but the UART only sends out the first byte and having tried lots of different things I don't understand what I need to do to make it push out the whole buffer. Code is as follows :-uint8_t myBuffer[2] = {0x55, 0x55};
DMA_DeInit(MEZZANINE_DMA_TX);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&UART5->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) myBuffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = 2;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(MEZZANINE_DMA_TX, &DMA_InitStructure);
DMA_Cmd( MEZZANINE_DMA_TX, ENABLE );
Many thanks in advance for any responses,
Dave
#dma #stm32-uart-usart
2012-12-29 01:31 PM
2012-12-29 03:28 PM
The example tries to minimize the amount of code required to illustrate basic DMA function, however the CPU utilization should be pretty minimal as the DMA is handled off core. Placing a WFI in the while(1) loop should illustrate this.
To handle a more practical implementation you'd need to provide some buffering, either in the form of a ring buffer, or a collection of buffers, which would be feed to the DMA unit at each TC (Transmit Complete) interrupt from the DMA unit, or the DMA could be turned off if no additional buffers were full. Basically you'd want to dispatch each new buffer to the DMA unit, and turn off the circular function. You should only dispatch buffers when output data is available rather than trying to play catch up, as there is no additional flow control. Providing a full featured buffering demo is beyond the scope of my forum participation, and also tends to wade into to personal implementation preferences which probably won't match your specific needs/requirements.2013-10-28 06:32 AM
Was there a question there, or an attempt to post from a mobile device?
2013-12-13 08:58 AM
Hi Clive,
This code looks really good and has been really useful in setting up my RX DMA, but just wondering how to go about sending with the TX DMA? Have you got any examples of sending various different strings using it?2013-12-13 09:28 AM
This code looks really good and has been really useful in setting up my RX DMA, but just wondering how to go about sending with the TX DMA? Have you got any examples of sending various different strings using it?
There is an example at the top end of the thread dealing with TX DMA, and discussion devolved from there. Do I have a prepacked example, no, but it would just need some slight modification. You'd need to use the DMA in normal rather than circular mode, and at each TC interrupt you'd reprogram the DMA to do the next string.
2013-12-13 10:11 AM
// STM32 USART6 DMA TX MULTI (Tx PC.6, Rx PC.7) STM32F4DIS-BB - sourcer32@gmail.com
#include ''stm32f4_discovery.h''
#include <
string.h
>
/**************************************************************************************/
void RCC_Configuration(void)
{
/* --------------------------- System Clocks Configuration -----------------*/
/* USART6 clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6, ENABLE);
/* GPIOC clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
/* DMA2 clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
}
/**************************************************************************************/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*-------------------------- GPIO Configuration ----------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; // PC.6 USART6_TX, PC.7 USART6_RX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Connect USART pins to AF */
GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_USART6);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_USART6);
}
/**************************************************************************************/
void USART6_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;
/* USARTx configuration ------------------------------------------------------*/
/* USARTx configured as follow:
- BaudRate = 115200 baud
- Word Length = 8 Bits
- One Stop Bit
- No parity
- Hardware flow control disabled (RTS and CTS signals)
- Receive and transmit enabled
*/
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART6, &USART_InitStructure);
USART_Cmd(USART6, ENABLE);
/* Enable the USART Tx DMA request */
USART_DMACmd(USART6, USART_DMAReq_Tx, ENABLE);
}
/**************************************************************************************/
// Output as a series of different length strings in a loop
char StringA[] = ''The quick brown fox jumps over the lazy dog
'';
char StringB[] = ''Danger Zombies Ahead
'';
char StringC[] = ''Do not cross the streams
'';
int StringIndex = 0;
char *StringList[] = { StringA, StringB, StringC, NULL };
void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
char *Buffer;
// USART6_TX DMA Channel 5, DMA2, Stream7 (alt Stream6 potential clash SDIO)
if (StringList[StringIndex] == NULL)
StringIndex = 0;
Buffer = StringList[StringIndex++];
DMA_DeInit(DMA2_Stream7);
DMA_InitStructure.DMA_Channel = DMA_Channel_5;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; // Transmit
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Buffer;
DMA_InitStructure.DMA_BufferSize = (uint16_t)strlen(Buffer);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART6->DR;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream7, &DMA_InitStructure);
/* Enable DMA Stream Transfer Complete interrupt */
DMA_ITConfig(DMA2_Stream7, DMA_IT_TC, ENABLE);
/* Enable the DMA TX Stream */
DMA_Cmd(DMA2_Stream7, ENABLE);
}
/**************************************************************************************/
void DMA2_Stream7_IRQHandler(void) // USART6_TX
{
/* Test on DMA Stream Transfer Complete interrupt */
if (DMA_GetITStatus(DMA2_Stream7, DMA_IT_TCIF7))
{
/* Clear DMA Stream Transfer Complete interrupt pending bit */
DMA_ClearITPendingBit(DMA2_Stream7, DMA_IT_TCIF7);
DMA_Configuration(); // Light off next string
}
}
/**************************************************************************************/
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure the Priority Group to 2 bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* Enable the USART6 TX DMA Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream7_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/**************************************************************************************/
int main(void)
{
RCC_Configuration();
NVIC_Configuration();
GPIO_Configuration();
USART6_Configuration();
DMA_Configuration();
while(1); // Don't want to exit
}
/**************************************************************************************/
2015-01-06 06:41 AM
If I understand correctly then you have to reconfigure DMA each time you want to repeat sending. In this example using:
DMA_Configuration(); in DMA2_Stream7_IRQHandler(void) How would code look like if I wanted to update the data strings from main()?2015-01-06 08:11 AM
How would code look like if I wanted to update the data strings from main()?
Not sure I'm up to code your application, but you'd probably want to have some buffering and linked list arrangement, and either chain that in the TC interrupt, or light it off when it's idle.
2016-06-01 11:36 PM
2016-06-02 09:11 AM
Could be for a whole host of reasons, I would tend to suspect the serial dongle being used, perhaps it is losing synchronization. You could increase the stop bit setting, so the inter-symbol gap is larger.