This project contains code examples of a the DFU bootloader modified to be built by gcc.
Note that the bootloader address was set to 0x34000
to make enough room for the build with debug option. If you build with release (or all) (that has optimization) you can move the bootloader up to have more room for your application.
Requirements
- nRF51 SDK version 6.0.0
- S130 0.5 alpha version and above.
- nRF51822 Development Kit version 2.1.0 or later
The project may need modifications to work with other versions or other boards.
This application is one of several applications that has been built by the support team at Nordic Semiconductor, as a demo of some particular feature or use case. It has not necessarily been thoroughly tested, so there might be unknown issues. It is hence provided as-is, without any warranty.
However, in the hope that it still may be useful also for others than the ones we initially wrote it for, we've chosen to distribute it here on GitHub.
The application is built to be used with the official nRF51 SDK, that can be downloaded from https://www.nordicsemi.no, provided you have a product key for one of our kits.
Please post any questions about this project on https://devzone.nordicsemi.com.
The S130 is not normally supported by this bootloader. There are quite some changes required to make it work.
The directory that you need is [device_firmware_updates/bootloader - gcc - BLE](nrf51-dfu-bootloader-for-gcc-compiler/nrf51822_v6.0.0 - GCC_Bootloader/Board/nrf6310/device_firmware_updates/bootloader - gcc - BLE).
One of the first things to note, is that the arm_startup_nrf51.s
file is not used for gcc
. The file
$NORDIC_SDK/Source/templates/gcc/gcc_startup_nrf51.s
is used instead. Instead of adjust that file in the Makefile
we set ASMFLAGS
to create reasonable size for stack and heap:
MEMORY_LIMITATIONS=-D__STACK_SIZE=1024 -D__HEAP_SIZE=1024
Also to make sure everything fits in the limited space, we adjust:
CFLAGS += -Os -flto -ffunction-sections -fdata-sections -fno-builtin
LDFLAGS = --specs=nano.specs -lc -lnosys -Wl,--gc-sections
Note that Os
might actually not be optimal for restricting memory usage. It is optimal with respect to space
required.
There are some references to pin layouts for our custom boards at DoBots
. Feel free to remove those. It basically
sets the right LEDS to go on/off.
The SoftDevice we currently use has a path at /opt/softdevices/s130_nrf51822_0.5.0-1.alpha_API/include/
. You'll have
to update it if your softdevice SDK resides at another path.
The configuration is described in dfu_types.h
. Note that most of the changes for the S130
series are similar to
the ones of the S310
series, so I use S310_STACK
as a define on compilation!
#define CODE_REGION_START 0x0001C000 // start of application (SoftDevice S130 is big!)
#define BOOTLOADER_REGION_START 0x00034000 // start of bootloader at end of memory
In the main.c
you will see one macro:
#define SERIAL
Disable that to get rid of the printing to uart.
If you use https://github.com/mrquincle/bluenet to write your binaries to your chip, you will have to use the following sequence:
./softdevice.sh all
./writebyte.sh 0x10001014 0x00034000
./firmware.sh all bootloader 0x00034000
It is essential to erase the flash before writing to it with writebyte
. The fastest way to do so is just by flashing
a new softdevice, hence the first command. Do not use writebyte.sh
without erasing that area first.
In the https://github.com/mrquincle/bluenet/scripts directory, there is also a script to upload over the air:
./upload_over_the_air.sh
If you use the firmware in that repository, you can also find code on how to enter the bootloader from the application.
Make sure you do not have any breakpoints set in an attached debugger. It works fine, but you might be thinking at
times: "What is it doing?" Attaching it is fine, but just remove any default breakpoints in for example gdbinit
or
similar scripts.
Then there is one real bug:
You will have to change the code in $NORDIC_SDK/Source/ble/ble_services/ble_dfu.c
. This is described on the Nordic Forums.
static uint32_t on_ctrl_pt_write(ble_dfu_t * p_dfu, ble_gatts_evt_write_t * p_ble_write_evt)
{
ble_gatts_rw_authorize_reply_params_t write_authorize_reply;
write_authorize_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
bool configured = true;
#ifdef S130_BUG_SQUASHED
configured = is_cccd_configured(p_dfu);
#endif
if (!configured)
...
If it bug is squashed you can put the is_cccd_configured
back in there again of course.
There is also a problem with sd_softdevice_disable
when called from the bootloader. Hence, I refrain from actually
disabling the softdevice and do so in the application code. This happens in bootloader.c
and the function
bootloader_app_start()
. You see how I even set these magic bytes, but whatever I do, there is some magic
disappearance of my running code under the debugger. I don't know what exactly happens there.
if (enabled && false) {
sd_mbr_command_t com = {SD_MBR_COMMAND_INIT_SD, };
err_code = sd_mbr_command(&com);
APP_ERROR_CHECK(err_code);
...
You see how I added false
to this if clause for now.