Day: June 25, 2016

Testing the Nordic UART Service for nRF51822

Today I decided to test the Nordic Uart Service (NUS) to enable a serial communication (emulated) between a Bluetooh Low Energy device (nRF51822) and an Android device.

The Nordic SDK comes with an example (nordic/examples/ble_peripheral/ble_app_uart) used for serial communication over BLE. For more info:
https://devzone.nordicsemi.com/documentation/nrf51/6.0.0/s110/html/a00066.html

I download the SDK modified to compile with open-source toolchains:
https://github.com/relayr/nrf51-sdk.git

For more info read me previous post:
https://acassis.wordpress.com/2016/02/25/using-openocd-to-program-a-homebrew-nrf51822-board/

The compilation was not so easy as it is supposed to do. I got some undefined references, like this one:

.../newlib/libc/reent/sbrkr.c:58: undefined reference to `_sbrk' 

I fixed it editting “relayr/ld/libc-nano.ld” file and adding:

EXTERN(_sbrk_r)
EXTERN(_write_r)
EXTERN(_close_r)
EXTERN(_lseek_r)
EXTERN(_read_r)
EXTERN(_fstat_r)
EXTERN(_isatty_r)

Also I created a custom board definition based on wunderbar-master-nrf.h

$ cp relayr/include/wunderbar-master-nrf.h relayr/include/custom_board.h

And finally created a build.mk with all files needed to compile the example:

DEVICE_VARIANT?= xxaa

DEFINES+= NRF51 NRF51822_QFAA_CA BOARD_CUSTOM
SDKINCDIRS+= toolchain toolchain/gcc drivers_nrf/hal device libraries/scheduler
SDKINCDIRS+= softdevice/common/softdevice_handler libraries/timer
SDKINCDIRS+= ble/ble_advertising libraries/button ble/ble_services/ble_nus
SDKINCDIRS+= drivers_nrf/uart drivers_nrf/gpiote drivers_nrf/config drivers_nrf/common
SDKINCDITS+= drivers_nrf/hal libraries/fifo

EXPINCDIR+= bsp
EXPINCDIR+= ble_peripheral/ble_app_uart/config

SDKSRCS+= toolchain/gcc/gcc_startup_nrf51.s toolchain/system_nrf51.c
SDKSRCS+= libraries/timer/app_timer.c
SDKSRCS+= ble/common/ble_advdata.c
SDKSRCS+= ble/common/ble_conn_params.c
SDKSRCS+= softdevice/common/softdevice_handler/softdevice_handler.c
SDKSRCS+= libraries/scheduler/app_scheduler.c
SDKSRCS+= libraries/timer/app_timer_appsh.c
SDKSRCS+= drivers_nrf/uart/app_uart_fifo.c
SDKSRCS+= ble/ble_services/ble_nus/ble_nus.c
SDKSRCS+= ble/ble_advertising/ble_advertising.c
SDKSRCS+= libraries/button/app_button.c
SDKSRCS+= drivers_nrf/gpiote/nrf_drv_gpiote.c
SDKSRCS+= drivers_nrf/common/nrf_drv_common.c
SDKSRCS+= libraries/fifo/app_fifo.c

EXPSRCS+= bsp/bsp.c
EXPSRCS+= bsp/bsp_btn_ble.c

USE_SOFTDEVICE?= s110

SDKDIR:= $(abspath $(dir $(lastword ${MAKEFILE_LIST})))
ifndef SDDIR
SDKINCDIRS+= softdevice/${USE_SOFTDEVICE}/headers
else
CFLAGS+= -I${SDDIR}/include
endif

SOFTDEV_HEX?= $(lastword $(wildcard ${SDKDIR}/nordic/components/softdevice/${USE_SOFTDEVICE}/hex/${USE_SOFTDEVICE}*softdevice.hex))

SDKINCDIRS+= $(sort $(dir ${SDKSRCS}) )

SRCS+= $(patsubst %,${SDKDIR}/nordic/examples/%,${EXPSRCS})

ifdef USE_RTX
DEFINES+= RTX __HEAP_SIZE=0 __STACK_SIZE=1024
SRCS+= ${SDKDIR}/nordic/external/rtx/port/RTX_Conf_CM.c
CFLAGS+= -I${SDKDIR}/nordic/external/rtx/include
LDLIBS+= ${SDKDIR}/nordic/external/rtx/source/GCC/libRTX_CM0.a
endif

ifeq ($(filter FALSE false NO no 0,${USE_SIMBLE}),)
include ${SDKDIR}/relayr/src/build.mk
endif

CPPFLAGS+= $(patsubst %,-D%,${DEFINES})

CFLAGS+= -I${SDKDIR}/relayr/include
CFLAGS+= $(patsubst %,-I${SDKDIR}/nordic/examples/%,${EXPINCDIR})

CFLAGS+= $(patsubst %,-I${SDKDIR}/nordic/components/%,${SDKINCDIRS})
CFLAGS+= -mcpu=cortex-m0 -mfloat-abi=soft -mthumb -mabi=aapcs	\
	-ffunction-sections -fdata-sections -fno-builtin \
	-fplan9-extensions
CFLAGS+= -std=gnu11
CFLAGS+= -fshort-wchar -Wl,--no-wchar-size-warning
CFLAGS+= -Wall -Wno-main -Werror
CFLAGS+= -g

LINKERSCRIPT?= gcc_nrf51_${USE_SOFTDEVICE}_${DEVICE_VARIANT}.ld

LDFLAGS+= -Wl,--gc-sections -fwhole-program --specs=nano.specs
LDFLAGS+= -Wl,-Map=${PROG}.map
LDFLAGS+= -Wl,-T,${SDKDIR}/relayr/ld/libc-nano.ld
LDFLAGS+= -Wl,-L${SDKDIR}/relayr/ld
LDFLAGS+= -Wl,-L${SDKDIR}/nordic/components/toolchain/gcc
LDFLAGS+= -Wl,-T,${LINKERSCRIPT}
LDFLAGS+= -lgcc -lc -lm -lg -lrdimon -lnosys

ASFLAGS+= -x assembler-with-cpp


SRCS+=	$(patsubst %,${SDKDIR}/nordic/components/%,${SDKSRCS})


CC=	arm-none-eabi-gcc
OBJCOPY=	arm-none-eabi-objcopy
OBJDUMP=	arm-none-eabi-objdump
GDB=	arm-none-eabi-gdb

GENERATE.d=	$(CC) -MM ${CFLAGS} ${CPPFLAGS} -MT $@ -MT ${@:.d=.o} -MP -MF $@ $<
COMPILE.s=	${COMPILE.S}


all: ${PROG}.hex ${PROG}.bin

define compile_source
ifneq ($(filter %.c %.S %.s,${1}),)
$(addsuffix .o,$(notdir $(basename ${1}))): ${1}
	$${COMPILE$(suffix ${1})} $${OUTPUT_OPTION} $$<
endif

ifneq ($(filter %.c,${1}),)
$(addsuffix .d,$(notdir $(basename ${1}))): ${1}
	$$(GENERATE.d)
endif

OBJS+=	$$(addsuffix .o,$(notdir $(basename ${1})))
endef

$(foreach f,${SRCS},$(eval $(call compile_source,$f)))

ifneq (${MAKECMDGOALS},clean)
-include $(patsubst %.o,%.d,${OBJS})
endif

CLEANFILES+= ${OBJS} ${OBJS:.o=.d} ${PROG}.hex ${PROG}.elf ${PROG}.bin ${PROG}.map ${PROG}.jlink ${PROG}-all.jlink

${PROG}.elf: ${OBJS}
	${CC} -o $@ ${CFLAGS} ${LDFLAGS} ${OBJS} ${LDLIBS}

%.hex: %.elf
	${OBJCOPY} -O ihex $< $@

%.bin: %.elf
	${OBJCOPY} -O binary $< $@

%.jlink: %.hex
	${OBJDUMP} -h $< | \
	awk '$$1 ~ /^[0-9]+$$/ {addr="0x"$$5; if (!min || addr < min) min = addr} END { printf "\
	loadbin %s,%s\n\
	r\n\
	g\n\
	exit\n", f, min}' f="$ $@

%-all.jlink: %.jlink ${SOFTDEV_HEX} FORCE
	@[ -e "${SOFTDEV_HEX}" ] || echo "cannot find softdevice hex image '${SOFTDEV_HEX}'" >&2
	# w4 0x4001e504, 0x2 -> enable erase: CONFIG.WEN = EEN
	# w4 0x4001e50c, 0x1 -> erase all: ERASEALL = 1
	printf "\
	device NRF51822_XXAA\n\
	halt\n\
	w4 0x4001e504, 0x2\n\
	w4 0x4001e50c, 0x1\n\
	sleep 1\n\
	loadbin %s,0\n" ${SOFTDEV_HEX} > $@
	cat $> $@

flash: ${PROG}.hex ${PROG}.jlink
	JLinkExe -device nRF51822_xxAA -if SWD ${PROG}.jlink

flash-all: ${PROG}.hex ${SOFTDEV_HEX} ${PROG}-all.jlink
	JLinkExe -device nRF51822_xxAA -if SWD ${PROG}-all.jlink

gdbserver: ${PROG}.elf
	JLinkGDBServer -device nRF51822_xxAA -if SWD

gdb: ${PROG}.elf
	${GDB} ${PROG}.elf -ex 'target extended-remote :2331'

GITREV= $(shell git describe --always)
MAILFILE= ${PROG}-${GITREV}.hex
CLEANFILES+= ${PROG}-*.hex

mailfile: ${MAILFILE}
	-$(foreach f,$(filter-out $<,$(wildcard ${PROG}-*.hex)),rm $f;)
	-@md5sum $<
	-@sha256sum $<

${PROG}-${GITREV}.hex: ${PROG}.hex
	cp $< $@

clean:
	-rm -f ${CLEANFILES}

.PHONY: all flash flash-all gdbserver gdb clean FORCE