cancel
Showing results for 
Search instead for 
Did you mean: 

DMA Memory To UART5

dclark9
Associate II
Posted on June 25, 2012 at 15:38

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
29 REPLIES 29
frankmeyer9
Associate II
Posted on June 25, 2012 at 15:48

I'm not sure why you want send 2 characters with DMA, bu t at first glance:

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;

will probably do no good. The first byte is written to UART->DR, and according this:


 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

the next byte is written to (UART->DR + 1).
dclark9
Associate II
Posted on June 25, 2012 at 15:55

Ah - that shouldn't be in there, that is something I was trying - with this disabled it still only sends out one byte.

Thanks for pointing out the error.

Posted on June 25, 2012 at 17:16

UART5 does not have DMA support on STM32F1 designs.

Something like this should work on an STM32F2 or STM32F4 based board.

// STM32 UART5 DMA TX (Tx PC.12, Rx PD.2) STM32F4 Discovery - sourcer32@gmail.com
#include ''stm32f4_discovery.h''
/**************************************************************************************/
void RCC_Configuration(void)
{
/* --------------------------- System Clocks Configuration -----------------*/
/* UART5 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE);
/* GPIOC and GPIOD clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD, ENABLE);
/* DMA1 clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
}
/**************************************************************************************/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*-------------------------- GPIO Configuration ----------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; // PC.12 UART5_TX, potential clash SDIN CS43L22
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_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; // PD.2 UART5_RX
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* Connect USART pins to AF */
GPIO_PinAFConfig(GPIOC, GPIO_PinSource12, GPIO_AF_UART5);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource2, GPIO_AF_UART5);
}
/**************************************************************************************/
void UART5_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(UART5, &USART_InitStructure);
USART_Cmd(UART5, ENABLE);
}
/**************************************************************************************/
char Buffer[] = ''The quick brown fox jumps over the lazy dog

'';
void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
DMA_DeInit(DMA1_Stream7);
DMA_InitStructure.DMA_Channel = DMA_Channel_4;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; // Transmit
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Buffer;
DMA_InitStructure.DMA_BufferSize = (uint16_t)sizeof(Buffer) - 1;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&UART5->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_Circular;
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(DMA1_Stream7, &DMA_InitStructure);
/* Enable the USART Tx DMA request */
USART_DMACmd(UART5, USART_DMAReq_Tx, ENABLE);
/* Enable DMA Stream Transfer Complete interrupt */
DMA_ITConfig(DMA1_Stream7, DMA_IT_TC, ENABLE);
/* Enable the DMA RX Stream */
DMA_Cmd(DMA1_Stream7, ENABLE);
}
/**************************************************************************************/
void DMA1_Stream7_IRQHandler(void)
{
/* Test on DMA Stream Transfer Complete interrupt */
if (DMA_GetITStatus(DMA1_Stream7, DMA_IT_TCIF7))
{
/* Clear DMA Stream Transfer Complete interrupt pending bit */
DMA_ClearITPendingBit(DMA1_Stream7, DMA_IT_TCIF7);
}
}
/**************************************************************************************/
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure the Priority Group to 2 bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* Enable the UART5 RX DMA Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = DMA1_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();
UART5_Configuration();
DMA_Configuration();
while(1); // Don't want to exit
}
/**************************************************************************************/
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf(''Wrong parameters value: file %s on line %d

'', file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
/**
* @}
*/
/**************************************************************************************/

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
dclark9
Associate II
Posted on June 25, 2012 at 18:04

Hi Clive,

Thanks for your response - fantastic example, and if that is the case that UART5 doesn't do DMA then I probably need to go and speak to my manager very quickly!

Is that documented in the specification? I will obviously search for it myself, just wondering if you had a reference to hand that I could use.

Thanks once again for you response. As previously it's very much appreciated.

Dave

dclark9
Associate II
Posted on June 25, 2012 at 18:14

Have found a reference.

Posted on June 25, 2012 at 18:24

Earlier versions I think illustrated this better, but Page 272 starts a list describing DMA resources, there are no UART5 drivers.

http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/REFERENCE_MANUAL/CD00171190.pdf

This is from the 105/107 manual in 2009, Doc 15274 Rev 4, Pg 19

''USART1, USART2 and USART3 also provide hardware management of the CTS and RTS signals, Smart Card mode (ISO 7816 compliant) and SPI-like communication capability. All interfaces can be served by the DMA controller except for UART5.''

A more current iteration, Rev 6, Pg 19

http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/DATASHEET/CD00220364.pdf

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
dclark9
Associate II
Posted on June 26, 2012 at 00:24

Hi Clive,

Thanks for the references.

On another note the whole reason I am doing this is because I have taken over a bit of software to drive the built in STM32 bootloader - just wondering if you have any familiarity with communicating with the bootloader.

The problem I have been trying to solve is that I can put the target processor in boot mode, and I can send it the 0x7F start byte and get an ACK, then the problems start.

I then send 0x31 and its compliment, but this doesn't always seem to work i.e. I don't always get an ACK, and my hunch as to why this is the case is because the previous owner of the software has used the STM32 library USART_SendData to send the 0x31, and then its compliment in 2 calls i.e. with start and stop bits around the 2 transmissions, and looking at the bootloader spec it kind of implies that you need to send the command and its compliment as one contigious set of bytes hence trying to use DMA to UART5 which regrettably is connected in hardware to USART1 on the target processor.

Just wondering if you have any thoughts about whether doing it this way (using USART_SendData) should work or not.

Thanks again - I will happily buy you many beers if you're ever in the Portsmouth area!

Dave

Posted on June 26, 2012 at 02:30

Yes, I've written some updating code, and have an annotated listing of the boot loader.

The critical thing is you need the parity set up right, 8E1, so you have to program the STM32 in 9-bit mode, with even parity, the parity bit being the 9th bit, as I recall.

Once the loader starts you send the 0x7F so that the timing can be measured (auto-bauding). Then it's just a matter of sending the bytes, and waiting for the appropriate ACK/NACK responses. You definitely shouldn't need DMA, and frankly interrupts would probably be overkill. The inter-character timing is not particularly important with async serial. The boot loader has a watchdog timer, but that's there to catch when things seize up and no characters.

It's been a few decades since I was in Portsmouth UK, on the other side of the Atlantic these days.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
dclark9
Associate II
Posted on June 26, 2012 at 16:12

Now have a working bootloader thanks to your help - was all to do with the 9 bit parity mode.