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
  • 1. When data are transmitted with PDC via SPI by channel different from 0 and channel 0 is not configured, then 2nd byte from buffer is skipped. It sends 1st, 3rd, 4th, 5th, etc... (checked with oscilloscope).
    Solution is to add about 0.5ms delay between selecting channel in SPI_MR and begining of transfer (this problem didn't appear while debug with F11 but appeared with step over with F10 ) or to coonfigure channel 0.
    Errata says about problems with lack of configuration of channel 0 but nothing about data loss. Especially in that way.

    2. When I use crystall (4MHz, 10MHz, 18.432MHz, 25MHz) as mck without pll I have to divide frequency at last by 2 in prescaller. I cannot use it without prescaller and then cpu not switches to RC oscillator because something is wrong with clock. Only reset helps.

    i do not think teh cpu has changed ???

    Me neither. But how to explain that one day I left work and device worked well. The next day morning I turned it on and then this problem appeared. How to explain that? And how to explain that copies which worked before, now aren't working?

    I have infinite loop on data abort.

Reply
  • 1. When data are transmitted with PDC via SPI by channel different from 0 and channel 0 is not configured, then 2nd byte from buffer is skipped. It sends 1st, 3rd, 4th, 5th, etc... (checked with oscilloscope).
    Solution is to add about 0.5ms delay between selecting channel in SPI_MR and begining of transfer (this problem didn't appear while debug with F11 but appeared with step over with F10 ) or to coonfigure channel 0.
    Errata says about problems with lack of configuration of channel 0 but nothing about data loss. Especially in that way.

    2. When I use crystall (4MHz, 10MHz, 18.432MHz, 25MHz) as mck without pll I have to divide frequency at last by 2 in prescaller. I cannot use it without prescaller and then cpu not switches to RC oscillator because something is wrong with clock. Only reset helps.

    i do not think teh cpu has changed ???

    Me neither. But how to explain that one day I left work and device worked well. The next day morning I turned it on and then this problem appeared. How to explain that? And how to explain that copies which worked before, now aren't working?

    I have infinite loop on data abort.

Children
  • how is all this related to the original problem? either way, it seems as if you are thumbling toward a "solution", and not solving anything actually. the fact that it comes and goes indicates that there is something fundamentally wrong with the program.

  • Problems with SPI and crystal aren't related to this problem. This is answer for question of Baffled Zeusti.

    I'll write functions for critical sections in pure assembler and check tomorrow.

  • I'll write functions for critical sections in pure assembler and check tomorrow.

    this is not a bad idea in itself, but I doubt whether it has anything to do with the problem at hand. either way, you better do it without inline assembly, thus:

    void __asm __swi(0) vEnterCritical( void );
    void __SWI_0 ( void )
    {
    .
    .
    .
    }
    

  • HI.

    <quote>
    the fact that it comes and goes indicates that there is something fundamentally wrong with the program.
    </quote>

    whot book does a conclushion get seen in? i want to stay away!

    but it is more probeble for problem in code and not strange spontanius changes in CPU.

    Always yo're freind.

    Zeusti.

  • 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?

  • The problem apperas when I use both SPI interfaces. When I use only SPI0 or SPI1 then all is OK.

    The question is if it is forbidden to use both at the same time? May be the problem in that I use PDC for both and there is a hardware conflict?

    It is hard to belive that Atmel didn't make any hardware protection... For example SPI transfer in master mode should be holded for a while if PDC can't access memory. Otherwise we cannot talk about any reliability of PDC.

    I need 15MHz and 5MHz on one SPI and 5MHz on the second SPI. MCK is 50MHz.

    Have anybody ever had such problemms?

    And second thing... In most cases there is Data Abort form ARM Core. Occasionally it stops in this:

       54:                     // PIT interrupt
    0x001017BC  E92D500F  STMDB     R13!,{R0-R3,R12,R14}
        55:         PIT.irq();
        56:
        57:         // DBGU interrupt
    0x001017C0  E59F00A8  LDR       R0,[PC,#0x00A8]
    0x001017C4  EBFFFD33  BL        _ZN7AT91PIT3irqEv(0x00100C98)
        58:         calibration.irq();
        59:
        60:         // end of interrupt
    0x001017C8  E59F00A4  LDR       R0,[PC,#0x00A4]
    0x001017CC  EB0026C3  BL        _ZN6CALIBR3irqEv(0x0010B2E0)
        61:         AT91F_AIC_AcknowledgeIt( AT91C_BASE_AIC );
        62:
    0x001017D0  E1A00000  NOP
       126:     pAic->AIC_EOICR = pAic->AIC_EOICR;
    0x001017D4  E59F009C  LDR       R0,[PC,#0x009C]
    0x001017D8  E5900130  LDR       R0,[R0,#0x0130]
    0x001017DC  E59F1094  LDR       R1,[PC,#0x0094]
    0x001017E0  E5810130  STR       R0,[R1,#0x0130]
       127: }
    0x001017E4  E1A00000  NOP
    0x001017E8  E8BD500F  LDMIA     R13!,{R0-R3,R12,R14}
    0x001017EC  E25EF004  SUBS      PC,R14,#0x00000004
    

    In last line...
    LR is 0x001017f0 what always results writing 0x001017ec to PC. It loops execution.