cancel
Showing results for 
Search instead for 
Did you mean: 

Code-gen problem when using file-pairs for peripheral initialization

bramble
Associate II

Hi all, my first post here, being new to STM32..

I have an STM32F439ZI Nucleo for which I have ADC1 nicely capturing data with TIM2 defining the sample rate and circular DMA.

This was working well until I regenerated the code using the option to initialize peripherals using separate file pairs for each peripheral. I realise that switching to that option doesn't handle migration of all User code as it should, that's OK, I could easily copy over the relevant code.

However, the new version is still broken: the ADC conversion complete callback it firing at the expected rate, but all ADC data are zero. When I switch back to code generation not using separate initialization files, the everything starts working again.

My application is also using DMA to drive an LCD, which is working OK, so DMA clearly isn't fundamentally broken.

I've carefully checked each of the init functions that are moved into the newly created files (dma.c/h, adc.c/h, tim.c/h etc), and I can't see anything that's changed, nor can I see an obvious change in the order in which the various initializations are done.

I must have overlooked something, but wonder whether anyone can suggest a more subtle root cause?

Searching these forums I saw that several people have reported similar issues on various other platforms in recent years, but none of those seem to match the issue I'm seeing.

Thanks in advance for any suggestions.

1 ACCEPTED SOLUTION

Accepted Solutions
bramble
Associate II

I have fixed my problem. The cause and solution were as follows:

In my original version (all code in main.c/h - i.e. not using separate file pairs for all peripherals), I had a static array declaration for the buffer used to receive ADC data via DMA:

 

#define RX_BUF_SIZE 1024
uint16_t rx_data[RX_BUF_SIZE];

 

Elsewhere, I was using rx_data as a pointer when initialising the ADC with DMA:

 

if (HAL_ADC_Start_DMA(&hadc1, rx_data, RX_DATA_BUF_SIZE_WORDS) != HAL_OK)
{
  error_handler("ADC1-init", true, 0);
}

 

The pointer rx_data was also used within the ADC completion callback to periodically handle data (this just being a temporary hack to take a quick look at the data as an initial stage in my development). This worked perfectly, no problems.

The problem arose after switching to using separate file pairs for peripheral initialisation, my FreeRTOS and the true peripherals (ADC, DMA, GPIO, Timer) all end up in separate files. In this case I initially placed the rx_data declaration at the top of main.c and used an extern reference to that array (as a uint16_t*) in the FreeRTOS source file from which I want to handle received data. I noticed occasional Hard_Fault exceptions and that led me to realise that there was a problem with this array reference.

The problem was solved by declaring rx_data as a raw uint16_t* and allocating at run-time from the heap (malloc) in the FreeRTOS task that looks after the ADC.

In summary, I'm sure there was no problem in the code generated by CubeMX. The problem lay in my attempt to share an array declared in one source file, via a raw pointer in another source file. I'm not sure whether the underlying issue was related to byte alignment, compiler optimisation or some other cause.

 

View solution in original post

3 REPLIES 3
Mahmoud Ben Romdhane
ST Employee

Hello @bramble ,

First let me thank you for posting and welcome to the ST Community.

For more investigation, I suggest that you provide please your Ioc.File.

Thanks.

Mahmoud

bramble
Associate II

Hi @Mahmoud Ben Romdhane ,

 

Ioc file now attached, many thanks.

bramble
Associate II

I have fixed my problem. The cause and solution were as follows:

In my original version (all code in main.c/h - i.e. not using separate file pairs for all peripherals), I had a static array declaration for the buffer used to receive ADC data via DMA:

 

#define RX_BUF_SIZE 1024
uint16_t rx_data[RX_BUF_SIZE];

 

Elsewhere, I was using rx_data as a pointer when initialising the ADC with DMA:

 

if (HAL_ADC_Start_DMA(&hadc1, rx_data, RX_DATA_BUF_SIZE_WORDS) != HAL_OK)
{
  error_handler("ADC1-init", true, 0);
}

 

The pointer rx_data was also used within the ADC completion callback to periodically handle data (this just being a temporary hack to take a quick look at the data as an initial stage in my development). This worked perfectly, no problems.

The problem arose after switching to using separate file pairs for peripheral initialisation, my FreeRTOS and the true peripherals (ADC, DMA, GPIO, Timer) all end up in separate files. In this case I initially placed the rx_data declaration at the top of main.c and used an extern reference to that array (as a uint16_t*) in the FreeRTOS source file from which I want to handle received data. I noticed occasional Hard_Fault exceptions and that led me to realise that there was a problem with this array reference.

The problem was solved by declaring rx_data as a raw uint16_t* and allocating at run-time from the heap (malloc) in the FreeRTOS task that looks after the ADC.

In summary, I'm sure there was no problem in the code generated by CubeMX. The problem lay in my attempt to share an array declared in one source file, via a raw pointer in another source file. I'm not sure whether the underlying issue was related to byte alignment, compiler optimisation or some other cause.