Skip to main content
Rick1
Associate II
November 9, 2020
Question

STM32CubeIDE: How to program everything from scratch without automatic code?

  • November 9, 2020
  • 3 replies
  • 2743 views

I'm starting to program STM32 cortex M0 uC, and I want to do it totally from scratch, without any code automatically generated for me, using STM32CubeIDE 1.4.0.

In my code, I've erased everything and letf only this:

int main(void)
{
 while (1)
 {
 }
}

But when I open the file "***.LIST" I can see a lot of code generated, including the interrupt handlers and other stuff.

How can I stop it from writting background code for me and let everything manually made for me?

Thanks

This topic has been closed for replies.

3 replies

Paul1
Senior III
November 9, 2020

Don't use STM32CubeMX to create project.

You will have to in your own code init everything, but that seems to be what you want (I don't have time to go that route anymore).

Slightly simpler is to use MX to create project, but don't enable any pins or features (No GPIO, No UART, No Clocks, etc.)

If I was in your boots I would:

  • Create a minimal project with MX and IDE. Keep this generated code as a reference when writing your own code.
  • Create a new project IDE>New>Pick a method without MX. Write your own code from main().
  • Depending on where you start you could hand write the code for all the vectors and exceptions (Reset jump to main...), though probably best to keep at least that much as it also does things like set your initialized variable values (zero most, or pre-load values to set in declarations).
  • See [startup_stm32xxxxxxxx.s], you can pretty well take over everything if you replace that with your own.

Paul

Rick1
Rick1Author
Associate II
November 9, 2020

Thanks for replying.

I took a look at [startup_stm32xxxxxxxx.s] but I must be missing something cuz I didn't get what I should delete or change to stop de initial code from compiling. I've tried do delete it all but some erros occurs when compilling.

Andrei Chichak
Lead
November 9, 2020

If you're going to mess with the startup_xxxx.s code (you're asking for a heap of hurt, but your choice), I'd suggest putting away the C compiler and going to raw assembly.

You're giving up the interrupt structure, memory testing, memory initialization, copying from flash to ram, setting up the stacks, setting up the heap, arranging the environment so that you can even branch to main and so that main can call subroutines and get back.

You've got a F1 car and you're wondering why it has brake pads and a crash structure since you're not planning on going slow or crashing. Okay. I suggest you start at the beginning, but if you insist you should look up the ARM programming reference and architecture manual for your processor. Learn about the memory layout, boot sequence, stacks, heap, ABI, registers, and fault handlers. But be cautious, the ARM family was designed to support compilers, you can code by hand in assembly, but it's working against the design.

Paul1
Senior III
November 9, 2020

I recommend not messing with the .s file, but instead studying it so you know what it does, most of it is critical required code I never touch.

Have you done a minimal project either:

  • MX with no pins and no modules enables, or
  • IDE new C project without MX

Don't be surprised if it takes hours/days of referring to Datasheet and Reference Manual for your IC to understand what's in the init code.

Much easier to leave it and just insert in generated main() a call to main2() which you write in a separate file (main2 should replace everything done main()).

Paul

Paul1
Senior III
November 9, 2020

OK, I understand wanting to know the details (and actually started that way, but found with 32bit you just have to think&work at a higher level as so much code and such complex ICs).

Look at the .s file under startup, but just to see the minimal functionality that is happening.

  • defines a few addresses that tell CPU where things are (variable init block in ROM, variable data space RAM, etc.)
  • Reset handler for lowest level actions at reset:
    • Set stack pointer
    • copy init block to variables, and to zero other variables.
    • library init
    • jump main()
    • endless loop if unexpectedly return from main(), consider a WDT to recover from this.
  • Vectors for code to handle exceptions, interrupts, and the like
  • Weak definitions that may be overridden by optional user code, weak definitions typically for unused interrupts and such.

Then look at main.c

  • main() will be simple or complex depending on what you enabled in STM32CubeMX, suggest starting with minimal enabled.
    • personally I insert a jump to main2() in main() as I've found messing with main() in generated files can result in lost code if you regenerate.
    • main() calls appropriate init code (HAL, Clock, modules enabled)
    • You can insert your init code here
    • main() then does endless loop, this is where you insert your run code (often a state machine or OS)

There's not much to it, unless you've enabled a bunch modules.

Paul