cancel
Showing results for 
Search instead for 
Did you mean: 

STM32U5 + ADF + GPDMA + STOPMODE1: Need help

coppercrimp
Senior

I’m working on a project that involves reading audio samples from ADF1 and storing them in an internal RAM buffer using the GPDMA. The GPDMA is configured using Linked Lists in circular mode. An interrupt is generated when the buffer is half-full and full. The STM32 should remain in STOP1 mode while the buffer is filled, and wake up when either of the two interrupts occur.

Note that FatFs is also used to write the buffered data to an SD card through the SDMMC interface.

I have this all working perfectly on my custom STM32U575 pcb, but only when I put the STM32 into sleep mode. It does not work in STOPMODE1. The interrupts never occur and the device never wakes from STOPMODE1. What am I missing? How can I make this work? I’ve looked for existing example code using GPDMA and STOP1, but have come up empty. See below for CUBEMX configuration and code:

coppercrimp_0-1757555614697.png

coppercrimp_1-1757555670472.png

coppercrimp_2-1757555762923.png

coppercrimp_3-1757555822455.png

Most of my code is in the main() function:

int main(void)
{
  FRESULT ReturnResult;
  FIL MyFile;

  int numberOfWrites = 16;

  HAL_Init();

  SystemPower_Config();

  SystemClock_Config();

  MX_GPDMA1_Init();
  __HAL_LINKDMA(&AdfHandle0, hdma, handle_GPDMA1_Channel11);
  MX_GPIO_Init();
  MX_ADF1_Init();
  MX_ICACHE_Init();
  MX_SDMMC1_SD_Init();

  HAL_DBGMCU_EnableDBGStopMode();

  FATFS_LinkDriver(&SD_Driver, SD_Path);

  ReturnResult = f_mount(&SDDISKFatFs, (TCHAR const*)SD_Path, 1);
  if(ReturnResult != FR_OK)
  {
    Error_Handler();
  }

  ReturnResult = f_open(&MyFile, "NewAudio1.raw", FA_CREATE_ALWAYS | FA_WRITE);
  if(ReturnResult != FR_OK)
  {
    Error_Handler();
  } 
  MX_MDFQueue_Config();
  /* Link SAI queue to DMA channel */
  HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel11, &MDFQueue);

  MDF_DMAConfig();


  if (HAL_MDF_AcqStart_DMA(&AdfHandle0, &AdfFilterConfig0, &DMAConfig) != HAL_OK)
  {
    Error_Handler();
  }
  HAL_PWREx_ConfigSRDDomain(PWR_SRD_DOMAIN_RUN);

  while (1)
  {
      HAL_SuspendTick();
      //HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); //<- THIS WORKS
      __HAL_RCC_PWR_CLK_ENABLE();
      HAL_PWREx_EnterSTOP1Mode(PWR_STOPENTRY_WFI);  //<- THIS DOES NOT WORK
      HAL_ResumeTick();

      if(DmaRecHalfBuffCplt == 1)
      {
        FatFsResult = f_write(&MyFile, &RecBuff[0], (UINT)((REC_BUFF_SIZE_DIV2 - 1) * 2), (void *)&byteswritten);
        if(FatFsResult != FR_OK)
        {
          Error();
        }
        DmaRecHalfBuffCplt  = 0;
      }

      if(DmaRecBuffCplt == 1)
      {
        FatFsResult = f_write(&MyFile, &RecBuff[REC_BUFF_SIZE_DIV2], (UINT)(REC_BUFF_SIZE_DIV2 * 2), (void *)&byteswritten);
        if(FatFsResult != FR_OK)
        {
          Error();
        }
        numberOfWrites--;
        DmaRecBuffCplt = 0;
      }

      if(numberOfWrites == 0)
      {
        HAL_MDF_AcqStop_DMA(&AdfHandle0);
        f_close(&MyFile);
        break;
      }
    }
    HAL_MDF_DeInit(&AdfHandle0);
    MX_GPDMA1_DeInit();
  while (1)
  {
  }
}

Below is my HAL_MDF_MspInit() function with some additional function calls in the user code area that I'd hoped would allow GPDMA to run in STOP1:

void HAL_MDF_MspInit(MDF_HandleTypeDef* hmdf)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
  if(IS_ADF_INSTANCE(hmdf->Instance))
  {
    /* USER CODE BEGIN ADF1_MspInit 0 */
    __HAL_RCC_ADF1_CLK_SLEEP_ENABLE();
    __HAL_RCC_GPDMA1_CLK_SLEEP_ENABLE();
    __HAL_RCC_LPGPIO1_CLK_SLEEP_ENABLE();
    __HAL_RCC_SRAM1_CLK_SLEEP_ENABLE();
    __HAL_RCC_MSIKSTOP_ENABLE();
    HAL_PWREx_EnableVddIO2();
    HAL_PWREx_EnableVddA();
    /* USER CODE END ADF1_MspInit 0 */

  /** Initializes the peripherals clock
  */
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADF1;
    PeriphClkInit.Adf1ClockSelection = RCC_ADF1CLKSOURCE_MSIK;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
    {
      Error_Handler();
    }

    /* Peripheral clock enable */
    __HAL_RCC_ADF1_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**ADF1 GPIO Configuration
    PB3 (JTDO/TRACESWO)     ------> ADF1_CCK0
    PB4 (NJTRST)     ------> ADF1_SDI0
    */
    GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF3_ADF1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* ADF1 interrupt Init */
    HAL_NVIC_SetPriority(ADF1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(ADF1_IRQn);
    /* USER CODE BEGIN ADF1_MspInit 1 */

    /* USER CODE END ADF1_MspInit 1 */
  }
}

 

 

2 REPLIES 2
coppercrimp
Senior

I'll try again... Anyone out there have an idea on how to get GPDMA and STOP1 working?

I was able to get this code working with LPDMA and STOP2 by learning from the "ADF_AudioSoundDetector" example that ST provides. However, due to some of the limitations of LPDMA and STOP2, I suspect my application might be more power efficient in STOP1 with GPDMA. I cant seem to find any similar example code for GPDMA and STOP1 however

The following is a screenshot of the Clock Configuration screen from CubeMX in case that offers any clues as to what I might be doing wrong

 

coppercrimp_0-1757900638166.png

 

Hai
ST Employee

Hello @coppercrimp 

Thanks a lot for your detailed and pertinent questions.

Regarding your issue I have remarked in your current code, the function call:

HAL_DBGMCU_EnableDBGStopMode();

enables debug during STOP mode. While this is useful for debugging, it prevents the CPU core from fully entering low-power STOP1 mode because the core remains gated and the MCU operates in a low-power emulation mode instead of true STOP mode.


Impact on Your Application

  • When debug is enabled in STOP mode, the MCU will not fully enter STOP1 mode, which can cause the GPDMA interrupts and wake-up behavior to not function as expected.
  • This can explain why your device does not wake up from STOP1 mode on GPDMA interrupts, as the core is effectively held in a debug state rather than a true low-power state.

Recommended Action

  • Disable debug in STOP mode for proper low-power operation.
  • Remove or comment out the line:
HAL_DBGMCU_EnableDBGStopMode();

 

Please feel free to respond and confirm whether this resolves your request or not.

Best regards,
Haifa.