I'm trying to set up a simple project that does the following:

  1. Enter sleep mode and in the main loop, it waits for interrupt - __WFI().

  2. Transmits data from a buffer[4] to the PC, via UART.

The second point of the program would ideally be done via DMA, so that the MCU wouldn't wake up from sleep.

To that effect, I was thinking of hooking up a DMA transfer in circular mode. So every time a timer (say timer1) overflows, it automatically triggers a UART transfer. When the DMA transfers the 4th byte of buffer, it would start over from the beginning.

Can I trigger a DMA when the CPU is in sleep mode?

  • \$\begingroup\$ You could always try just setting it up like normal then going to sleep and seeing if it works. According to the training powerpoints it is possible. \$\endgroup\$
    – DKNguyen
    Commented Feb 11, 2021 at 14:34
  • \$\begingroup\$ I sincerely have no clue how to use the DMA controller in circular mode. When I trigger a transfer directly, if in circular mode, it just sends all the data in the buffer continuously. \$\endgroup\$
    – PauLEffect
    Commented Feb 11, 2021 at 15:12
  • \$\begingroup\$ That's what it does. You have to have the MCU swoop in a grab the data before it wraps around and overwrites it. \$\endgroup\$
    – DKNguyen
    Commented Feb 11, 2021 at 15:14
  • \$\begingroup\$ I understand that. But im not receiving. Im trying to transmit. So data should not be overwritten. \$\endgroup\$
    – PauLEffect
    Commented Feb 11, 2021 at 15:17
  • \$\begingroup\$ Oh, circular mode shouldn't really be used for transmit I don't think. I can't think of cases where it is useful transmitting since you need the MCU to wake up to place new data anyways. \$\endgroup\$
    – DKNguyen
    Commented Feb 11, 2021 at 15:20

1 Answer 1


So, I generated a standard CubeMX project. I used USART1 & TIMER1.

hdma_tim1_up.Instance = DMA2_Channel2;
hdma_tim1_up.Init.Request = DMA_REQUEST_TIM1_UP;
hdma_tim1_up.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_tim1_up.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_tim1_up.Init.MemInc = DMA_MINC_ENABLE;
hdma_tim1_up.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_tim1_up.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_tim1_up.Init.Mode = DMA_CIRCULAR;
hdma_tim1_up.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_tim1_up) != HAL_OK)

In the main function, after the initialization of the peripherals, I simply call

HAL_DMA_Start(htim1.hdma[TIM_DMA_ID_UPDATE], (uint32_t)&testPWM, (uint32_t)&huart1.Instance->TDR, 4);
/* Infinite loop */
while (1)

testPWM is a 4 byte array {0, 1, 2, 3}

The main loop is empty, no callbacks are used in code. The DMA controller sends 0 1 2 3 to the PC via UART, on each timer overflow event. When it reaches 3, it wraps back to 0.

  • \$\begingroup\$ I believe this answer will send one character per timer event, not the entire contents of testPWM. \$\endgroup\$
    – gordonC
    Commented Sep 29, 2023 at 16:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.