Skip to main content
PGump.1
Senior II
April 11, 2024
Solved

Release build won't run

Hi all,

I have a simple project using a STM32C011J4. Using STM32CubeIDE V1.15. I compile it for both Debug & Release.

I program it via STM32Programmer V2.10.

The Debug elf file works okay, however, the Release elf does NOT run…

Yes! I have checked that the Debug & Release files are up to date (and time)...

Yes! The NRST pin is correct level…

What else should I check?

Kind regards
Pedro

This topic has been closed for replies.
PGump.1
PGump.1Best answer
Senior II
April 15, 2024

Hi all,

I'm happy to report that 'volatile' has fixed it! @Andrew Neil  thank you for planting that seed.

@MM..1  using Debug as Release is a waste of resources, particularly in parts with very limited resources.

Anyway, if I hadn't been so lazy, I would have coded it up in assembler, and saved myself a week... :face_with_tears_of_joy:

Kind regards
Pedro

AI = Artificial Intelligence, NI = No Intelligence, RI = Real Intelligence.

29 replies

Andrew Neil
Super User
April 11, 2024

Look at what's different between your Release and Debug versions

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
PGump.1
PGump.1Author
Senior II
April 11, 2024

Thank you for your reply.

There is no difference in the c code for the Release and Debug versions.

STM32CubeProgrammer reports Debug elf contains approx 2900 bytes, and 1050 bytes for the Release elf.

The only difference is the compiler options set by STM32CudeIDE.

Kind regards
Pedro

 

AI = Artificial Intelligence, NI = No Intelligence, RI = Real Intelligence.
Andrew Neil
Super User
April 11, 2024

@PGump.1 wrote:

There is no difference in the c code for the Release and Debug versions.


No conditional compilation; including things like ASSERT - which will behave differently between release & debug ?

 


@PGump.1 wrote:

The only difference is the compiler options set by STM32CudeIDE.


So what is/are the difference(s) there?

 

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
PGump.1
PGump.1Author
Senior II
April 11, 2024

PS: HAL functions are only called during initialization, as per STM32CubeMX code generator.

I'm not calling any HAL functions in my portion of the code.

Other than Systick(), there are no interrupts.

Watchdogs are not enabled (yet).

Kind regards
Pedro

AI = Artificial Intelligence, NI = No Intelligence, RI = Real Intelligence.
PGump.1
PGump.1Author
Senior II
April 12, 2024

I think 'volatile' is the key - I'm passing a boolean from Systick() to main() via a global variable. I can see how a compiler may think this is a static value...

The machine this fitted to is busy today. I'll try it Monday...

Kind regards
Pedro

AI = Artificial Intelligence, NI = No Intelligence, RI = Real Intelligence.
Andrew Neil
Super User
April 12, 2024

Another common one is race conditions in the code. And other marginal timing.

You might get away with these in the unoptimised (slower) Debug build, but they bite you in the optimised (faster) Release build.

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
PGump.1
PGump.1Author
Senior II
April 13, 2024

Thanks for the input. An interesting point given that Systick() and main() are asynchronous. However, I should point out that I'm using C (not C++), and the interconnection between the two functions is a boolean variable. If a compiler makes a boolean anything other than an atomic variable, particularly for an ARM processor, then it is a rubbish compiler...

Even if the compiler handled this boolean variable in a non-thread-safe manor, it can only be interpreted as True or False. Only a rubbish compiler could do something different...

Kind regards
Pedro

 

AI = Artificial Intelligence, NI = No Intelligence, RI = Real Intelligence.
PGump.1
PGump.1AuthorBest answer
Senior II
April 15, 2024

Hi all,

I'm happy to report that 'volatile' has fixed it! @Andrew Neil  thank you for planting that seed.

@MM..1  using Debug as Release is a waste of resources, particularly in parts with very limited resources.

Anyway, if I hadn't been so lazy, I would have coded it up in assembler, and saved myself a week... :face_with_tears_of_joy:

Kind regards
Pedro

AI = Artificial Intelligence, NI = No Intelligence, RI = Real Intelligence.
Andrew Neil
Super User
April 15, 2024

@PGump.1 wrote:

@MM..1  using Debug as Release is a waste of resources,


I think you missed that @MM..1 suggested using the same optimisation level - whether for "debgug" or "release"?

 

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
PGump.1
PGump.1Author
Senior II
April 16, 2024

Hi all,

My original code had the declaration of my boolean variable in main.c as :-

bool x = false;

and in stm32c0xx_it.c as

extern bool x;

Swapping the declarations around is another solution.

This is because c compilers don't retain/share meta-data on variables between individual c files. In my case, x doesn't get written to in main(), the compiler wouldn't know that the declaration of x is going to be exported so, it is quite understandable that it is assumed to be non-volatile in main.c.

Swapping the declarations around stops the compiler from making that incorrect assumption...

The moral of this story is - this was a very simple project that I took far too simplistic approach too...

I hope this helps someone.

Kind regards
Pedro

AI = Artificial Intelligence, NI = No Intelligence, RI = Real Intelligence.
Andrew Neil
Super User
April 16, 2024

@PGump.1 wrote:

My original code had the declaration of my boolean variable in main.c as :-

bool x = false;


That's the definition.

 


@PGump.1 wrote:

and in stm32c0xx_it.c as

extern bool x;


That's a declaration.

They need to be both qualified as 'volatile'.

 

Also, rather than manually transcribing the declaration into each source file that needs it, it would be better to have it in a header file; eg, in main.h:

extern volatile bool x;

Then both main.c and any/all other .c files which need it can #include "main.h"

Apart from the saving of duplication, this has the advantage that, when compiling main.c, the compiler will see both the declaration and the definition - thus will be able to detect any discrepancy.

See:

https://community.st.com/t5/stm32cubeide-mcus/adding-new-c-source-files-to-my-project-and-navigating-through/m-p/657455/highlight/true#M25847

And:

https://community.st.com/t5/stm32cubeide-mcus/adding-new-c-source-files-to-my-project-and-navigating-through/m-p/658310/highlight/true#M25925

 

 

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.