Essentially there are 3 levels of board initialization:
Called immediately on boot up to set what resources are needed to boot this system. This includes a little bit of low level driver initialization if needed by up_initialize().
The OS is not yet initialized the nothing in stm32_board_initialize() can use ANY OS service. Nothing.
2. board_initialize() – (optional)
Called just before the application is started.
Here the OS is fully initialized, but you have to be careful because it is still running on the IDLE thread. That means that there are many things that you cannot do: You cannot wait for anything. You can’t use semaphores for example.
(There is CONFIG_BOARD_INITTHREAD that can be used to run board_intialize() on a separate thread if necessary).
board_initialize() is really only needed by code built with CONFIG_BUILD_KERNEL or CONFIG_BUILD_PROTECTED.
3. board_apps_initialize() via boardctrl()
Called after the application has started. This runs on the thread of the applications so it is always the best when available.
Note: This explanation is from an email from Greg Nutt, I decided to post it here to help other people to decide where to put their code.