Search code examples
c++arduinofreertosmicrochip

Missing binary operator before token "long"


I'm trying to implement FreeRTOS on my Arduino ATmega2560, and during this process, I came across 2 errors that I don't understand. And don't know how to fix. hopefully someone here does. The first error is missing binary operator before token "long".

The error points to the following line in FreeRTOSConfig.h:

#define configCPU_CLOCK_HZ ((unsigned long) 16000000)

And here is the output of the build:

C:\Projects\src\config\FreeRTOSConfig.h(36,39): error: missing binary operator before token "long"
     #define configCPU_CLOCK_HZ ((unsigned long) 16000000)
                                           ^

This define is only used in port.c which has another error that I haven't been able to fix. This error comes from the auto-generated makefile. Not sure if these 2 errors are connected, but better add it here if someone knows how to fix it. The error is:

recipe for target 'src/Core/FreeRTOS/port.o' failed

And this is what I find in the Makefile:

src/Core/FreeRTOS/port.o: ../src/Core/FreeRTOS/port.c
@echo Building file: $<
@echo Invoking: AVR/GNU C Compiler : 5.4.0
$(QUOTE)C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe$(QUOTE)  -x c -DDEBUG -DBOARD=USER_BOARD  -I"C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.7.374\include" -I"../src/ASF/common/boards/user_board" -I"../src/ASF/common/boards" -I"../src/ASF/mega/utils/preprocessor" -I"../src/ASF/mega/utils" -I"../src/ASF/common/utils" -I"../src" -I"../src/config"  -O1 -fdata-sections -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -mrelax -g3 -Wall -mmcu=atmega2560 -B "C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.7.374\gcc\dev\atmega2560" -c -std=gnu99 -fno-strict-aliasing -Wstrict-prototypes -Wmissing-prototypes -Werror-implicit-function-declaration -Wpointer-arith -mrelax -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)"   -o "$@" "$<" 
@echo Finished building: $<

Solution

  • missing binary operator before token "long"

    This error occurs when you try to use the macro in a pre-processor directive. For example, compile the following C++ code:

    #define configCPU_CLOCK_HZ ((unsigned long) 16000000)
    
    #if configCPU_CLOCK_HZ > 0x1000
    #endif
    

    avr-g++ will complain:

    *.cpp:1:39: error: missing binary operator before token "long"
     #define configCPU_CLOCK_HZ ((unsigned long) 16000000)
                                           ^
    *.cpp:3:5: note: in expansion of macro 'configCPU_CLOCK_HZ'
     #if configCPU_CLOCK_HZ > 0x1000
         ^
    

    So the problem is very likely that configCPU_CLOCK_HZ is used in a pre-processor directive like above, but configCPU_CLOCK_HZ is not appropriate for such usage.

    Yet another problem is that the environment that you are using drops a part of the diagnostics.

    16000000 is already of type long because it doesn't fit in int, which is 16-bit type in avr-gcc. So in most cases you can just use plain 16000000.

    If you want something that can be used in preprocessor directives, you can use 16000000ul. Moreover, C99's stdint.h provides macros that yield constants of bit-widths that can be used in preprocessor macros like

    #include <stdint.h>
    #define configCPU_CLOCK_HZ UINT32_C(16000000)
    

    which will expand to an unsigned 32-bit type. Notice however, that older versions of AVR-LibC had a bug with these macros: It just used casts which does not comply to the language standard, which states that [U]INTXX_C must be usable in pre-processor macros.