Skip to main content
Associate
April 10, 2024
Solved

DMA USART not working as expected (MEM2MEM mode) STM32F303K8T6

  • April 10, 2024
  • 6 replies
  • 1926 views

Hi,

I am trying to get DMA to work with memory as source and peripheral as dest (UART) and i am not using HAL (this is a learning exercise), but only so far i have managed to get a single character out and the transmission reports as completed (Transfer complete status is set in ISR register and CNDTR from configured value becomes 0).

#define buff_size 6U

uint8_t source_buff[buff_size] = {'h', 'e', 'l', 'l', '0', '\n'};

void DMAInit(void) {
// Enable DMA1
RCC->AHBENR |= (1U << 0);

// Channel configuration
DMA1_Channel7->CCR &= ~(1U << 0); // disable

// wait for DMA to disable
while(DMA1_Channel7->CCR & (1U << 0));

// memory size set to 8 bits
DMA1_Channel7->CCR &= ~(1U << 10);
DMA1_Channel7->CCR &= ~(1U << 11);

// peripheral size set to 8 bits
DMA1_Channel7->CCR &= ~(1U << 8);
DMA1_Channel7->CCR &= ~(1U << 9);

// read from memory to peripheral, DIR = 1
DMA1_Channel7->CCR |= (1U << 4);

// mem inc
DMA1_Channel7->CCR |= (1U << 7);

// peipheral constant addr
DMA1_Channel7->CCR &= ~(1U << 6);

// CIRC circular buffer disable
DMA1_Channel7->CCR &= ~(1U << 5);

// MEM2MEM enable
DMA1_Channel7->CCR |= (1U << 14);

// dest address
DMA1_Channel7->CPAR = (uint32_t)&USART2->TDR;

// source buffer
DMA1_Channel7->CMAR = (uint32_t)source_buff;

// enable priority, very high
DMA1_Channel7->CCR |= (1U << 13);
DMA1_Channel7->CCR |= (1U << 12);

// size of transfer
DMA1_Channel7->CNDTR = buff_size; //buff_size;

// reset global interrupt flag.
DMA1->IFCR |= (1U << 24);

return;
}

here is how i am triggering the DMA request

void startTransfer(void) {
// clear TC flag by setting TCCF bit in UART CR
USART2->ICR |= UART2_ICR_TCCF;

// Enable DMA
DMA1_Channel7->CCR |= (1U << 0);

// Monitor TC for entire block transfer complete notification
while(!(USART2->ISR & UART2_ICR_TC));

return;
}

 

any help or pointers is appreciated.

Thanks.

This topic has been closed for replies.
Best answer by waclawek.jan

Contrary to the title, this *does* work as expected.

M2M DMA transfers data as quickly as possible, with no regard what the target does with that data. So here it simply dumps data to the UART's data register, and UART simlpy ignores every data written to that register while TXE status bit is not set (which is not set that quickly).

There is a reason why DMA transfers directed to peripherals should be triggered by that peripheral (here, the UART_Tx trigger) and should not be M2M.

JW

 

PS. Style: don't write registers (here DMAx_Channelx_CCR) piece-wise. Assemble the value you want to write there and perform one write. Also, for individual fields in registers (or for the shift amounts, if it's not a single-bit value) use the symbols defined in the device header.

PS2. When posting code here, please use the "</>" icon at top of the editor pane.

6 replies

waclawek.jan
waclawek.janBest answer
Super User
April 10, 2024

Contrary to the title, this *does* work as expected.

M2M DMA transfers data as quickly as possible, with no regard what the target does with that data. So here it simply dumps data to the UART's data register, and UART simlpy ignores every data written to that register while TXE status bit is not set (which is not set that quickly).

There is a reason why DMA transfers directed to peripherals should be triggered by that peripheral (here, the UART_Tx trigger) and should not be M2M.

JW

 

PS. Style: don't write registers (here DMAx_Channelx_CCR) piece-wise. Assemble the value you want to write there and perform one write. Also, for individual fields in registers (or for the shift amounts, if it's not a single-bit value) use the symbols defined in the device header.

PS2. When posting code here, please use the "</>" icon at top of the editor pane.

starkm42Author
Associate
April 10, 2024

starkm42_0-1712748023119.png

this diagram states that TXE flag is acknowledged by DMA and cleared after every read, so is this not the case on M2M ?

sorry if i am missing the obvious, this is my first micro-controller, and still am getting hang of things.

also if i remember properly, M2M is just a way of triggering DMA request right ?

Thanks.

waclawek.jan
Super User
April 10, 2024

First that text should say "Cleared by DMA *write* (as TDR is *written* by DMA, not read) ( @Imen.D , can you please have a look at this? It's RM0316. Btw. the next figure, Fig.345 has an error, too, in labeling the first line, it should be Rx rather than Tx. Thanks.)

Second M2M DMA mode does not work out the peripheral triggers (the more correct expression, used also on that figure is "requests"); it simply shovels data from source to destination as quickly as possible.

JW

 

ST Technical Moderator
April 15, 2024

Hi @waclawek.jan,

Thank you for highlighting this.

An internal ticket (number 178892) is submitted in order to fix the typos.
PS: Ticket number is only for reference, not available outside of ST.

In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question. Thanks
starkm42Author
Associate
April 11, 2024

yes, disabling M2M seems to get the intended results, thanks !

> Second M2M DMA mode does not work out the peripheral triggers (the more correct expression, used also on that figure is "requests"); it simply shovels data from source to destination as quickly as possible.

just curious, where is this information specified ?

PS:

> PS. Style: don't write registers (here DMAx_Channelx_CCR) piece-wise. Assemble the value you want to write there and perform one write. Also, for individual fields in registers (or for the shift amounts, if it's not a single-bit value) use the symbols defined in the device header.

yes, that makes sense, will do.

 

> PS2. When posting code here, please use the "</>" icon at top of the editor pane.

got it !, i overlooked that symbol :)

waclawek.jan
Super User
April 11, 2024

It's kind of a "common knowledge" one is supposed to learn in college or so. Nonetheless, it's thankfully properly documented in the RM, too:

waclawekjan_0-1712817743277.png

 

JW