Page 1 of 2

anybody got the ADC on stm32H743 working with DMA?

Posted: Thu Dec 09, 2021 1:24 pm
by jay_stm
I'm a bit stuck with my project, i know variables are created in ITCMRAM space wich is not accesable by DMA and should be setup in D2 RAM space.
Several solutions offered like assigning a variable to a section in the loader file do not work, the variable is always assigned to 0x00000000.
Either that or i get a message after compilation that there is not enough disc space insert disc blabla.
Does anybody have DMA working on the onboard ADC on the H743?
Arduino platform.
Yes, polling works
Yes, i read and tried the article: https://community.st.com/s/article/FAQ- ... H7-devices

Re: anybody got the ADC on stm32H743 working with DMA?

Posted: Fri Dec 10, 2021 11:10 am
by jay_stm
Maybe a little bit of code helps, i finally got the buffer setup in D2 ram, i can read and write it so thats done. But still nothing going on regarding callbacks and interrupts, if i start the following program i get a start message and thats it, it never goes into the callbacks, any clue?


ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;
static uint32_t HAL_RCC_ADC12_CLK_ENABLED = 0;
boolean ADC1_done = false;
uint16_t ADC1ConvertedValue[10240] __attribute__((section(".ram_d2_sram1")));
void setup() {
Serial.begin(115200);
Serial.println("start");

SCB_DisableICache();
SCB_DisableDCache();

HAL_Init();
Stm32_Clock_Init(120, 1, 2, 2);
MX_DMA_Init();
MX_ADC1_Init();
MY_HAL_ADC_MspInit(&hadc1);

__HAL_RCC_TIM1_CLK_ENABLE();
__HAL_RCC_USART3_CLK_ENABLE();

__HAL_RCC_D2SRAM1_CLK_ENABLE();
__HAL_RCC_D2SRAM2_CLK_ENABLE();
__HAL_RCC_D2SRAM3_CLK_ENABLE();

HAL_ADC_Start_DMA(&hadc1,
(uint32_t *)ADC1ConvertedValue,
20
);

}

void loop() {
if (ADC1_done) {
Serial.println("adc done");
ADC1_done = false;
}
delay(10);
}

void Stm32_Clock_Init(uint32_t plln, uint32_t pllm, uint32_t pllp, uint32_t pllq)
{
HAL_StatusTypeDef ret = HAL_OK;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;

MODIFY_REG(PWR->CR3, PWR_CR3_SCUEN, 0);
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
while ((PWR->D3CR & (PWR_D3CR_VOSRDY)) != PWR_D3CR_VOSRDY) {}
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSIState = RCC_HSI_OFF;
RCC_OscInitStruct.CSIState = RCC_CSI_OFF;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLN = plln;
RCC_OscInitStruct.PLL.PLLM = pllm;
RCC_OscInitStruct.PLL.PLLP = pllp;
RCC_OscInitStruct.PLL.PLLQ = pllq;
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_2;
ret = HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | \
RCC_CLOCKTYPE_HCLK | \
RCC_CLOCKTYPE_D1PCLK1 | \
RCC_CLOCKTYPE_PCLK1 | \
RCC_CLOCKTYPE_PCLK2 | \
RCC_CLOCKTYPE_D3PCLK1);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV4;
ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
if (ret != HAL_OK) while (1);
__HAL_RCC_CSI_ENABLE() ;
__HAL_RCC_SYSCFG_CLK_ENABLE() ;
HAL_EnableCompensationCell();

RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
/** Initializes the peripherals clock
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_ADC;
PeriphClkInitStruct.PLL2.PLL2M = 1;
PeriphClkInitStruct.PLL2.PLL2N = 18;
PeriphClkInitStruct.PLL2.PLL2P = 2;
PeriphClkInitStruct.PLL2.PLL2Q = 2;
PeriphClkInitStruct.PLL2.PLL2R = 2;
PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_3;
PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOMEDIUM;
PeriphClkInitStruct.PLL2.PLL2FRACN = 6144;
PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
error1();
}
}

void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Stream0_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
}

/* ADC1 init function */
void MX_ADC1_Init(void)
{
ADC_MultiModeTypeDef multimode = {0};
ADC_ChannelConfTypeDef sConfig = {0};
/** Common config
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2;
hadc1.Init.Resolution = ADC_RESOLUTION_10B;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_ONESHOT;
//hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;
hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
hadc1.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
hadc1.Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
error1();
}
/** Configure the ADC multi-mode
*/
// multimode.Mode = ADC_MODE_INDEPENDENT;
// if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
// {
// error1();
// }
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_16;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_8CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
sConfig.OffsetSignedSaturation = DISABLE;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
error1();
}
}

void MY_HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if (adcHandle->Instance == ADC1)
{
/* ADC1 clock enable */
HAL_RCC_ADC12_CLK_ENABLED++;
if (HAL_RCC_ADC12_CLK_ENABLED == 1) {
__HAL_RCC_ADC12_CLK_ENABLE();
}
__HAL_RCC_GPIOA_CLK_ENABLE();

__HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_CLKP);

/**ADC1 GPIO Configuration
PA0 ------> ADC1_INP16
*/
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* ADC1 DMA Init */
/* ADC1 Init */
hdma_adc1.Instance = DMA1_Stream0;
hdma_adc1.Init.Request = DMA_REQUEST_ADC1;
hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
//hdma_adc1.Init.Mode = DMA_NORMAL;
hdma_adc1.Init.Mode = DMA_CIRCULAR;
hdma_adc1.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
{
error1();
}
__HAL_LINKDMA(adcHandle, DMA_Handle, hdma_adc1);
}
}


void DMA1_Stream0_IRQHandler(void)
{
Serial.println("stream0");
ADC1_done = true;
}

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
Serial.println("call back");
ADC1_done = true;
}

void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc) {
Serial.println("half call back");
ADC1_done = true;
}

void error1(void) {
Serial.println("error 1");
}

Re: anybody got the ADC on stm32H743 working with DMA?

Posted: Fri Dec 10, 2021 12:21 pm
by fpiSTM
Add extern "C" before each callback and handler declaration

Re: anybody got the ADC on stm32H743 working with DMA?

Posted: Fri Dec 10, 2021 12:36 pm
by jay_stm
Thanks, tried it but same result. If i put some data into the buffer and read it back later in the main loop, the first value is changed and seems to reflect the analog input. Looks like only 1 value is transferred but none of the callbacks are triggered.

Re: anybody got the ADC on stm32H743 working with DMA?

Posted: Fri Dec 10, 2021 2:16 pm
by ag123
maybe you missed out something like

Code: Select all

HAL_DMA_RegisterCallback(hdma, HAL_DMA_XFER_CPLT_CB_ID	, pCallback); 
HAL_DMA_RegisterCallback(hdma, HAL_DMA_XFER_HALFCPLT_CB_ID, pCallback);
...
?

note that there are
  • HAL_DMA_XFER_CPLT_CB_ID
  • HAL_DMA_XFER_HALFCPLT_CB_ID
  • HAL_DMA_XFER_M1CPLT_CB_ID
  • HAL_DMA_XFER_M1HALFCPLT_CB_ID
  • HAL_DMA_XFER_ERROR_CB_ID
  • HAL_DMA_XFER_ABORT_CB_ID

Re: anybody got the ADC on stm32H743 working with DMA?

Posted: Fri Dec 10, 2021 6:57 pm
by jay_stm
I believe the default callbacks dont need to be registered, have not seen this in any demo.
Anyway there is only 1 adc value collected so these callbacks are never called.

Re: anybody got the ADC on stm32H743 working with DMA?

Posted: Fri Dec 10, 2021 6:58 pm
by jay_stm
(++) ADC conversion with transfer by DMA:
(+++) Activate the ADC peripheral and start conversions
using function HAL_ADC_Start_DMA()
(+++) Wait for ADC conversion completion by call of function
HAL_ADC_ConvCpltCallback() or HAL_ADC_ConvHalfCpltCallback()
(these functions must be implemented in user program)
(+++) Conversion results are automatically transferred by DMA into
destination variable address.
(+++) Stop conversion and disable the ADC peripheral
using function HAL_ADC_Stop_DMA()

[..]

(@) Callback functions must be implemented in user program:
(+@) HAL_ADC_ErrorCallback()
(+@) HAL_ADC_LevelOutOfWindowCallback() (callback of analog watchdog)
(+@) HAL_ADC_ConvCpltCallback()
(+@) HAL_ADC_ConvHalfCpltCallback

Re: anybody got the ADC on stm32H743 working with DMA?

Posted: Mon Dec 20, 2021 8:44 pm
by jay_stm
Got it working, as often multiple issues are involved. The CPU was hanging during dma transfers, incompatibility issues between mxcube generated code and stm32duino, indeed memory access issues between dma and default variable memory. All sorted out now.

Re: anybody got the ADC on stm32H743 working with DMA?

Posted: Wed Apr 20, 2022 5:13 pm
by golden-teacher
Hi @jay_stm ,
I am looking to get the ADC working with the DMA as well. Would you be so kind to share the code you got working?
I am experiencing some problems with my CubeMX-generated code. I suspect it is due to the ADC buffer memory allocation, but I am not certain.

Cheers,
Matt

Re: anybody got the ADC on stm32H743 working with DMA?

Posted: Mon May 09, 2022 1:42 pm
by Eternalist0
Hi,

You need to invalidate cache when DMA completed transfer.