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

SWI switches to interrupt

I have problemm with critical sections again :(

When I execute vEnterCritical or vExitCritical step by step they works well.

When I step over this functions they switches CPU to interrupt mode... I can't understand such mess.

Here is my code

volatile unsigned int uiCriticalNesting = 0;
extern "C" void __SWI_0 ( void );
extern "C" void __SWI_1 ( void );


void __swi(0) vEnterCritical( void );
void __SWI_0 ( void )
{
        int R12;
        __asm{ MRS      R12, SPSR               };
        __asm{ ORR      R12, R12, #0xC0 };
        __asm{ MSR      SPSR_CXSF, R12  };
        ++uiCriticalNesting;
}


void __swi(1) vExitCritical( void );
void __SWI_1 ( void )
{
        if( uiCriticalNesting )
        {
                --uiCriticalNesting;
                if( uiCriticalNesting == 0 )
                {
                        int R12;
                        __asm{ MRS      R12, SPSR               };
                        __asm{ BIC      R12, R12, #0xC0 };
                        __asm{ MSR      SPSR_CXSF, R12  };
                }
        }
}

and:

T_Bit                   EQU     0x20

                                PRESERVE8                                               ; 8-Byte aligned Stack
                                AREA    SWI_Area, CODE, READONLY
                                ARM

                                EXPORT  SWI_Handler
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

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

It worked for a months... Now it stopped working.
Can anybody help?

Parents Reply Children
  • I found source of problemm but I have no idea how to solve it.
    I use pit irq and ubgu irq, they both share system irq. When I disable dbgu irq all works ok.

    So how to configure it to work properly?
    I have 3 constructors to create 3 global objects: one to initialize sys irq, one to initialize pit and enable it's irq and one to initialize dbgu and it's irq. I tried to change order of constructors, but with no positive result :(

    void __irq AT91IRQ_SYS::IRQ (void)
    {
            PIT.irq();
            calibration.irq();
            AT91F_AIC_AcknowledgeIt( AT91C_BASE_AIC );
    }
    
    AT91IRQ_SYS::AT91IRQ_SYS( void )
    {
            AT91F_AIC_DisableIt( AT91C_BASE_AIC, AT91C_ID_SYS );
            AT91F_AIC_ConfigureIt( AT91C_BASE_AIC, AT91C_ID_SYS, AT91C_AIC_PRIOR_LOWEST + 1,
                                   AT91C_AIC_SRCTYPE_HIGH_LEVEL, (void(*)())IRQ );
            AT91F_AIC_EnableIt( AT91C_BASE_AIC, AT91C_ID_SYS );
    }
    
    void AT91PIT::irq( void )
    {
        if ( AT91F_PITGetStatus( AT91C_BASE_PITC ) & AT91C_PITC_PITS )
            {
                    timestamp += AT91F_PITGetPIVR( AT91C_BASE_PITC ) >> 20;
        }
    }
    
    AT91PIT::AT91PIT( void )
    {
            AT91F_PITC_CfgPMC();
            AT91F_PITInit( AT91C_BASE_PITC, PIT_PERIOD, BOARD_MCK_MHZ );
            AT91F_PITEnableInt( AT91C_BASE_PITC );
    }
    
    CALIBR::CALIBR( AT91PS_DBGU DBGU, unsigned int ID, unsigned int IO, unsigned int speed,
                    AT91PS_PIO port, unsigned int pin, volatile calibration_table_crc * data,
                    volatile internal & wew, volatile range & rng, volatile protect & p,
                    unsigned short msk )
            :
                    state( READY2LISTEN ),
                    bytes2read( 0 ),
                    alreadyread( 0 ),
                    calib_data( data ),
                    int_data( wew ),
                    int_rng( rng ),
                    status( p.state ),
                    mask( msk ),
                    keep_alive( UNIWIBR( time_alive ) ),
                    valid_command( UNIWIBR( time_gap ) )
    {
            dbgu = new AT91USART( reinterpret_cast<AT91PS_USART>(DBGU), ID, IO, AT91C_US_USMODE_NORMAL, speed, par_none, stop_1 );
    
            AT91F_PIO_CfgPeriph( port, IO, 0 );
    
            AT91F_US_DisableIt( dbgu->pUSART, 0xFFFF );
    
            dbgu->pUSART->US_PTCR = AT91C_PDC_TXTDIS | AT91C_PDC_RXTDIS;
    
            AT91F_US_GetChar( dbgu->pUSART );
    
            AT91F_US_EnableIt( dbgu->pUSART, AT91C_US_RXRDY );
    
            dbgu->pUSART->US_CR = AT91C_US_RXEN;
    
    }
    

    Any idea what to do?