cancel
Showing results for 
Search instead for 
Did you mean: 

Problems with H723ZG and ADC with DMA after integrating ETH and LWIP.

JohnPeterson
Associate II
Dear STMicroelectronics community,
 
My name is John Peterson, and I am trying to develop on the NUCLEO-H723ZG board.
 
I am having a hard time figuring out how to make ADC with DMA and ETH/LWIP work concurrently.
 
If I create a new STM32 project with my H723ZG as the target, and configure ADC1 as per this tutorial video (which includes setting up the DMA for the ADC), everything works great:
 
 
 
Here's some of the code that I incorporated into my main.c file:
 
 

 

 

 

 

/* USER CODE BEGIN PV */
int adcEnd = 0;

#define ADC_BUF_LEN 2000
uint16_t adc_buf[ADC_BUF_LEN];


/* USER CODE BEGIN 4 */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
	if (hadc == &hadc1)
	{
		adcEnd = 1;
	}
}

void HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc)
{
	int errorCode = hadc->ErrorCode;
}

uint16_t* process_request_adc()
{
	adcEnd = 0;

	memset(adc_buf, 0x00, sizeof(adc_buf));

	// Trigger the ADC.
	HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buf, sizeof(adc_buf));


	// Wait for the ADC collection to complete.
	while(!adcEnd)
	{
		HAL_Delay(10);
	}

	return adc_buf;
}

 

 

 

 

 
 
If I invoke process_request_adc() from main() after everything initializes it functions exactly as hoped.  The adc_buf[] array is populated with values that I would expect to see from the ADC.
 
However, once I integrate and configure ETH/LWIP -- even withOUT using any ETH/LWIP features (this includes disabling the LWIP initialization) -- the ADC no longer seems to update the buffer.  All the ADC calls seem to execute as before but the adc_buf[] remains unchanged, even after the HAL_ADC_ConvCpltCallback() returns successfully.  There is no indication of error.  Whatever value I memset() into the adc_buf[] remains in that array.
 
I configured the ETH/LWIP elements akin to these videos:
 
 
Doing a web search revealed a couple of STM32 community posts on issues similar to ours:
 
 
However, in reviewing these threads, and the proposed links therein, there really didn't seem to be any actionable advice.
 
I've reviewed the memory aspects.  It seems that the ETH/LWIP/MPU is configured to use the start of SRAM1 (0x3000000), and that's pretty much the default values/ranges that were proposed when enabling ETH/LWIP.  As per the videos, I enabled the IOC's System Core -> CORTEX_M7 -> Parameter Settings -> Cortex Interface Settings and enabled both the CPU ICache and DCache.  I modified several other parameters in that section, and updated the linker file (Flash.id) accordingly.  The ETH/LWIP functionality works great!
 
The adc_buf[] is in application variable space, so far away from the ETH/LWIP memory space.  I can use the Build Analyzer in the CubeIDE to see the Memory Regions and Memory Details for these aspects and know that they're in discrete areas.  But maybe there are other memory regions associated with the ADC/DMA and ETH/LWIP for which I'm unfamiliar?
 
To recap, the ADC/DMA aspects were working before ETH/LWIP was integrated.  Afterwards, it's as if the ADC/DMA no longer updates the associated buffer but no errors appear to manifest.  How can I debug and fix this to get the ADC/DMA to work again with ETH/LWIP?
 
Thanks for your consideration!
 
Very kind regards,
 
John Peterson

 

5 REPLIES 5
STea
ST Employee

Hello @JohnPeterson ,

welcome to the ST community.

I have some question that and information I need to know to help you with your investigation.

could you share the .IOC file used to generate the code are you sure there are no conflicting pins used by ZDC and Ethernet.

also check the following article which can give you good tips on usage of ADC alongside Ethernet. 
ADC value affected by ETH PHY 50 MHz from RMII int... - STMicroelectronics Community

Regards

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Dear STea,

 

Thanks for the response!  I've shared my ADC_Test.ioc file.  How will you identify whether there are conflicting pins or not?

 

When hovering over the three ADC options, I *do* note that they claim to potentially be in conflict with ETH RMII:

 

JohnPeterson_0-1729181653831.png

 

Yet it's not clear WHAT might be in conflict.  I am not using PB0 (as far as I know).

With my board, my ONLY option for the ETH mode is RMII:

 

JohnPeterson_1-1729181741066.png

 

If the ADCs are really in conflict with the ETH RMII...does this mean this board is not suitable to run both components simultaneously?

 

Thanks for the provided link.  I feel like my situation is a bit different, as I'm not getting "noise" in the ADC buffer (at least, I don't think so), but rather the buffer isn't being populated at all.

 

I'm eager to learn what you can glean from the .ioc file!

 

Thanks in advance for any help you can provide!

Hello @JohnPeterson ,

sorry for the delayed response but I have some questions as a follow-up .seems like there is no conlicts betwwen ADC pin PF11 and the RMII pins used.

after seeing the configuration that you are using i would like to see if you can get values of ADV conversions in polling mode instead of DMA mode.
also, I would like to know what the behavior with another ADC instance and maybe another line.
Regards

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Dear STea,

Thanks for the reply.  I'd like to share some additional findings regarding this issue. I believe that maybe my ADC/DMA problem is less related to ETH/LWIP, but instead related to enabling the I/DCache (which I enable as part of the ETH/LWIP configuration).

Consider the following steps to create a brand new project from the CubeIDE:

  • File -> New -> STM32 Project
  • Board Selector tab -> Commercial Part Number: NUCLEO-H723ZG
  • Select the board in the lower right-hand pane and click Next.
  • Fill out the Project Name (e.g., ADC_Test) and click Finish.
  • When prompted with "Initialize all peripheral with their default Mode?", click No (otherwise the ETH and other peripherals will be enabled by default).

 When the IDE loads the new IOC file:

 Under Pinout & Configuration:

  • Select Analog -> ADC1
  • Configure IN2 as IN2 Single-ended.
  • Under DMA Settings, click Add and then select ADC1 from the dropdown in the DMA Request column.

 Switch to Clock Configuration:

  • Click Resolve Clock Issues and accept the defaults.

 Back under Pinout & Configuration.

Under the ADC1 Parameter Settings, it should look like:

JohnPeterson_0-1729812065286.png

Save the IOC file and click Yes to generate code.

In main.c, add the following code before the main(void) function in the USER CODE 0 section:

 

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
#define ADC_BUF_LEN 2000
int adcEnd = 0;
uint16_t adc_buf[ADC_BUF_LEN];
 
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
	if (hadc == &hadc1)
	{
		adcEnd = 1;
	}
}
 
void HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc)
{
	int errorCode = hadc->ErrorCode;
}
 
void process_request_adc()
{
	adcEnd = 0;
 
	memset(adc_buf, 0x0F, sizeof(adc_buf)); // Decimal 3855 - just some arbitrary value to see if the buffer changes.
 
	// Trigger the ADC.
	HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buf, sizeof(adc_buf));
 
	while(!adcEnd)
	{
		HAL_Delay(10);
	}
 
	uint32_t* test = adc_buf;
}
/* USER CODE END 0 */

 

In the main(void) function, within the USER CODE 2 section, add the following:

 

  /* USER CODE BEGIN 2 */
  process_request_adc();
  /* USER CODE END 2 */

 

Save and debug the application, placing a breakpoint at the last line of the process_request_adc() function to be able to view the contents of adc_buf (or set it up as a Watch variable). You'll note that the 3885 values have been overwritten to some random values, which indicates a successful ADC/DMA action.

Stop debugging.

Under the IOC Pinout & Configuration:

  • System Core -> CORTEXT_M7
  • Enable Cortex Interface Settings CPU ICache and DCache.

Save the IOC file and click Yes to generate code.

Debug again. Note that the contents of adc_buf now remain unchanged from their initialized values of 3855. The ADC callback is being invoked, but the contents of the buffer we're using for the DMA are not being overwritten.

Why?!?

Hello @JohnPeterson ,

The issue you are experiencing is likely due to data coherency problems between the CPU cache and the DMA controller. When the cache is enabled, the CPU may be reading stale data from the cache instead of the updated data from the SRAM, where the DMA controller writes the converted ADC values

you should either try to disable cache for this region of memory where you buffer resides (Use the Memory Protection Unit (MPU) to change the DMA buffers to non-cacheable (device mode)) via MPU configuration or implement Before enabling DMA, perform a cache clean operation to ensure that any data in the cache is written to SRAM. Before reading the data, perform a cache clean and invalidate operation to ensure that the CPU reads the updated data from SRAM.

Regards 

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.