Compiling problem with IAR's new EWAVR3...

sapient84 wrote on Tuesday, September 03, 2013:

Hello,

I’m using the AVR32 AT32UC3C0512C Microcontroller and ASF 3.11 Framework. I’m having some issues with the IAR compiler after updating IAR Workbench from 4.10 to 4.20 new version.

I realized, there have been made some changes in the compiler as shown here (Acuallly not for EWAVR32 but EWAVR):

"Error  +  when using inline assembler:

Labels must be referred in the same assembler statement as they are declared. The behavior was not correct in earlier versions of the compiler platform. The new release uses a new internal compiler platform which is a bit more strict."

I’m having the same issue but the code, which is not able to compile belongs to the FreeRTOS port. I assume that the compiler does not recognize the label LABEL_INT_SKIP_RESTORE_CONTEXT_ because it is not defined in the same asm statement. So, I mailed IAR to get more information about this problem (I was actually able to compile the same code with the old version 4.10) and I’ve got the following answer:

"The label functionality is intentional. It resolves an issue where functions containing inline assembler statements with labels would cause compilation to fail (label defined multiple times in the same function) by making all labels in one inline assembler block unique and local to that block.

We currently have no plans to allow labels to be reused between inline assembler blocks.

It is also worth noting that this problem is not part of ASF. It is part of the FreeRTOS code. The way the inline assembler code is used in that macro can only be labeled as “less than ideal”. The code relies heavily on compiler implementation behavior meaning that the likelihood that code breaks on new versions of the compiler is high."

Hier is the code, that you can easily find in the ASF as a FreeRTOS example (…asf-3.11.0\common\services\usb\class\msc\device\example_freertos\at32uc3c0512c_uc3c_ek\iar\example_freertos.eww)

#define portRESTORE_CONTEXT_OS_INT()                                                                      \
{                                                                                                         \
  extern volatile unsigned portLONG ulCriticalNesting;                                                    \
  extern volatile void *volatile pxCurrentTCB;                                                            \
                                                                                                          \
  /* Check if AVR32_INTC_INT0 or higher were being handled (case where the OS tick interrupted another */ \
  /* interrupt handler (which was of a higher priority level but decided to lower its priority */         \
  /* level and allow other lower interrupt level to occur). */                                            \
  /* In this case we don't want to do a task switch because we don't know what the stack */               \
  /* currently looks like (we don't know what the interrupted interrupt handler was doing). */            \
  /* Saving SP in pxCurrentTCB and then later restoring it (thinking restoring the task) */               \
  /* will just be restoring the interrupt handler, no way!!! */                                           \
  __asm__ __volatile__ (                                                                                  \
    "ld.w    r0, sp[9*4]\n\t"                                                       /* Read SR in stack */\
    "bfextu  r0, r0, 22, 3\n\t"                                         /* Extract the mode bits to R0. */\
    "cp.w    r0, 1\n\t"                            /* Compare the mode bits with supervisor mode(b'001) */\
    "brhi    LABEL_INT_SKIP_RESTORE_CONTEXT_"ASTRINGZ(__LINE__)                                           \
  );                                                                                                      \
                                                                                                          \
  /* Else */                                                                                              \
  /* because it is here safe, always call vTaskSwitchContext() since an OS tick occurred. */              \
  /* A critical section has to be used here because vTaskSwitchContext handles FreeRTOS linked lists. */  \
  portENTER_CRITICAL();                                                                                   \
  vTaskSwitchContext();                                                                                   \
  portEXIT_CRITICAL();                                                                                    \
                                                                                                          \
  /* Restore all registers */                                                                             \
                                                                                                          \
  __asm__ __volatile__ (                                                                                  \
    /* Set SP to point to new stack */                                                                    \
    "mov     r8, LWRD("ASTRINGZ(pxCurrentTCB)")\n\t"                                                      \
    "orh     r8, HWRD("ASTRINGZ(pxCurrentTCB)")\n\t"                                                      \
    "ld.w    r0, r8[0]\n\t"                                                                               \
    "ld.w    sp, r0[0]\n"                                                                                 \
                                                                                                          \
    "LABEL_INT_SKIP_RESTORE_CONTEXT_"ASTRINGZ(__LINE__)":\n\t"                                            \
                                                                                                          \
    /* Restore ulCriticalNesting variable */                                                              \
    "ld.w    r0, sp++\n\t"                                                                                \
    "mov     r8, LWRD("ASTRINGZ(ulCriticalNesting)")\n\t"                                                 \
    "orh     r8, HWRD("ASTRINGZ(ulCriticalNesting)")\n\t"                                                 \
    "st.w    r8[0], r0\n\t"                                                                               \
                                                                                                          \
    /* Restore R0..R7 */                                                                                  \
    "ldm     sp++, r0-r7\n\t"                                                                             \
                                                                                                          \
    /* Now, the stack should be R8..R12, LR, PC and SR */                                                 \
    "rete"                                                                                                \
  );                                                                                                      \
                                                                                                          \
  /* Force import of global symbols from assembly */                                                      \
  ulCriticalNesting;                                                                                      \
  pxCurrentTCB;                                                                                           \
}
#endif

The compiler reports the following error:

Error: Undefined symbol: LABEL_INT_SKIP_RESTORE_CONTEXT_215
Error: Undefined symbol: LABEL_INT_SKIP_RESTORE_CONTEXT_215

I’ve been thinking to try to call switch the context inside the asm statement but I’m not sure if this is the best option and if it really would work. So, it would be great to get some advice here, how to restore the context in another way and avoid the compiling error.

Thank you so much

sapient84 wrote on Tuesday, September 03, 2013:

Sorry about the format of the code before… now it yould be better :slight_smile:

#define portRESTORE_CONTEXT_OS_INT()
{
  extern volatile unsigned portLONG ulCriticalNesting;
  extern volatile void *volatile pxCurrentTCB;
  /* Check if AVR32_INTC_INT0 or higher were being handled (case where the OS tick interrupted another */ 
  /* interrupt handler (which was of a higher priority level but decided to lower its priority */
  /* level and allow other lower interrupt level to occur). */
  /* In this case we don't want to do a task switch because we don't know what the stack */
  /* currently looks like (we don't know what the interrupted interrupt handler was doing). */
  /* Saving SP in pxCurrentTCB and then later restoring it (thinking restoring the task) */
  /* will just be restoring the interrupt handler, no way!!! */
  __asm__ __volatile__ (
    "ld.w    r0, sp[9*4]\n\t"                                                       /* Read SR in stack */
    "bfextu  r0, r0, 22, 3\n\t"                                         /* Extract the mode bits to R0. */
    "cp.w    r0, 1\n\t"                            /* Compare the mode bits with supervisor mode(b'001) */
    "brhi    LABEL_INT_SKIP_RESTORE_CONTEXT_"ASTRINGZ(__LINE__)
  );
  /* Else */
  /* because it is here safe, always call vTaskSwitchContext() since an OS tick occurred. */
  /* A critical section has to be used here because vTaskSwitchContext handles FreeRTOS linked lists. */
  portENTER_CRITICAL();
  vTaskSwitchContext();
  portEXIT_CRITICAL();
  /* Restore all registers */
  __asm__ __volatile__ (
    /* Set SP to point to new stack */
    "mov     r8, LWRD("ASTRINGZ(pxCurrentTCB)")\n\t"
    "orh     r8, HWRD("ASTRINGZ(pxCurrentTCB)")\n\t"
    "ld.w    r0, r8[0]\n\t"
    "ld.w    sp, r0[0]\n" 
    "LABEL_INT_SKIP_RESTORE_CONTEXT_"ASTRINGZ(__LINE__)":\n\t"
    /* Restore ulCriticalNesting variable */
    "ld.w    r0, sp++\n\t"
    "mov     r8, LWRD("ASTRINGZ(ulCriticalNesting)")\n\t"
    "orh     r8, HWRD("ASTRINGZ(ulCriticalNesting)")\n\t"
    "st.w    r8[0], r0\n\t"
    /* Restore R0..R7 */
    "ldm     sp++, r0-r7\n\t"
    /* Now, the stack should be R8..R12, LR, PC and SR */
    "rete"
  );
  /* Force import of global symbols from assembly */
  ulCriticalNesting;
  pxCurrentTCB;
}
#endif