Home

Awesome

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

Support

Status

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

Toolchain / Host

BoardLinux - GCCLinux - LLVMWindows
AppNearMe MicroNFCBoardPassPassPass
Freescale Freedom KL25PassPassPass
Nordic nRF52 Preview DKPassPassPass
NXP LP1768 mbedPassPassPass
ST STM32L476 NucleoPassPassNot Tested

Application

BoardBaremetalCMSIS RTOSFreeRTOS
AppNearMe MicroNFCBoardPassPassFail
Freescale Freedom KL25PassPassPass
Nordic nRF52 Preview DKPassPassPass
NXP LP1768 mbedPassPassPass
ST STM32L476 NucleoPassPassPass

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
cmake -DAPPLICATION=<application_vendor/application_name> -DBOARD=<board_vendor/board_name> ../ && make
cmake -DAPPLICATION=<application_vendor/application_name> ../ && make
cmake -DAPPLICATION=<application_vendor/application_name> -DCMAKE_BUILD_TYPE=Release ../ && make
cmake -DAPPLICATION=<application_vendor/application_name> ../ && make VERBOSE=1
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

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 variableValueDescription
FIRMWARE_HEAPintegerSize in bytes of the firmware heap
FIRMWARE_STACKintegerSize 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_BAUDRATEintegerDebug 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_MAXintegerNumber maximum of PolyMCU Timer tasks (default: 5)
SUPPORT_RTOSstringEnable 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 variableValueDescription
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 variableValueDescription
DEVICE_USB_VENDOR_IDintegerUSB Vendor ID
DEVICE_USB_PRODUCT_IDintegerUSB Product ID
DEVICE_USB_DEVICE_REVISIONintegerUSB Device Revision
DEVICE_USB_DEVICE_MANUFACTURERstringUSB Device Manufacturer string
DEVICE_USB_DEVICE_PRODUCTstringUSB Device Product string
DEVICE_USB_DEVICE_SERIALstringUSB Device Serial Number string
DEVICE_USB_HID_INPUT_REPORT_SIZEintegerSize of the USB HID Input Report
DEVICE_USB_HID_OUTPUT_REPORT_SIZEintegerSize of the USB HID Output Report
DEVICE_USB_HID_FEATURE_REPORT_SIZEintegerSize of the USB HID Feature Report

RTOS variables

CMake variableValueDescription
SUPPORT_RTOS_NO_CMSIS(0|1)Disable CMSIS wrapper of the RTOS.
RTOS_CLOCKintegerFrequency in Hz of the processor
RTOS_TICKintegerWhen OS_SYSTICK is not set we might need to provide a different tick
RTOS_TASK_COUNTintegerNumber of RTOS task
RTOS_TASK_STACK_SIZEintegerSize in bytes of the task (excluding the main and private tasks)
RTOS_MAIN_STACK_SIZEintegerSize in bytes of the main task
RTOS_IDLE_STACK_SIZEintegerSize in bytes of the idle task
RTOS_TIMER_STACK_SIZEintegerSize in bytes of the timer task
RTOS_TIMER_CALLBACK_COUNTintegerNumber of concurrent active timer callback functions
RTOS_TASK_PRIVATE_STACK_COUNTintegerNumber of private tasks
RTOS_TASK_PRIVATE_STACK_SIZEintegerSize in bytes of the private task
RTOS_STACK_WATERMARK(0|1)Disable/Enable the stack watermark

Device Specific variables

CMake variableValueDescription
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
(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
(gdb) dump binary memory /tmp/gdb.bin 0x0 0x1000

Debug UART Settings

All the board UARTs are set with the following settings: