This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Decompressor overwrites my variables...

cpu: at91sam7x256

I have in my project some global objects, they are by default placed at address 0x200000. My program seems to work properly but occasionally beginning of RAM is filled with zeros by Keil library function at label: __decompress1 in deassembly window. It makes some my variables and pointers are useles and program stops responding. The worst is, that pointers are defined as const and they are not expected to change.

Any idea how to solve this error?

Parents Reply Children
  • T_Bit              EQU     0x20
    
                    PRESERVE8                       ; 8-Byte aligned Stack
                    AREA    SWI_Area, CODE, READONLY
                    ARM
    
                    EXPORT  SWI_Handler
    SWI_Handler
    
                    STMFD   SP!, {R12, LR}          ; Store R12, LR
                    MRS     R12, SPSR               ; Get SPSR
                    STMFD   SP!, {R8, R12}          ; Store R8, SPSR
                    TST     R12, #T_Bit             ; Check Thumb Bit
                    LDRNEH  R12, [LR,#-2]           ; Thumb:Load Halfword
                    BICNE   R12, R12, #0xFF00       ;       Extract SWI Number
                    LDREQ   R12, [LR,#-4]           ; ARM:  Load Word
                    BICEQ   R12, R12, #0xFF000000   ;       Extract SWI Number
    
                    LDR     R8, SWI_Count
                    CMP     R12, R8
                    BHS     SWI_Dead                ; Overflow
                    ADR     R8, SWI_Table
                    LDR     R12, [R8,R12,LSL #2]    ; Load SWI Function Address
                    MOV     LR, PC                  ; Return Address
                    BX      R12                     ; Call SWI Function
    
                    LDMFD   SP!, {R8, R12}          ; Load R8, SPSR
                    MSR     SPSR_cxsf, R12          ; Set SPSR
                    LDMFD   SP!, {R12, PC}^         ; Restore R12 and Return
    
    SWI_Dead        B               SWI_Dead        ; None Existing SWI
    
    SWI_Cnt         EQU    (SWI_End-SWI_Table)/4
    SWI_Count       DCD     SWI_Cnt
    
                    IMPORT  __SWI_0
                    IMPORT  __SWI_1
    SWI_Table
                    DCD     __SWI_0                 ; SWI 0 Function Entry
                    DCD     __SWI_1                 ; SWI 1 Function Entry
    SWI_End
    
                    END
    

    Do you think I should change something?
    This code touches SPSR to switch beetwen ARM and Thumb... Maybe I missed it touches int falgs...

  • Thank you very much :)
    I changed in code CPSR to SPSR and removed line with MSR SPSR_cxsf, R12. And now everything works :)
    The most crazy is that my project has worked OK for 2 months with no real critical section.

  • Here is updated SWI handler. This one does not allow nested interrupts, but solves your interrupt disable problem.

    SWI_Handler
    
                    STMFD   SP!, {R8, LR}          ; Store R8, LR
                    MRS     R12, SPSR              ; Get SPSR
                    TST     R12, #T_Bit            ; Check Thumb Bit
                    LDRNEH  R12, [LR,#-2]          ; Thumb: Load Halfword
                    BICNE   R12, R12, #0xFF00      ;        Extract SWI Number
                    LDREQ   R12, [LR,#-4]          ; ARM:   Load Word
                    BICEQ   R12, R12, #0xFF000000  ;        Extract SWI Number
    
                    LDR     R8, SWI_Count
                    CMP     R12, R8
                    BHS     SWI_Dead               ; Overflow
                    ADR     R8, SWI_Table
                    LDR     R12, [R8,R12,LSL #2]   ; Load SWI Function Address
                    MOV     LR, PC                 ; Return Address
                    BX      R12                    ; Call SWI Function
    
                    LDMFD   SP!, {R8, PC}^         ; Restore R8 and Return
    
    SWI_Dead        B       SWI_Dead               ; None Existing SWI
    

  • Why don't you 'push' and 'pop' R12 ?

  • Because r12 is a scratch register that may be modified by the callee. The caller is responsible for saving it. The SVC (formerly known as SWI) is a synchronous call (unlike an IRQ for instance), i.e. the compiler has to apply the same rules as for a normal function call.

    Regards
    Marcus
    http://www.doulos.com/arm/