Вопрос

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 have found in IAR's technical support notes that some changes have been made related to inline assembly. (Acuallly not for EWAVR32 but EWAVR):

Error [Og005] + [Og006] 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. Here is the code:

#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

I've been thinking to try to switch the context inside the asm statement (Call c function using inline assembly) 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!

In case you need it, you can easily find this code 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)

Это было полезно?

Решение

Well, as I already said in my question I just tried to switch the context inside the asm statement (Call c function with an inline assembler instruction). So, using "RCALL" (Relative call to subroutine):

"RCALL vPortEnterCritical\n\t"
"RCALL vTaskSwitchContext\n\t"
"RCALL vPortExitCritical\n\t"

the hole code would look like this:

#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__)"\n\t" 

        /* 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. */ 
        "RCALL vPortEnterCritical\n\t"
        "RCALL vTaskSwitchContext\n\t"
        "RCALL vPortExitCritical\n\t" 

        /* Restore all registers */  
        /* 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; 
} 

This worked for me and I did not see so far any differences in the behavior of our system. I hope this can help someone wo has to migrate from IAR Workbench 4.10 to 4.20.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top