cancel
Showing results for 
Search instead for 
Did you mean: 

Hi, I want to use a DMA to simply output array values to a whole GPIO port. I don't think I set it up correctly, as it doesn't work. I generated most of the code with CubeMX and used HAL. Should my code work ? How can I make it work ? Thanks !

JMarc.1
Associate II

Here's the context:

  • I'm working on a STM32H743, I managed to output the array values manually to GPIOD (ie my MCU is not fried... You never know)
  • I paid close attention to using the correct region D2 as stated here :
//In my main.c:
 
#define BUFFER_SIZE 			32
#define __SECTION_RAM_D2 __attribute__((section(".RAM_D2"))) /* AHB SRAM (D2 domain): */
 
volatile __SECTION_RAM_D2 uint16_t Buffer[BUFFER_SIZE] = {0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF};
 
//In my STM32H743xxx.Id, at the end of the file:
 
/* Definition for DMA area  */
  .RAM_D2 :
  {
        KEEP(*(.RAM_D2)) /* ORIGIN = 0x30000000, LENGTH = 288K */
  } >RAM_D2
  • After my init sequence, and before my main loop, here's the part dealing with the DMA (and my timer !):
__HAL_TIM_ENABLE_DMA(&htim1, TIM_DMA_CC4);
  HAL_DMA_Start_IT(htim1.hdma[TIM_DMA_ID_CC4], (uint32_t)Buffer, (uint32_t)DAC3_D0_GPIO_Port->ODR, BUFFER_SIZE);
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3);
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_4);
  • DAC_D0_GPIO_Port is my GPIOD, where my array should be output
    • My timer is setup and running as PWM generation, i can see it correctly running at about 1.2MHz (setup through CubeMX)
  • Here is my DMA setup in CubeMX: 0693W000000Tl1yQAC.png

I must be missing something evident, but it is the first time I am using an STM32, and a DMA.

Thanks in advance for your help ! :D

2 REPLIES 2
berendi
Principal

I could not figure it out with CubeMX/HAL, but it works for me with the register interface as documented in the reference manual.

DMAMUX1_Channel0->CCR = (DMA_REQUEST_TIM1_CH4 << DMAMUX_CxCR_DMAREQ_ID_Pos); // map timer channel event to DMA1 Stream0.
DMA1->LIFCR = DMA_LIFCR_CTCIF0 | DMA_LIFCR_CHTIF0; // clear DMA complete flags
DMA1_Stream0->PAR = (uint32_t)&(GPIOx->BSRR); // you can use ODR as well
DMA1_Stream0->M0AR = (uint32_t)bits_out; // address of the buffer
DMA1_Stream0->NDTR = out_n; // bytes to transfer
DMA1_Stream0->CR =
	DMA_SxCR_MSIZE_1 | // 10: 32 bit
	DMA_SxCR_PSIZE_1 | // 10: 32 bit
	DMA_SxCR_MINC    | // memory address increment
	DMA_SxCR_DIR_0   | // 00: P->M, 01:M->P, 10:M->M
	DMA_SxCR_CIRC    | // circular mode, comment it out when you don't need continuous transfer
	DMA_SxCR_EN; // enable DMA channel

 Don't forget to disable caching of the buffer, or flush (clean) the cache before starting DMA.

https://community.st.com/s/question/0D50X0000CEr14wSQB/h745-memory-regions-attributes-cache

Thank you for your reply !

I had also tried without CubeMX/HAL, without success.

I tried using your code and adapting it to my needs (and I flushed the cache before starting DMA), but no luck on this, nothing happens on GPIOD.

My guess right now is that my timer doesn't trigger the DMA transfer (or rather the DMA is not configured to be triggered by the right timer event).

Also it (TIM1) is configured as PWM generation, is it a correct way to use it for DMA ? I've seen some code from my company using OC mode rather than PWM but i'm not sure it is fitted for my needs.