aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUri Shaked2021-10-24 15:33:09 +0300
committerUri Shaked2021-10-24 15:33:09 +0300
commita7132e3766deb4ee49f94513b702525b42af2c1f (patch)
treeb37a178f75476109090d98949defccaf1833d672
parent0.18.3 (diff)
downloadavr8js-a7132e3766deb4ee49f94513b702525b42af2c1f.tar.gz
avr8js-a7132e3766deb4ee49f94513b702525b42af2c1f.tar.bz2
avr8js-a7132e3766deb4ee49f94513b702525b42af2c1f.zip
fix(eeprom): EEPROM interrupt not firing #110
fix #110
Diffstat (limited to '')
-rw-r--r--src/cpu/cpu.ts5
-rw-r--r--src/peripherals/eeprom.spec.ts27
-rw-r--r--src/peripherals/eeprom.ts8
3 files changed, 35 insertions, 5 deletions
diff --git a/src/cpu/cpu.ts b/src/cpu/cpu.ts
index 2675d1d..fe3bf63 100644
--- a/src/cpu/cpu.ts
+++ b/src/cpu/cpu.ts
@@ -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 {
diff --git a/src/peripherals/eeprom.spec.ts b/src/peripherals/eeprom.spec.ts
index 8f08e47..a90116f 100644
--- a/src/peripherals/eeprom.spec.ts
+++ b/src/peripherals/eeprom.spec.ts
@@ -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;
@@ -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
});
diff --git a/src/peripherals/eeprom.ts b/src/peripherals/eeprom.ts
index 8056847..045ffe8 100644
--- a/src/peripherals/eeprom.ts
+++ b/src/peripherals/eeprom.ts
@@ -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 {
/**
@@ -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);
}
@@ -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
@@ -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;
};
}
}