CortexM4Port
Cortex M4 STM32F4 Port
{i} This is work in progress! Please post in the forum to discuss this topic!
Introduction
This document documents the port to the new main FC CPU STM32F4. The source code of the port has been merged to trunk.
We use the STM32F4 Discovery board to do the initial port and testing. Currently a shell is available on UART2 and UART3.
Ports:
- UART2: PA2 => TX, PA3 => RX
- UART3: PD8 => TX, PD9 => RX
- SPI2/LISL: PB13 => SCL, PB14 => SDO, PB15 => SDA, PB0 = CS LISL.
http://www.st.com/internet/evalboard/product/252419.jsp
Toolchain
To compile NGOS on STM32F4 we use GCC 4.8.2 EABI (optionally including Gold Linker with LTO support). The ngos/tools/toolchain/build-arm-toolchain.sh script using the argument cortex-eabi-4.8.2 should generate a working toolchain in the folder /opt/cortext-arm-ngos-eabi-4.8.2/ when started as root. Note: CPU-Defaults need to be set to Cortex-M4 in order to compile newlib with correct CPU features).
{i} You better use our toolchain build script to build the toolchain. It compiles NEWLIB with certain defines which are needed by NGOS. Essentially it uses -DSMALL_MEMORY to make NEWLIB choose 128 byte chunks over 8096 byte chunks for sbrk().
libopencm3
Because the official STM32F4 library does not contain a specific license, we choose the open source library libopencm3. Beside the includes and linker configuration we also link against this library in order to make use of the comfort functions.
The configure script of NGOS will recognize libopencm3 when you point it to the right directory with the –with-libopencm3=DIR argument.
By default the folder sources/ngos/lib/libopencm3 gets choosen which can be filled with a libopencm3 checkout like this:
$ cd sources/ngos/lib
$ git clone git://github.com/libopencm3/libopencm3.gitYou don’t have to compile libopencm3. The build process of NGOS will take care to configure libopencm3 according to the configured parameters of NGOS.
{i} If you use LTO (Link time optimization) to build NGOS (e.g. –enable-lto), its required to compile libopencm3 with Link time optimization too! This is because LTO renames functions and breaks overwriting of weak defined functions.
/!\ Note that NGOS build process will automatically detect, configure and compile libopencm3 for you!
For documentation purposes we will show here how to compile libopencm3 by hand for NGOS:
$ PREFIX=arm-ngos-eabi FP_FLAGS="-mfloat-abi=hard -mfpu=fpv4-sp-d16 -flto" LDFLAGS="-flto -fuse-linker-plugin" make lib/stm32/f4Code Structure
In order to support multiple architectures, the code has to be restructured. The following code layout has been choosen
kernel/ -- the core kernel features (driver, timer) as well as quadrocopter specific features like controller, behaviors etc.
arch/include -- Common interface to architecture (include protection start with ARCH_)
arch/stm32f4 -- STM32F4 specific implementations of core, actor and sensor (include protection start with ARCH_STM32F4_)
arch/lpc2148 -- LPC2148 specific implementations of core, actor and sensor (include protection start with ARCH_LPC2148_)
core/ -- NGOS core features, arch independent part (timer, detected devices, configuration)
actor/ -- Actor drivers, arch independent part (motors, servos)
sensor/ -- Sensor drivers, arch independent part (gps, rc-receivers, gyros and acceleration sensor)
behavior/ -- Behavior specific code
controller/ -- Controller specific code
hal/ -- Hardware abstraction layer for actors
fsp/ -- Flight state programms (not yet finished)
math/ -- common Math and Filter code
user/ -- the NGOS task scheduler, runs a shell on every monitor, detects and runs GPS, M-Link, S3D and other serial peripherals.
task/ -- Task scheduler
terminal/ -- NGOS Terminal
cmd/ -- NFOS Commands (all user space commands, ported from the kernel files)Note: Its common that for a specific aspect three header files exists:
- kernel/arch/*/core/
- kernel/arch/include/
- kernel/core/ Since the arch dependent aspect can make use of the kernel’s core functions, and since the kernel’s core function needs to access architecture dependent aspects, these files are going to included from two sides. Since all files have the same name (e.g. timer.[c/h]) the include protector need to be different for those files….
Normally includes are used like this:
- The
kernel/core/timer.cincludes its own interface definitionkernel/core/timer.candkernel/arch/include/timer.hin order to access arch dependent functions. - The
kernel/arch/*/core/timer.cincludes its own definition atkernel/arch/*/core/timer.c(if any architecture specific functions need to exported) and the common architecture interface atkernel/arch/include/timer.h - Everyone else should access through the
kernel/core/timer.hinterface… The linker makes sure that the correct implementation is going to be linked (depending on —with-arch in ./configure)
Configure NGOS
The configuration and makefiles are altered in order to support both CPU’s with the same code base. These configurations are noteworthy in order to develop with STM32F4:
Switches the architecture in general (#ifdef ARCH_STM32F4)
--with-arch=stm32f4Configure NGOS for the STM32 Discovery Board
If you plan to use the Discovery board, a new board switch was introduced which enables some defines to make the NGOS work with different UART, LISL and LED settings (#ifdef STM32F4DISCOVERY).
--with-board=discoveryThe Path to libopencm3 is ngos/lib/libopencm3. Download, place it in ngos/lib. NGOS’s build process will configure and build it. The library libopencm3_stm32f4.a in the lib/libopencm3/lib directory is automatically linked against NGOS. The include/ directory is automatically added to the search path for include headers (only for kernel/ directory).
As stated before, we use the eabi toolchain.
--with-toolchaindir=/opt/cortex-arm-ngos-eabi-gcc-4.8.2/ --with-crossprefix=arm-ngos-eabiWe use OpenOCD to flash through STM’s stlink. No JTAG adapter is needed. The interface file stlink-v2.cfg (included in OpenOCD), the target stm32f4x_stlink.cfg (included in OpenOCD) and the OpenOCD script file (included in NGOS at sources/ngos/conf/jtag/) called openocd-stm32f4discovery.cfg.
--with-openocd-script=openocd-stm32f4discovery.cfg
--with-openocd_target=stm32f4x_stlink.cfg
--with-openocd_interface=stlink-v2.cfgFull configuration:
./configure --enable-ctrl-amir --enable-ctrl-amir-ng --enable-ctrl-pt1 --enable-rc-s3d-dsl --with-toolchaindir=/opt/cortex-arm-ngos-eabi-4.8.2/ --with-crossprefix=arm-ngos-eabi --with-openocd-interface=stlink-v2.cfg --with-openocd-target=stm32f4x_stlink.cfg --with-openocd-script=openocd-stm32f4.cfg --with-openocd-script=openocd-stm32f4.cfg --with-arch=stm32f4 --with-board=discoveryConfigure NGOS for the HW-0.30 Board
HW-0.30 is the default board for NGOS on the STM32. So many parameters are set correctly by default and do not have to be specified explicitly.
The Path to libopencm3 is ngos/lib/libopencm3. Download, place it in ngos/lib. NGOS’s build process will configure and build it. The library libopencm3_stm32f4.a in the lib/libopencm3/lib directory is automatically linked against NGOS. The include/ directory is automatically added to the search path for include headers (only for kernel/ directory).
As stated before, we use the eabi toolchain.
--with-toolchaindir=/opt/cortex-arm-ngos-eabi-gcc-4.8.2/ --with-crossprefix=arm-ngos-eabiWe use OpenOCD to flash through the USB connection to the JTAG adapter embedded in HW-0.30. No separate JTAG adapter is needed.
You do not need to specify OpenOCD script, OpenOCD interface nor OpenOCD target to configure, all default values are set correctly for HW-0.30.
Full configuration:
./configure --enable-ctrl-amir --enable-ctrl-amir-ng --enable-ctrl-pt1 --enable-rc-s3d-dsl --with-toolchaindir=/opt/cortex-arm-ngos-eabi-4.8.2/ --with-crossprefix=arm-ngos-eabi \ --with-arch=stm32f4State of Port
This tree is meant to summarize and coordinate the work
- kernel/
- arch/*/core/:
- –(UART)–: hardware specific UART configuration
- IAP/configuration: conf stubs are in place, IAP should be available from libopencm3
- –(Monitor)–: hardware specific monitor count need to be altered according to UART configuration
- USB
- RTC: stubs in place
- NGPP: still supported? -> Yes, as it sits on top of i2c_task (which we will support). i2c_task sits on top of i2c (which we will support)
- –(Timer)–: partly, 50ms ticks, calls to controller
- Watchdog
- I2C: general support done (needs cleanup, e.g. I2C device number as parameter instead of specific function names)
- arch/*/actor/:
- –(LED)–
- –(I2C)– (needs testing for special cases, needs cleanup, I2C addresses should be real I2C addresses, excluding the read/write bit)
- –(Sound)–
- VDrive: (Stefan)
- arch/*/sensor/:
- ADC
- I2C: Device Probing (HMC5883L/PCA9685/MK3MAG), Device Driver (HMC5883L/PCA9685/MK3MAG)
- –(GPS/Position)–: Is now parsed in task
- Venus: Need to move some functions to GPS (Stefan)
- SPI: Device Pobing (—(MPU6050)—/–(LISL)–/—(MS56xx)—), Device Driver (—(MPU6050)—/—(LISL)—/MS56xx)
- core: Most code in here is ported from arch/lpc2148 in order to make use of it on the STM32F4
- ctrl/:
- ctrl/ctrl.c
- Mostly done, except of calibration task (gyro/compass), controller statistics partly done… need more xxxx_tick from various devices)
- ctrl/ctrl.c
- behavior: Not done yet!
- hal: Done
- core/fifo.h: Lockfree FIFO framework (single reader, single writer), used in uart code
- arch/*/core/:
- math/: Done
- user/
- task/
- –(Terminal)–: Done, ctrl specific commands missing
- –(Task)–: Using the monitor, a task can directly access UART/USB now (using monitor_getch(int monitor))
- –(Modbus)–: should we drop it? - incomplete and not used - yes, drop it
- cmd/
- SPI
- I2C
- ADC
- Behavior
- task/