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