How can I install and configure TinyCC, then invoke the compiler and the linker to produce the .bin
file that I can flash into my STM32 demo board? Please include specific steps. I am on Ubuntu 19.10 x86_64.

- 32,014
- 33
- 141
- 226
-
Any reason why you would not use a more standard/supported set of tools, such as [gcc-arm-none-eabi](https://developer.arm.com/-/media/Files/downloads/gnu-rm/9-2019q4/gcc-arm-none-eabi-9-2019-q4-major-x86_64-linux.tar.bz2?revision=108bd959-44bd-4619-9c19-26187abf5225&la=en&hash=E788CE92E5DFD64B2A8C246BBA91A249CB8E2D2D) ? – Frant Mar 07 '20 at 19:21
-
1probably educational purpose. I was using TCC for boot time kernel compilation :). Totally useless but good fun – 0___________ Mar 07 '20 at 22:26
-
@P__J__ If the goal is to tackle a challenging task, I can understand. However, requesting 'specific steps' does not fill well in this picture. – Frant Mar 08 '20 at 00:29
-
@exebook: What is exactly the demo board you are targeting ? – Frant Mar 08 '20 at 04:08
-
@Frant Bluepill – exebook Mar 09 '20 at 19:02
-
@Frant of course to learn and have fun. I love TinyC, it's small and fast and does a great job. What I cannot understand is how to make it cross compile to ARM from Linux x86_64. Then this .bin format is a mistery for me, to that's also to learn in the process. – exebook Mar 09 '20 at 19:05
1 Answers
TinyCC
was originally designed for building executable files in ELF format containing user-mode programs for Linux.It does support Cortex-A profile, but chances you can use it as is for cross-compiling for a Cortex-M STM32F103 are non-existent IMHO.
Here is what I would suggest:
- Keep TinyCC on the side for the time being, while you are learning about the STM32F103 using your Blue Pill board.
- Use the GCC toolchain referenced hereafter for explaining how the .bin can be produced. Once you will feel comfortable with GCC and the STM32F103, you can go back to experimenting with TinyCC.
How to a create a.bin
file from a C program for the STM32F103, and how it does relate to the corresponding ELF file:
- install git on your Ubuntu 19.10:
apt-get install git
- create/choose a working directory:
mkdir bluepill
- change your current working directory to bluepill:
cd bluepill
- clone a nice, small example program available on
github
:
git clone https://github.com/satoshinm/pill_blink.git
- Download/extract the GCC 9.2.1 toolchain for Cortex-M provided by arm:
wget "https://developer.arm.com/-/media/Files/downloads/gnu-rm/9-2019q4/gcc-arm-none-eabi-9-2019-q4-major-x86_64-linux.tar.bz2?revision=108bd959-44bd-4619-9c19-26187abf5225&la=en&hash=E788CE92E5DFD64B2A8C246BBA91A249CB8E2D2D" -O gcc-arm-none-eabi-9-2019-q4-major-x86_64-linux.tar.bz2
tar Jxf gcc-arm-none-eabi-9-2019-q4-major-x86_64-linux.tar.bz2
- add the toolchain bin directory to your current path:
export PATH=$(pwd)/gcc-arm-none-eabi-9-2019-q4-major/bin:$PATH
- verify gcc can be executed:
arm-none-eabi-gcc --version
You should see:
arm-none-eabi-gcc (GNU Tools for Arm Embedded Processors 9-2019-q4-major) 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599]
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
You can now build the example contained in the pill_blink/bare-metal
directory:
make -C pill_blink/bare-metal all
You should have built an executable in ELF format, and a .bin containing only the code and the data that was built from the ELF file using arm-none-eabi-objcopy
should now be available - please refer to pill_blink/bare-metal/Makefile
for the exact command:
ls -gG pill_blink/bare-metal
total 72
-rw-rw-r-- 1 255 Mar 11 14:35 bluepill.ld
-rw-rw-r-- 1 483 Mar 11 14:35 Makefile
-rwxrwxr-x 1 440 Mar 11 14:36 pill_blink.bin
-rw-rw-r-- 1 1059 Mar 11 14:35 pill_blink.c
-rw-rw-r-- 1 27 Mar 11 14:36 pill_blink.d
-rwxrwxr-x 1 82452 Mar 11 14:36 pill_blink.elf
-rw-rw-r-- 1 21528 Mar 11 14:36 pill_blink.o
-rw-rw-r-- 1 326 Mar 11 14:35 README.md
The ELF file does contain the compiled C program, along with a lot of metadata, as explained in the ELF article referenced above. You can use arm-none-objdump
for exploring the .ELF file:
arm-none-eabi-objdump -x pill_blink/bare-metal/pill_blink.elf
pill_blink/bare-metal/pill_blink.elf: file format elf32-littlearm
pill_blink/bare-metal/pill_blink.elf
architecture: armv7, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x08000151
Program Header:
LOAD off 0x00010000 vaddr 0x08000000 paddr 0x08000000 align 2**16
filesz 0x000001b8 memsz 0x000001b8 flags r-x
private flags = 5000200: [Version5 EABI] [soft-float ABI]
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 000001b8 08000000 08000000 00010000 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .debug_info 0000017f 00000000 00000000 000101b8 2**0
CONTENTS, READONLY, DEBUGGING
2 .debug_abbrev 000000d4 00000000 00000000 00010337 2**0
CONTENTS, READONLY, DEBUGGING
3 .debug_aranges 00000020 00000000 00000000 0001040b 2**0
CONTENTS, READONLY, DEBUGGING
4 .debug_macro 00000a9b 00000000 00000000 0001042b 2**0
CONTENTS, READONLY, DEBUGGING
5 .debug_line 00000086 00000000 00000000 00010ec6 2**0
CONTENTS, READONLY, DEBUGGING
6 .debug_str 00002dfb 00000000 00000000 00010f4c 2**0
CONTENTS, READONLY, DEBUGGING
7 .comment 00000079 00000000 00000000 00013d47 2**0
CONTENTS, READONLY
8 .ARM.attributes 0000002d 00000000 00000000 00013dc0 2**0
CONTENTS, READONLY
9 .debug_frame 00000020 00000000 00000000 00013df0 2**2
CONTENTS, READONLY, DEBUGGING
SYMBOL TABLE:
08000000 l d .text 00000000 .text
00000000 l d .debug_info 00000000 .debug_info
00000000 l d .debug_abbrev 00000000 .debug_abbrev
00000000 l d .debug_aranges 00000000 .debug_aranges
00000000 l d .debug_macro 00000000 .debug_macro
00000000 l d .debug_line 00000000 .debug_line
00000000 l d .debug_str 00000000 .debug_str
00000000 l d .comment 00000000 .comment
00000000 l d .ARM.attributes 00000000 .ARM.attributes
00000000 l d .debug_frame 00000000 .debug_frame
00000000 l df *ABS* 00000000 pill_blink.c
08000150 w F .text 00000068 reset_handler
08000000 g O .text 00000150 vector_table
arm-none-eabi-objdump -d pill_blink/bare-metal/pill_blink.elf
pill_blink/bare-metal/pill_blink.elf: file format elf32-littlearm
Disassembly of section .text:
08000000 <vector_table>:
8000000: 00 00 00 00 51 01 00 08 00 00 00 00 00 00 00 00 ....Q...........
...
08000150 <reset_handler>:
8000150: 4b13 ldr r3, [pc, #76] ; (80001a0 <reset_handler+0x50>)
8000152: 681b ldr r3, [r3, #0]
8000154: 4a12 ldr r2, [pc, #72] ; (80001a0 <reset_handler+0x50>)
8000156: f043 0310 orr.w r3, r3, #16
800015a: 6013 str r3, [r2, #0]
800015c: 4b11 ldr r3, [pc, #68] ; (80001a4 <reset_handler+0x54>)
800015e: 4a11 ldr r2, [pc, #68] ; (80001a4 <reset_handler+0x54>)
8000160: 681b ldr r3, [r3, #0]
8000162: 6013 str r3, [r2, #0]
8000164: 4b0f ldr r3, [pc, #60] ; (80001a4 <reset_handler+0x54>)
8000166: 681b ldr r3, [r3, #0]
8000168: 4a0e ldr r2, [pc, #56] ; (80001a4 <reset_handler+0x54>)
800016a: f443 1300 orr.w r3, r3, #2097152 ; 0x200000
800016e: 6013 str r3, [r2, #0]
8000170: 4b0d ldr r3, [pc, #52] ; (80001a8 <reset_handler+0x58>)
8000172: f44f 5200 mov.w r2, #8192 ; 0x2000
8000176: 601a str r2, [r3, #0]
8000178: 2400 movs r4, #0
800017a: e001 b.n 8000180 <reset_handler+0x30>
800017c: bf00 nop
800017e: 3401 adds r4, #1
8000180: 4b0a ldr r3, [pc, #40] ; (80001ac <reset_handler+0x5c>)
8000182: 429c cmp r4, r3
8000184: ddfa ble.n 800017c <reset_handler+0x2c>
8000186: 4b0a ldr r3, [pc, #40] ; (80001b0 <reset_handler+0x60>)
8000188: f44f 5200 mov.w r2, #8192 ; 0x2000
800018c: 801a strh r2, [r3, #0]
800018e: 2400 movs r4, #0
8000190: e001 b.n 8000196 <reset_handler+0x46>
8000192: bf00 nop
8000194: 3401 adds r4, #1
8000196: 4b07 ldr r3, [pc, #28] ; (80001b4 <reset_handler+0x64>)
8000198: 429c cmp r4, r3
800019a: ddfa ble.n 8000192 <reset_handler+0x42>
800019c: e7e8 b.n 8000170 <reset_handler+0x20>
../..
Now, using, say, hexdump
, for displaying the content of the .bin file, you will be able to correlate this content with the content of the ELF file:
hexdump -C pill_blink/bare-metal/pill_blink.bin
00000000 00 00 00 00 51 01 00 08 00 00 00 00 00 00 00 00 |....Q...........|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000150 13 4b 1b 68 12 4a 43 f0 10 03 13 60 11 4b 11 4a |.K.h.JC....`.K.J|
00000160 1b 68 13 60 0f 4b 1b 68 0e 4a 43 f4 00 13 13 60 |.h.`.K.h.JC....`|
00000170 0d 4b 4f f4 00 52 1a 60 00 24 01 e0 00 bf 01 34 |.KO..R.`.$.....4|
00000180 0a 4b 9c 42 fa dd 0a 4b 4f f4 00 52 1a 80 00 24 |.K.B...KO..R...$|
00000190 01 e0 00 bf 01 34 07 4b 9c 42 fa dd e8 e7 00 bf |.....4.K.B......|
000001a0 18 10 02 40 04 10 01 40 10 10 01 40 3f 42 0f 00 |...@...@...@?B..|
000001b0 14 10 01 40 1f a1 07 00 |...@....|
000001b8
Since the .bin
file is supposed to be flashed verbatim at address 0x08000000
, that means you can correlate the content of addresses 0x00000000
and 0x00000150
of the hexdump
output
with the output of the arm-none-eabi-objdump -d
command, but at addresses 0x08000000+0x00000000
and 0x08000000+0x00000150
, i.e. 0x08000000
and 0x08000150
.
I hope this does answer your question.

- 5,382
- 1
- 16
- 22