An open framework for micro-controller software
Switch branches/tags
Clone or download

README.md

Introduction

PolyMCU has been designed from the beginning to be as flexible as possible: host OS independent (support Linux, Windows, MacOS), support any toolchain (GCC, LLVM), any RTOS (ARM RTX, FreeRTOS), any micro-controller vendor SDK (Nordic Semiconductor, NXP, Freescale, ST).
Enabling such flexibility provides by the same time better software quality by testing the same piece of software in various configurations. It supports C and C++ languages.

The framework is based on CMake. It provides some examples to build baremetal and RTOS-based projects. In opposition to ARM mBed that provides its own library, PolyMCU used Newlib. No new interface layout has been introduced in the framework. The abstraction layout for ARM architecture is driven by ARM CMSIS v3.0.

Quick start

  • For AppNearMe's MicroNFCBoard: here
  • To port a new vendor SDK to PolyMCU: here
  • Build & Install CMSIS RTOS Conformance test: here

Support

  • CMake - version 2.8

  • Toolchains:

  • RTOS:

    • ARM RTX: V4.79
    • FreeRTOS V8.2.3
    • RioT-OS 2015.09
  • Boards:

    • AppNearMe MicroNFCBoard
    • Freescale Freedom KL25
    • Nordic nRF52 Preview DK
    • NXP LP1768 mbed
    • ST STM32L476 Nucleo
  • Features:

    • The application defined by APPLICATION can live out of the PolyMCU tree if APPLICATION defined an absolute path.

Status

The latest test results are available at http://labapart.com/products/polymcu/test_results.

Toolchain / Host

Board Linux - GCC Linux - LLVM Windows
AppNearMe MicroNFCBoard Pass Pass Pass
Freescale Freedom KL25 Pass Pass Pass
Nordic nRF52 Preview DK Pass Pass Pass
NXP LP1768 mbed Pass Pass Pass
ST STM32L476 Nucleo Pass Pass Not Tested

Application

Board Baremetal CMSIS RTOS FreeRTOS
AppNearMe MicroNFCBoard Pass Pass Fail
Freescale Freedom KL25 Pass Pass Pass
Nordic nRF52 Preview DK Pass Pass Pass
NXP LP1768 mbed Pass Pass Pass
ST STM32L476 Nucleo Pass Pass Pass

Building on Linux

The cross compilation toolchain is either in your PATH or defined by the environment variable CROSS_COMPILE. The latest cross-compilation toolchain for ARM Cortex-M can be found at https://launchpad.net/gcc-arm-embedded.

It is recommended to build out of tree. To do that, create a new directory:

mkdir Build && cd Build
  • Case when the application can support multiple board:
cmake -DAPPLICATION=<application_vendor/application_name> -DBOARD=<board_vendor/board_name> ../ && make
  • Case when the application targets only a specific board:
cmake -DAPPLICATION=<application_vendor/application_name> ../ && make
  • To build a release build:
cmake -DAPPLICATION=<application_vendor/application_name> -DCMAKE_BUILD_TYPE=Release ../ && make
  • To make the build verbose:
cmake -DAPPLICATION=<application_vendor/application_name> ../ && make VERBOSE=1
  • To build with Clang:
CC=<path-to-clang> cmake -DAPPLICATION=<application_vendor/application_name> ../ && make

Building on Windows

Requirements

Build

  1. Download the latest sources of PolyMCU at https://github.com/labapart/polymcu/archive/master.zip

  2. Un-archive master.zip

  3. Start a command line shell (ie: cmd.exe)

  4. Add CMake and MinGW to your PATH if it is not already done. For instance:

SET PATH="c:\Program Files (x86)\CMake\bin";%PATH%
SET PATH=C:\MinGW\bin;%PATH%
  1. Add your toolchain into the CROSS_COMPILE. For instance:
SET CROSS_COMPILE=c:\Users\Olivier\gcc-arm-none-eabi-4_9-2015q3-20150921-win32\bin\arm-none-eabi-
  1. Create the Build directory into PolyMCU root
cd <PolyMCU Root>
mkdir Build
cd Build
  1. [Optional] To build with LLVM
set PATH="C:\Program Files (x86)\LLVM\bin";%PATH%
set CC=clang.exe
  1. Build the project
cmake -G "MinGW Makefiles" -DAPPLICATION=<application_vendor/application_name> -DBOARD=<board_vendor/board_name> ..
mingw32-make
  • To make the build verbose: mingw32-make VERBOSE=1

Support

All CMake variables that do not start with CMAKE_ and _ are defined in ${CMAKE_BINARY_DIR}/polymcu_config.h which is generated at build time.
This include file can be included in your project to access CMake configuration variables.

Basic variables

CMake variable Value Description
FIRMWARE_HEAP integer Size in bytes of the firmware heap
FIRMWARE_STACK integer Size in bytes of the firmware stack
SUPPORT_RUN_FROM_RAM (0|1) Define the firmware must be built to run from RAM
EXTERNAL_PROJECT_IN_BINARY_DIR (0|1) Build the external project into the binary directory instead of the source directory
SUPPORT_DEBUG_UART (none|itm|usb|1) Define which UART support to use for debugging
DEBUG_UART_BAUDRATE integer Debug UART Baud Rate (default: 115200)
SUPPORT_TIMER (0|1) Add PolyMCU Timer API
SUPPORT_TIMER_SYSTICK (0|1) Use SysTick for PolyMCU Timer API (default:1)
TIMER_TASK_MAX integer Number maximum of PolyMCU Timer tasks (default: 5)
SUPPORT_RTOS string Enable RTOS support with the name of specified RTOS
SUPPORT_WATCHDOG (0|1) Add PolyMCU Watchdog API
SUPPORT_RAM_VECTOR_TABLE (0|1) Tell if the Vector Table lives in RAM

Device variables

CMake variable Value Description
SUPPORT_DEVICE_USB (0|1) Add USB Device support
SUPPORT_DEVICE_USB_SERIAL (0|1) Add Serial USB Device support
SUPPORT_DEVICE_USB_HID (0|1) Add HID USB Device support
SUPPORT_DEVICE_USB_DFU (0|1) Add DFU USB Device support
SUPPORT_DEVICE_USB_MSC (0|1) Add MSC USB Device support
SUPPORT_BLE_CENTRAL (0|1) Add Bluetooth Low Energy (BLE) Central support
SUPPORT_BLE_PERIPHERAL (0|1) Add Bluetooth Low Energy (BLE) Peripheral support
SUPPORT_I2C (0|1) Add I2C support
SUPPORT_SPI (0|1) Add SPI support

USB Specific Variables

CMake variable Value Description
DEVICE_USB_VENDOR_ID integer USB Vendor ID
DEVICE_USB_PRODUCT_ID integer USB Product ID
DEVICE_USB_DEVICE_REVISION integer USB Device Revision
DEVICE_USB_DEVICE_MANUFACTURER string USB Device Manufacturer string
DEVICE_USB_DEVICE_PRODUCT string USB Device Product string
DEVICE_USB_DEVICE_SERIAL string USB Device Serial Number string
DEVICE_USB_HID_INPUT_REPORT_SIZE integer Size of the USB HID Input Report
DEVICE_USB_HID_OUTPUT_REPORT_SIZE integer Size of the USB HID Output Report
DEVICE_USB_HID_FEATURE_REPORT_SIZE integer Size of the USB HID Feature Report

RTOS variables

CMake variable Value Description
SUPPORT_RTOS_NO_CMSIS (0|1) Disable CMSIS wrapper of the RTOS.
RTOS_CLOCK integer Frequency in Hz of the processor
RTOS_TICK integer When OS_SYSTICK is not set we might need to provide a different tick
RTOS_TASK_COUNT integer Number of RTOS task
RTOS_TASK_STACK_SIZE integer Size in bytes of the task (excluding the main and private tasks)
RTOS_MAIN_STACK_SIZE integer Size in bytes of the main task
RTOS_IDLE_STACK_SIZE integer Size in bytes of the idle task
RTOS_TIMER_STACK_SIZE integer Size in bytes of the timer task
RTOS_TIMER_CALLBACK_COUNT integer Number of concurrent active timer callback functions
RTOS_TASK_PRIVATE_STACK_COUNT integer Number of private tasks
RTOS_TASK_PRIVATE_STACK_SIZE integer Size in bytes of the private task
RTOS_STACK_WATERMARK (0|1) Disable/Enable the stack watermark

Device Specific variables

CMake variable Value Description
SUPPORT_NXP_USE_XTAL (0|1) Use external oscillator instead of the internal one

Debug

Run an application from RAM

To build the firmware to run from RAM:

cmake -DAPPLICATION=<application_vendor/application_name> -DSUPPORT_RUN_FROM_RAM=1 .. && make

Debug with GDB

  1. Start the debugger server
pyocd-gdbserver
  1. Start the GDB client
arm-none-eabi-gdb <filepath_of_the_ELF_application>
target remote localhost:3333
continue
  • Examples of some GDB commands:
(gdb) print $pc
$1 = (void (*)()) 0x200000d8
(gdb) print $sp
$2 = (void *) 0x1fffff58
(gdb) print/x *0x400
$3 = 0x21004692
(gdb) set {int}0x20000000 = 1
(gdb) set arm force-mode thumb
(gdb) display /10i 0x0
1: x/10i 0x0
   0x0 <__Vectors>:	strh	r0, [r0, #0]
   0x2 <__Vectors+2>:	movs	r0, #0
   0x4 <__Vectors+4>:	lsls	r1, r1, #24
   0x6 <__Vectors+6>:	movs	r0, r0
   0x8 <__Vectors+8>:	lsls	r1, r7, #24
   0xa <__Vectors+10>:	movs	r0, r0
   0xc <__Vectors+12>:	adds	r0, #37	; 0x25
   0xe <__Vectors+14>:	movs	r0, r0
   0x10 <__Vectors+16>:	movs	r0, r0
   0x12 <__Vectors+18>:	movs	r0, r0
(gdb) display /10i $pc
2: x/10i $pc
=> 0x1a96 <ARM_USART_Send+18>:	ldr	r3, [sp, #16]
   0x1a98 <ARM_USART_Send+20>:	ldrb	r3, [r3, #0]
   0x1a9a <ARM_USART_Send+22>:	mov	r0, r3
   0x1a9c <ARM_USART_Send+24>:	bl	0x2da8 <app_uart_put>
   0x1aa0 <ARM_USART_Send+28>:	str	r0, [sp, #12]
   0x1aa2 <ARM_USART_Send+30>:	ldr	r3, [sp, #12]
   0x1aa4 <ARM_USART_Send+32>:	cmp	r3, #0
   0x1aa6 <ARM_USART_Send+34>:	bne.n	0x1a96 <ARM_USART_Send+18>
   0x1aa8 <ARM_USART_Send+36>:	ldr	r3, [sp, #16]
   0x1aaa <ARM_USART_Send+38>:	adds	r3, #1
  • Dump memory into a file:
(gdb) dump binary memory /tmp/gdb.bin 0x0 0x1000

Debug UART Settings

All the board UARTs are set with the following settings:

  • Baud Rate: 115200
  • Data Bits: 8
  • Stop Bits: 1
  • Parity: None
  • Flow Control: None