Sunday, September 6, 2015

Bug Reported And __critical Purged

I reported the bug just now. It's at https://sourceforge.net/p/sdcc/bugs/2416/.

Now I have to figure out how to handle critical sections.

For now, just two functions--di() and ei(). They will use a global variable uint8_t interruptDisableReferenceCount. If it's 0, interrupts are enabled. It will initialize to 1.

I also dealt with the __interrupt bug where it doesn't generate ei before reti.

Here is my interrupt.c file for now:

#include "tick.h"
#include "uart.h"
#include "membank.h"

/*
; for crt0.s
.globl _do_RST_00H
.globl _do_RST_08H
.globl _do_RST_10H
.globl _do_RST_01H
.globl _do_RST_20H
.globl _do_RST_28H
.globl _do_RST_30H
.globl _do_RST_38H
.globl _do_NMI
*/

uint8_t interruptDisableRefCount = 1;

void do_RST_00H() 
{
}

void do_RST_08H()
{
}

void do_RST_10H()
{
}

void do_RST_18H()
{
}

void do_RST_20H()
{
}

void do_RST_28H()
{
}

void do_RST_30H()
{
}

// Has to be naked because __interrupt fails to generate the ei before the reti
void do_RST_38H() __naked
{
    __asm__("push af");
    __asm__("push bc");
    __asm__("push de");
    __asm__("push hl");
    __asm__("push ix");
    __asm__("push iy");

#ifdef INT_SAVE_ALT_REG
    __asm__("exx");
    __asm__("push af");
    __asm__("push bc");
    __asm__("push de");
    __asm__("push hl");
    __asm__("push ix");
    __asm__("push iy");
#endif

    //tickISR();
    uartISR();

#ifdef INT_SAVE_ALT_REG
    __asm__("pop iy");
    __asm__("pop ix");
    __asm__("pop hl");
    __asm__("pop de");
    __asm__("pop bc");
    __asm__("pop af");
    __asm__("exx");
#endif

    __asm__("pop iy");
    __asm__("pop ix");
    __asm__("pop hl");
    __asm__("pop de");
    __asm__("pop bc");
    __asm__("pop af");
    __asm__("ei");
    __asm__("reti");
}

void do_NMI() __interrupt __critical
{
    //nmiISR();
}

void di() __naked
{
    __asm__("push af");
    __asm__("ld a, (_interruptDisableRefCount)");
    __asm__("or a");
    __asm__("jr nz, skip_di");
    __asm__("di");
    __asm__("skip_di:");
    __asm__("inc a");
    __asm__("ld (_interruptDisableRefCount), a");
    __asm__("pop af");
    __asm__("ret");
}

void ei() __naked
{
    __asm__("push af");
    __asm__("ld a, (_interruptDisableRefCount)");
    __asm__("dec a");
    __asm__("ld (_interruptDisableRefCount), a");
    __asm__("or a");
    __asm__("jr nz, skip_ei");
    __asm__("pop af");
    __asm__("ret");
    __asm__("skip_ei:");
    __asm__("pop af");
    __asm__("ei");
    __asm__("ret");
}



I have also purged __critical from my code and placed di() and ei() where I need it.

No comments:

Post a Comment