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 am not sure I understand the main issue here. Do you see unexpected behavior, or is it just that you decided to take a look at the disassembly and are wondering about what you are seeing?

    Generally, debug configurations should not do any optimization, to make the machine code map as closely to the C code as possible. So it is intentional and expected that there is no constant folding etc. For the release configuration it is different, but exactly how the compiler optimized the code depends on the optimization configuration. Generally though the compiler is much better at finding smart optimizations than humans, so it is not normally so that you can look at a small piece of disassembly and with good reason conclude that "here the compiler did something wrong/stupid".

  • Actually the problem was that sd_ble_gap_device_name_set returned an error for invalid parameters.

    Besides SES 6.32 crashes very frequently with my PC.

    So I reverted to version 5.66 which works fine.

  • I have tried on a clean machine, to check if there was an interference with other software, but the problem persists.

    I am using:

    nRF5 SDK v16.0.0
    ------------------------
    Release Date: October, 2019

    Maybe I should try upgrading to latest softdevice; but I wonder what happens on existing products; I mean, a product contains:

    1. SOFTDEVICE
    2. DFU
    3. FIRMWARE

    What happens of the other components when I upgrade the FIRMWARE compiled for the new SDK/SOFTDEVICE?

  • Hi,

    Are you using a vanilla SDK or have you made any changes to it?

    What error do you get now? Is it sill that you get NRF_ERROR_INVALID_PARAM returned from sd_ble_gap_device_name_set(), or is the issue something else? Please explain. If this is the error, then what parameters do you provide to sd_ble_gap_device_name_set()? (the error indicate an issue here)

    cmag said:
    Maybe I should try upgrading to latest softdevice; but I wonder what happens on existing products; I mean, a product contains:

    The application (firmware) is built with header files for a specific SoftDevice. If you change to a new SoftDevice you need to rebuild the application. Also, a SoftDevice with a different version number typically has a number of API changes that needs to be addresses when updating SoftDevice.

    cmag said:
    What happens of the other components when I upgrade the FIRMWARE compiled for the new SDK/SOFTDEVICE?

    If you update just the application, then that is OK as long as it is built for the SoftDevice you are using. Typically the bootloader has no dependency on the application. However, the bootloader also has dependencies on the SoftDevice (provided it uses Bluetooth), so you also need to re-build the bootloader if changing SoftDevice.

  • I am using the standard SDK, but I am starting to suspect that the SDK has nothing to do with it.

    To prove this I have defined my version of the called procedure:

    __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;
    }

    The code generated to call this function is:

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
    B500     push {lr}
    B087     sub sp, sp, #28
    2311     movs r3, #17
    F88D300C strb.w r3, [sp, #12]
    --- main.c -- 358 ------------------------------------------
    err_code = sd_ble_gap_device_name_set0(&sec_mode,
    F001FE7F bl 0x0002935C <cfgGetDeviceName>
    9001     str r0, [sp, #4]
    F001FE7C bl 0x0002935C <cfgGetDeviceName>
    F012F93A bl 0x000398DC <strlen>
    9901     ldr r1, [sp, #4]
    B282     uxth r2, r0
    A803     add r0, sp, #12
    F7FFFFE9 bl 0x00027644 <sd_ble_gap_device_name_set0>

    It keeps sec_mode in r3, then calls strlen, which (I checked) uses R3, and has any right to use R0 to R3 for its own purposes, then calls sd_ble_gap_device_name_set0 with R3 corrupted.

    Frankly I cannot believe that GNU C compiler makes such mistakes; I am starting to suspect that the project has some settings appropriate with the old version that interfere with the new version.

    I will try to rebuild the project settings from scratch with the new release.

    To make the second part of my question more clear. Say that I build my application with version 1 of the SDK and libraries, then I deploy and my device has:

    • SoftDevice 1
    • Bootloader 1
    • Application 1.1

    No problem till I keep using the same SDK; I will get:

    • SoftDevice 1
    • Bootloader 1
    • Application 1.2

    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?

Related