3

I've got a Stellaris Launchpad board with a Cortex M4F on it. I want to use FreeRTOS on the board with some of my own C++ code. FreeRTOS, however, is written in C so will not compile with G++; I've tried.

I read somewhere that I should compile FreeRTOS with gcc, then compile my application code with g++, then pull them together using the linker. This makes sense, but I'm really struggling with how to put this behaviour down in a Makefile. I found this Makefile which just confused me more.

Currently, I'm just using the Makefile distributed with the FreeRTOS example in the Stellaris demos, but that's set up for C code only. This question is asking something similar to what I'm after, but I can't wrap my head around how to compile FreeRTOS with GCC and the rest of my code with G++.

FreeRTOS apparently wraps it's code in extern "C" { } directives but attempting using G++ still fails when compiling the FreeRTOS codebase.

I don't like posting large amounts of code on SO, but the more information the better I suppose. The Stellaris demos have a common makedefs file:

# Get the operating system name.  If this is Cygwin, the .d files will be
# munged to convert c: into /cygdrive/c so that "make" will be happy with the
# auto-generated dependencies.
os:=${shell uname -s}

# The compiler to be used.
ifndef COMPILER
COMPILER=gcc
endif

# Definitions for using GCC.
ifeq (${COMPILER}, g++)

# Get the prefix for the tools to use.  Use arm-stellaris-eabi if it exists,
# otherwise fall back to arm-none-eabi.
PREFIX=${shell type arm-stellaris-eabi-gcc > /dev/null 2>&1 && \
         echo arm-stellaris-eabi || echo arm-none-eabi}

# The command for calling the compiler.
CC=${PREFIX}-${COMPILER}

# The location of the C compiler
# ARMGCC_ROOT is used by some makefiles that need to know where the compiler
# is installed.  It is not used further for normal stellarisware apps
ARMGCC_ROOT:=${shell dirname '${shell sh -c "which ${CC}"}'}/..

# Determine the compiler CPU/FPU options based on the processor variant.
ifndef VARIANT
CPU=-mcpu=cortex-m3
FPU=
else
ifeq (${VARIANT}, cm3)
CPU=-mcpu=cortex-m3
FPU=
else
ifeq (${VARIANT}, cm4f)
CPU=-mcpu=cortex-m4
FPU=-mfpu=fpv4-sp-d16 -mfloat-abi=softfp
else
$(error Unknown processor variant ${VARIANT}!)
endif
endif
endif

# The flags passed to the assembler.
AFLAGS=-mthumb \
       ${CPU}  \
       ${FPU}  \
       -MD

# The flags passed to the compiler.
CFLAGS=-mthumb             \
       ${CPU}              \
       ${FPU}              \
       -Os                 \
       -ffunction-sections \
       -fdata-sections     \
       -MD                 \
       -Wall               \
       -pedantic           \
       -DPART_${PART}      \
       -c

# The command for calling the library archiver.
AR=${PREFIX}-ar

# The command for calling the linker.
LD=${PREFIX}-ld

# The flags passed to the linker.
LDFLAGS=--gc-sections

# Get the location of libgcc.a from the GCC front-end.
LIBGCC=${shell ${CC} ${CFLAGS} -print-libgcc-file-name}

# Get the location of libc.a from the GCC front-end.
LIBC=${shell ${CC} ${CFLAGS} -print-file-name=libc.a}

# Get the location of libm.a from the GCC front-end.
LIBM=${shell ${CC} ${CFLAGS} -print-file-name=libm.a}

# The command for extracting images from the linked executables.
OBJCOPY=${PREFIX}-objcopy

# Tell the compiler to include debugging information if the DEBUG environment
# variable is set.
ifdef DEBUG
CFLAGS+=-g -D DEBUG
endif

# Add the tool specific CFLAGS.
CFLAGS+=${CFLAGSgcc}

# Add the include file paths to AFLAGS and CFLAGS.
AFLAGS+=${patsubst %,-I%,${subst :, ,${IPATH}}}
CFLAGS+=${patsubst %,-I%,${subst :, ,${IPATH}}}

# The rule for building the object file from each C source file.
${COMPILER}${SUFFIX}/%.o: %.c
    @if [ 'x${VERBOSE}' = x ];                            \
     then                                                 \
         echo "  CC    ${<}";                             \
     else                                                 \
         echo ${CC} ${CFLAGS} -D${COMPILER} -o ${@} ${<}; \
     fi
    @${CC} ${CFLAGS} -D${COMPILER} -o ${@} ${<}
ifneq ($(findstring CYGWIN, ${os}), )
    @sed -i -r 's/ ([A-Za-z]):/ \/cygdrive\/\1/g' ${@:.o=.d}
endif

# The rule for building the object file from each assembly source file.
${COMPILER}${SUFFIX}/%.o: %.S
    @if [ 'x${VERBOSE}' = x ];                               \
     then                                                    \
         echo "  AS    ${<}";                                \
     else                                                    \
         echo ${CC} ${AFLAGS} -D${COMPILER} -o ${@} -c ${<}; \
     fi
    @${CC} ${AFLAGS} -D${COMPILER} -o ${@} -c ${<}
ifneq ($(findstring CYGWIN, ${os}), )
    @sed -i -r 's/ ([A-Za-z]):/ \/cygdrive\/\1/g' ${@:.o=.d}
endif

# The rule for creating an object library.
${COMPILER}${SUFFIX}/%.a:
    @if [ 'x${VERBOSE}' = x ];     \
     then                          \
         echo "  AR    ${@}";      \
     else                          \
         echo ${AR} -cr ${@} ${^}; \
     fi
    @${AR} -cr ${@} ${^}

# The rule for linking the application.
${COMPILER}${SUFFIX}/%.axf:
    @if [ 'x${SCATTERgcc_${notdir ${@:.axf=}}}' = x ];                    \
     then                                                                 \
         ldname="${ROOT}/${COMPILER}/standalone.ld";                      \
     else                                                                 \
         ldname="${SCATTERgcc_${notdir ${@:.axf=}}}";                     \
     fi;                                                                  \
     if [ 'x${VERBOSE}' = x ];                                            \
     then                                                                 \
         echo "  LD    ${@} ${LNK_SCP}";                                  \
     else                                                                 \
         echo ${LD} -T $${ldname}                                         \
              --entry ${ENTRY_${notdir ${@:.axf=}}}                       \
              ${LDFLAGSgcc_${notdir ${@:.axf=}}}                          \
              ${LDFLAGS} -o ${@} $(filter %.o %.a, ${^})                  \
              '${LIBM}' '${LIBC}' '${LIBGCC}';                            \
     fi;                                                                  \
    ${LD} -T $${ldname}                                                   \
          --entry ${ENTRY_${notdir ${@:.axf=}}}                           \
          ${LDFLAGSgcc_${notdir ${@:.axf=}}}                              \
          ${LDFLAGS} -o ${@} $(filter %.o %.a, ${^})                      \
          '${LIBM}' '${LIBC}' '${LIBGCC}'
    @${OBJCOPY} -O binary ${@} ${@:.axf=.bin}
endif

The above file is included by the Makefile itself (below):

# Defines the part type that this project uses.
PART=LM4F120H5QR

# Set the processor variant.
VARIANT=cm4f

# The base directory for StellarisWare.
ROOT=../lib

COMPILER=gcc

# Include the common make definitions.
include ${ROOT}/makedefs

# Where to find source files that do not live in this directory.
VPATH=${ROOT}/FreeRTOS/Source/portable/GCC/ARM_CM4F
VPATH+=${ROOT}/FreeRTOS/Source/portable/MemMang/
VPATH+=${ROOT}/FreeRTOS/Source
VPATH+=${ROOT}/drivers
VPATH+=${ROOT}/utils

# Where to find header files that do not live in the source directory.
IPATH=.
IPATH+=..
IPATH+=${ROOT}
IPATH+=${ROOT}/FreeRTOS/Source/portable/GCC/ARM_CM4F
IPATH+=${ROOT}/FreeRTOS
IPATH+=${ROOT}/FreeRTOS/Source/include
IPATH+=${ROOT}

# The default rule, which causes the FreeRTOS example to be built.
all: ${COMPILER}
all: ${COMPILER}/freertos_demo.axf

# The rule to clean out all the build products.
clean:
    @rm -rf ${COMPILER} ${wildcard *~}

# The rule to create the target directory.
${COMPILER}:
    @mkdir -p ${COMPILER}

# Rules for building the FreeRTOS example.
${COMPILER}/freertos_demo.axf: ${COMPILER}/buttons.o
${COMPILER}/freertos_demo.axf: ${COMPILER}/freertos_demo.o
${COMPILER}/freertos_demo.axf: ${COMPILER}/heap_2.o
${COMPILER}/freertos_demo.axf: ${COMPILER}/led_task.o
${COMPILER}/freertos_demo.axf: ${COMPILER}/list.o
${COMPILER}/freertos_demo.axf: ${COMPILER}/port.o
${COMPILER}/freertos_demo.axf: ${COMPILER}/queue.o
${COMPILER}/freertos_demo.axf: ${COMPILER}/rgb.o
${COMPILER}/freertos_demo.axf: ${COMPILER}/startup_${COMPILER}.o
${COMPILER}/freertos_demo.axf: ${COMPILER}/switch_task.o
${COMPILER}/freertos_demo.axf: ${COMPILER}/tasks.o
${COMPILER}/freertos_demo.axf: ${COMPILER}/uartstdio.o
${COMPILER}/freertos_demo.axf: ${COMPILER}/ustdlib.o
${COMPILER}/freertos_demo.axf: ${ROOT}/driverlib/${COMPILER}-cm4f/libdriver-cm4f.a
${COMPILER}/freertos_demo.axf: freertos_demo.ld
SCATTERgcc_freertos_demo=freertos_demo.ld
ENTRY_freertos_demo=ResetISR
CFLAGSgcc=-DTARGET_IS_BLIZZARD_RA1

# Include the automatically generated dependency files.
ifneq (${MAKECMDGOALS},clean)
-include ${wildcard ${COMPILER}/*.d} __dummy__
endif

Some of my directory structure is as follows:

Projects/
    lib/
        FreeRTOS/
        driverlib/
        drivers/
        inc/
        utils/
        makedefs
    TestProject/
        loads.cpp
        of.cpp
        files.h
        here.h
        Makefile

If I'm correct in saying that FreeRTOS must be compiled with GCC, then linked with my C++ project code, how can I modify my current Makefile to do that? I want a reasonably generic solution so I can re-use it in other projects, but I don't know much about the C/C++ build process or Makefiles, hence me asking this (lengthy) question. I don't want/mean to sound like I'm asking a "do this for me" question, but I really cannot work out how to do this despite searching on Google and on SO.

Community
  • 1
  • 1
Bojangles
  • 99,427
  • 50
  • 170
  • 208
  • After a quick scanning of makefiles I'd advice to set environment variable COMPILER to g++, however i'm not very good in makefiles... – PiotrNycz Nov 18 '12 at 17:22
  • @PiotrNycz I forgot to mention that I tried that, but FreeRTOS won't compile on account of being written in C. – Bojangles Nov 18 '12 at 17:25

1 Answers1

0

I don't use FreeRTOS with C++ myself, but it has been discussed many times on the FreeRTOS forum and there are a few C++ frameworks in the FreeRTOS Interactive site.

Richard
  • 126
  • 1
  • Thanks for the suggestion, but after a quick trawl, the forums seem to be full of unanswered questions and old posts `:(`. – Bojangles Nov 19 '12 at 12:26
  • 1
    How about this one? [link](http://www.freertos.org/FreeRTOS_Support_Forum_Archive/July_2010/freertos_Is_it_possible_create_freertos_task_in_c_3778071.html) – peter_mcc Feb 15 '13 at 09:48