8 years, 8 months ago.

offline compilation (nRF51-DK)

the exported programs are completely broken. when using the online compiler the resulting binary works. using the binary produced by the offline compilation fails.

at the moment the mbed environment is not really useable in a production environment.

it looks like that the only way is using the nordic sdk and doing everything yourself.

Question relating to:

Bluetooth Low Energy (a.k.a Bluetooth LE, BTLE, Bluetooth Smart)

Fails how? Can you be more specific?

posted by Martin Kojtal 19 Aug 2015

I just gave it a try too... I made a New project for NRF51-DK, based on BLE_LED, updating the libraries, then choose "Export Program" from the dropdown, choose either Keil or gcc-arm-mbedded as the target, then.... nothing happens.

posted by Janek Mann 19 Aug 2015

yes, i can. there was a linker message saying there where duplicated cmsis functions and the makefile points to the wrong softdevice.

posted by robert bouwens 19 Aug 2015

I am seeing the same issue when using the NRF51_DK target. I can export the blinky app from the online ide; run "make" then "make merge" using my local gcc compiler, and download to the target (which correctly runs the app). When I try to export using the workspace_tools/project.py the "make" runs but the "make merge" fails to run (python project.py -m NRF51_DK -p 27 -i gcc_arm). Looking closer at the exported projects: the online export generates a different dir structure than the workspace_tools export.

The make merge fails because the path to the softdevice.hex file is wrong. <from Makefile> SOFTDEVICE = mbed/TARGET_NRF51_DK/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_7_1_0/s110_nrf51822_7.1.0_softdevice.hex But the correct path is mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s110_nrf51822_8_0_0/s110_nrf51822_8.0.0_softdevice.hex Modifying SOFTDEVICE path in the Makefile will allow "make merge" to generate a combined.hex file; but when downloading the combined.hex file to the target, the app does not run (no LEDs blink).

A couple of questions: 1) Why would the online export function create a different dir structure than the workspace_tools export function? 2) How can I get a log from the online export showing the command line parameters used (so I can verify I am using the same target name, etc...)? 3) I used git to download mbed from https://github.com/mbedmicro/mbed; is that the same mbed repo that the online tools use?

Thanks, David.

posted by David Plentovich 01 Sep 2015

you are correct - you should use the softdevice s130 - then it should blink again. cheers robert

posted by robert bouwens 02 Sep 2015

Success. Changing the SOFTDEVICE path to s130 now allows the blinky app to run on the nRF51_DK target. Also was able to get the s110 softdevice to run by following the "Nordic S110 and S130" topic (slightly modified for 32K ram device: different ram length and ignored CC_SYMBOLS flag addition). https://developer.mbed.org/forum/team-63-Bluetooth-Low-Energy-community/topic/17027/ Thanks, David.

posted by David Plentovich 02 Sep 2015

and now one more happy user :-)

posted by robert bouwens 02 Sep 2015

1 Answer

8 years, 7 months ago.

I use the following CMakeLists.txt to build on linux with armgcc. You'll need to edit MBED_SRC_PATH, BLE_API_SRC_PATH, and NRF51822_SRC_PATH; optionally TOOLCHAIN.

This CMakeLists.txt could be placed in the same folder as main.cpp. I create a Build/ subfolder, relative to where CMakeLists.txt is, cd into the Build/ subfolder, and execute cmake ... This generates a makefile.

#
# CMake configuration
#
# Please refer to http://www.cmake.org/cmake/help/documentation.html
# You may also refer to http://www.cmake.org/cmake/help/syntax.html for a quick
# introduction to CMake's syntax.

cmake_minimum_required (VERSION 2.8)

# The name of our project is "BLE_HEART_RATE". CMakeLists files in this project can
# refer to the root source directory of the project as ${BLE_HEART_RATE_SOURCE_DIR}
# and to the root binary directory of the project as ${BLE_HEART_RATE_BINARY_DIR}.
project (BLE_HEART_RATE)

# define some more paths to projects we depend on
set (MBED_SRC_PATH     ${BLE_HEART_RATE_SOURCE_DIR}/../../mbed-src/libraries/mbed)
set (BLE_API_SRC_PATH  ${BLE_HEART_RATE_SOURCE_DIR}/../../BLE_API)
set (NRF51822_SRC_PATH ${BLE_HEART_RATE_SOURCE_DIR}/../../nRF51822)


# It's best to hide all the details of setting up the variable SRCS in a CMake
# macro. The macro can then be called in all the project CMake list files to add
# sources.
#
# The macro first computes the path of the source file relative to the project
# root for each argument. If the macro is invoked from inside a project sub
# directory the new value of the variable SRCS needs to be propagated to the
# parent folder by using the PARENT_SCOPE option.
#
# Source: http://stackoverflow.com/questions/7046956/populating-srcs-from-cmakelists-txt-in-subdirectories
macro (add_sources)
    file (RELATIVE_PATH _relPath "${CMAKE_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
    foreach (_src ${ARGN})
        if (_relPath)
            list (APPEND SRCS "${_relPath}/${_src}")
        else()
            list (APPEND SRCS "${_src}")
        endif()
    endforeach()
    if (_relPath)
        # propagate to parent directory
        set (SRCS ${SRCS} PARENT_SCOPE)
    endif()
endmacro()

# Decide about the actual compilers to be used; uncomment one of the following.
set(TOOLCHAIN armgcc)
#set(TOOLCHAIN armcc)

set(HEX_TARGET         ${PROJECT_NAME}.hex)
set(COMBINED_SD        "combined.hex"
    CACHE FILE         "Output name for the bundled bootloader+softdevice")

if (TOOLCHAIN STREQUAL "armcc")
    set(TOOLCHAIN_SYSROOT /home/rgrover/ext/arm-toolchains/rvct/ARMCompiler_5.03_117_Linux)
    set(CMAKE_CXX_COMPILER ${TOOLCHAIN_SYSROOT}/bin/armcc)
    set(CMAKE_C_COMPILER   ${TOOLCHAIN_SYSROOT}/bin/armcc)
    set(SIZE_COMMAND       size)

    SET(CMAKE_CXX_LINK_FLAGS "--libpath=${TOOLCHAIN_SYSROOT}/lib --info=totals --list=.link_totals.txt --map --scatter ${MBED_SRC_PATH}/targets/cmsis/TARGET_NORDIC/TARGET_MCU_NRF51822/TOOLCHAIN_ARM_STD/TARGET_MCU_NORDIC_16K/nRF51822.sct")

    SET(CMAKE_CXX_LINK_EXECUTABLE
        "armlink <CMAKE_CXX_LINK_FLAGS> <OBJECTS> -o <TARGET>")
elseif(TOOLCHAIN STREQUAL "armgcc")
    set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
    set(CMAKE_C_COMPILER   arm-none-eabi-gcc)
    set(SIZE_COMMAND       arm-none-eabi-size)
    set(OBJCOPY_COMMAND    arm-none-eabi-objcopy)
else()
    message(FATAL_ERROR "failed to match against known toolchains")
endif()

set(MAIN_TARGET        ${PROJECT_NAME}.elf)
enable_language(ASM)

message(STATUS "C compiler  : ${CMAKE_C_COMPILER}")
message(STATUS "C++ compiler: ${CMAKE_CXX_COMPILER}")
message(STATUS "Size command: ${SIZE_COMMAND}")
message(STATUS "Main target : ${MAIN_TARGET}")

############################################################################
# Build type should be clear from here so we
# can continue with selecting include directors, defines
# and other compiler/linker flags ...
############################################################################
# include directories
include_directories(
    ${BLE_HEART_RATE_SOURCE_DIR}
    ${MBED_SRC_PATH}/
    ${MBED_SRC_PATH}/api
    ${MBED_SRC_PATH}/common
    ${MBED_SRC_PATH}/hal
    ${MBED_SRC_PATH}/targets
    ${MBED_SRC_PATH}/targets/cmsis
    ${MBED_SRC_PATH}/targets/cmsis/TARGET_NORDIC
    ${MBED_SRC_PATH}/targets/cmsis/TARGET_NORDIC/TARGET_MCU_NRF51822
    ${MBED_SRC_PATH}/targets/hal
    ${MBED_SRC_PATH}/targets/hal/TARGET_NORDIC
    ${MBED_SRC_PATH}/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822
    ${MBED_SRC_PATH}/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib
    ${MBED_SRC_PATH}/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/nordic_sdk/components/libraries/crc16
    ${MBED_SRC_PATH}/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/nordic_sdk/components/libraries/scheduler
    ${MBED_SRC_PATH}/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/nordic_sdk/components/libraries/util
    ${MBED_SRC_PATH}/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/TARGET_NRF51822_MKIT
    ${BLE_API_SRC_PATH}
    ${NRF51822_SRC_PATH}/source/
    ${NRF51822_SRC_PATH}/source/btle
    ${NRF51822_SRC_PATH}/source/btle/custom
    ${NRF51822_SRC_PATH}/source/common
    ${NRF51822_SRC_PATH}/source/nordic
    ${NRF51822_SRC_PATH}/source/nordic-sdk/components/
    ${NRF51822_SRC_PATH}/source/nordic-sdk/components/ble
    ${NRF51822_SRC_PATH}/source/nordic-sdk/components/ble/ble_services/ble_dfu
    ${NRF51822_SRC_PATH}/source/nordic-sdk/components/ble/ble_radio_notification
    ${NRF51822_SRC_PATH}/source/nordic-sdk/components/ble/common
    ${NRF51822_SRC_PATH}/source/nordic-sdk/components/ble/device_manager
    ${NRF51822_SRC_PATH}/source/nordic-sdk/components/ble/device_manager/config
    ${NRF51822_SRC_PATH}/source/nordic-sdk/components/drivers_nrf
    ${NRF51822_SRC_PATH}/source/nordic-sdk/components/drivers_nrf/ble_flash
    ${NRF51822_SRC_PATH}/source/nordic-sdk/components/drivers_nrf/hal
    ${NRF51822_SRC_PATH}/source/nordic-sdk/components/drivers_nrf/pstorage
    ${NRF51822_SRC_PATH}/source/nordic-sdk/components/drivers_nrf/pstorage/config
    ${NRF51822_SRC_PATH}/source/nordic-sdk/components/libraries
    ${NRF51822_SRC_PATH}/source/nordic-sdk/components/libraries/bootloader_dfu
    ${NRF51822_SRC_PATH}/source/nordic-sdk/components/libraries/bootloader_dfu/hci_transport
    ${NRF51822_SRC_PATH}/source/nordic-sdk/components/libraries/crc16
    ${NRF51822_SRC_PATH}/source/nordic-sdk/components/libraries/gpiote
    ${NRF51822_SRC_PATH}/source/nordic-sdk/components/libraries/hci
    ${NRF51822_SRC_PATH}/source/nordic-sdk/components/libraries/scheduler
    ${NRF51822_SRC_PATH}/source/nordic-sdk/components/libraries/util
    ${NRF51822_SRC_PATH}/source/nordic-sdk/components/softdevice
    ${NRF51822_SRC_PATH}/source/nordic-sdk/components/softdevice/common
    ${NRF51822_SRC_PATH}/source/nordic-sdk/components/softdevice/common/softdevice_handler
    ${NRF51822_SRC_PATH}/source/nordic-sdk/components/softdevice/s130
    ${NRF51822_SRC_PATH}/source/nordic-sdk/components/softdevice/s130/include
)
if (TOOLCHAIN STREQUAL "armcc")
    include_directories(${MBED_SRC_PATH}/targets/cmsis/TARGET_NORDIC/TARGET_MCU_NRF51822/TOOLCHAIN_ARM_STD)
elseif(TOOLCHAIN STREQUAL "armgcc")
    include_directories(${MBED_SRC_PATH}/targets/cmsis/TARGET_NORDIC/TARGET_MCU_NRF51822/TOOLCHAIN_GCC_ARM)
endif()

# Generic compiler flags
add_definitions(
    -O3
    -DNRF51
    -DDEBUG_NRF_USER
    -DTARGET_NRF51822
    -DTARGET_M0
    -DTARGET_NORDIC
    -D__CORTEX_M0
    -DARM_MATH_CM0
    -D__MBED__=1
    -DMBED_BUILD_TIMESTAMP=1399904910.34
    -DMBED_USERNAME=rohgro01
)

if (TOOLCHAIN STREQUAL "armcc")
    add_definitions(
        --cpu=Cortex-M0
        --gnu
        -Ospace
        --split_sections
        --apcs=interwork
        --brief_diagnostics
        --restrict
        --md
        --no_depend_system_headers
        -DTOOLCHAIN_ARM_STD
        -DTOOLCHAIN_ARM
    )

    # Language specifc compiler flags.
    set(CMAKE_CXX_FLAGS
        "${CMAKE_CXX_FLAGS} --cpp --no_rtti --multibyte-chars --no_exceptions")
    set(CMAKE_C_FLAGS
        "${CMAKE_C_FLAGS} --c99")
elseif(TOOLCHAIN STREQUAL "armgcc")
    add_definitions(
        -mcpu=cortex-m0
        -mthumb
        -Wall
        -Wextra
        -Wno-unused-parameter
        -Wno-missing-field-initializers
        -Wno-error=switch
        -Wno-switch
        -Wa,-adhlns=$@.lst
        -fmessage-length=0
        -fno-builtin
        -ffunction-sections
        -fdata-sections
        -fno-delete-null-pointer-checks
        -fomit-frame-pointer
        -fno-common
        -funsigned-bitfields
        -DTOOLCHAIN_GCC_ARM
        -DTOOLCHAIN_GCC
        -DTARGET_NRF51822_MKIT
        -DTARGET_MCU_NRF51822
        -DTARGET_MCU_NORDIC_16K
    )

    # Language specifc compiler flags.
    set(CMAKE_CXX_FLAGS
        "${CMAKE_CXX_FLAGS} -std=gnu++98 -fno-rtti -fno-exceptions -fno-threadsafe-statics")
    set(CMAKE_C_FLAGS
        "${CMAKE_C_FLAGS} -std=gnu99 -Wno-pointer-sign -Wno-pointer-to-int-cast")
    set(CMAKE_ASM_FLAGS
        "${COMMON_COMPILE_FLAGS} -x assembler-with-cpp")

    SET(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS
        -T${MBED_SRC_PATH}/targets/cmsis/TARGET_NORDIC/TARGET_MCU_NRF51822/TOOLCHAIN_GCC_ARM/TARGET_MCU_NORDIC_16K/NRF51822.ld)
    SET(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS
        "${CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS} -Wl,--gc-sections -Wl,--wrap,main -Wl,-Map=${PROJECT_NAME}.map -mcpu=cortex-m0 -mthumb --specs=nano.specs -lstdc++ -lsupc++ -lm -lc -lgcc -lnosys -lstdc++ -lsupc++ -lm -lc -lgcc -lnosys")
endif()

# A macro to collect local sources into ${SRCS}.
# This variable gets propagated to the parent scope and is ultimately used in
# the top-level CMakeLists.txt to define the dependencies for the build target.
#
# Please note that files within this list are relative to the current folder.
# Please also note that this macro must be used at all CMakeLists.txt files at
# intermediate levels even if the list is empty--this is due to the Cmake magic
# involved in propagating variables to only the parent scope.
add_sources(
    main.cpp
)

# Use file globbing to collect all sources from external repositories. File-
# globbing is discouraged by CMake, except when collecting sources from an
# external source which remains mostly frozen. The risk with globbing is that
# CMake doesn't automatically update the makefiles if new sources are added to
# the globbed location.
#
file(GLOB MBED_SRC_SOURCES
          ${MBED_SRC_PATH}/common/*.c
          ${MBED_SRC_PATH}/common/*.cpp
          ${MBED_SRC_PATH}/targets/cmsis/TARGET_NORDIC/TARGET_MCU_NRF51822/*.c
          ${MBED_SRC_PATH}/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/*.c
    )
add_sources(${MBED_SRC_SOURCES})
if (TOOLCHAIN STREQUAL "armcc")
    add_sources(${MBED_SRC_PATH}/targets/cmsis/TARGET_NORDIC/TARGET_MCU_NRF51822/TOOLCHAIN_ARM_STD/sys.cpp)
elseif(TOOLCHAIN STREQUAL "armgcc")
    #add_sources(${MBED_SRC_PATH}/targets/cmsis/TARGET_NORDIC/TARGET_MCU_NRF51822/TOOLCHAIN_GCC_ARM/sys.cpp)
endif()

file(GLOB BLE_API_SOURCES
          ${BLE_API_SRC_PATH}/source/*.cpp
          ${BLE_API_SRC_PATH}/source/services/*.cpp
    )
add_sources(${BLE_API_SOURCES})
file(GLOB NRF51822_SOURCES
          ${NRF51822_SRC_PATH}/source/*.cpp
          ${NRF51822_SRC_PATH}/source/btle/*.cpp
          ${NRF51822_SRC_PATH}/source/btle/custom/*.cpp
          ${NRF51822_SRC_PATH}/source/nordic-sdk/components/ble/ble_services/ble_dfu/*.c
          ${NRF51822_SRC_PATH}/source/nordic-sdk/components/ble/ble_radio_notification/*.c
          ${NRF51822_SRC_PATH}/source/nordic-sdk/components/ble/device_manager/*.c
          ${NRF51822_SRC_PATH}/source/nordic-sdk/components/ble/common/*.c
          ${NRF51822_SRC_PATH}/source/nordic-sdk/components/drivers_nrf/hal/*.c
          ${NRF51822_SRC_PATH}/source/nordic-sdk/components/drivers_nrf/pstorage/*.c
          ${NRF51822_SRC_PATH}/source/nordic-sdk/components/libraries/bootloader_dfu/*.c
          ${NRF51822_SRC_PATH}/source/nordic-sdk/components/libraries/bootloader_dfu/experimental/*.c
          ${NRF51822_SRC_PATH}/source/nordic-sdk/components/libraries/crc16/*.c
          ${NRF51822_SRC_PATH}/source/nordic-sdk/components/libraries/hci/*.c
          ${NRF51822_SRC_PATH}/source/nordic-sdk/components/libraries/scheduler/*.c
          ${NRF51822_SRC_PATH}/source/nordic-sdk/components/libraries/util/*.c
          ${NRF51822_SRC_PATH}/source/nordic-sdk/components/softdevice/common/softdevice_handler/*.c
    )
add_sources(${NRF51822_SOURCES})

if (TOOLCHAIN STREQUAL "armcc")
    add_sources(${MBED_SRC_PATH}/targets/cmsis/TARGET_NORDIC/TARGET_MCU_NRF51822/TOOLCHAIN_ARM_STD/TARGET_MCU_NORDIC_16K/startup_nRF51822.S)
elseif(TOOLCHAIN STREQUAL "armgcc")
    add_sources(${MBED_SRC_PATH}/targets/cmsis/TARGET_NORDIC/TARGET_MCU_NRF51822/TOOLCHAIN_GCC_ARM/startup_NRF51822.s)
endif()

############################################################################
# By now, we've traversed all subdirectories and have collected everything that
# needs to be built. We can define the build targets.
############################################################################
# add MbedTest as a build target depending on all the sources
add_executable(${MAIN_TARGET} ${SRCS})

# Add a post-build dependency like printing size of the
# resulting binary and copying to the target.
if (TOOLCHAIN STREQUAL "armcc")
    add_custom_command(
        TARGET ${MAIN_TARGET}
        COMMAND ${SIZE_COMMAND} ${MAIN_TARGET}
    )
    add_custom_target(${HEX_TARGET} ALL
        DEPENDS ${MAIN_TARGET}
        COMMAND ${TOOLCHAIN_SYSROOT}/bin/fromelf --i32combined -o ${PROJECT_NAME}.hex ${MAIN_TARGET}
    )
elseif(TOOLCHAIN STREQUAL "armgcc")
    add_custom_command(
        TARGET ${MAIN_TARGET}
        COMMAND ${SIZE_COMMAND} ${MAIN_TARGET}
        COMMAND arm-none-eabi-objcopy -O ihex ${MAIN_TARGET} ${HEX_TARGET} # convert .elf to .hex (redundancy: only one of either .hex or .bin is needed)
    )
endif()

add_custom_target(${COMBINED_SD} ALL
    COMMENT "Add a SoftDevice to the HEX package"
    DEPENDS ${HEX_TARGET}
    COMMAND srec_cat
        ${MBED_SRC_PATH}/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/Lib/s130_nrf51822_1_0_0/s130_nrf51_1.0.0_softdevice.hex -intel
        ${HEX_TARGET} -intel
        -o ${COMBINED_SD} -intel -obs=16
    COMMAND srec_info ${COMBINED_SD} -intel
    # follow this by copying the resulting combined.hex onto the target (possibly over USB)
)

hi, the startup name for GCC is wrong - the should be a capital S. then it compiles nicely. only the linker is not so nice: /home/robert/gcc-arm-none-eabi-4_8-2014q3/bin/../lib/gcc/arm-none-eabi/4.8.4/../../../../arm-none-eabi/bin/ld: cannot open linker script file /mnt/yocto/mbed/libraries/mbed/targets/cmsis/TARGET_NORDIC/TARGET_MCU_NRF51822/TOOLCHAIN_GCC_ARM/TARGET_MCU_NORDIC_16K/NRF51822.ld: No such file or directory collect2: error: ld returned 1 exit status make[2]: * [BLE_HEART_RATE.elf] Error 1 make[1]: * [CMakeFiles/BLE_HEART_RATE.elf.dir/all] Error 2 make: * [all] Error 2

need to check what is wrong.

posted by robert bouwens 25 Aug 2015

ok, instead of checking monti python a simple:

ln -s TARGET_MCU_NORDIC_32K TARGET_MCU_NORDIC_16K

solves the problem

posted by robert bouwens 25 Aug 2015