This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

IAR 8.10 produce bugs when compiling nrf_delay_us()

Hello, We are migrating from IAR 760 to IAR 8.10 compiler does not produce the same assembly for the SDK12 inline function nrf_delay_us. The original C Function is :

__STATIC_INLINE void nrf_delay_us(uint32_t number_of_us) {
    const uint32_t clock16MHz = CLOCK_FREQ_16MHz;
    if (number_of_us)
    {
__ASM volatile (
#if ( defined(__GNUC__) && (__CORTEX_M == (0x00U) ) )
        ".syntax unified\n"
#endif
"1:\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " CMP %[SystemCoreClock],%[clock16MHz]\n"
       " BEQ.n 2f\n"
       " NOP\n"
#if defined(NRF52) || defined(NRF52840_XXAA) || defined(NRF52832)
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
       " NOP\n"
#endif
"2:\n"
       " SUBS %0, %0, #1\n"
       " BNE.n 1b\n"
#if __CORTEX_M == (0x00U)
#ifdef __GNUC__
    ".syntax divided\n"
#endif
    :"+l" (number_of_us) :
#else
    :"+r" (number_of_us) :
#endif
                [SystemCoreClock] "r" (SystemCoreClock),
                [clock16MHz] "r" (clock16MHz)
        );
#ifdef __ICCARM__
        __DMB();
#endif
    }
}

The assembler generated by IAR 7.60 is :

  0x1ffda: 0x4a39         LDR.N     R2, [PC, #0xe4]         ; 0xf42400 (16000000)
  0x1ffdc: 0x6008         STR       R0, [R1]
  0x1ffde: 0x202f         MOVS      R0, #47                 ; 0x2f
  0x1ffe0: 0x4936         LDR.N     R1, [PC, #0xd8]         ; SystemCoreClock
  0x1ffe2: 0x6809         LDR       R1, [R1]
  0x1ffe4: 0xbf00         NOP
  0x1ffe6: 0xbf00         NOP
  0x1ffe8: 0xbf00         NOP
  0x1ffea: 0xbf00         NOP
  0x1ffec: 0xbf00         NOP
  0x1ffee: 0xbf00         NOP
  0x1fff0: 0xbf00         NOP
  0x1fff2: 0xbf00         NOP
  0x1fff4: 0x4291         CMP       R1, R2
  0x1fff6: 0xd02f         BEQ.N     0x20058
  0x1fff8: 0xbf00         NOP
  0x1fffa: 0xbf00         NOP
  0x1fffc: 0xbf00         NOP
  0x1fffe: 0xbf00         NOP
  0x20000: 0xbf00         NOP
  0x20002: 0xbf00         NOP
  0x20004: 0xbf00         NOP
  0x20006: 0xbf00         NOP
  0x20008: 0xbf00         NOP
  0x2000a: 0xbf00         NOP
  0x2000c: 0xbf00         NOP
  0x2000e: 0xbf00         NOP
  0x20010: 0xbf00         NOP
  0x20012: 0xbf00         NOP
  0x20014: 0xbf00         NOP
  0x20016: 0xbf00         NOP
  0x20018: 0xbf00         NOP
  0x2001a: 0xbf00         NOP
  0x2001c: 0xbf00         NOP
  0x2001e: 0xbf00         NOP
  0x20020: 0xbf00         NOP
  0x20022: 0xbf00         NOP
  0x20024: 0xbf00         NOP
  0x20026: 0xbf00         NOP
  0x20028: 0xbf00         NOP
  0x2002a: 0xbf00         NOP
  0x2002c: 0xbf00         NOP
  0x2002e: 0xbf00         NOP
  0x20030: 0xbf00         NOP
  0x20032: 0xbf00         NOP
  0x20034: 0xbf00         NOP
  0x20036: 0xbf00         NOP
  0x20038: 0xbf00         NOP
  0x2003a: 0xbf00         NOP
  0x2003c: 0xbf00         NOP
  0x2003e: 0xbf00         NOP
  0x20040: 0xbf00         NOP
  0x20042: 0xbf00         NOP
  0x20044: 0xbf00         NOP
  0x20046: 0xbf00         NOP
  0x20048: 0xbf00         NOP
  0x2004a: 0xbf00         NOP
  0x2004c: 0xbf00         NOP
  0x2004e: 0xbf00         NOP
  0x20050: 0xbf00         NOP
  0x20052: 0xbf00         NOP
  0x20054: 0xbf00         NOP
  0x20056: 0xbf00         NOP
  0x20058: 0x1e40         SUBS      R0, R0, #1
  0x2005a: 0xd1c3         BNE.N     0x1ffe4
    __DMB();
  0x2005c: 0xf3bf 0x8f5f  DMB

The assembler generated by IAR 8.10 is :

  0x22110: 0x4a3a         LDR.N     R2, [PC, #0xe8]         ; 0xf42400 (16000000)
  0x22112: 0x6001         STR       R1, [R0]
  0x22114: 0x4838         LDR.N     R0, [PC, #0xe0]         ; SystemCoreClock
  0x22116: 0x6801         LDR       R1, [R0]
  0x22118: 0xbf00         NOP
  0x2211a: 0xbf00         NOP
  0x2211c: 0xbf00         NOP
  0x2211e: 0xbf00         NOP
  0x22120: 0xbf00         NOP
  0x22122: 0xbf00         NOP
  0x22124: 0xbf00         NOP
  0x22126: 0xbf00         NOP
  0x22128: 0x4291         CMP       R1, R2
  0x2212a: 0xd02f         BEQ.N     0x2218c
  0x2212c: 0xbf00         NOP
  0x2212e: 0xbf00         NOP
  0x22130: 0xbf00         NOP
  0x22132: 0xbf00         NOP
  0x22134: 0xbf00         NOP
  0x22136: 0xbf00         NOP
  0x22138: 0xbf00         NOP
  0x2213a: 0xbf00         NOP
  0x2213c: 0xbf00         NOP
  0x2213e: 0xbf00         NOP
  0x22140: 0xbf00         NOP
  0x22142: 0xbf00         NOP
  0x22144: 0xbf00         NOP
  0x22146: 0xbf00         NOP
  0x22148: 0xbf00         NOP
  0x2214a: 0xbf00         NOP
  0x2214c: 0xbf00         NOP
  0x2214e: 0xbf00         NOP
  0x22150: 0xbf00         NOP
  0x22152: 0xbf00         NOP
  0x22154: 0xbf00         NOP
  0x22156: 0xbf00         NOP
  0x22158: 0xbf00         NOP
  0x2215a: 0xbf00         NOP
  0x2215c: 0xbf00         NOP
  0x2215e: 0xbf00         NOP
  0x22160: 0xbf00         NOP
  0x22162: 0xbf00         NOP
  0x22164: 0xbf00         NOP
  0x22166: 0xbf00         NOP
  0x22168: 0xbf00         NOP
  0x2216a: 0xbf00         NOP
  0x2216c: 0xbf00         NOP
  0x2216e: 0xbf00         NOP
  0x22170: 0xbf00         NOP
  0x22172: 0xbf00         NOP
  0x22174: 0xbf00         NOP
  0x22176: 0xbf00         NOP
  0x22178: 0xbf00         NOP
  0x2217a: 0xbf00         NOP
  0x2217c: 0xbf00         NOP
  0x2217e: 0xbf00         NOP
  0x22180: 0xbf00         NOP
  0x22182: 0xbf00         NOP
  0x22184: 0xbf00         NOP
  0x22186: 0xbf00         NOP
  0x22188: 0xbf00         NOP
  0x2218a: 0xbf00         NOP
  0x2218c: 0x1e40         SUBS      R0, R0, #1
  0x2218e: 0xd1c3         BNE.N     0x22118
    __DMB();
  0x22190: 0xf3bf 0x8f5f  DMB

The R0 register seems not to be initialized with IAR 8.10 so the program does not exit the loop. We can see in the code generated by IAR 7.60 that R0 is initialized with 47 (the Value we give to parameter "number_of_us" for this call). In IAR 8.10 R0 seems not to be initialized. This could have been made before function call due to compiler optimizations but it seems not to be the case (we have checked on debugger R0 register value). Can you help us?

  • Hi,

    We have had several reports of this problem the last days, and it seems to be a bug in IAR version 8. We are currently working with IAR to fix the bug. I would recommend to downgrade to version 7 for now if possible.


    EDIT: Attached is a patched version of the nrf_delay header that should work with IAR 8. You can replace the old one located in \SDK_folder\components\drivers_nrf\delay with this one.

    Attachment: nrf_delay.h

  • Thank you for your answer. I have tried to use nrf_delay of SDK11 : the function seems works but I have other problems... Can other functions be concerned? Here is the mails exchanged with IAR support : CALL 592812s_IAR

    Good morning Kévin,

    Thanks for the information. Yes, according to Help > C/C++ Development Guide, chapter 'FUNCTION ENTRANCE':

    +++ Parameters can be passed to a function using one of these basic methods:  * In registers  * On the stack It is much more efficient to use registers than to take a detour via memory, so the calling convention is designed to use registers as much as possible. +++

    Chapter 'Register parameters' says that Scalar and floating-point values no larger than 32 bits can be passed in R0 to R3.

    But, when you inline a function, there is no function call. So R0 won't be in use (?). So what happens if you try to remove __STATIC_INLINE?

    Best Regards, Niklas Källman IAR Systems AB Technical Support E-mail: [email protected] Website: www.iar.com

    -------- Original Email -------- Good morning,

    Thanks for your answer. I think the function parameter 'number_of_us' should be in R0 like in the assembler generated by IAR 7.60. I took this assembler at the same place for the two versions of IAR. The parameter 'number_of_us' is 47. We can see at the line 3 of the assembler generated by IAR 7.60 that R0 is initialized at 47 as expected but in the code generated by IAR 8.10 this value is never loaded in R0. This value could have been loaded in R0 before due to compiler optimizations but when we see the debugger it seems to not be the case. This code has been created by Nordic Semiconductor (we work with nRF52832 microcontroller). I am going to ask Nordic Semiconductor support about that.

    Best Regards, Kévin Duplantier Embedded software engineer +33 5.61.24.80.90 3 avenue Didier Daurat 31400 TOULOUSE - France www.ffly4u.com | [email protected]

    -----Message d'origine----- De : Niklas Källman [mailto:[email protected]] Envoyé : mercredi 5 avril 2017 08:49 À : Kevin DUPLANTIER [email protected] Objet : Re[1]: RFTA: problem of assembler generation -- CALL 592812s_IAR

    CALL 592812s_IAR

    Dear Duplantier Kevin,

    Thank you for using our products and taking the time to contact us.

    The R0 register is not initialized by your assembler code. Could you please explain where the init value from R0 should come from?

    Is it the function parameter 'number_of_us' that should be in R0?

    If that is the case, possibly using __STATIC_INLINE is a bad idea, since the function may be inlined (and there will be no function call).

    Please explain where R0 should get its value from, and please also try to remove the __STATIC_INLINE, just as a test.

  • @Kevin, Does the attached file fixes the problem?

  • IAR 8 issues are fixed in SDK 12.3

    The fixed files are:

     - SDK_folder/components/drivers_nrf/delay/nrf_delay.h
     - SDK_folder/components/libraries/hardfault/nrf52/handler/hardfault_handler_iar.c
     - SDK_folder/components/libraries/uart/retarget.c
     - SDK_folder/external/freertos/portable/IAR/nrf52/port.c
    

    For nRF51, use the files in the corresponding nrf51 folder instead.

    You can download SDK 12.3 here.

Related