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

SPI interrupt at wrong address

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!

  • Does anyone know why is that?

    nobody can till you show your code

    the start of the SPI ISR should do

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

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