This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

newlib vs SEGGER runtime Library cJSON library

Hi DevZone,

We are trying to move our existing application from SEGGER compilation to a GCC build for CI / CD purposes. However we are seeing a strange bug with uint64_t types and our cJSON library.

We can compile the following snippet in both applications, however, only the SEGGER build succesfully prints out the formatted cJSON string:

cJSON *json_object = cJSON_CreateObject();

/* Timestamp and ID are the same for all measurement types */
uint64_t integer_64 = (((uint64_t)1) << 63);
uint32_t integer_32 = 684956;
cJSON_AddNumberToObject(json_object, "integer64", integer_64);
cJSON_AddNumberToObject(json_object, "integer32", integer_32);

char* json_string = cJSON_PrintUnformatted(json_object);
if (!json_string) {
	NRF_LOG_ERROR("Could not create string");
}
NRF_LOG_INFO("%llu: %s", integer_64, json_string);

Which outputs:

GCC Output:
<info> main: 0: {"integer64":,"integer32":684956}

SEGGER Output:
<info> main: 0: {"integer64":9223372036854776000,"integer32":684956}

I tried printing out NRF_LOG_INFO("Newlib: %s", _NEWLIB_VERSION); and it seems that SEGGER is using a different libc implementation as __NEWLIB_VERSION is only defined in the GCC build, so this must be a clue in what's going wrong. I don't know why newlib wouldn't work with the above code. 

Any help in figuring out how to get this working under GCC? Thank you for the help.

Best regards,

Mattia

  • I've also found this issue: https://github.com/DaveGamble/cJSON/issues/162 which seems to indicate uint64_t shouldn't even be supported under cJSON...

  • Hi,

    Is there any answer to this? We are blocked by this in moving forward with our CI. I can provide some extra info on my environment:

    - nrf5_sdk_17.0.2_d674dde using the embedded cJSON library

    - GCC 9

    /**
     * Copyright (c) 2014 - 2020, Nordic Semiconductor ASA
     *
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     *
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     *
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     *
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     *
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     *
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */
    /** @file
     *
     * @defgroup blinky_example_main main.c
     * @{
     * @ingroup blinky_example
     * @brief Blinky Example Application main file.
     *
     * This file contains the source code for a sample application to blink LEDs.
     *
     */
    
    #include <stdbool.h>
    #include <stdint.h>
    #include "nrf_delay.h"
    #include "boards.h"
    
    #ifdef NRF_LOG_USES_TIMESTAMP
    #undef NRF_LOG_USES_TIMESTAMP
    #endif
    
    #define NRF_LOG_MODULE_NAME tests
    #define NRF_LOG_LEVEL 4
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    NRF_LOG_MODULE_REGISTER();
    
    #include "cJSON.h"
    
    static char *json_string;
    
    /**
     * @brief Function for application main entry.
     */
    int main(void)
    {
    	NRF_LOG_DEFAULT_BACKENDS_INIT();
    	cJSON *json_object = cJSON_CreateObject();
    
    	/* Timestamp and ID are the same for all measurement types */
    	uint64_t integer_64 = (((uint64_t)1) << 63);
    	uint32_t integer_32 = 684956;
    	cJSON_AddNumberToObject(json_object, "integer64", integer_64);
    	cJSON_AddNumberToObject(json_object, "integer32", integer_32);
    
    	json_string = cJSON_PrintUnformatted(json_object);
    	if (!json_string) {
    		NRF_LOG_ERROR("Could not create string");
    	}
    	NRF_LOG_INFO("sizeof 64: %i, %llu: %s", sizeof(integer_64), integer_64, json_string);
    	// NRF_LOG_FLUSH();
    
    	// if (strcmp("9223372036854776000", 
    
    }
    
    /**
     *@}
     **/
    
    blinky_gcc_nrf52.ld

    PROJECT_NAME     := blinky_FreeRTOS_pca10056
    TARGETS          := nrf52840_xxaa
    OUTPUT_DIRECTORY := _build
    
    SDK_ROOT := ../../../../
    PROJ_DIR := ..
    
    $(OUTPUT_DIRECTORY)/nrf52840_xxaa.out: \
      LINKER_SCRIPT  := blinky_FreeRTOS_gcc_nrf52.ld
    
    # Source files common to all targets
    SRC_FILES += \
      $(SDK_ROOT)/modules/nrfx/mdk/gcc_startup_nrf52840.S \
      $(SDK_ROOT)/components/libraries/log/src/nrf_log_frontend.c \
      $(SDK_ROOT)/components/libraries/log/src/nrf_log_str_formatter.c \
      $(SDK_ROOT)/components/boards/boards.c \
      $(SDK_ROOT)/external/freertos/source/croutine.c \
      $(SDK_ROOT)/external/freertos/source/event_groups.c \
      $(SDK_ROOT)/external/freertos/source/portable/MemMang/heap_1.c \
      $(SDK_ROOT)/external/freertos/source/list.c \
      $(SDK_ROOT)/external/freertos/portable/GCC/nrf52/port.c \
      $(SDK_ROOT)/external/freertos/portable/CMSIS/nrf52/port_cmsis.c \
      $(SDK_ROOT)/external/freertos/portable/CMSIS/nrf52/port_cmsis_systick.c \
      $(SDK_ROOT)/external/freertos/source/queue.c \
      $(SDK_ROOT)/external/freertos/source/stream_buffer.c \
      $(SDK_ROOT)/external/freertos/source/tasks.c \
      $(SDK_ROOT)/external/freertos/source/timers.c \
      $(SDK_ROOT)/components/libraries/button/app_button.c \
      $(SDK_ROOT)/components/libraries/util/app_error.c \
      $(SDK_ROOT)/components/libraries/util/app_error_handler_gcc.c \
      $(SDK_ROOT)/components/libraries/util/app_error_weak.c \
      $(SDK_ROOT)/components/libraries/timer/app_timer_freertos.c \
      $(SDK_ROOT)/components/libraries/util/app_util_platform.c \
      $(SDK_ROOT)/components/libraries/util/nrf_assert.c \
      $(SDK_ROOT)/components/libraries/atomic/nrf_atomic.c \
      $(SDK_ROOT)/components/libraries/balloc/nrf_balloc.c \
      $(SDK_ROOT)/external/fprintf/nrf_fprintf.c \
      $(SDK_ROOT)/external/fprintf/nrf_fprintf_format.c \
      $(SDK_ROOT)/components/libraries/memobj/nrf_memobj.c \
      $(SDK_ROOT)/components/libraries/ringbuf/nrf_ringbuf.c \
      $(SDK_ROOT)/components/libraries/strerror/nrf_strerror.c \
      $(SDK_ROOT)/integration/nrfx/legacy/nrf_drv_clock.c \
      $(SDK_ROOT)/components/drivers_nrf/nrf_soc_nosd/nrf_nvic.c \
      $(SDK_ROOT)/components/drivers_nrf/nrf_soc_nosd/nrf_soc.c \
      $(SDK_ROOT)/modules/nrfx/soc/nrfx_atomic.c \
      $(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_clock.c \
      $(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_gpiote.c \
      $(SDK_ROOT)/components/libraries/bsp/bsp.c \
      $(SDK_ROOT)/modules/nrfx/mdk/system_nrf52840.c \
      $(SDK_ROOT)/components/libraries/queue/nrf_queue.c
    
    # Include folders common to all targets
    INC_FOLDERS += \
      $(PROJ_DIR)/config \
      $(SDK_ROOT)/components \
      $(SDK_ROOT)/modules/nrfx/mdk \
      $(SDK_ROOT)/components/libraries/timer \
      $(SDK_ROOT)/components/libraries/strerror \
      $(SDK_ROOT)/components/toolchain/cmsis/include \
      $(SDK_ROOT)/external/freertos/source/include \
      $(SDK_ROOT)/external/freertos/config \
      $(SDK_ROOT)/components/libraries/util \
      $(PROJ_DIR)/config \
      $(SDK_ROOT)/components/libraries/balloc \
      $(SDK_ROOT)/components/libraries/ringbuf \
      $(SDK_ROOT)/modules/nrfx/hal \
      $(SDK_ROOT)/components/libraries/bsp \
      $(SDK_ROOT)/components/libraries/log \
      $(SDK_ROOT)/components/libraries/button \
      $(SDK_ROOT)/modules/nrfx \
      $(SDK_ROOT)/components/libraries/experimental_section_vars \
      $(SDK_ROOT)/integration/nrfx/legacy \
      $(SDK_ROOT)/external/freertos/portable/CMSIS/nrf52 \
      $(SDK_ROOT)/integration/nrfx \
      $(SDK_ROOT)/components/drivers_nrf/nrf_soc_nosd \
      $(SDK_ROOT)/components/libraries/atomic \
      $(SDK_ROOT)/components/boards \
      $(SDK_ROOT)/components/libraries/memobj \
      $(SDK_ROOT)/external/freertos/portable/GCC/nrf52 \
      $(SDK_ROOT)/modules/nrfx/drivers/include \
      $(SDK_ROOT)/external/fprintf \
      $(SDK_ROOT)/components/libraries/log/src \
      $(SDK_ROOT)/components/libraries/delay \
      $(SDK_ROOT)/external/segger_rtt \
      $(SDK_ROOT)/components/libraries/queue
    
    # Test includes and sources
    SRC_FILES += \
      $(PROJ_DIR)/app_files/dali/dali.c \
      $(PROJ_DIR)/app_files/dali/dali_transport.c \
      $(PROJ_DIR)/app_files/dali/dali_instance.c \
      $(PROJ_DIR)/app_files/dali/dali_light_sensor.c \
      $(PROJ_DIR)/app_files/dali/dali_occupancy_sensor.c \
      $(PROJ_DIR)/app_files/dali/dali_control_device.c \
      $(PROJ_DIR)/app_files/sensors/pir.c \
      $(PROJ_DIR)/tests/test_dali.c \
      $(SDK_ROOT)/components/libraries/log/src/nrf_log_default_backends.c \
      $(SDK_ROOT)/components/libraries/log/src/nrf_log_backend_rtt.c \
      $(SDK_ROOT)/components/libraries/log/src/nrf_log_backend_serial.c \
      $(SDK_ROOT)/external/segger_rtt/SEGGER_RTT.c \
      $(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_ppi.c \
      $(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_timer.c \
      $(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_rng.c \
      $(SDK_ROOT)/integration/nrfx/legacy/nrf_drv_rng.c
    
    INC_FOLDERS += \
      $(PROJ_DIR)/app_files/dali \
      $(PROJ_DIR)/app_files/sensors \
      $(PROJ_DIR)/tests \
      $(PROJ_DIR)/BAM_Node/s140/config \
      $(SDK_ROOT)/integration/nrfx/legacy
    
    # Libraries common to all targets
    LIB_FILES += \
    
    # Optimization flags
    OPT = -O3 -g3
    # Uncomment the line below to enable link time optimization
    #OPT += -flto
    
    # C flags common to all targets
    CFLAGS += $(OPT)
    CFLAGS += -DDEBUG=1
    CFLAGS += -DBOARD_PCA10056
    CFLAGS += -DCONFIG_GPIO_AS_PINRESET
    CFLAGS += -DFLOAT_ABI_HARD
    CFLAGS += -DFREERTOS
    CFLAGS += -DNRF52840_XXAA
    CFLAGS += -mcpu=cortex-m4
    CFLAGS += -mthumb -mabi=aapcs
    CFLAGS += -Wall -Werror
    CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
    # keep every function in a separate section, this allows linker to discard unused ones
    CFLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing
    CFLAGS += -fno-builtin -fshort-enums
    
    # C++ flags common to all targets
    CXXFLAGS += $(OPT)
    
    # Assembler flags common to all targets
    ASMFLAGS += -g3
    ASMFLAGS += -DDEBUG=1
    ASMFLAGS += -mcpu=cortex-m4
    ASMFLAGS += -mthumb -mabi=aapcs
    ASMFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
    ASMFLAGS += -DBOARD_PCA10056
    ASMFLAGS += -DCONFIG_GPIO_AS_PINRESET
    ASMFLAGS += -DFLOAT_ABI_HARD
    ASMFLAGS += -DFREERTOS
    ASMFLAGS += -DNRF52840_XXAA
    # Linker flags
    LDFLAGS += $(OPT)
    LDFLAGS += -mthumb -mabi=aapcs -L$(SDK_ROOT)/modules/nrfx/mdk -T$(LINKER_SCRIPT)
    LDFLAGS += -mcpu=cortex-m4
    LDFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
    # let linker dump unused sections
    LDFLAGS += -Wl,--gc-sections
    # use newlib in nano version
    LDFLAGS += --specs=nano.specs
    
    nrf52840_xxaa: CFLAGS += -D__HEAP_SIZE=8192
    nrf52840_xxaa: CFLAGS += -D__STACK_SIZE=8192
    nrf52840_xxaa: ASMFLAGS += -D__HEAP_SIZE=8192
    nrf52840_xxaa: ASMFLAGS += -D__STACK_SIZE=8192
    
    # Add standard libraries at the very end of the linker input, after all objects
    # that may need symbols provided by these libraries.
    LIB_FILES += -lc -lnosys -lm
    
    
    .PHONY: default help
    
    # Default target - first one defined
    default: nrf52840_xxaa
    
    # Print all targets that can be built
    help:
    	@echo following targets are available:
    	@echo		nrf52840_xxaa
    	@echo		sdk_config - starting external tool for editing sdk_config.h
    	@echo		flash      - flashing binary
    
    TEMPLATE_PATH := $(SDK_ROOT)/components/toolchain/gcc
    
    include $(TEMPLATE_PATH)/Makefile.common
    
    $(foreach target, $(TARGETS), $(call define_target, $(target)))
    
    .PHONY: flash erase
    
    # Flash the program
    flash: default
    	@echo Flashing: $(OUTPUT_DIRECTORY)/nrf52840_xxaa.hex
    	nrfjprog -f nrf52 --program $(OUTPUT_DIRECTORY)/nrf52840_xxaa.hex --sectorerase
    	nrfjprog -f nrf52 --reset
    
    erase:
    	nrfjprog -f nrf52 --eraseall
    
    SDK_CONFIG_FILE := ../config/sdk_config.h
    CMSIS_CONFIG_TOOL := $(SDK_ROOT)/external_tools/cmsisconfig/CMSIS_Configuration_Wizard.jar
    sdk_config:
    	java -jar $(CMSIS_CONFIG_TOOL) $(SDK_CONFIG_FILE)
    

  • Hello,

    Nordic is not responsible for the libc implementation and what is supported. This is something you need to ask the developers of the toolchain about.

    What you can try is either disable the newlib nano flag in the makefile, to compile the full newlib instead of the nano version, or you can find a workaround where you for instance print the uint64 number as two 32 bit numbers instead.

Related