Skip to content

Commit d3ebb7a

Browse files
committed
fix(pio): incorrect FDEBUG TXSTALL/RXSTALL behavior
Writing to FDEBUG clears the TXSTALL/RXSTALL, even if the FIFOs are still empty/full (respectively), which is not the correct behavior.
1 parent b6f11ae commit d3ebb7a

File tree

2 files changed

+49
-4
lines changed

2 files changed

+49
-4
lines changed

src/peripherals/pio.spec.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ const SM0_PINCTRL = 0x502000dc;
5656
const SM2_INSTR = 0x50200108;
5757
const INTR = 0x50200128;
5858
const IRQ0_INTE = 0x5020012c;
59+
const FDEBUG = 0x50200008; // Debug register
5960

6061
const NVIC_ISPR = 0xe000e200;
6162
const NVIC_ICPR = 0xe000e280;
@@ -85,6 +86,9 @@ const EXECCTRL_WRAP_BOTTOM_SHIFT = 7;
8586
const EXECCTRL_WRAP_TOP_SHIFT = 12;
8687
const EXECCTRL_STATUS_N_SHIFT = 0;
8788

89+
// FDEBUG bits
90+
const FDEBUG_TXSTALL = 1 << 24;
91+
8892
const DBG_PADOUT = 0x5020003c;
8993

9094
const SET_COUNT_SHIFT = 26;
@@ -559,6 +563,38 @@ describe('PIO', () => {
559563
expect((await cpu.readUint32(NVIC_ISPR)) & PIO_IRQ0).toEqual(PIO_IRQ0);
560564
});
561565

566+
it('should set TXSTALL flag in FDEBUG when trying to pull from an empty TX FIFO and only clear it after TX is no longer stalled', async () => {
567+
await resetStateMachines();
568+
569+
// Clear FDEBUG register
570+
await cpu.writeUint32(FDEBUG, 0xffffffff);
571+
expect(await cpu.readUint32(FDEBUG)).toBe(0);
572+
573+
// Make sure TX FIFO is empty
574+
expect(await cpu.readUint32(FLEVEL)).toEqual(0 << TX0_SHIFT);
575+
576+
// Attempt to pull from an empty TX FIFO
577+
await cpu.writeUint32(SM0_INSTR, pioPULL(false, false));
578+
579+
// Check that the TXSTALL flag is set
580+
expect((await cpu.readUint32(FDEBUG)) & (FDEBUG_TXSTALL << 0)).toEqual(FDEBUG_TXSTALL << 0);
581+
582+
// Try clearing the TXSTALL flag while TX FIFO is still empty
583+
await cpu.writeUint32(FDEBUG, FDEBUG_TXSTALL << 0);
584+
585+
// Verify the flag is NOT cleared because TX is still stalled
586+
expect((await cpu.readUint32(FDEBUG)) & (FDEBUG_TXSTALL << 0)).toEqual(FDEBUG_TXSTALL << 0);
587+
588+
// Push something to TX FIFO to unstall it
589+
await cpu.writeUint32(TXF0, 42);
590+
591+
// Now try clearing the flag again
592+
await cpu.writeUint32(FDEBUG, FDEBUG_TXSTALL << 0);
593+
594+
// Now the flag should be cleared
595+
expect((await cpu.readUint32(FDEBUG)) & (FDEBUG_TXSTALL << 0)).toEqual(0);
596+
});
597+
562598
it('should update RXFNEMPTY flag in INTR according to the level of the RX FIFO (issue #73)', async () => {
563599
await resetStateMachines();
564600
await cpu.writeUint32(IRQ0_INTE, INTR_SM0_RXNEMPTY);

src/peripherals/pio.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ export class StateMachine {
187187
return;
188188
}
189189
this.txFIFO.push(value);
190+
this.pio.txStall &= ~(FDEBUG_TXSTALL << this.index);
190191
this.updateDMATx();
191192
this.checkWait();
192193
if (this.txFIFO.full) {
@@ -200,6 +201,7 @@ export class StateMachine {
200201
return 0;
201202
}
202203
const result = this.rxFIFO.pull();
204+
this.pio.rxStall &= ~(FDEBUG_RXSTALL << this.index);
203205
this.updateDMARx();
204206
this.checkWait();
205207
if (this.rxFIFO.empty) {
@@ -504,7 +506,8 @@ export class StateMachine {
504506
this.updateDMARx();
505507
this.pio.checkInterrupts();
506508
} else {
507-
this.pio.fdebug |= FDEBUG_RXSTALL << this.index;
509+
this.pio.rxStall |= FDEBUG_RXSTALL << this.index;
510+
this.pio.fdebug |= this.pio.rxStall;
508511
this.wait(WaitType.rxFIFO, false, this.inputShiftReg);
509512
}
510513
this.inputShiftCount = 0;
@@ -523,7 +526,8 @@ export class StateMachine {
523526
this.updateDMATx();
524527
this.pio.checkInterrupts();
525528
} else {
526-
this.pio.fdebug |= FDEBUG_TXSTALL << this.index;
529+
this.pio.txStall |= FDEBUG_TXSTALL << this.index;
530+
this.pio.fdebug |= this.pio.txStall;
527531
this.wait(WaitType.Out, false, arg);
528532
}
529533
}
@@ -556,7 +560,8 @@ export class StateMachine {
556560
this.updateDMATx();
557561
this.pio.checkInterrupts();
558562
} else {
559-
this.pio.fdebug |= FDEBUG_TXSTALL << this.index;
563+
this.pio.txStall |= FDEBUG_TXSTALL << this.index;
564+
this.pio.fdebug |= this.pio.txStall;
560565
if (block) {
561566
this.wait(WaitType.txFIFO, false, 0);
562567
} else {
@@ -578,7 +583,8 @@ export class StateMachine {
578583
this.updateDMARx();
579584
this.pio.checkInterrupts();
580585
} else {
581-
this.pio.fdebug |= FDEBUG_RXSTALL << this.index;
586+
this.pio.rxStall |= FDEBUG_RXSTALL << this.index;
587+
this.pio.fdebug |= this.pio.rxStall;
582588
if (block) {
583589
this.wait(WaitType.rxFIFO, false, this.inputShiftReg);
584590
}
@@ -928,6 +934,8 @@ export class RPPIO extends BasePeripheral implements Peripheral {
928934

929935
stopped = true;
930936
fdebug = 0;
937+
txStall = 0;
938+
rxStall = 0;
931939
inputSyncBypass = 0;
932940
irq = 0;
933941
pinValues = 0;
@@ -1098,6 +1106,7 @@ export class RPPIO extends BasePeripheral implements Peripheral {
10981106
}
10991107
case FDEBUG:
11001108
this.fdebug &= ~this.rawWriteValue;
1109+
this.fdebug |= this.txStall | this.rxStall;
11011110
break;
11021111
case TXF0:
11031112
this.machines[0].writeFIFO(value);

0 commit comments

Comments
 (0)