An embedded system is computer hardware with software embedded in it. Or we can say it is a combination of computer processors, computer memory, and input/output devices and it can be an independent system or a part of a large system.
Hi folks, we are back again with another interesting article which is actually a continuation of our previous part. In this article, we’ll gonna take a look at why our binary doesn’t have a valid Entry point address
and we’ll also try to flash the binary into our board (STM32F3DISCOVERY).
Alright!!! let’s start to update our knowledge pool by adding one more interesting row in it.
In our previous article, we were able to cross-compile our binary successfully however after validating it we got to know, the cross-compiled binary doesn’t contain a valid entry point address
. Now, the question arises why???
The reason behind this is we haven’t provided a memory layout of the target device via linker script that’s why the cross-compiled binary doesn’t have a valid entry point address
.
Let’s provide a memory layout
To provide a memory layout we need to add a linker script named memory.x
which specifies the memory available in the device. The content of memory.x
contains at least two MEMORY
regions FLASH
and RAM
. To be more precise the .text
and .rodata
sections of the program will be placed in the FLASH
region, whereas the .bss
and .data
sections, as well as the heap, will be placed in the RAM
region.
Now we got enough information about the linker script, now let’s provide it for our board which is SMT32F3Discvoery.
/* memory.x(file_name) */
/* Linker script for the STM32F303VCT6 */
MEMORY
{
/* 1 K = 1 KiBi = 1024 bytes */
FLASH : ORIGIN = 0x08000000, LENGTH = 256K
RAM : ORIGIN = 0x20000000, LENGTH = 40K
}
We have to place this linker script somewhere so that the linker can find it. So we’ll place this parallel to our source directory. Like this:
Now, our next step is to provide the configuration so that our program uses the correct linker script.
Configuration
We’ll be providing configuration via .cargo/config.toml
file.
# .cargo/config.toml
[target.thumbv7em-none-eabihf]
# use Tlink.c script from the cortex-m-rt crate
rustflags = [
"-C", "link-arg=-Tlink.x",
]
In the above file, we linked our program using cortex-m-rt
‘s linker script: link.x
with the help of rustflags
for a target thumbv7em-none-eabihf
.
Alright!! we have provided the target’s memory layout via linker script and linked it with the program as well, now we all set to re-compile the binary for our STM32Discovery board.
Let’s recompile it using:
cargo build --target thumbv7em-none-eabihf
Okay, the binary is successfully cross-compiled, now let’s check its header using cargo’s readobj
:
cargo readobj --target thumbv7em-none-eabihf --bin stm32 -- --file-header
Great!!! this time we got a valid value for entry point address
, it means this binary has a valid starting point.
So without any further delay, let’s flash this binary into the microcontroller(STM32F3Discvoery
).
Flash the binary
The term flashing means moving our program into the microcontroller’s memory. It means our binary will be the only program in the microcontroller’s memory, in other words, our binary will have full control over the broad.
To actually flash the binary, firstly we need to launch OpenOCD
(Open On-Chip Debugger), which is used to provide debugging, in-system programming, and boundary-scan testing for embedded target devices and provides some services like a GDB
server. Secondly, we need to execute the GDB
. Thirdly, and most importantly, loading the binary into the board.
Before proceeding further, let’s try to understand what will happen under the hood when we follow the above-mentioned steps.SMT32F3Discovery
(F3) board has two micro-controllers, ST-LINK
, and STM32F303
. ST-LINK
is used as a programmer/debugger and it is connected to STM32F303
(target micro-controller) using SWD
(Serial Wire Debug) interface which is used to debug and flash a micro-controller. And also connected with the USB ST-LINK
port so that it can act as a USB device.
Now, let’s take a look at the OpenOCD
command:
openocd -f interface/stlink-v2-1.cfg -f target/stm32f3x.cfg
Here, we are instructing OpenOCD
to look for an ST-LINK USB
device by specifying interface/stlink-v2-1.cfg
and expecting an STM32F3XX
microcontroller to be connected to the `ST-LINK` by this target/stm32f3x.cfg
.
Let’s fire the OpenOCD
in temp
directory after connecting F3 with the computer:
Launch OpenOCD
It indicates we have 6 breakpoints and 4 watchpoints available.
Now our next step is to execute the GDB server:
Execute GDB service
gdb-multiarch -q -ex "target remote :3333" target/thumbv7em-none-eabihf/debug/smt32
gdb-multiarch -q
is the version of the GDB server, we can select any version that works for us. After the version, we specified the target location (target remote :3333) as the GDB
server listens on TCP port 3333, and at last, we just provided the path to the cross-compiled binary.
Let’s fire this command:
These instruction shows that we have successfully executed our GDB server. And if we look at the OpenOCD console we got something like this:
Alright!! now it’s time to actually load our binary into the Microcontroller.
Load the binary
To load binary we just need to trigger a load
command in GDB
console, like this:
This shows our binary is loaded and logs are reflected in the OpenOCD
console as well:
This confirms that the binary is successfully loaded into the microcontroller(STM32F3Discovery).
That’s all about this article, in the next article we’ll try to play with some components of the STM32F3Discovery
board.
Thanks for reading!!!
References:
If you want to read more content like this? Subscribe Rust Times Newsletter and receive insights and latest updates, bi-weekly, straight into your inbox. Subscribe Rust Times Newsletter: https://bit.ly/2Vdlld7 .


2 thoughts on “Embedded-Rust: Build & Flash binary to STM32F3DISCOVERY7 min read”
Comments are closed.