Skip to content

Commit

Permalink
fix(eeprom): EEPROM interrupt not firing #110
Browse files Browse the repository at this point in the history
fix #110
  • Loading branch information
urish committed Oct 24, 2021
1 parent cd0cb03 commit a7132e3
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 5 deletions.
5 changes: 3 additions & 2 deletions src/cpu/cpu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,10 @@ export class CPU {
}

updateInterruptEnable(interrupt: AVRInterruptConfig, registerValue: u8) {
const { enableMask, flagRegister, flagMask } = interrupt;
const { enableMask, flagRegister, flagMask, inverseFlag } = interrupt;
if (registerValue & enableMask) {
if (this.data[flagRegister] & flagMask) {
const bitSet = this.data[flagRegister] & flagMask;
if (inverseFlag ? !bitSet : bitSet) {
this.queueInterrupt(interrupt);
}
} else {
Expand Down
27 changes: 26 additions & 1 deletion src/peripherals/eeprom.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,30 @@ describe('EEPROM', () => {
cpu.writeData(EEDR, 0x55);
cpu.writeData(EEARL, 15);
cpu.writeData(EEARH, 0);
cpu.writeData(EECR, EEMPE | EERIE);
cpu.writeData(EECR, EEMPE);
cpu.data[SREG] = 0x80; // SREG: I-------
cpu.writeData(EECR, EEPE | EERIE);
cpu.cycles += 1000;
cpu.tick();
// At this point, write shouldn't be complete yet
expect(cpu.data[EECR] & EEPE).toEqual(EEPE);
expect(cpu.pc).toEqual(0);
cpu.cycles += 10000000;
// And now, 10 million cycles later, it should.
cpu.tick();
expect(eepromBackend.memory[15]).toEqual(0x55);
expect(cpu.data[EECR] & EEPE).toEqual(0);
expect(cpu.pc).toEqual(0x2c); // EEPROM Ready interrupt
});

it('should clear the fire an interrupt when there is a pending interrupt and the interrupt flag is enabled (issue #110)', () => {
const cpu = new CPU(new Uint16Array(0x1000));
const eepromBackend = new EEPROMMemoryBackend(1024);
new AVREEPROM(cpu, eepromBackend);
cpu.writeData(EEDR, 0x55);
cpu.writeData(EEARL, 15);
cpu.writeData(EEARH, 0);
cpu.writeData(EECR, EEMPE);
cpu.data[SREG] = 0x80; // SREG: I-------
cpu.writeData(EECR, EEPE);
cpu.cycles += 1000;
Expand All @@ -112,6 +135,8 @@ describe('EEPROM', () => {
cpu.tick();
expect(eepromBackend.memory[15]).toEqual(0x55);
expect(cpu.data[EECR] & EEPE).toEqual(0);
cpu.writeData(EECR, EERIE);
cpu.tick();
expect(cpu.pc).toEqual(0x2c); // EEPROM Ready interrupt
});

Expand Down
8 changes: 6 additions & 2 deletions src/peripherals/eeprom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ const EEMPE = 1 << 2;
const EERIE = 1 << 3;
const EEPM0 = 1 << 4;
const EEPM1 = 1 << 5;
const EECR_WRITE_MASK = EEPE | EEMPE | EERIE | EEPM0 | EEPM1;

export class AVREEPROM {
/**
Expand Down Expand Up @@ -91,6 +92,9 @@ export class AVREEPROM {

const addr = (this.cpu.data[EEARH] << 8) | this.cpu.data[EEARL];

this.cpu.data[EECR] = (this.cpu.data[EECR] & ~EECR_WRITE_MASK) | (eecr & EECR_WRITE_MASK);
this.cpu.updateInterruptEnable(this.EER, eecr);

if (eecr & EERE) {
this.cpu.clearInterrupt(this.EER);
}
Expand All @@ -116,6 +120,7 @@ export class AVREEPROM {
if (eecr & EEPE) {
// If EEMPE is zero, setting EEPE will have no effect.
if (this.cpu.cycles >= this.writeEnabledCycles) {
this.cpu.data[EECR] &= ~EEPE;
return true;
}
// Check for write-in-progress
Expand Down Expand Up @@ -147,10 +152,9 @@ export class AVREEPROM {
// When EEPE has been set, the CPU is halted for two cycles before the
// next instruction is executed.
this.cpu.cycles += 2;
return true;
}

return false;
return true;
};
}
}

0 comments on commit a7132e3

Please sign in to comment.