This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS 5.3 optimization issue

Other Parts Discussed in Thread: AM3358, AM3359

Good morning.

On CCS 5.3 is an issue when I use optimization.

The issue is this:

CPUIntStatus:
8051524c:   E10F0000 MRS             R0, CPSR
80515250:   E20000C0 AND             R0, R0, #192
80515254:   E12FFF1E BX              R14


CPUirqd:
804d1e5c:   E10F0000 MRS             R0, CPSR
804d1e60:   E3800080 ORR             R0, R0, #128
804d1e64:   E121F000 MSR             CPSR_c, R0
804d1e68:   E12FFF1E BX              R14

The up two functions is writed in ASM linguage.

When I compile the "sys_arch_protect" funcion from lwip 1.4.0 without optimization, all is compiled correct.

sys_arch_protect:
8050c684:   E92D4008 STMFD           R13!, {R3, R14}
62          status = (IntMasterStatusGet() & 0xFF);
8050c688:   EBFF16F3 BL              IntMasterStatusGet
8050c68c:   E5CD0000 STRB            R0, [R13]
64          IntMasterIRQDisable();
8050c690:   EBFF16E8 BL              IntMasterIRQDisable
65          return status;
8050c694:   E5DD0000 LDRB            R0, [R13]
66        }
8050c698:   E8BD8008 LDMFD           R13!, {R3, PC}


With optimization level 3, this is the result:

sys_arch_protect:
804d2280:   E92D4008 STMFD           R13!, {R3, R14}
593           return CPUIntStatus();
804d2284:   EB00AE5D BL              CPUIntStatus
545           CPUirqd();
804d2288:   EBFFFFF8 BL              CPUirqd
65          return status;
804d228c:   E6EF0070 UXTB            R0, R0, ROR #0
804d2290:   E8BD8008 LDMFD           R13!, {R3, PC}

Can be observed that both of ASM functions use the R0 register, but the "CPUIntStatus" function return the CPSR value in R0, the "CPUirqd" will modify the R0 register, and finally the "sys_arch_protect" will return the R0 register modified by the "CPUirqd". This is an issue of compiler, that can not back-up the R0 register when is used by the "CPUirqd".

I correct this issue with these changes:

In lwip libray:
on sys_arch.c
from:
sys_prot_t
sys_arch_protect(void)
{
  sys_prot_t status;
  status = (IntMasterStatusGet() & 0xFF);

  IntMasterIRQDisable();
  return status;
}

to

sys_prot_t
sys_arch_protect(void)
{
  volatile sys_prot_t status;
  status = (IntMasterStatusGet() & 0xFF);

  IntMasterIRQDisable();
  return status;
}

The same issue is present in "usbhostenum.c" on "USBHCDMain".

But if I changed from:

 unsigned int ulIntState;

to volatile unsigned int ulIntState;

will go to abort.

I changed from:

        ulIntState = IntDisable();

to
        IntDisable();

and from:

        IntEnable(ulIntState);

to

        IntEnable(0);

With these changes everything works OK the lwip library and USB host.



  • I cannot reproduce this.  We're going to need a more complete test case, including: the compiler version (it is not the same as the CCS version), the complete command-line options, and a compilable test case which demonstrates the problem.  This means you need to include all header files needed to compile the test case, or preprocess the C source file and send the .pp file.

  • Good morning Archaeologist.

    You can download the entire project from here. I used Google drive because is a large archive, and my internet connection is GSM, I can not upload directly here.

    For ARM Comipler

    -mv7A8 --code_state=32 --float_support=vfplib --abi=eabi -me -O3 --opt_for_speed=3 -g --include_path="C:/ti/ccsv5/tools/compiler/arm_5.0.1/include" --include_path="C:/SDK_Probe" --include_path="C:/SDK/platform/am33" --include_path="C:/SDK/platform/am33/board/beaglebone" --include_path="C:/SDK/lib" --include_path="C:/SDK/lib/net/lwip-1.4.0/src/include/ipv4" --include_path="C:/SDK/lib/net/lwip-1.4.0/src/include" --include_path="C:/SDK/lib/net/lwip-1.4.0/src/include/lwip" --include_path="C:/SDK/lib/net/lwip-1.4.0/ports/cpsw/include" --include_path="C:/SDK/lib/net/lwip-1.4.0" --pch --gcc --define=DMA_MODE --define=am335x --define=am3358 --define=am3359 --diag_warning=225 --display_error_number --neon --signed_chars --optimizer_interlist --opt_for_cache

    For ARM Linker

    -mv7A8 --code_state=32 --float_support=vfplib --abi=eabi -me -O3 --opt_for_speed=3 -g --pch --gcc --define=DMA_MODE --define=am335x --define=am3358 --define=am3359 --diag_warning=225 --display_error_number --neon --signed_chars --optimizer_interlist --opt_for_cache -z --stack_size=0x800 -m"SDK.map" --heap_size=0x800 -i"C:/ti/ccsv5/tools/compiler/arm_5.0.1/lib" -i"C:/SDK/platform/am33/lib" -i"C:/SDK/platform/am33/board/beaglebone" -i"C:/ti/ccsv5/tools/compiler/arm_5.0.1/include" --reread_libs --warn_sections --display_error_number --ram_model

    Compiler version is TI v5.0.1

    You can observe that the "sys_arch_protect" will return the 0x9F value, with this value the function "sys_arch_unprotect" will not restore the global interrupt flag.

    In "main.asm" at line 576338 and 576346 is showing how the compiler has compiled the "sys_arch_protect" function.

    You can prove the firmware on BeagleBone with LCD3 Cape or Beaglebone Expansion V2 from chipsee, or without cape, the firmware will detect the attached board, or can work without any extension board.

  • For some reason, nothing shows up when I access that URL, not even an error message.

    Thank you for the options and compiler version; unfortunately it is not enough for me to reproduce the problem.

    Probably all I need is the definition of the functions IntMasterStatusGet and IntMasterIRQDisable.

  • I change the link to my server.

    Please keep a lock and to "interrupt_api.c" that is located to "lib/api" directory and is used by "usbhostenum.c" in "am33/interface/usblib" by "USBHCDMain" function, here the compiler has the same behavior.

  • Okay, I've extracted a far smaller test case which demonstrates the problem, which I show below, with conditional compilation showing the fix.  The problem is that you've defined the assembly function CPUirqd as a C function with a body that consists entirely of an __asm statement.  The compiler sees CPUirqd as a function with no C statements, so it thinks it does not modify R0.  The TI compiler does not in general suppot using __asm statements inside a C function body; use __asm statements inside C functions at your own risk.  The only safe way to use it is as you've already done for CPUIntStatus: define the entire function in assembly code, as demonstrated below

    __asm("    .sect \".text:CPUIntStatus\"\n"
              "    .clink\n"
              "    .global CPUIntStatus\n"
              "CPUIntStatus:\n"
              "    mrs     r0, CPSR \n"
              "    and     r0, r0, #0xC0\n"
              "    bx      lr");
    
    
    #if 0
    void CPUirqd(void)
    {
        /* Disable IRQ in CPSR */
        asm("    mrs     r0, CPSR\n\t"
            "    orr     r0, r0, #0x80\n\t"
            "    msr     CPSR_c, r0");
    }
    #else
    __asm("    .sect \".text:CPUirqd\"\n"
              "    .clink\n"
              "    .global CPUirqd\n"
              "CPUirqd:\n"
            "    mrs     r0, CPSR\n\t"
            "    orr     r0, r0, #0x80\n\t"
            "    msr     CPSR_c, r0\n\t"
            "    bx      lr");
    }
    #endif
    
    unsigned int CPUIntStatus();
    void CPUirqd();
    
    typedef unsigned int sys_prot_t;
    
    sys_prot_t IntMasterStatusGet() { return CPUIntStatus(); }
    void IntMasterIRQDisable() { CPUirqd(); }
    
    sys_prot_t
    sys_arch_protect(void)
    {
        sys_prot_t status;
        status = (IntMasterStatusGet() & 0xFF);
    
        IntMasterIRQDisable();
        return status;
    }
    
  • Thank you very much for this clarification, now I understand from where is the problem.

    I work with ASM code(for atmel 8bit core) from about 7-8 years, and I have a good experience with ASM language, but when I took with ASM inside C-C++, or another hi level language for me is very strange, I don't understand nothing about how to import and export variables to/from C section to ASM section and from ASM section to C section.

    If you have some documentation about how to use ASM code inside the C-C++ code please help me, a compact documentation (strictly at object) will help me very much.

    Among others reasons, I want to translate the NEON optimization library from mpeg12 video decoder library, at this moment the optimization for neon core is made for IAR I think, but I like only the open source thinks, accessible to all people (my entire work about programing is open source).

    Best regards,

    Iulian Gheorghiu.

  • The TI compiler does not support accessing C variables from within inline assembly.  There isn't any documentation because it's not an intended mode of operation.

    For safety, you should put assembly code in assembly functions, and then you can call them.