anybody got the ADC on stm32H743 working with DMA?

Post here first, or if you can't find a relevant section!
jay_stm
Posts: 11
Joined: Mon Oct 18, 2021 2:33 pm

anybody got the ADC on stm32H743 working with DMA?

Post 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
by fpiSTM » Fri Dec 10, 2021 12:21 pm
Add extern "C" before each callback and handler declaration
Go to full post
jay_stm
Posts: 11
Joined: Mon Oct 18, 2021 2:33 pm

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

Post 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");
}
User avatar
fpiSTM
Posts: 1723
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

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

Post by fpiSTM »

Add extern "C" before each callback and handler declaration
jay_stm
Posts: 11
Joined: Mon Oct 18, 2021 2:33 pm

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

Post 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.
ag123
Posts: 1653
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

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

Post 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
jay_stm
Posts: 11
Joined: Mon Oct 18, 2021 2:33 pm

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

Post 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.
jay_stm
Posts: 11
Joined: Mon Oct 18, 2021 2:33 pm

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

Post 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
jay_stm
Posts: 11
Joined: Mon Oct 18, 2021 2:33 pm

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

Post 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.
golden-teacher
Posts: 1
Joined: Wed Apr 20, 2022 5:09 pm

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

Post 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
Eternalist0
Posts: 2
Joined: Mon May 09, 2022 1:41 pm

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

Post by Eternalist0 »

Hi,

You need to invalidate cache when DMA completed transfer.
Post Reply

Return to “General discussion”