Menu

Interrupts

Help
2017-11-28
2017-12-28
  • bas knippels

    bas knippels - 2017-11-28

    I am writing a C program for an emulated 80c51 chip on a FPGA, which is currently still being done in assembly.
    I have all features like serial communication, CANbus and timer routines working but one. The external interrupt.

    The external interrupts work different than on a real 80c51. To begin we have 8 interrupts, all on port P1. The problem I am having is that I dont know to work arround the specific syntax used for the ISR. I mean this:

    void timer0 (void) __interrupt 1
    {   
    
    }
    

    The interrupt 1 (and __interrupt 4 for the serial one)

    I know that these interrupts 1 and 4 point to addresses 0x0b and 0x23 respectively but I do not know how or where this happens. The only references I could find in all used software is in the bottem of at89x51.h

    /* Interrupt numbers: address = (number * 8) + 3 */
    #define IE0_VECTOR      0     // 0x03 external interrupt 0 
    #define TF0_VECTOR      1       // 0x0b timer 0 
    #define IE1_VECTOR      2       // 0x13 external interrupt 1 
    #define TF1_VECTOR      3       // 0x1b timer 1 
    #define SI0_VECTOR      4       // 0x23 serial port 0 
    

    But they are just simple defines and not sfr and this does not do anything for me.

    We use special bits to configure the interrupt. The only respons I have so far is that triggering the I/O pin disables my timer and possibly also the serial interrupts. And my co-worker confirmed that I am setting the bits fine. The problem is that the ISR doesn't get called. I tried using __interrupt 0 which is at address 0x03

    But no luck. I simply don't know how the system works between these numbered interrupts and the address pointing. Is this cooked in SDCC?? I also tried pulling some information out of the generated .asm file but so far I have not been able to find what I am looking for.

     
  • bas knippels

    bas knippels - 2017-11-28

    I forgor the attachment

     
  • Nikolay

    Nikolay - 2017-11-29

    I used SDCC with stm8 a bit, but I could find vector table in more human-readable format in .rst file not in .asm (produced when linking, with absolute addresses). As I understand the associations between interrupt number and address are hardcoded in SDCC (maybe it can be changed but I don't know how to do this).

    Sample from .rst file:

                                         38     .area HOME
          008000                         39 __interrupt_vect:
          008000 82 00 80 3B             40     int s_GSINIT ; reset
          008004 82 00 00 00             41     int 0x0000 ; trap
          008008 82 00 00 00             42     int 0x0000 ; int0
          00800C 82 00 00 00             43     int 0x0000 ; int1
          008010 82 00 00 00             44     int 0x0000 ; int2
          008014 82 00 00 00             45     int 0x0000 ; int3
          008018 82 00 00 00             46     int 0x0000 ; int4
          00801C 82 00 00 00             47     int 0x0000 ; int5
          008020 82 00 00 00             48     int 0x0000 ; int6
          008024 82 00 00 00             49     int 0x0000 ; int7
          008028 82 00 00 00             50     int 0x0000 ; int8
          00802C 82 00 00 00             51     int 0x0000 ; int9
          008030 82 00 00 00             52     int 0x0000 ; int10
          008034 82 00 80 58             53     int _TIM1_UPDOVF_IRQ_Handler ; int11
    
     
  • bas knippels

    bas knippels - 2017-11-29

    As I understand the associations between interrupt number and address are hardcoded in SDCC

    this is what I feared :( thanks for your reply

     
  • Frieder Ferlemann

    There is little to fear. The 8051 architecture reserves 3 bytes at the start for an LJMP, then there are small (8 bytes) code blocks reserved for each IRQ. Usually these also contain a LJMP but very small IRQ routines might fit in there too.

    It would be extremely unusual for an 8051 FPGA implementation to break the assumption cited in your original post "address = (number * 8) + 3". In fact it could be argued that this should not be called a 8051 implementation any more.

    So you should be fine by just specifying the matching IRQ number:

    void irq_routine9(void) __interrupt (9)
    {
      irq_cntr2--;
    }
    
    void irq_routine10(void) __interrupt (10)
    {
      irq_cntr2++;
    }
    

    this gives you, looking at the .rst file as Nikolay proposed:

       0000 02 00 5B            118         ljmp    __sdcc_gsinit_startup
       0003 32                  119         reti
       0004                     120         .ds     7
       000B 02 01 34            121         ljmp    _timer0_interrupt
       000E                     122         .ds     5
       0013 32                  123         reti
       0014                     124         .ds     7
       001B 32                  125         reti
       001C                     126         .ds     7
       0023 32                  127         reti
       0024                     128         .ds     7
       002B 32                  129         reti
       002C                     130         .ds     7
       0033 32                  131         reti
       0034                     132         .ds     7
       003B 32                  133         reti
       003C                     134         .ds     7
       0043 02 00 B7            135         ljmp    _irq_routine
       0046                     136         .ds     5
       004B 02 00 C6            137         ljmp    _irq_routine9
       004E                     138         .ds     5
       0053 02 00 DB            139         ljmp    _irq_routine10
    

    In the very strange case that this does not match your hardware, you do not yet have to give up.
    The table is generated in line 226 here:
    https://sourceforge.net/p/sdcc/code/HEAD/tree/trunk/sdcc/src/mcs51/main.c
    If you should need to adapt, please report back.

     
  • Maarten Brock

    Maarten Brock - 2017-12-28

    It seems to me that the part you do not understand should be in the documentation for the fpga implementation of the 8051. You say you have 8 external interrupts. According to the documentation what should happen when, say, the first is triggered? To what vector is the core supposed to jump? And for the second? And the last?

    The 'hardcoded' vectors in sdcc are there because (almost) every 8051 has them hardcoded that way.

     

    Last edit: Maarten Brock 2017-12-28

Log in to post a comment.