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?
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 ) { . . . }
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.