Variable Declaration Issue in C (STM32 MCU) - Page 1
Forum section: electronics / general

author: TonyBe
author_rank: Regular Contributor
timestamp: April 03, 2020, 08:18:50 am
content: Hi Forum,i've really run into a strange problem here. I'm trying to program the DMA for my STM32H750 MCU. When using the HAL Drivers from STM, everything is done by using peripheral handlers, which are declared in the source files generated by CubeMX.When using the Timers and the UART, everything works fine. But now, i've get an "undeclared (first use in this function)" error when trying to call HAL_DMA_Start function with the "hdma_adc1" handler. When stepping through the code with the debugger, i can clearly see that the handler is declared and even initialized. And even more strange: when clicking on the hdma_adc1 in the function call (which is underlined red for being the error) i can jump to declaration without any problem. So why can i jump there when the compiler says, that it is not declared anywhere?Here is some code:This is the Init section at the beginning of my code. As seen with the HAL_TIM_OC_Start, the dereferenced handlers are used to call the functions f.ex. "&tim2".Code:/* Initialize all configured peripherals */MX_GPIO_Init();MX_DMA_Init();MX_ADC1_Init();MX_ADC3_Init();MX_DAC1_Init();MX_SPI1_Init();MX_TIM2_Init();MX_TIM3_Init();MX_UART4_Init();MX_USB_OTG_FS_PCD_Init();MX_ADC2_Init();MX_TIM1_Init();MX_SPI2_Init();/* USER CODE BEGIN 2 */HAL_TIM_OC_Start(&htim2, TIM_CHANNEL_2);// Start timer for heartbeat LEDUSR_send_Board_Info();HAL_Delay(2000);HAL_DMA_Start(&hdma_adc1, (uint32_t)&(hadc1.Instance->DR), (uint32_t)&samples, 1999);HAL_ADC_Start(&hadc1);The compiler marks the line which calls HAL_DMA_Start(&hdma_adc1,...).hdma_adc1 gets declared in the source file, which includes the MX_ADC1_INIT():Code:/* Includes ------------------------------------------------------------------*/#include "adc.h"/* USER CODE BEGIN 0 *//* USER CODE END 0 */ADC_HandleTypeDef hadc1;ADC_HandleTypeDef hadc2;ADC_HandleTypeDef hadc3;DMA_HandleTypeDef hdma_adc1;/* 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_DIV1;hadc1.Init.Resolution = ADC_RESOLUTION_16B;...The type of hdma_adc1 is (as seen) "DMA_HandleTypeDef". When checking the HAL_DMA_Start() function, this type should be totaly fine:Code:/*** @brief Starts the DMA Transfer.* @param hdma : pointer to a DMA_HandleTypeDef structure that contains* the configuration information for the specified DMA Stream.* @param SrcAddress: The source memory Buffer address* @param DstAddress: The destination memory Buffer address* @param DataLength: The length of data to be transferred from source to destination* @retval HAL status*/HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength){HAL_StatusTypeDef status = HAL_OK;...So what is going on here? Is this a compiler bug? If there were some typos or anything similar, I shouldn't be able to jump to declaration, didn't I?Please let me know if you need more code to get a better understanding.Thanks in advanceKind RegardsTony

author: Siwastaja
author_rank: Super Contributor
timestamp: April 03, 2020, 08:57:15 am
content: Just a guess,It's not obvious from your excerpts, but the definitionDMA_HandleTypeDef hdma_adc1;should comebeforeaccessing that variable:HAL_DMA_Start(&hdma_adc1, (uint32_t)&(hadc1.Instance->DR), (uint32_t)&samples, 1999);These should be in the same file, and in this order. Maybe the order is different? If this is the case, you can either move the definition above the code that uses the variable, or if you can't/don't want to do that, add adeclaration:extern DMA_HandleTypeDef hdma_adc1;which tells the compiler the type of the variable, and that it will be defined somewhere else, let the linker figure that out.The declaration is also handy when you define the variable in some other .c file; then you add the declaration to a .h file which you can include elsewhere.

author: TonyBe
author_rank: Regular Contributor
timestamp: April 03, 2020, 09:12:09 am
content: Thank you for your quick reply.Well indeed, this declaration is done before the HAL_DMA_Start function is called, since the MX_ADC_Init() is called above and therefore the hdma_adc1 handler is initialized as well.Regarding the declaration with the "extern" operator: i've also thought about that, but in every other case (UART, Timer) this isn't necessary at all and i really don't want to change the basic structure and idea of the HAL and MX Code just to build around the problem. There must be something else,.. with the compiler maybee?Any other suggestions?Thanks a lotRegards

author: Siwastaja
author_rank: Super Contributor
timestamp: April 03, 2020, 09:21:42 am
content: Any other warnings or errors? Full error message(s)?

author: TonyBe
author_rank: Regular Contributor
timestamp: April 03, 2020, 09:31:14 am
content: Quote from: Siwastaja on April 03, 2020, 09:21:42 am../Core/Src/main.c: In function 'main':../Core/Src/main.c:122:18: error: 'hdma_adc1' undeclared (first use in this function); did you mean 'hdac1'?HAL_DMA_Start(&hdma_adc1, (uint32_t)&(hadc1.Instance->DR), (uint32_t)&samples, 1999);^~~~~~~~~hdac1../Core/Src/main.c:122:18: note: each undeclared identifier is reported only once for each function it appears inmake: *** [Core/Src/subdir.mk:70: Core/Src/main.o] Error 1make: *** Waiting for unfinished jobs...."make -j8 all" terminated with exit code 2. Build might be incomplete.10:49:16 Build Failed. 3 errors, 0 warnings. (took 10s.951ms)That's all...Regards

author: Siwastaja
author_rank: Super Contributor
timestamp: April 03, 2020, 10:00:21 am
content: I don't get it. When in stuck in such a case which 99% likely is some super stupid mistake I'm unable to see, I try to narrow it down using things like:1) Move the declaration just before the function call. Or make an extra declaration with the same type, different name, locally in that function. Doesn't need to be functional that way - it's enough to see if it passes the compiler.2) Change the type of the variable to, for example,int. Now the error message should be about the wrong type.Eventually you'll figure it out by narrowing it down by such tests.

author: greenpossum
author_rank: Frequent Contributor
timestamp: April 03, 2020, 10:07:35 am
content: The error mentions a hdac1. I don't see that anywhere else, but there is a hadc1. Did your finger slip and type hdac1 for hadc1?As for the debugger working it probably ran the last good executable generated before this error.

author: TonyBe
author_rank: Regular Contributor
timestamp: April 03, 2020, 10:52:28 am
content: Ok i found the problem with the help of some colleagues. In the adc.h file, the extern variable declaration for hdma_adc1 was missing. I've actually checked that yesterday and it was there,... somehow after genereating new code with CubeMX this line was deleted.Thank you anyway!Have a good oneRegards

author: Siwastaja
author_rank: Super Contributor
timestamp: April 03, 2020, 01:41:05 pm
content: Oh, so the definitionwasin a different file after all!Autogenerating code carries risks such as this.

author: TonyBe
author_rank: Regular Contributor
timestamp: April 04, 2020, 09:46:49 am
content: Quote from: Siwastaja on April 03, 2020, 01:41:05 pmYes, sorry that this wasn't clear after my description above.I'm really trying to avoid auto generation of code,... but in this case, I had to go with it.Thanks againRegards!