Author Topic: Is ST Cube IDE a piece of buggy crap?  (Read 165194 times)

0 Members and 4 Guests are viewing this topic.

Offline eutectique

  • Frequent Contributor
  • **
  • Posts: 392
  • Country: be
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #1050 on: March 22, 2024, 04:03:13 pm »
Something like

Code: [Select]
static void funcA(void) { ... }
static void funcB(void) { ... }
static void funcC(void) { ... }

__attribute__((used,section(".preinit_array"))) static void (*blah[])(void) = {
    funcA,
    funcB,
    funcC
};
 
The following users thanked this post: peter-h

Offline wek

  • Frequent Contributor
  • **
  • Posts: 495
  • Country: sk
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #1051 on: March 25, 2024, 09:02:30 am »
... even though 80% of the internet says it is C++ only :)

Sounds like a Pavlov's dog reaction: "constructor" --> "C++"

Can you please point to a good source thoroughly documenting what "constructor" might mean?

JW Pavlov's dog
 

Offline eutectique

  • Frequent Contributor
  • **
  • Posts: 392
  • Country: be
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #1052 on: March 25, 2024, 02:40:03 pm »
Can you please point to a good source thoroughly documenting what "constructor" might mean?

For explanation of "constructor" in context of C programming language and corresponding compilers, you might have a look at ARM documentation or GNU documentation. Good enough source for me, but YMMV.

For broad sense of "constructor", there is Cambridge Dictionary. The page comes with multiple useful examples.
 

Offline wek

  • Frequent Contributor
  • **
  • Posts: 495
  • Country: sk
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #1053 on: March 25, 2024, 03:19:43 pm »
Can you please point to a good source thoroughly documenting what "constructor" might mean?
For explanation of "constructor" in context of C programming language and corresponding compilers, you might have a look at ARM documentation or GNU documentation. Good enough source for me, but YMMV.
Okay, so, would you agree, that in C, "constructor" means "function in user code, which has the 'constructor' attribute (which in turn implies it will be run before main())"?

This would then be different from "constuctor" in C++, which means "code added automatically by the compiler, which in case of static constructiors will be run before main()". The difference is, that it's *compiler generated* rather than written by user (read, user has less control on the former than on the latter).

Or, I might've rephrased the question, is there any code output by compiler for C which will be run before main()? And, if yes, is there a comprehensive documentation for individual compilers (and I am particularly interested in gcc) of these codes, and under which conditions are they generated?

Thanks,

JW
 

Offline tru

  • Regular Contributor
  • *
  • Posts: 107
  • Country: gb
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #1054 on: March 25, 2024, 04:02:52 pm »
For those who are curious, here is an example of the compiler automatically adding to the .init_array list:

By adding some C++ files to my STM32 led_blink project, the .init_array section is now 8 bytes - an extra pointer was added automatically for the global class object instance (with default constructor):
Code: [Select]
static led_state_class ls0;

Demonstration C++ and C wrapper files:

Minimal class class_test.h:
Code: [Select]
#ifndef INC_CLASS_TEST_H_
#define INC_CLASS_TEST_H_

#include <stdbool.h>

class led_state_class{
public:
bool is_enabled;

led_state_class(){
is_enabled = false;
}
};

#endif

class_test_wrapper.h
Code: [Select]
#ifndef INC_CLASS_TEST_C_H_
#define INC_CLASS_TEST_C_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <stdbool.h>

bool get_enabled(void);
void set_enabled(bool is_enabled);

#ifdef __cplusplus
}
#endif

#endif

class_wrapper.cpp
Code: [Select]
#include "class_test_wrapper.h"
#include "class_test.h"

#ifdef __cplusplus
extern "C" {
#endif

static led_state_class ls0;

bool get_enabled(void){
return ls0.is_enabled;
}

void set_enabled(bool is_enabled){
ls0.is_enabled = is_enabled;
}

#ifdef __cplusplus
}
#endif
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3700
  • Country: gb
  • Doing electronics since the 1960s...
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #1055 on: March 25, 2024, 04:27:03 pm »
Quote
is there any code output by compiler for C which will be run before main()

We may be talking cross-wires since you obviously know this, but AFAICT with GCC there is none other than what it does for any other C function.

The name "main()" has a special meaning to Cube IDE (and maybe to other IDEs) only in that there is a feature to auto-insert a breakpoint on the main() source line. Actually this feature has been moved and I can no longer find it, and it may have been removed because I no longer get that breakpoint. I am not aware that the compiler cares about the function main() other than insisting that it is type int and is a void, though that may be because there is a prototype for it (but I cannot find one).

The code execution starts at the 2nd word in the vector table and that starts execution at whatever code happens to be at that address (the linkfile.ld controls that). That code then eventually calls main().

I have just stepped through some code and at the start of main() I see this (the memcpy line is just further code; not relevant)



I think it is just setting up a stack frame for variables, but there aren't any.

So the answer to the Q above seems to be NO.

Mysteriously, the disassembly listing no longer works (Cube 1.14.1); maybe Cube has got confused



It shows it as the bottom if I Open New View. Fixed, by deleting the empty Disassembly window and dragging the working one from the bottom to the top right. Oh well...
« Last Edit: March 25, 2024, 04:44:55 pm by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline eutectique

  • Frequent Contributor
  • **
  • Posts: 392
  • Country: be
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #1056 on: March 25, 2024, 05:42:57 pm »
Okay, so, would you agree, that in C, "constructor" means "function in user code, which has the 'constructor' attribute (which in turn implies it will be run before main())"?

If the expression "in C" means "in some implementations of C language standard by some compilers", then yes, I would agree.



This would then be different from "constuctor" in C++, which means "code added automatically by the compiler, which in case of static constructors will be run before main()". The difference is, that it's *compiler generated* rather than written by user (read, user has less control on the former than on the latter).

My rather limited knowledge of C++ tells me that C++ constructors are hand-written by a live person. Consider the following piece of code:
Code: [Select]
class Schwartz {
    public:
        // This is constructor
        Schwartz() {
            cout << "WHOA! Liquid Schwartz!!";
        }
};

int main() {
    Schwartz theSchwartz; // Calling the constructor
    return 0;
}

In C++, the developer has the complete control over when and what constructor is called (there could be constructors with parameters for the same class).

In C, the constructors are called in undefined order, if special means are not taken by a developer. As documented, they are called before main(), period.


Or, I might've rephrased the question, is there any code output by compiler for C which will be run before main()?

I am not a compiler engineer, but to the best of my knowledge, and from my experience, no code before main() is generated by C compiler. Instead, the start-up code is hand-written by a person -- an end-user of the chip/compiler or the chip vendors' engineers. The start-up code even calls main(), otherwise it will never be executed. We are talking now about narrow niche of MCUs and armcc/gcc/llvm compilers which generate flashable code.


And, if yes, is there a comprehensive documentation for individual compilers (and I am particularly interested in gcc) of these codes, and under which conditions are they generated?

Sure!

Embedded Artistry:
Exploring Startup Implementations: Newlib (ARM)

Memfault:
From Zero to main(): Bare metal C
From Zero to main(): Bootstrapping libc with Newlib
From Zero to main(): Demystifying Firmware Linker Scripts

Tellurium (a member here):
A bare metal programming guide
 
The following users thanked this post: wek

Online radiolistener

  • Super Contributor
  • ***
  • Posts: 3385
  • Country: ua
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #1057 on: March 25, 2024, 06:25:28 pm »
In C++, the developer has the complete control over when and what constructor is called (there could be constructors with parameters for the same class).

Here is the code where sequence of constructor calling is undefined, the compiler can call it A, B, C or B, A, C it depends on compiler:
Code: [Select]
#include <iostream>

class A {
public:
    A() { std::cout << "A()\n"; }
};

class B {
public:
    B() { std::cout << "B()\n"; }
};

class C : public A, public B {
public:
    C() { std::cout << "C()\n"; }
};

int main() {
    C c;
    return 0;
}

Another example:
Code: [Select]
#include <iostream>

class A {
public:
    A() { std::cout << "A()\n"; }
};

class B {
public:
    B() { std::cout << "B()\n"; }
};

class C : public A, public B {
public:
    C(int x) : B(), A() { std::cout << "C()\n"; }
};

int main() {
    C c(0);
    return 0;
}

Here we declaring that constructor C should call B and A, but the sequence of calling is undefined and depends on compiler.

This is one of examples why multiple inheritance is not good...  :)
« Last Edit: March 25, 2024, 06:31:30 pm by radiolistener »
 
The following users thanked this post: eutectique

Online gf

  • Super Contributor
  • ***
  • Posts: 1183
  • Country: de
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #1058 on: March 25, 2024, 08:10:49 pm »
In C++, the developer has the complete control over when and what constructor is called (there could be constructors with parameters for the same class).

Here is the code where sequence of constructor calling is undefined, the compiler can call it A, B, C or B, A, C it depends on compiler:
...

The order is defined, see here: https://en.cppreference.com/w/cpp/language/constructor

Quote from: https://en.cppreference.com/w/cpp/language/constructor
direct bases are initialized in left-to-right order as they appear in this class's base-specifier list
 
The following users thanked this post: eutectique

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3700
  • Country: gb
  • Doing electronics since the 1960s...
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #1059 on: March 25, 2024, 11:56:22 pm »
Having bits of code called in an order which is compiler version dependent, with only "before main()" being assured, is really dangerous, and difficult to debug.
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Online dietert1

  • Super Contributor
  • ***
  • Posts: 2073
  • Country: br
    • CADT Homepage
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #1060 on: March 26, 2024, 07:49:40 am »
Having bits of code called in an order which is compiler version dependent, with only "before main()" being assured, is really dangerous, and difficult to debug.
And yet it happens all the time, e.g. to initialize static variables in C. Those without explicit assignment are initialized to zero. Or it can put a data pattern to later detect stack usage/errors. You can work without using all that if you prefer so. There are compiler switches.

Regards, Dieter
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4199
  • Country: us
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #1061 on: March 27, 2024, 08:50:26 am »

 
Quote
is there any code output by compiler for C which will be run before main()?

In avr-gcc, this is done by putting code in “.initN” sections, where values of N are well defined to happen at various points of the code initialization.
https://www.nongnu.org/avr-libc/user-manual/mem_sections.html


Some sort of provision for pre-main code seems important for embedded development (say to set up a non-standard stack), but having multiple different implementations is confusing.
« Last Edit: March 27, 2024, 08:52:43 am by westfw »
 
The following users thanked this post: wek

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3700
  • Country: gb
  • Doing electronics since the 1960s...
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #1062 on: March 27, 2024, 12:53:01 pm »
Quote
Some sort of provision for pre-main code seems important for embedded development

In theory yes but with ARM GCC it only sets up a stack frame, which you can chuck away immediately with 1 line of asm

int main(void)
{
     asm volatile ("ldr sp, = 0x20000000 \n");

     etc
}
« Last Edit: March 27, 2024, 01:32:11 pm by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline wek

  • Frequent Contributor
  • **
  • Posts: 495
  • Country: sk
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #1063 on: March 27, 2024, 01:58:15 pm »
Quote from: me
is there any code output by compiler for C which will be run before main()?
In avr-gcc, this is done by putting code in “.initN” sections, where values of N are well defined to happen at various points of the code initialization.
https://www.nongnu.org/avr-libc/user-manual/mem_sections.html
Yes, but that does not imply that it's the *C compiler* which inserts code there.

Quote from: westfw
having multiple different implementations is confusing.
I continue to agree ;-)

JW
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4199
  • Country: us
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #1064 on: March 28, 2024, 09:39:16 am »
Quote
with ARM GCC it [pre-main code]  only sets up a stack frame
Really?  What about, zeroing bss and copying initialized data from flash to ram?
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3700
  • Country: gb
  • Doing electronics since the 1960s...
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #1065 on: March 28, 2024, 12:03:58 pm »
The compiler does not do that. The code which main() { } generates is just as I showed - the stack frame for main().

Zeroing BSS, copying ROM init data to RAM, you have to do somewhere else before reaching main() - in ARM GCC anyway.

Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline paulca

  • Super Contributor
  • ***
  • Posts: 4055
  • Country: gb
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #1066 on: March 28, 2024, 05:36:38 pm »
Isn't all that covered in startup.s in STM32?
"What could possibly go wrong?"
Current Open Projects:  STM32F411RE+ESP32+TFT for home IoT (NoT) projects.  Child's advent xmas countdown toy.  Digital audio routing board.
 

Offline paulca

  • Super Contributor
  • ***
  • Posts: 4055
  • Country: gb
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #1067 on: March 28, 2024, 05:39:14 pm »
... and does the "elf" executable format not get used on STM32?

So if you are looking for how to setup the memory maps and all the rest it would be in the ELF part of the build, which I believe is the linker?

ELF's just is to load the application and provide what is needed to call main... and take the return code (don't test this, it goes badly wrong on STM32 and their docs says as much).
"What could possibly go wrong?"
Current Open Projects:  STM32F411RE+ESP32+TFT for home IoT (NoT) projects.  Child's advent xmas countdown toy.  Digital audio routing board.
 

Offline eutectique

  • Frequent Contributor
  • **
  • Posts: 392
  • Country: be
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #1068 on: March 28, 2024, 05:52:10 pm »
... and does the "elf" executable format not get used on STM32?

If you mean that an ELF file is flashed to bare-metal STM32 (or NXP S32K, or Ambiq Apollo), then no. Even if it contains FreeRTOS, or NuttX, or Zephyr -- no.


So if you are looking for how to setup the memory maps and all the rest it would be in the ELF part of the build, which I believe is the linker?

Kind of correct, but an ELF file is produces based on linker script. That is the source and description of memory maps.


ELF's just is to load the application and provide what is needed to call main... and take the return code (don't test this, it goes badly wrong on STM32 and their docs says as much).

ELF is used during the build as an intermediate format to generate binary and hex files. And these will be be loaded onto the MCU.
 
The following users thanked this post: paulca

Offline Tation

  • Contributor
  • Posts: 38
  • Country: pt
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #1069 on: March 28, 2024, 05:56:24 pm »
In C++, the developer has the complete control over when and what constructor is called (there could be constructors with parameters for the same class).

Here is the code where sequence of constructor calling is undefined, the compiler can call it A, B, C or B, A, C it depends on compiler:
...

The order is defined, see here: https://en.cppreference.com/w/cpp/language/constructor

Quote from: https://en.cppreference.com/w/cpp/language/constructor
direct bases are initialized in left-to-right order as they appear in this class's base-specifier list

In both gcc and clang __attribute__((constructor(<priority>))) can be used to, explicitly, specify the execution order of static constructors. Not exactly elegant, but working.
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3700
  • Country: gb
  • Doing electronics since the 1960s...
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #1070 on: March 28, 2024, 07:22:52 pm »
Quote
Isn't all that covered in startup.s in STM32?

Yes.

Quote
and does the "elf" executable format not get used on STM32?

AFAIK the ELF is used only to load up the STLINK debugger, which writes the FLASH.

But if you want a binary for some reason, say to distribute firmware updates:

rem generate x.dat
arm-none-eabi-objcopy -S --strip-all -R .bss -R .main_heap -R .ccmram -O binary x.elf x.bin

Probably this is used internally to load the debugger?

Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 
The following users thanked this post: paulca

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3700
  • Country: gb
  • Doing electronics since the 1960s...
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #1071 on: April 09, 2024, 01:47:37 pm »
Does this Cube IDE feature literally allow the installation of different versions of GCC, without weird side effects?

When you open this form, it just shows the current version (11.3) and then it says "fetching index..." and it fills in all the others visible here



I struggle to see how this "just works" given that different versions have different default command line options, etc.

« Last Edit: April 09, 2024, 02:09:51 pm by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline ace1903

  • Regular Contributor
  • *
  • Posts: 237
  • Country: mk
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #1072 on: April 09, 2024, 08:52:49 pm »
Idea behind more version of tools in toolchain manager is to be able to use newest IDE with older projects.
When I need to check something on old project now I can use configuration(IDE version) that I have currently on the PC.
Think ST was motivated by people like me that were pissed when IDE auto updated and code that was compiling with older GCC fine with newer version refused to compile.
Newest GNU tools are always the best, but sometimes I just need to make debug session on old code without modifying it.
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3700
  • Country: gb
  • Doing electronics since the 1960s...
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #1073 on: April 09, 2024, 09:51:46 pm »
Quote
Newest GNU tools are always the best

That's quite a philosophical debate actually :) What is the "best" when you have a solid product which is selling, and you recompile it with GCC v n+1 and it no longer runs. You may have to spend loads of time on a) finding out why and b) regression testing a potentially large project. It is extremely poor business risk management! The correct way is to freeze the tools version some considerable time before the product is released.

It reminds me of the old debates back when I used to do FPGA design consultancy in the late 1990s - Xilinx. You were of course supposed to design the whole project fully synchronously, so you have just a single clock net (or multiple clock nets doing different bits) and control the clock routing by gating it. That way, in theory, when Xilinx changed the silicon without telling anybody and made it 5x faster, the thing "should still work". There were many problems with that e.g. a) the power consumption was maximised because basically the whole die was going up and down at the clock speed b) if you were doing ASIC prototyping you were often targeting power consumption which is incompatible with a), c) the same "good business risk management" approach as with the STM32 above.

A purist will argue puritanically because that is what a purist does, but the purist is most likely paid by the hour and doesn't care if something breaks, because fixing stuff puts bread on the table at home :)

I froze my project at Cube 1.14.1 / GCC 11.3.

But my Q stands: does this really work? What I mean is e.g. in Cube IDE you specify compiler options (indirectly by checkboxes which indirectly select the libc.a version which uses the specified newlib with hardware floats, etc) but in this tools version selector which can select a GCC version which does not 1:1 map with that. Or does GCC always 1:1 map with the compiler and linker (library / printf type) switches? Not sure I am making sense.
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline paulca

  • Super Contributor
  • ***
  • Posts: 4055
  • Country: gb
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #1074 on: April 10, 2024, 09:10:53 am »
That's quite a philosophical debate actually :) What is the "best" when you have a solid product which is selling, and you recompile it with GCC v n+1 and it no longer runs. You may have to spend loads of time on a) finding out why and b) regression testing a potentially large project. It is extremely poor business risk management! The correct way is to freeze the tools version some considerable time before the product is released.

In depends on what you are developing.  In my world...  Tool chains have security vulnerabilities. It is not uncommon for the toolchain (and build infrastructure) to be shared between many projects and they are usually upgraded, with warning, when vulnerabilities are raised.  If a particular project runs into issues with the new toolchain, there is usually a way to manually configure an "exceptional" toolchain config.  This will however give the project an "Out of compliance" flag which is summarised to management weekly.  You can't stay out of compliance without higher and higher up approvals as time goes on.

Even AFTER release when a vulnerability is discovered in either the app code or the toolchain/libraries a new release is created within 2 weeks (or more out of compliance).

Now lets say that you "own" project A.  Project A, it's tool chain and it's libraries are squeaky clean.  However, you depend on Project B's service.  Project B has red flags and needs to do a release.  You need to test your project against their new release (or they do!).  You can then encounter "breaking changes" and start into negotiations, but usually end up fixing it on yourside if they have a more upto date release.

I mean, not all software has an active and frequent release cycle.  Not all software or toolchain output is affected by security vuls.

I have a Casio calculator that has the same firmware it had back in 1994.  It still works.  I have not checked Casio's errata on it, but I would imagine there have been bugs found, but due to the vintage, there is no way to fix them, other than returning them to the factor to replace the blob IC.

A lot of embedded projects have so little external influences they have a tiny security surface area to consider.  So old stale releases with bugs are fine.

We talked about this before.  A large part of embedded software is now working on the modern "agile, constant release" project cadence.  This is what causes all those pesky "Update Available" for firmware in modern 'IoT' eco-systems.  Hell even if you use an Arduino and depend on a board file and a lib, they get updated frequently too!

The "Maintenance" phase of the software life cycle is not one you can simply ignore.  Depending on how long a life the software has the "Maintenance" and "Support" phase is usually the most expensive bit.

EDIT:  Also, in my world, we have quite a lot of processes, techniques, tools and prior work to lean on when it comes to testing.  Most projects slowly grow in automation.  In the first instance of an upgrade in shared dependencies or toolchians, the pipeline will automatically build, run the unit tests, check the code for smells and even in some setups run the full end2end integration tests automatically and produce a report.  If all that comes back green, then the only thing you need is a pre-prod sanity check when it's deployed, to sign it off for PROD.
« Last Edit: April 10, 2024, 09:15:12 am by paulca »
"What could possibly go wrong?"
Current Open Projects:  STM32F411RE+ESP32+TFT for home IoT (NoT) projects.  Child's advent xmas countdown toy.  Digital audio routing board.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf