I am using Atmel AT89C51CC03, and it is configured so in Keil too. The data sheet lists the SPI interrupt vector as 0x0053h, and I do define my interrupt as interrupt #10. However, the map file show my SPI interrupt has address of 0x0026h.
Does anyone know why is that? Anything I can do to make it right?
Thanks in advance!
The interrupt routine is like this:
static void SPICommISR(void) interrupt 10 { UINT8 tmpchar; if (SPSCR & 0x80) { tmpchar = SPDAT; SPDAT = 0xCC; } }
Please also show the (allegedly) erroneous section of the MAP file.
Also, does a disassembly give any clues?
This is the portion of map file:
* * * * * * * C O D E M E M O R Y * * * * * * * CODE 0000H 0003H ABSOLUTE CODE 0003H 0003H ABSOLUTE CODE 0006H 001CH UNIT ?PR?_READ_EEPROM?NVMEM CODE 0022H 0001H UNIT ?PR?DPSE_FORCE_INPUT_UPDATE?USER CODE 0023H 0003H ABSOLUTE CODE 0026H 002BH UNIT ?PR?SPICOMMISR?SPI_COMM CODE 0051H 0001H UNIT ?PR?DPSE_START_C1?DPSE CODE 0052H 0001H UNIT ?PR?DPSE_STOP_C1?DPSE CODE 0053H 0003H ABSOLUTE CODE 0056H 0694H UNIT ?C?LIB_CODE CODE 06EAH 0549H UNIT ?CO?SPI_COMM
The assembly code looks OK to me:
; FUNCTION SPICommISR (BEGIN) 0000 C0E0 PUSH ACC 0002 C083 PUSH DPH 0004 C082 PUSH DPL 0006 63A201 XRL AUXR1,#01H 0009 C083 PUSH DPH 000B C082 PUSH DPL ; SOURCE LINE # 469 ; SOURCE LINE # 476 000D E5D5 MOV A,SPSCR 000F 30E70B JNB ACC.7,?C0003 ; SOURCE LINE # 477 ; SOURCE LINE # 479 0012 900000 R MOV DPTR,#tmpchar 0015 E5D6 MOV A,SPDAT 0017 F0 MOVX @DPTR,A ; SOURCE LINE # 480 0018 75D6CC MOV SPDAT,#0CCH ; SOURCE LINE # 481 001B B2C0 CPL P4_0 ; SOURCE LINE # 624 ; SOURCE LINE # 625 001D ?C0003: 001D D082 POP DPL 001F D083 POP DPH 0021 63A201 XRL AUXR1,#01H 0024 D082 POP DPL 0026 D083 POP DPH 0028 D0E0 POP ACC 002A 32 RETI ; FUNCTION SPICommISR (END)
I do have a line toggle I/O line (P4_0)inside interrupt for debugging purpose because it did not work the way I think. What I see on the scope is that the P4_0 toggles even when Chip Select is high. But I figure if the interrupt is at wrong place, anything could happen.
I mean a disassembly of the vector table.
I'm not familiar with this Atmel device but should the interrupt be #11 not #10? Bradford
in the data sheet, the SPI interrupt address vector is 0053h, and if you count, it is #10. Priority number is 11 though.
How do I check disassembly of the vector table?
http://www.keil.com/support/man/docs/uv3/uv3_cm_unassemble.htm
I checked disassembly, and it seems the compiler does put interrupt at 0026h. But I just don't understand why the compiler does that.
C:0x0023 022217 LJMP com_isr(C:2217) 469: static void SPICommISR(void) interrupt 10 470: { 471: static UINT8 SpiHeader; 472: UINT8 tmpchar; 473: static UINT8 crcvalue; 474: static BOOLEAN SpiValid; 475: C:0x0026 C0E0 PUSH ACC(0xE0) C:0x0028 C083 PUSH DPH(0x83) C:0x002A C082 PUSH DPL(0x82) C:0x002C 63A201 XRL AUXR1(0xA2),#0x01 C:0x002F C083 PUSH DPH(0x83) C:0x0031 C082 PUSH DPL(0x82) 476: if (SPSCR & 0x80) C:0x0033 E5D5 MOV A,0xD5 C:0x0035 30E70B JNB 0xE0.7,C:0043 477: { 478: #ifdef SPIDEBUG 479: tmpchar = SPDAT; C:0x0038 90036B MOV DPTR,#0x036B C:0x003B E5D6 MOV A,0xD6 C:0x003D F0 MOVX @DPTR,A 480: SPDAT = 0xCC; C:0x003E 75D6CC MOV 0xD6,#TL2(0xCC) 481: P4_0 = ~P4_0; C:0x0041 B2C0 CPL P4_0(0xC0.0) 624: } C:0x0043 D082 POP DPL(0x82) C:0x0045 D083 POP DPH(0x83) C:0x0047 63A201 XRL AUXR1(0xA2),#0x01 C:0x004A D082 POP DPL(0x82) C:0x004C D083 POP DPH(0x83) C:0x004E D0E0 POP ACC(0xE0) C:0x0050 32 RETI
The CPU vectors to the interrupt address. The compiler puts the address of the subroutine it wants call there. the full subroutine would most likely not fit since Intel only left a few bytes before the next interrupt vector.
Is there any setting I should change to make compiler do that? There are only 8 bytes from one interrupt vector address to next. And with all the push/pop, I do need a LJUMP. At address 0023, compiler does have a LJMP for my UART interrupt, but I just don't know why it would not do it for SPI interrupt.
For the UART interrupt I have
static void com_isr (void) interrupt 4 using 2
Does a different bank help?
I do need a LJUMP. At address 0023, compiler does have a LJMP for my UART interrupt, but I just don't know why it would not do it for SPI interrupt.
Why don't you disassemble the instruction that is at address 0x53 and see what it is? I'll bet i can guess.
CODE 0053H 0003H ABSOLUTE
And with all the push/pop, I do need a LJUMP.
And you got one. It's just not where you're looking for it. The LJMP is at 0x53, just where the interrupt vector for interrupt number 10 belongs. But it would be rather wasteful if the linker were to put nothing at all in the entire address range from 0x26 to 0x53. So it found something that fits in the gap and put it there. Your SPI interrupt routine apparently fit the bill.
If you wished, You could prevent that by ensuring that you do provide an ISR for all possible interrupts; eg,
static void dummyISRxx(void) interrupt xx { for(;;); }
You could use this to prevent any unexpected behaviour if one of the "unused" interrupts should, somehow, accidentally get enabled...
You guys are right. I do have a LJMP at 0x53. Then I still do not know what causes my problem. In my interrupt routine, I basically toggle P4_0, but on my scope, I can see the P4_0 toggles even when chip select is high. Too bad that I can not post screen shot here, but basically my MOSI rest at 2.7V, and every 12.5 usec, there are two small pulses pull the voltage to 3.6V. P4_0 toggles at the rising edge of the first small pulse, and my chip select is solid high. I know the voltage is a little strange and I don't know what cause these small pulses, but if the chip select is high, then it should not trigger interrupt at all, right? Any suggestions? Thanks,
Can you post it somewhere else, and then provide a Link here?
Take me a while to bypass company firewall, but here you are:
www.flickr.com/.../42986638@N02/3963290758/
www.flickr.com/.../42986638@N02/3963290852/