FreeRTOS 10 on a SAMD21

maxgerhardt wrote on Monday, December 18, 2017:

I am currently working on integrating FreeRTOS10 with the Arduino environment (over platformio) on an Adafruit Feather M0 (ATSAMD21G18, ARM Cortex-M0+ Core, 48MHz, 256K Flash, 32K RAM). I am having problems getting the assembler instructions to compile.

I am using the port file from portable/GCC/ARM_CM0. Without any modifications, the compilation fails with following errors (gcc version 6.3.1 20170215):

arm-none-eabi-gcc -o .pioenvs/adafruit_feather_m0/lib/FreeRTOS/port.o -c -std=gnu11 -ffunction-sections -fdata-sections -Wall -mthumb -mcpu=cortex-m0plus -nostdlib --param max-inline-insns-single=500 -O1 -Wall -Wextra -DF_CPU=48000000L -DUSBCON -DPLATFORMIO=30500 -DARDUINO_ARCH_SAMD -DARDUINO_SAMD_ZERO -DARDUINO_SAMD_FEATHER_M0 -D__SAMD21G18A__ -DARDUINO=10616 -DUSB_VID=0x239A -DUSB_PID=0x800B "-DUSB_PRODUCT=\"Adafruit Feather M0\"" -DUSB_MANUFACTURER=\"Adafruit\" -Ilib/FreeRTOS/src -I/home/max/.platformio/packages/framework-arduinosam/cores/adafruit -I/home/max/.platformio/packages/framework-arduinosam/system/samd/CMSIS/CMSIS/Include -I/home/max/.platformio/packages/framework-arduinosam/system/samd/CMSIS-Atmel/CMSIS/Device/ATMEL -I/home/max/.platformio/packages/framework-arduinosam/variants/feather_m0 lib/FreeRTOS/src/port.c

/tmp/cc3dVYt3.s: Assembler messages:
/tmp/cc3dVYt3.s:50: Error: cannot honor width suffix -- `mov r3,#0'
/tmp/cc3dVYt3.s:54: Error: lo register required -- `add r3,r3,#1'
/tmp/cc3dVYt3.s:86: Error: lo register required -- `sub r3,r0,#4'
/tmp/cc3dVYt3.s:87: Error: cannot honor width suffix -- `mov r4,#128'
/tmp/cc3dVYt3.s:88: Error: cannot honor width suffix -- `lsl r4,r4,#17'
/tmp/cc3dVYt3.s:90: Error: lo register required -- `sub r3,r3,#4'
/tmp/cc3dVYt3.s:92: Error: lo register required -- `sub r3,r3,#4'
/tmp/cc3dVYt3.s:95: Error: lo register required -- `sub r3,r3,#20'
/tmp/cc3dVYt3.s:97: Error: lo register required -- `sub r0,r0,#64'
/tmp/cc3dVYt3.s:125: Error: cannot honor width suffix -- `mov r2,#255'
/tmp/cc3dVYt3.s:126: Error: cannot honor width suffix -- `lsl r2,r2,#16'
/tmp/cc3dVYt3.s:127: Error: cannot honor width suffix -- `orr r2,r1'
/tmp/cc3dVYt3.s:130: Error: cannot honor width suffix -- `mov r2,#255'
/tmp/cc3dVYt3.s:131: Error: cannot honor width suffix -- `lsl r2,r2,#24'
/tmp/cc3dVYt3.s:132: Error: cannot honor width suffix -- `orr r2,r1'
/tmp/cc3dVYt3.s:135: Error: cannot honor width suffix -- `mov r3,#0'
/tmp/cc3dVYt3.s:142: Error: cannot honor width suffix -- `mov r1,#7'
/tmp/cc3dVYt3.s:149: Error: cannot honor width suffix -- `mov r0,#0'
/tmp/cc3dVYt3.s:172: Error: cannot honor width suffix -- `mov r3,#250'
/tmp/cc3dVYt3.s:173: Error: cannot honor width suffix -- `lsl r3,r3,#2'
/tmp/cc3dVYt3.s:196: Error: cannot honor width suffix -- `mov r2,#128'
/tmp/cc3dVYt3.s:197: Error: cannot honor width suffix -- `lsl r2,r2,#21'
/tmp/cc3dVYt3.s:227: Error: lo register required -- `add r2,r2,#1'
/tmp/cc3dVYt3.s:263: Error: lo register required -- `sub r3,r3,#1'
/tmp/cc3dVYt3.s:369: Error: cannot honor width suffix -- `mov r2,#128'
/tmp/cc3dVYt3.s:370: Error: cannot honor width suffix -- `lsl r2,r2,#21'

The error messages are also depended on the optimization level.

The errors stem from the function xPortPendSVHandler and vPortStartFirstTask. Once I remove the “.syntax unified” as the first line of every “asm volatile (…)” block, the errors change to

/tmp/ccR2bJjp.s: Assembler messages:
/tmp/ccR2bJjp.s:24: Error: instruction not supported in Thumb16 mode -- `adds r0,#32'
/tmp/ccR2bJjp.s:318: Error: instruction not supported in Thumb16 mode -- `subs r0,r0,#32'
/tmp/ccR2bJjp.s:335: Error: instruction not supported in Thumb16 mode -- `adds r0,r0,#16'
/tmp/ccR2bJjp.s:344: Error: instruction not supported in Thumb16 mode -- `subs r0,r0,#32'

Finally, changing “adds” to “add” and “subs” to “sub” lets the code compile. Disassembly shows

00000000 <vPortStartFirstTask>:
   0:	4a0b      	ldr	r2, [pc, #44]	; (30 <pxCurrentTCBConst2>)
   2:	6813      	ldr	r3, [r2, #0]
   4:	6818      	ldr	r0, [r3, #0]
   6:	3020      	adds	r0, #32
   8:	f380 8809 	msr	PSP, r0
   c:	2002      	movs	r0, #2
   e:	f380 8814 	msr	CONTROL, r0
  12:	f3bf 8f6f 	isb	sy
  16:	bc3f      	pop	{r0, r1, r2, r3, r4, r5}
  18:	46ae      	mov	lr, r5
  1a:	bc08      	pop	{r3}
  1c:	bc04      	pop	{r2}
  1e:	b662      	cpsie	i
  20:	4718      	bx	r3

I’m writing this post for the following questions:

  1. Am I using the wrong compiler settings which cause the FreeRTOS provided port.c file to not compile out of the box? Is this maybe something you should fix?
  2. Does the generated byte code look correct?

I’ll provide project files and more infos if needed.

rtel wrote on Monday, December 18, 2017:

Can you try updating your GCC version. I think 7.x is the latest
version and the code was recently updated to ensure it builds with the
latest. For example, the latest version needs ‘adds’ rather than ‘add’
are you commented yours only builds if you take the ‘s’ off.

maxgerhardt wrote on Monday, December 18, 2017:

Thanks, I’ll to try get the newest compiler in my platformio environment, retry compilation and report back tomorrow. I’ll also post my minimal example to show that this doesn’t compile out of the box, with various compiler versions.
Also, the funny thing is although I change “adds” to “add”, the compiler still generates “adds”, if I can trust objdump which disassembles the code to “adds”. On my initial tests, FreeRTOS is in fact functional when making these changes (remove .syntax unified, adds->add, subs->sub).

maxgerhardt wrote on Tuesday, December 19, 2017:

Hi again. I found out a few things:

I thought that I was using the newer GCC 6.3.1 because I installed it, but platformio was in fact still using the old compiler. The port.c file compiles out-of-the box when actually using GCC 6.3.1.

The build fails when building with gcc version 4.8.4 20140725. This toolchain is e.g. used in the Arduino IDE. I have replicated the issue by creating a minimal example with the original code and a Makefile which uses gcc 4.8 and 6.3 on the same source file with the same options. GCC 4.8 fails, GCC 6.3 compiles. (Source: https://pastebin.com/UD8WeEW2 Makefile: https://pastebin.com/Y7JmrZ7L).

So, I don’t really know what to make of this. Once I insert some ASM code, GCC 4.8 goes crazy, throws error messages even changing with optimization level. I’ll just use the newer compiler version and move on.