Looking for Xiao BLE "official Bootloader/SoftDevice code/source

I want to port an application from a non Xiao NRF52840 dev board that uses FreeRTOS via an Adafruit runtime implementation ( not mbed RTOS)

I’m looking for a couple things.

  1. the “official” bootloader/SoftDevice hex file for the Xiao BLE (not Sense if that matters)
  2. pointer to the bootloader source used to build the above, if available to get a better understanding of what is going on.

My issue:
When FreeRTOS starts, it starts the first task/thread via an “SVC 0” instruction call. The RTOS code sets up a stack much like is done with
a normal branch to a subroutine, saves registers, sets return PC, LR, etc… then executes the “SVC 0”. The difference is the LR is set to 0xFFFF FFFD (EXEC_RETURN).

The SVC handler should run and then should properly decode that stack content. The handler should take the return address from the premade stack, not via the actual LR which is 0XFFFFFFD (EXEC_RETURN : Exception Return Mechanism - an overview | ScienceDirect Topics).

As I understand it at execution time the address of the interrupt vector table
can be found at address 0x2000 0000. The SVC_Handler address should
then be at this base address + 0x2c.

I have two Bootloader/SoftDevice binaries that I’m uploading:

  1. Refereced at the wiki: Getting Started with XIAO BLE (Sense) - Seeed Wiki

This version seems to be calling the SVC_Handler in bootloader address space.
The vector table address is 0xF4000, thus the handler at the address found in 0xF402c is called. This runs some looping code (trying to determine the SCV number perhaps???) and ends up returning to the actual LR address, 0xFFFFFFC, not the one from within the stack.

  1. Another version taken from the Nordic site
    S140 - nordicsemi.com (version 7.3.0)

This version seems to be calling the SVC_Handler in SoftDevice address space. The vector table address is 0x1000, thus the handler address found in 0x102c is called.
This runs a few instructions, but (no looping), ends up returning to an
address taken from the built stack, not the actual LR content, entering the first task as expected.

So, I can use the Nordic version, but it does not appear to have a bootloader, thus we loose the double reset button taking us to DFU mode and who knows what else.
I would like to understand why the Seeed version is not handling the SVC 0 as expected.

Is the XIAO BLE official bootloader open source? Can anyone get the hex file? Hope seeedstudio will help regarding this issue.

Using what I think is the proper Seeed bootloader/SoftDevice image:

A couple of assumptions about the image content, that appear to be correct:
0x1000 is the address of the SoftDevice interrupt vector table
0xF4000 is the address of the BootLoader interrupt vector table

As I’ve come to understand this, the address of the first level interrupt vector table used when processing an SVC instruction is located at address 0x2000 0000.

At program load time (using Ozone), normal code, I see the vector table address at 0x2000 0000 is 0xF4000. the bootloader vector table. ( The Nordic image has an address of 0x1000, SD address space).

If I manually reset the vector table address within main() to the location of the SoftDevice vector table (rather than BootLoader) via:

main ()
{
#define MYBOOTLDR    (*((volatile unsigned long *) 0x20000000))
MYBOOTLDR = 0x1000;
...
}

Then we do return as expected and proceed to execute the first task.

It seems to me that the bootloader SVC_Handler() is not properly handling an SVC of 0. It’s not clear to me what is currently happening. It would seem the handler should forward execution to perhaps the SoftDevice SVC_Handler, which might then forward to the app level SVC_Handler if the SVC is not targeting Bootloader or SD.
But then again, this is not real clear to me.

Looking at the source for this bootloader might help.

Looking at this further I believe:
The Nordic version calls the SoftDevice SVC_Handler addr via the SoftDevice interrupt table, which then checks the SVC #. If not in its range of #s to handle the code then loads the application SVC_Handler addr via the secondary (application?? ) interrupt vector table.
Execution then is passed to the proper RTOS SVC_Handler.

The Seeed version calls the Bootloader SVC_Handler addr via it’s interrupt vector table, checks the #, if not in range returns an error code. No attempt is made to pass that SVC on to the app.

As a note, the FreeRTOS code passes an SVC of 0. That will not work. Its a valid # for the Seeed implementation so it will try to do something with it.
In the Nordic world there is something about an extended SVC that I believe #0 is reserved for. FreeRTOS does not actually use the #, so changing it to 3 should be a safe bet.

I’m afraid this is as far as I can take this. I think it would be a benefit if we can get this to work, but it’s beyond me at the moment.

1 Like

I believe this all boils down to a version mismatch of the SoftDevice code used for building the bootloader vs the building the application code.

The Adafruit runtime/app defines SoftDevice version at 6.1.1
The bootloader is built targeting version 7.3.0

The data within the two versions of the SoftDevice is at different addresses hence the user SVC was not being forwarded to the user app as expected.

If I rebuild the bootloader to target SD 6.1.1, then re-flash bootloader, the app seems to work ok.
I’ve not yet attempted to re-target both to use 7.3.0 SD.

The sources:
bootloader: https://github.com/0hotpotman0/Adafruit_nRF52_Bootloader

Adafruit PlatformIO runtime:

(you will need to craft variant files for the Xiao)