SES 6.32: Strange behaviour

I am experiencing a strange behavior with SES 6.32, using GCC and I wonder if I should choose a different compiler.

COMPILING THIS PART OF CODE (I added line numbers for reference)

342 static void gap_params_init(void)
343 {
344    ret_code_t err_code;
345    ble_gap_conn_params_t gap_conn_params;
346    ble_gap_conn_sec_mode_t sec_mode;
347
348    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
349
350    err_code = sd_ble_gap_device_name_set(&sec_mode,
351                                          (const uint8_t *)cfgGetDeviceName(),
352                                          strlen(cfgGetDeviceName()));

USING MY RELEASE CONFIGURATION


<configuration Name="Release"
   c_preprocessor_definitions="NDEBUG"
   gcc_debugging_level="None"
   gcc_optimization_level="Level 1" />

--- main.c -- 346 ------------------------------------------
ble_gap_conn_sec_mode_t sec_mode;
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
err_code = sd_ble_gap_device_name_set(&sec_mode,
F001FEF6 bl 0x00029278 <cfgGetDeviceName>
4604     mov r4, r0
F001FEF3 bl 0x00029278 <cfgGetDeviceName>
F011FEEF bl 0x00039274 <strlen>
B282     uxth r2, r0
4621     mov r1, r4
A801     add r0, sp, #4
F7FFFFA2 bl 0x000273E4 <sd_ble_gap_device_name_set>

No trace of BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);

USING MY DEBUG CONFIGURATION

<configuration Name="Debug"
   c_preprocessor_definitions="DEBUG"
   gcc_debugging_level="Level 3"
   gcc_optimization_level="None" />

--- main.c -- 344 ------------------------------------------
ret_code_t err_code;
ble_gap_conn_params_t gap_conn_params;
ble_gap_conn_sec_mode_t sec_mode;
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
F89D3004 ldrb.w r3, [sp, #4]
2201     movs r2, #1
F3620303 bfi r3, r2, #0, #4
F88D3004 strb.w r3, [sp, #4]
F89D3004 ldrb.w r3, [sp, #4]
2201     movs r2, #1
F3621307 bfi r3, r2, #4, #4
F88D3004 strb.w r3, [sp, #4]
--- main.c -- 349 ------------------------------------------
err_code = sd_ble_gap_device_name_set(&sec_mode,
(const uint8_t *)cfgGetDeviceName(),
F003FC76 bl 0x0002B0B8 <cfgGetDeviceName>
4604     mov r4, r0
--- main.c -- 352 ------------------------------------------
strlen(cfgGetDeviceName()));
F003FC73 bl 0x0002B0B8 <cfgGetDeviceName>
4603     mov r3, r0
4618     mov r0, r3
F023F857 bl 0x0004A888 <strlen>
4603     mov r3, r0
--- main.c -- 350 ------------------------------------------
err_code = sd_ble_gap_device_name_set(&sec_mode,
B29A     uxth r2, r3
AB01     add r3, sp, #4
4621     mov r1, r4
4618     mov r0, r3
F7FFFF7C bl 0x000276E0 <sd_ble_gap_device_name_set>
9007     str r0, [sp, #28]

Not even constant folding, but the code works.

USING MY RELEASE CONFIGURATION AGAIN
<configuration Name="Release"
   c_preprocessor_definitions="NDEBUG"
   gcc_debugging_level="None"
   gcc_optimization_level="Level 1" />

BUT
REPLACING: ble_gap_conn_sec_mode_t sec_mode;
WITH : static ble_gap_conn_sec_mode_t sec_mode;

--- main.c -- 348 ------------------------------------------
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
B510     push {r4, lr}
4C17     ldr r4, =0x20008688 <sec_mode.5>
B084     sub sp, sp, #16
2311     movs r3, #17
7023     strb r3, [r4]
--- main.c -- 349 ------------------------------------------
err_code = sd_ble_gap_device_name_set(&sec_mode,
F002FB1F bl 0x00029A40 <cfgGetDeviceName>
9001     str r0, [sp, #4]
F002FB1C bl 0x00029A40 <cfgGetDeviceName>
F015FC4C bl 0x0003CCA4 <strlen>
9901     ldr r1, [sp, #4]
B282     uxth r2, r0
4620     mov r0, r4
F7FFFFE7 bl 0x000273E4 <sd_ble_gap_device_name_set>

I have no clue about this behavior of the compiler; is someone experiencing the same problem?

I am using GCC; is any other compiler (SEGGER, SEGGER-NG or CLANG) better?

  • Hi,

    I must admit I am not fluent in assembly, but I do not see what is obviously wrong here? Also, I still do not get why you are digging into this particular part? I wonder if it is related to the next question though, with SoftDevice version compatibility?

    cmag said:

    What happen if I switch to SDK version 2; I suspect that having:

    • SoftDevice 1
    • Bootloader 1
    • Application 2.3

    Could cause problems, as Application 2.3 would expect to interact with SoftDevice 2; what is the correct way to proceed at this point, using the BLE DFU?

    The SoftDevice API is generally not compatible between major versions, so in this case you cannot update the application without also updating the SoftDevice. Moreover, the BLE bootloader also relies on the SoftDevice, so you need to update this at the same time as well. If you want to keep the old SoftDevice and bootloader, you could change the SoftDevice header files in the application to use the old header files and port the new application to the old SoftDevice (there will typically be some API changes, and this goes both ways). If you build the new application for the old SoftDevice, then you can update just the application via DFU.

    I would generally say that if you update SDK version it probably also makes sense to update the SoftDevice, though. And if you update the SoftDevice, you must also update the BLE Bootloader, as that depends on the SoftDevice. So in this case you would need to update all three, and make a DFU zip package that include all three. Then the DFU procedure works so that the application is deleted, and the SoftDevice and bootloader are updated together (first transferred to the application region, before being copied into the correct place by the MBR which is never updated). Lastly the new application is transferred.

  • My mistake: the call was by reference, so the register overwritten is not the problem.

    Still there is a difference when calling the Softdevice function defined as follows (a few excerpts):

    #define SVCALL(number, return_type, signature) \
    _Pragma("GCC diagnostic push") \
    _Pragma("GCC diagnostic ignored \"-Wreturn-type\"") \
    __attribute__((naked)) \
    __attribute__((unused)) \
    static return_type signature \
    { \
    __asm( \
    "svc %0\n" \
    "bx r14" : : "I" (GCC_CAST_CPP number) : "r0" \
    ); \
    } \
    _Pragma("GCC diagnostic pop")

    SVCALL(SD_BLE_GAP_DEVICE_NAME_SET, uint32_t, sd_ble_gap_device_name_set(ble_gap_conn_sec_mode_t const *p_write_perm, uint8_t const *p_dev_name, uint16_t len));

    With the following line of code:

    err_code = sd_ble_gap_device_name_set(&sec_mode, (const uint8_t *)cfgGetDeviceName(), 
                                          strlen(cfgGetDeviceName()));

    R0 point to sec_mode:

    R0: 0x2003ff8c -> 07 79

    And calling a function with a standard C signature:

    __attribute__ ( (noinline))
    uint32_t sd_ble_gap_device_name_set0(ble_gap_conn_sec_mode_t const *p_write_perm, uint8_t const *p_dev_name, uint16_t len)

    {
    sd_ble_gap_device_name_set0test = *p_write_perm;
    }

    With the following line of code:

    err_code = sd_ble_gap_device_name_set0(&sec_mode, (const uint8_t *)cfgGetDeviceName(),
                                           strlen(cfgGetDeviceName()));

    R0 points to sec_mode:

    R0: 0x2003ff8c -> 11 0C

    But the time the correct value is stored in memory.

    So maybe it is an incompatibility between the compiler and the library. It seems that the compiler still tries to pass &sec_mode in R0 (I do not know if this is correct with SVCALL) but the fails to initialize sec_mode.

    I will try to recompile with the latest library to check if this solves the problem.

  • Hi,

    All SoftDevice API calls are SVC calls, so you should not compare with normal function calls.

    I am still unsure about what the issue issue is and why you are digging into this, though? What is not working? Which problem are you trying to solve?

  • With the old compiler release I used to have the following settings for DEBUG and RELEASE:

    <configuration
    Name="Debug"
    c_preprocessor_definitions="DEBUG"
    gcc_debugging_level="Level 3"
    gcc_optimization_level="None" />
    <configuration
    Name="Release"
    c_preprocessor_definitions="NDEBUG"
    gcc_debugging_level="None"
    gcc_omit_frame_pointer="Yes"
    gcc_optimization_level="Level 1" />

    With the new compiler DEBUG configuration works fine, while RELEASE crashes, unless I set gcc_optimization_level="None".

    This was the origin of all.

    What I have noticed that in RELEASE configuration the sec_mode parameter was not initialized before calling sd_ble_gap_device_name_set and sd_ble_gap_device_name_set gave an error of invalid parameter.

  • Aha, I see. I was not able to reproduce here, but that could be a coincidence. Generally it could be a good idea to use a toolchain version that is mentioned in the release notes of the SDK you are using, as that version was used during release testing. It is not the first time we have seen issues with specific compiler versions, though it is quite rare.

Related