NOTE: this article is obsolete. Bluetooth SDK 2.3.0 (released March 2017) includes beta support for GCC toolchain.





This is a simple BLE example that can be built with GCC. It is intended only for testing. This is not for production use.


GCC is not fully supported yet and there are some features (like OTA) that do not work with GCC. Any feedback is appreciated, you can either

1) comment directly to this article (Preferred method)

2) create a new thread on our forum or

3) create a private support ticket at


Options 2) and 3): remember to mention that you are using GCC to build.




To run this example you will need to have Simplicity Studio v4 and BLE SDK 2.0 installed. For instructions, see this article:


This example has been tested with MinGW and Cygwin. 


Example content


The example is a minimal BLE peripheral that turns on advertising at boot. It uses a soft timer to blink the development board LEDs in an alternating pattern. You can use this as a template for your own experiments.


The project is split into three directories:

src - source files. Whole application is in main.c.

bgbuild - the GATT database is defined here. Edit gatt.xml to customize the GATT for your own project.

gcc - for building with GCC. You can find the Makefile here.


Building the example with MinGW


To build the example with MinGW:


  1. Extract the attached to
  2. open MinGW terminal

  3. cd to

4) run 'mingw32-make' to build project

5) run 'mingw32-make load' to build and load binary to target


Below is a screenshot showing successful build and flashing from MinGW terminal.




To build with Cygwin, run "make" instead of "mingw32-make". NOTE: when building with Cygwin you need to run make twice the first time you build the project.






  • Thunderboard Kits
  • Knowledge Base Articles
  • Bluetooth Low Energy
  • I have tested this on Linux Mint 17.3 and it works fine! Then I have tried configuring the empty_ble example to compile from Simplicity IDE. I had to add include directories containing missing .h files (C/C++ General > Paths and Symbols > Includes > GNU C): stacks/ble/v2.0.0.0/platform/emlib/inc stacks/ble/v2.0.0.0/platform/Devices/SiliconLabs/EFR32BG1B/Include stacks/ble/v2.0.0.0/platform/CMSIS/Include I had to add Symbols (C/C++ General > Paths and Symbols > Symbols > GNU C): _NO_SYSTEM_INIT ERF32BG1B232F256GM48 I had to add Other objects to Linker (C/C++ Build > Settings > GNU ARM C Linker > Miscelaneous) /home/miceuz/Downloads/SimplicityStudio_v4/developer/stacks/ble/v2.0.0.0/protocol/bluetooth_2.0/lib/binbootloader.o /home/miceuz/Downloads/SimplicityStudio_v4/developer/stacks/ble/v2.0.0.0/protocol/bluetooth_2.0/lib/binstack.o /home/miceuz/Downloads/SimplicityStudio_v4/developer/stacks/ble/v2.0.0.0/protocol/bluetooth_2.0/lib/stack.a /home/miceuz/Downloads/SimplicityStudio_v4/developer/stacks/ble/v2.0.0.0/platform/Device/SiliconLabs/EFR32BG1B/Source/GCC/startup_efr32bg1b.S I had to deselect No startup or default libs (-nostdlib) checkbox in C/C++ Build > Settings > GNU ARM C Linker > General so that linker stopped complaining about missing _start symbol. Then I just had to provide an empty main() function and the build was successful. I'm still not sure if this produces a runnable code, some compiler and linker settings might be suboptimal. Will try to build a more real example tomorrow.
  • I have tried building Thermometer SOC example today. It build successfully, but does not work on the real hardware. I'm using BGM111M256KV1.1 module with wireless starter kit. I'm assuming there is EFR32BG1B232F256GM48 processor in this module and use ld and startup files from stacks/ble/v2.0.0.0/platform/Device/SiliconLabs/EFR32BG1B/Source/GCC. The code crashes with Usage Fault caused by attempting to access a coprocessor at 0x0000A484 instruction vldmia in function gecko_init from stack.a. My linker command is: arm-none-eabi-gcc -D__NO_SYSTEM_INIT --specs=nosys.specs -g3 -gdwarf-2 -mcpu=cortex-m4 -mthumb -T "/home/miceuz/Downloads/SimplicityStudio_v4/developer/stacks/ble/v2.0.0.0/platform/Device/SiliconLabs/EFR32BG1B/Source/GCC/efr32bg1b.ld" -L"/home/miceuz/Downloads/SimplicityStudio_v4/developer/stacks/ble/v2.0.0.0//protocol/bluetooth_2.0/lib/" -Xlinker --gc-sections -Xlinker -Map="" -o soc-thermometer_2.axf -l:binbootloader.o -l:binstack.o -l:stack.a "./src/InitDevice.o" "./gatt_db.o" "./main.o" "./kit/BRD4300ArevA02/bsp_bcc.o" "./kit/BRD4300ArevA02/bsp_stk.o" "./kit/BRD4300ArevA02/bsp_stk_leds.o" "./kit/BRD4300ArevA02/i2cspm.o" "./kit/BRD4300ArevA02/si7013.o" "./kit/BRD4300ArevA02/tempsens.o" "./kit/BRD4300ArevA02/udelay.o" "./emlib/em_gpio.o" "./emlib/em_i2c.o" "./emlib/em_rtcc.o" "./emlib/em_usart.o" ""/home/miceuz/Downloads/SimplicityStudio_v4/developer/stacks/ble/v2.0.0.0//platform/Device/SiliconLabs/EFR32BG1B/Source/GCC/startup_efr32bg1b.S"" -Wl,--start-group -lgcc -lc -lnosys -Wl,--end-group Any help would be highly apreciated.
  • if I add -march=armv7e-m I also get a usage exception that is hard to catch and debug - if I run the code, I get Usage Fault: invalid combination of EPSR and instruction, if I step thru the code I get the same "attempting to access a coprocessor" Usage Fault on instruction blx at 0x00008dc4
  • When I use your ld script and startup file and -march=armv7e-m, I get Bus Fault: imprecise data bus error. Your linker files are named efr32mg1 - which supposes use of Mighty Gecko processor. As far as I can see, BG1 anf MG1 linker files are the same in the sdk, but different from yours. Could you please provide linker script and startup file for EFR32BG1?
  • Finally I was able to make the Thermometer SOC example to compile on Linux and work on BGM111 module! The last thing to do was to remove all OTA references: in gecko config in main.c and OTA service in gatt_db.bgproj.
  • The basic GCC example worked well on Windows 7 x64. The following links may be helpful for installing Cygwin and GCC.



    NOTE: Did not need to perform step 3 (Download, Build and Install the Latest GCC)



  • For everyone's information: this also works on MAC OS.


    Just extract the zip to /Applications/Simplicity, then open the terminal and navigate to /Applications/Simplicity and run 'make' twice. The second run will generate a *.bin file which you can load using SS Flash Programmer.

  • I got it to build and MOSTLY run on the EFR32 Blue Gecko starter kit (SLWSTK6020A), which has a EFR32BG1P instead of an EFR32BG1B.  Distressingly, there are two serious problems:


    - stack.a in the BLE stack lib directory is not a static library (per the name), but an object file.  It took me a while to figure out why I could look at it with nm and objdump, but not ar.

    - There are several device-specific object files linked in which I had to remove with objcopy; I stripped EMU*, CMU*, INT* and System* and added the device-appropriate emlib files to my project to replace them.  Without this step, the init routines would bug out because the struct sizes for the EFR32BG1B appear to be larger, and they live at the top of the stack, so it immediately tried to access out-of-bounds memory.


    So I have something that compiles and runs.  Unfortunately, something seems wrong with the stack; the gecko_evt_system_boot_id message never seems to get received after init.  It seems like something is wrong with the gecko_wait_event() function, because the assembly it steps into is garbage for what it should be doing:

    000071dc: strb r1,[r0,#0x1c]
    000071de: movs r1,#0x0
    000071e0: str r1,[r0]
    000071e2: bx lr


    I'll keep hacking on it.  It's progress, anyway!

  • Oh, I see.  stack.a is just a pile of addresses that point to absolute locations in binstack.o and the like, and I wasn't using the included linker script which kept binstack and binbootloader in the correct locations.  What a mess.  This isn't a great way to provide a library, for what it's worth.  I know you want to strip the symbol names, but must be better ways of doing that.

  • Well, I get an executable that's much closer to the right size when I add the binstack and binbootloader sections into the linker script appropriate for my part.  However, I get the feeling that the bootloader may not be 100% compatible with my part, since it never seems to make it to main().  I haven't bothered stepping through to see where it's getting hung up, though it doesn't appear to be getting stuck on a HardFault or anything of the like.  Is there a reason the bootloader is necessary?  I rather like to see how my chip is getting initialized.