Skip to content

Setting up Firmware Development Software

db4ple edited this page Jan 30, 2021 · 68 revisions

Building the Software

Building and installing the firmware is quite easy. However, please read and follow the instructions outlined below before asking. If you feel that the instructions can be improved, extended, shortened: Feel free to do so and share your knowledge with all of us. Log into your GitHub account and start improving this document. Thank you!

If you want to contribute your improvements, read the guidelines for contributing to learn how to do this.

Important Information regarding Board Revisions and Development

If you want to be seriously involved in firmware development, the use of a cheap real-time debugger such as the ST-Link is a real time-saver. Unfortunately, Rev 0.5 of the UI Board removes the previously available connections from the P8 header to the Debug interface and repurpose the pins. For that reason it is going to be very difficult to connect the debugger to the CPU. While it is not impossible to wire it up, TRY TO AVOID UI Board Rev. 0.5 if you plan to use the debugging capabilities at any later time. MCHF Rev 0.6 readds the headers AND adds the GND pin. Nice!

Normal use of the mcHF Rev 0.5 will not suffer from the missing Debug interface.

Building for different hardware configurations

As this UHSDR firmware now supports 3 different processor types (STM32F4, STM32F7 and STM32H7) running on different hardware configurations (OVI40 UI board, MCHF UI board) with potentially different RF hardware, and can build both a bootloader and the firmware from the source, you will have to follow certain instructions to get the right build done.

See instructions in the Running a Build section below.

Requirements and Setup

Basic Software for Compilation

The project uses gcc for compilation. Other compilers have not been tested and are not supported by the build environment. Feel free to add support for other compilers.

We do not recommend to use compilers older than 8.1 because this is the one we are using right now for official builds so builds may fail with older compilers. To our knowledge, currently gcc versions 4.9 to 8.1 are being used with success. Older gcc releases had issues during linking, suse of older releases is not and will not be supported.

Minimum version for tools (applies to all operating systems):

Tool Minium Version Required Comment
GNU make GNU Make 4.0 we use function file, available with 4.0 or newer
GCC 4.9 We recommend to use newest stable GCC

Linux

On many newer distributions you can use the compiler environment provided as packages with the distribution. If it is a gcc 4.9 or newer, you should be fine. To get the newest compiler, you can look at the GNU Arm Embedded Toolchain. However, for now we recommend to stick with the recommended configurations first. Feel free to add more instructions to this wiki.

If you happen to run a Raspberry Pi or similar ARM based linux machines, you could use the provided compiler, but this is not tested.

Ubuntu
Ubuntu 17.04 and newer:

Use apt install gcc-arm-linux-gnueabihf to get the newest available compiler release including all tools required to build the firmware.

Ubuntu 15.04:

Use of standard compiler and tools packages included works for Ubuntu 15.04 and newer. Use apt-get install gcc-arm-linux-gnueabihf to get the newest available compiler release including all tools required to build the firmware. Install openocd if you plan to run hardware assisted debugging.

Ubuntu 14.04

Use the instructions given below for Debian Jessie, installing the backport works perfectly to get gcc 4.9.

Debian-based Systems
Debian Jessie
   sudo add-apt-repository "deb http://ftp.debian.org/debian jessie-backports main"
   sudo apt-get update
   sudo apt-get install -t jessie-backports -y --force-yes gcc-arm-none-eabi libnewlib-arm-none-eabi libstdc++-arm-none-eabi-newlib openocd

Windows

On Windows you can follow two approaches. You may go for a IDE based environment or use a command line build approach. For command line builds, you will have to use a Unix emulation (MinGW) or Bash on Ubuntu on Windows (WSL available on Windows 10). For IDE builds you will have to use the GCC Compiler for ARM.

See here for a strictly Windows 7/8/10 x64 build environment.

GCC Compiler for ARM

The GNU Arm Embedded Toolchain provides installers for Windows and more. Ubuntu users can still use the "old" GCC ARM Embedded Project PPA to get GCC packages.

Important Information: Do not use the 2018 Q4 GCC on Windows. It has an issue when linking. Remain on 2018 Q2 until a newer release is available or this information is removed. Linux and MacOS are not affected and can use the newest compiler.

Download the most recent installer and run it, leaving all settings to the defaults.

MinGW

MinGW provides a Unix emulation, we simply install all the nice Unix tools and can run a Makefile build.

  • Install MinGW
  • Install gcc-arm (but preferrably you should use the Windows GCC downloaded from the website above)
  • Install git
  • Optional but recommended: git-shell etc.

After that it performs the same way as on Linux.

Bash on Ubuntu on Windows

Since Windows 10 "Anniversary Update", Bash on Ubuntu on Windows provides developers with a familiar Bash shell and Linux environment in which you can run most Linux command-line tools, directly on Windows, UNMODIFIED, without needing an entire Linux virtual machine. This is very similar to MinGW with the advantage of a full access to the Ubuntu and Debian software library.

First, install Bash on Ubuntu on Windows with the help of the Installation Guide. You will get Ubuntu 14.04 (trusty) on Windows 10 Anniversary Update (version 1607) or Ubuntu 16.04 (xenial) on Windows 10 Creator Update(version 1703).

Next, install the development tools:

   sudo apt-get update
   sudo apt-get upgrade
   sudo apt-get install build-essential
   sudo apt-get install python-minimal

On Creator Update, install the cross compiler:

   sudo apt-get install gcc-arm-none-eabi

On Anniversary Update, install the cross compiler as on Debian Jessie above.

Finally, get the source files and compile:

   cd
   git clone https://github.com/df8oe/UHSDR.git
   cd UHSDR/mchf-eclipse
   make all

Mac OS

In order to install a build environment on Mac OS, you should first install Homebrew:

   /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Afterwards, you can install the cross compiler and GNU sed:

   brew cask install gcc-arm-embedded
   brew install gnu-sed

IDEs

GNU MCU Eclipse (formerly GNU ARM Eclipse)

Following the complete instructions on the GNU MCU Eclipse pages for installing will give you a nice working setup including nice debugging capabilities. It might seem like a lot of instructions and you have to jump between pages, but this is well-spent effort, especially on Windows.

Do not forget to install the packs for the STM32F4 processor (or STM32F7 if you are using F7 based hardware). Detailed instructions for this step may appear here in future.

Important Hint for Eclipse Upgrades

If you upgrade your Eclipse installation during upgrade you will get a box which points to a new/different workspace folder. It is mandatory to choose a new workspace like it is proposed! Later you have to import UHSDR project again and all will work fine. If you use workspace which was created by a former Eclipse version you will run into trouble.

EmBitz IDE (in search of a maintainer, builds will not work)

See the instructions in the mchf-embitz project folder of the repository

CoIDE (no longer supported after switching to HAL based libraries at middle of March,2017)

CoIDE is a all-in-one IDE for ARM processors on Windows. It is simpler to use than Eclipse but also less extensible.

The GitHub project contains a working CoIDE 1.7.x project. Download CoIDE 1.7.8. In addition you will need only a GCC ARM Tool Chain. Follow the instructions given above to install one.

DO NOT USE CoIDE 2.0 or newer. Build fails on these. There are no plans to migrate the CoIDE project to 2.0, however, if you made a successful migration, let us know and we may be able to integrate that. Otherwise, stick to CoIDE 1.7.8.

Hardware for Flashing and Debugging

Please note: mcHF UI Board 0.5 does not provide the debug port on its P8 connector (although it has P8, it is bascially useless, check the schematic). mcHF UI Board 0.4 and 0.6 provide the signals on P8.

ST-LINK V2

  • Get yourself a ST-LINK V2 compatible USB stick. These sell for 8-15USD/EUR/GBP on Amazon
  • Update to newest stick to newest ST LINK V2 firmware. This solves some issues.
  • Solder a 4 or 5 pin strip 90 degrees to connector P8 (Rev 0.4: 4 Pin, Rev. 0.6 5 Pin)
  • Rev 0.4 only: Solder another pin from a pin strip to a place where you can get a ground connection (or clip a wire to the casing of one of the USB sockets)
  • Connect SWDIO and SWDCLK to the respective pins on P8: Rev 0.4: Pin 4 -> SWDCLK, Pin 3 -> SWDIO, Rev 0.6: Pin 5 SWDCLK, Pin 4: SWDIO, Pin 1 GND. Rev. 0.4 only: Connect ground pin from stick to mcHF.
  • To connect the original ST-LINK/V2 you have to connect pin 1 from 20 pin header from ST-LINK to UI_3V_MCU on UI board. E.g. you can use one of P6 pins. If you use a "clone" ST-LINK/V2 stick, you do not have to connect 3.3V
  • One of the verified configurations in ST-LINK Utility - Mode: Hot Plug, Reset Mode: Hardware Reset, Frequency: 1,8MHz
  • Use a SHORT cable to connect ST-LINK and mcHF. Less than 10cm is recommended. All sort of sporadic errors happen with longer cables. You have been warned.

Other HW Debuggers for ARM

There are many other hardware interfaces on the market for debugging ARM processors. If you buy one of these and get to work, just document it here. In other words: Not yet supported.

Do I need git to be installed and to have a GitHub account?

No, not for compiling and debugging. But for contributing, getting up-to-date source code easily, collaborating, .... That's way we recommend strongly to have both.

Getting and Preparing The Source Code

Getting the Source Code

Depending on what you are intending to do, there are three different approachs how to get the software and stay in sync with development progress. See the subsections below. Then, depending on your build environment see instructions in next section, which will tell you how to "install" the sources for a build.

Zip: I just want to compile my own binary once

Git: I potentially want to build binaries regularily with the latest and greatest and my changes in

git clone https://github.com/df8oe/UHSDR.git

puts the repository on your disk and links it with the main repository.

  • Later, if you want to get the newest state, run git pull. This will even keep handle changes you did. But be aware, sometimes the automatic merge of your changes with the newest state from Github will fail, and git will ask for your support.
  • Go the next section telling you what to do to prepare the source for use with your build environment.

GitHub: I potentially want to contribute

In a nutshell, you will need your own GitHub account and a fork of this repository in your own GitHub account area.

Please follow the instructions given in the guidelines for contributing in order to setup the git connections to GitHub correctly and understand the way of working we use in this project.

Although not strictly technically necessary, please follow the naming conventions for the remote GitHub repositories! It makes discussion about git/github so much easier, if we all use same names for the remotes!

Preparing The Code For Compilation

make

Nothing to do, just go into the directory "mchf-eclipse" with your command line and run the build according to instructions.

Eclipse IDE

You need to make the UHSDR project configuration known to Eclipse. This action is called "Import an Existing Project". Please, do not import the source code into an existing Eclipse project (there is an option for that, but this is the wrong way). Here we go:

  • Start Eclipse
  • "File"->"Import"->"General"->"Existing project"
  • "Archived"
  • Navigate to the ZIP and select it
  • mchf-eclipse Project should be listed and selected in the previously empty list box
  • "Finish"
  • Project will appear in Eclipse workspace view.

For advanced users/use cases: There are other ways to get the project into the Eclipse workspace but for sake of simplicity we don't document or support them here to keep instructions complexity low.

Embitz IDE

See the instructions in the mchf-embitz project folder of the repository

Running a build

Selecting what to build

From the same source we can build the firmware or the bootloader. With C compiler defines we control what hardware and software features are supported in a build. There are also C compiler defines to configure the processor. In addition to that some paths have to set according to the processor and firmware vs. bootloader build type.

The Makefile and/or the IDE configurations hide most of this from you.

Your main choices are (used in all build systems):

What Makefile Variable/Define Valid choices Default Comment
Processor Type BUILDFOR 'F4' 'F4', 'F7', 'H7', 'F4-512KB' 'F4-512KB' for building for F4 with 512kB flash with reduced functionality
UI Board + RF_BOARD CONFIGFLAGS "-DUI_BRD_MCHF" or "-DUI_BRD_OVI40" plus "-DRF_BRD_MCHF" and/or "-DRF_BRD_OVI40" "-DUI_BRD_MCHF -DUI_BRD_OVI40" ui boards are mutually exclusive, rf boards any combination possible
TRX Display Name TRX_NAME "MCHF", "OVI40', "OVI40H7" "MCHF" any string if not too long works
TRX ID TRX_ID "mchf", "i40h7', "ovi40" "mchf" string with at most 5 characters, used for naming the binaries fw-... / bl-...

To put this together, an example for a make call to build a OVI40 UI firmware using the H7 processor with support for the MCHF RF board:

make BUILDFOR="H7" TRX_ID="i40h7" TRX_NAME="OVI40H7" CONFIGFLAGS="-DUI_BRD_OVI40 -DRF_BRD_MCHF -DRF_BRD_OVI40" all

In the IDEs such as Eclipse the different build configuration set these values for you. See below for details. Not all the settings are done in the IDE case in the same way as in the Makefile technically, so you will not find for instance the BUILDFOR variable being used in Eclipse. Nevertheless the table above gives you the general idea of what is possible (and is exactly what we use in Makefiles).

On the Command Line with make

In addiion to the settings above, the make process uses a few more settings specific to the Makefile build process and have no direct counterpart in the IDE cases:

What Makefile Variable/Target Valid choices Default Comment
Build Target make all 'all', 'firmware' or 'bootloader' none mutually exlusive, 'all' builds firmware and also the documentation
Separate Build ROOTLOC path to the mchf-eclipse directory "." (current dir) this can be used to build in a different directory located outside the original source tree
Compiler location OPT_GCC_ARM path to top level directory of package none must point to top level directory of arm gcc compiler package, not the /bin directory!

To put this together, an example for a make call to build a OVI40 UI firmware using the H7 processor with support for the MCHF RF board assuming the sourc located in /opt/src/UHSDR/mchf-eclipse and the build in /opt/build/ovi40_h7_build, the compiler is in /opt/gcc:

make -f "/opt/src/UHSDR/mchf-eclipse/Makefile" ROOTLOC="/opt/src/UHSDR/mchf-eclipse" OPT_GCC_ARM="/opt/gcc" BUILDFOR="H7" TRX_ID="i40h7" TRX_NAME="OVI40H7" CONFIGFLAGS="-DUI_BRD_OVI40 -DRF_BRD_MCHF -DRF_BRD_OVI40" all

On Linux Systems

cd mchf-eclipse
make all

will produce, if successful, the file firmware mchf.bin in this directory. make clean will remove all generated files.

cd mchf-eclipse
make bootloader

will compile the bootloader code.

If it fails, make sure that all the required tools are in the execution path.

On Windows Systems

First see MinGW install information above. Then run it just like on Linux.

make clean  
make all 

On Mac OS

The build process on Mac OS is similar to Linux or Windows, you just need to set the correct prefix:

   export OPT_GCC_ARM=/usr/local
   make clean
   make all

With an IDE

Eclipse

  • Import project first, see instructions above.
  • Make sure to be in the "C/C++" perspective. This is visible in the window title bar (you will see "C/C++" as part of the window title. If not, "Window"->"Perspective"->"Open Perspective"->"C/C++" oder ... "Other"->"C/C++" will get you there.
  • Select "DebugLibMCHF" build configuration using "Project"->"Build Configurations"->"Set Active"->"DebugLibMCHF"
  • Run "Project->Build". Build uses make just like a command line build.
  • Select "DebugMCHF" build configuration using "Project"->"Build Configurations"->"Set Active"->"DebugLibMCHF"
  • Run "Project->Build". Build uses make just like a command line build.
  • Resulting firmware file (mchf-eclipse.bin) is in directory "DebugMCHF".

Now you can change the code and run "Project->Build".

The bootloader can be build by selecting "DebugBoootloaderMCHF" and can be found in "DebugBootloaderMCHF".

EmBitz (No Longer Supported!)

See the instructions in the mchf-embitz project folder of the repository

CoIDE (No Longer Supported!)

  • Start IDE, open project using file firmware.coproj.
  • Run "Project->Build Project".
  • Resulting firmware file is placed by default in firmware_target/Debug

Installing the binary

There are different ways how to get the newly built binary on the mcHF. While the first two alternatives work, the third choice which uses a USB dongle, is the quickest way to do it and the only one which gives you also full debugging support in real-time.

Flashing using an USB Pendrive - UHSDR Bootloader

See wiki page for firmware updates

Flashing using mcHF Manager - M0NKA Bootloader on Windows

See wiki page for firmware updates

Flashing using the ST-Link V2 USB interface

  • Connect stick to PC, use either direct connection or good cables/hubs. Bad USB extension cables caused problems during flashing.

  • Now put your finger on the Power button and do not release it. Flashing will stop the internal "power hold" mechanism and switch off the TRX before the new firmware has been loaded. If this happens, your UHSDR TRX may be temporarily "bricked". To fix this you may need to either restart the flashing process (this time with power button hold all the time). Or if this doesn't work, you may have to reflash the bootloader using the Jumper P6 method described elsewhere in this wiki. You have been warned!

  • CoIDE:

    • Just press the "Flash" button. This will start first the flashing and then start the mcHF.
  • Eclipse:

    • Make sure you have the right run configuration selected.
    • Just press the "Run" button. This will start first the flashing then start the mcHF.
  • Command Line:

    • Start openocd with openocd -f support/MCHF.cfg -c "init" -c "reset halt". Depending on the UHSDR TRX you may have to use support/ovi40.cfg etc. This should produce some output and mention the successful connection to the target MCU. Attention: You need to keep the Power button pressed, otherwise the TRX will switch off.
    • Change in the directory where your UHSDR fimrware .elf is located (e.g. fw-mchf.elf).
    • Start gdb with arm-none-eabi-gdb in a separate terminal window. Once the gdb session starts, enter
          target remote localhost:3333
          file fw-mchf.elf
          load
          monitor reset halt
          cont
      
    • This flashes the binary and starts it. BTW: Hitting CTRL-C will stop the firmware and gdb tells you where it was.

Debugging

Live Debuggging

The easiest way to debug the UHSDR Software is to run the transceiver connected to a PC via ST LINK V2 USB Adapter and Eclipse installed as described before. This offers starting and stopping the processor, reading the memory, variables, setting breakpoints easily in the code editor and so on. You can even use special calls (trace_printf/trace_write) which will insert debug output in the code. The output is shown on the PC (data is sent via the debug interface, no extra connection required).

Similar functionality is available on the command line, with gdb and openocd.

In a nutshell, if you can flash the firmware using Eclipse or gdb/openocd, you can also run debug using the same interface.

How to Enable Debug Output (CURRENTLY NOT SUPPORTED, TEXT KEPT)

By default the debug output via semihosting is disabled. Two reasons for that: It takes resources and even more importantly, if enabled, it produces binaries which do not work without the ST LINK debugger active! Only activate this in your local builds.

In order to have semihosting working, you need to add two defines to your build system:

  • OS_USE_TRACE_SEMIHOSTING_STDOUT
  • TRACE

In Eclipse, you can select the Build Configuration "DebugSemihosting", which has these defines set.

Profiling

We added support for profiling the UHSDR software (sort of). It helps you to count how often something happens and/or how long something takes at the granularity of single CPU clock cycle, which is 5,9nS (yes, nanoseconds).

You have to include "profiling.h" in the source file of interest, define a new profiling event in ProfiledEventNames (or reuse an existing one, if it is not in use, check carefully).

Profiling will be disabled by default. If "PROFILE_EVENTS" is defined, it is active.

Event Counting

Call profileEvent(EventName). This will increment the counter of the event in the eventProfile datastructure. Access the data there via "eventProfile[EventName].count". You may use the trace print functionality to print out the counter or you simply use the debugger to inspect the value in memory.

Event Timing

This is a little more complex.

  • First start the cycle timer with "profileTimeEventInit()" .This resets the timer and makes it run.
  • At any time call profileTimedEventStart(EventName) to have the start being recorded. At the end of the event call profileTimedEventStop(EventName)

The duration of a single event should not be longer then 2^32 / clock frequency, i.e. ~25s @168 Mhz for a single event. Total duration recorded should not be more than 2^64 cycles which is quite a lot, i.e. there is no limit on that for the average person in this universe.

Due to the approach multiple events can be recorded simultaneously correctly but outer events include the overhead of the calculation of the duration of the inner ones. Only the innermost events are more or less accurate. In many cases this deficit is neglectable since the measurement has very low overhead.

The recorded data is the time in cycles of the all active periods of that event. There is also a counter, so that it is possible to calculate the average event duration: "eventProfile[].duration/eventProfile[EventName].count"

Debugging Tips

Quick Start: Debugging with gdb and ST-Link

If you were able to flash the firmware using the commandline (see above) you can simply debug using any generic gdb tutorial (set breakpoints, step over instructions, etc.). You don't need to restart gdb if you recompiled your binary, just start with the instructions for flash at file <path_to_firmware_elf_file> and all following commands given above. Breakpoints remain set in this case. It is recommended to set a break to at the main function. (break main). This will stop after cont at main. At this point you can stop pressing your finger on the Power button. Now continue with another cont.

Quick Start: Debugging with Eclipse and ST-Link

Hit the "Debug" toolbar button (look like a bug) and Eclipse will switch to debug mode, compile, flash, and start the firmware and then stop at the first instruction in the main() function. At this point you can stop pressing your finger on the Power button. You have to press "Play/Continue" toolbar button in order to run the firmware. Press "Pause" at any time to pause the firmware execution.

Clone this wiki locally