crownstone / bluenet

Bluenet is the in-house firmware on Crownstone hardware. Functions: switching, dimming, energy monitoring, presence detection, indoor localization, switchcraft.
https://crownstone.rocks
91 stars 62 forks source link

Bootloader doesn't start app properly #66

Closed mrquincle closed 5 years ago

mrquincle commented 5 years ago

The app runs perfectly. The bootloader runs perfectly. However, the bootloader doesn't run the app properly.

mrquincle commented 5 years ago

Solved in https://github.com/crownstone/bluenet/blob/sdk15-debug/conf/cmake/CMakeLists.txt.

The target in CMake makes use of objcopy. Check:

    ADD_CUSTOM_COMMAND(OUTPUT ${PROJECT_NAME}.tmp
            COMMAND ${CMAKE_OBJCOPY_OVERLOAD} ${INCLUDE_ONLY_SECTIONS} -O binary ${PROJECT_NAME} ${PROJECT_NAME}.tmp
            COMMAND ${CMAKE_OBJCOPY_OVERLOAD} ${INCLUDE_ONLY_SECTIONS} -O ihex ${PROJECT_NAME} ${PROJECT_NAME}.hex

Here ${INCLUDE_ONLY_SECTIONS} contained -j .text and -j .data. Due to the updates in the more recent SDKs, there are however many more sections that have to be copied.

This is not encountered in a straightforward manner because there's (probably, not checked) some Nordic magic that copies the handlers to those sections if they're still at 0xFFFFFFFF.

This explains also how running the program the first time will work, but subsequent times there is a checksum error in the bootloader. The checksum is calculated offline (with the nrfutil) without e.g. the .sdh_soc_observers and other sections taken into account. However, after the application is run, the checksum is not correct anymore.

Setting ${INCLUDE_ONLY_SECTIONS} to just an empty string copies all sections and will solve this bug.

Note, that there is one additional thing to take into account. Before nrf_bootloader_app_start_final in the Nordic code at nrf_bootloader_app_start.c interrupts are disabled. If NRF_LOG_FLUSH is called after disabling the interrupts the code will hang there. You will have to remove that line in that file.

This is at least the case in SDK 15.3.0:

nRF5_SDK_15.3.0_59ac345/components/libraries/bootloader/nrf_bootloader_app_start.c

It's very easy to check with gdb. Set a breakpoint at nrf_bootloader_app_start_final which will never be reached, while nrf_dfu_mbr_irq_forward_address_set is actually reached.

vliedel commented 5 years ago

Fixed as of https://github.com/crownstone/bluenet/commit/03dfd3b184f84cccfb396dfb0161a3bf0fae6505