MOS6526 CIA detailed test vectors and models

Es gibt 44 Antworten in diesem Thema, welches 13.071 mal aufgerufen wurde. Der letzte Beitrag (12. Januar 2021 um 00:20) ist von merlintwa.

  • You already know the discussion here: Bitte melde dich an, um diesen Link zu sehen.? This is the background for (some of) the VICE test progs.

  • You already know the discussion here: Bitte melde dich an, um diesen Link zu sehen.? This is the background for (some of) the VICE test progs.

    Thanks, no I wasn't aware of that thread. From my background, it looks like some internal transistor dimensions difference between IC production batches, cause some CIA batches to have slightly different behaviour when internal drivers are competing. Or something.

    Anyway I'd noticed and implemented the SDR buffering too. The datasheet does mention you can write and keep the buffer filled for continuous transmission.

    I've now been measuring and taking into account the resetting of the SDR shift counter that happens whenever you switch between SPmode input and output - although I've not exhaustively tested those cases yet. Also there is some strange behaviour when you write to SDR while it is in input mode - it seems to skip one input bit in some cases.

    I've observed and am reproducing the behaviour when reading and /or writing twice or more in the same PHI2 high phase to multiple registers. The reason to test and implement this, is that it you get a model much closer to the real thing meaning crazy corner cases are easier to find and reproduce. Like what exactly causes start and stop

    The hardest part still is the Timer A / B behaviour when cycle-accurately reading or writing very close to the timer overflows. For example the exact cycle that the start bit goes to stop when in one-shot mode, or re-starting a timer right before, during or after it stopped. I don't see any other way than exhaustively creating all the test cases one by one.

    I'm still not sure about reproducing the infamous Timer B bug. I see a lot of glitches and strange behaviour - but I've not yet seen a case the ICR skips a Timer B interrupt valid for at least one cycle. I'll try working on that more. Maybe its a combination of 6510 behaviour + 6526

  • I've now been measuring and taking into account the resetting of the SDR shift counter that happens whenever you switch between SPmode input and output - although I've not exhaustively tested those cases yet. Also there is some strange behaviour when you write to SDR while it is in input mode - it seems to skip one input bit in some cases.

    As I am currently working on serial data transfer with the SDR (for OpenCBM and a 1570/1571/1581 drive): can you elaborate a little bit about what you found out? This seems interesting to me.
    I am currently having the case the the transfer works for 3 to 5 MB, but every know and then, the transfer stops. To me, it seems that some byte was skipped. That's why what you wrote above sounds very interesting to me.

  • Hi Strik,

    > I am currently having the case the the transfer works for 3 to 5 MB, but every know and then, the transfer stops. To me, it seems that some byte was skipped. That's why what you wrote above sounds very interesting to me.

    Well I've not seen all the details to comment, but in general I'd expect a skipped interrupt then. It could be an as yet unknown bug, like the infamous timer B bug where you read ICR on the exact cycle timer B has an underflow.


    But I'm not aware of any details of the 1570/71/81 so I couldn't say if there is any issue in there somewhere.

    If there is some issue that happens truly randomly in time it might also be caused by meta-stability issues. Then again at these kind of slow speeds that would surprise me.

    Thinking about it a bit more - maybe I'd check the signal integrity coming from the PC side (or what you're using) and flank steepness to see if that couldnt' trigger something twice.

    Then again, I described above my experience with PC using high speed interfacing: you just can't do anything realtime of any sort with PCs. Chipsets also vary too much and have (in some cases poorly understood) timing bugs. So anything on PC would in my opinion need full handshaking. But some type of Arduino inbetween should work just fine.

  • WHen I clock SDR in any faster than CNT three cycles low, three cycles high, then I get unreliable state. Something is still working but not reliably. This must mean the exact internal state is meant to go no faster than 3 cycles (which is 4 cycles of an external part which then could be 3 cycles occasionaly due to clock drift between systems)

    Motivated by @strik's recent work on the SRQ-transfer for opencbm that he mentions, I recently did some tests by hooking up a FPGA board to my C64's CIA and using different timings to check which of them are relevant when receiving into the shift register.

    My impression was that after the positive edge of CNT the CIA samples SP on the second rising edge of PHI2 following the next falling edge of PHI2. That's true even if CNT goes low again before this time (but a second rising edge of CNT before the data is sampled seems to kill the cycle). This would suggest that it takes 1,5 (best case) to 3,5 (worst case) PHI2 cycles to sample the data, depending on the phase difference between PHI2 and CNT. And I could in fact "reliably" transfer data into the SR with about double the nominal rate (that it, 2 x PHI2 instead of 4 x) when I aligned CNT to just before the negative PHI2 edges. (I didn't transfer MBs but only KBs, but I found the results to be pretty reproducible in either way).

    I also had cases where the SR would receive the correct value, but the IRQ bit wouldn't be set. I haven't found what could cause that, though, and I suspect it might well be a bug in my test setup.

  • Hi Thierer, Strik,

    So I got interested in the interrupt details from your questions, and I've tried to create a case like the Timer B bug. Which promptly appeared in my test output.

    Read 0xd: 0x93 // TA&TB irqs cleared.

    Scan 0xd: 0x82 // Scan means keep PHI2=1 and complete the cycle on a different address. CIA never completes the read-side-effects. TB underflows in this exact cycle.

    Scan 0xd: 0x91 // Timer A interrupt appears, Timer B present in last cycle has now disappeared. This is the infamous Timer B bug.

    I also tried testing what happens when CNT runs faster or slower and its effect on the IC. Below is a CNT test to the Timer A input.

    To understand whats below: it is important to note that I have connected RS[2] to the CNT input (with a series resistor)

    R() means a normal read cycle is done with phi2=1, the 2nd value is what the IC had on its output. Then , PHI2=0.

    L() Sets some lines to a value, D: FFFF means set to data input.

    P() are comments.

    The test does not always have the exact same result, below you can see one place where the delay of CNT to TA change is a cycle less than other cases. Actually that is the normal progression now I think of it.

    But I do get more and more the impression some part of the IC is running on phi2/2, from the FLAG and CNT capturing at higher speeds. Or the edge-capture logic is not being reset properly when FLAG or CNT run faster than phi2/3

    W('h4,'h03); P("Write TAL: 03");

    W('h5,'h00); P("Write TAH: 00");

    W('hD,'h83); P("Write ICR: 83");

    W('hE,'h31); P("Write CRA: 31");

    ...

    P("CNT 1->0->1->0->1 pulses, phi2= fixed 1");

    R('h4,'h01); P("Read TAL");

    R('h4,'h01); P("Read TAL");

    R('h4,'h00); P("Read TAL");

    L(1,0,1,'h0,'hFFFF); P("Set PHI2: 1, CSN: 0, RWN: 1, RS: 0, D: FFFF");

    L(1,0,1,'h4,'hFFFF); P("Set PHI2: 1, CSN: 0, RWN: 1, RS: 4, D: FFFF");

    L(1,0,1,'h0,'hFFFF); P("Set PHI2: 1, CSN: 0, RWN: 1, RS: 0, D: FFFF");

    L(1,0,1,'h4,'hFFFF); P("Set PHI2: 1, CSN: 0, RWN: 1, RS: 4, D: FFFF");

    R('h4,'h00); P("Read TAL");

    R('h4,'h00); P("Read TAL");

    R('h4,'h03); P("Read TAL");

    P("CNT 1->0->1->0->1 pulses, phi2= fixed 0");

    L(0,0,1,'h0,'hFFFF); P("Set PHI2: 0, CSN: 0, RWN: 1, RS: 0, D: FFFF");

    L(0,0,1,'h4,'hFFFF); P("Set PHI2: 0, CSN: 0, RWN: 1, RS: 4, D: FFFF");

    L(0,0,1,'h0,'hFFFF); P("Set PHI2: 0, CSN: 0, RWN: 1, RS: 0, D: FFFF");

    L(0,0,1,'h4,'hFFFF); P("Set PHI2: 0, CSN: 0, RWN: 1, RS: 4, D: FFFF");

    R('h4,'h03); P("Read TAL");

    R('h4,'h03); P("Read TAL");

    R('h4,'h03); P("Read TAL");

    R('h4,'h02); P("Read TAL");

    P("CNT = PHI2 4 pulses A2");

    R('h4,'h02); P("Read TAL");

    R('h1,'hBF); P("Read PB");

    R('h4,'h02); P("Read TAL");

    R('h1,'hBF); P("Read PB");

    R('h4,'h02); P("Read TAL");

    R('h1,'hBF); P("Read PB");

    R('h4,'h01); P("Read TAL");

    R('h1,'hBF); P("Read PB");

    R('h4,'h03); P("Read TAL");

    R('h1,'hBF); P("Read PB");

    R('h4,'h03); P("Read TAL");

    R('h1,'hBF); P("Read PB");

    P("CNT = phi2/2 4 pulses A2");

    R('h4,'h02); P("Read TAL");

    R('h4,'h01); P("Read TAL");

    R('h1,'hBF); P("Read PB");

    R('h1,'hBF); P("Read PB");

    R('h4,'h00); P("Read TAL");

    R('h4,'h00); P("Read TAL");

    R('h1,'hBF); P("Read PB");

    R('h1,'hBF); P("Read PB");

    R('h4,'h03); P("Read TAL");

    R('h4,'h03); P("Read TAL");

    R('h1,'hBF); P("Read PB");

    R('h1,'hBF); P("Read PB");

    R('h4,'h02); P("Read TAL");

    R('h4,'h02); P("Read TAL");

    R('h1,'hBF); P("Read PB");

    R('h1,'hBF); P("Read PB");

    P("CNT = phi2/4 4 pulses A2");

    R('h4,'h01); P("Read TAL");

    R('h4,'h01); P("Read TAL");

    R('h4,'h01); P("Read TAL");

    R('h4,'h00); P("Read TAL"); //3 delay

    R('h1,'hBF); P("Read PB");

    R('h1,'hBF); P("Read PB");

    R('h1,'hBF); P("Read PB");

    R('h1,'hBF); P("Read PB");

    R('h4,'h00); P("Read TAL");

    R('h4,'h00); P("Read TAL");

    R('h4,'h03); P("Read TAL"); // 2 delay

    R('h4,'h03); P("Read TAL");

    R('h1,'hBF); P("Read PB");

    R('h1,'hBF); P("Read PB");

    R('h1,'hBF); P("Read PB");

    R('h1,'hBF); P("Read PB");

    R('h4,'h03); P("Read TAL");

    R('h4,'h03); P("Read TAL");

    R('h4,'h03); P("Read TAL");

    R('h4,'h02); P("Read TAL"); // 3 delay

    R('h1,'hBF); P("Read PB");

    R('h1,'hBF); P("Read PB");

    R('h1,'hBF); P("Read PB");

    R('h1,'hBF); P("Read PB");

    R('h4,'h02); P("Read TAL");

    R('h4,'h02); P("Read TAL");

    R('h4,'h02); P("Read TAL");

    R('h4,'h01); P("Read TAL"); // 3 delay

    R('h1,'hBF); P("Read PB");

    R('h1,'hBF); P("Read PB");

    R('h1,'hBF); P("Read PB");

    R('h1,'hBF); P("Read PB");

    R('h4,'h01); P("Read TAL");

    R('h4,'h01); P("Read TAL");

    R('h4,'h01); P("Read TAL");

    R('h4,'h00); P("Read TAL"); // 3 delay

    R('h1,'hBF); P("Read PB");

    R('h1,'hBF); P("Read PB");

    R('h1,'hBF); P("Read PB");

    R('h1,'hBF); P("Read PB");

    R('h4,'h00); P("Read TAL");

    R('h4,'h00); P("Read TAL");

    R('h4,'h03); P("Read TAL"); // 2 delay

    R('h4,'h03); P("Read TAL");

    R('h1,'hBF); P("Read PB");

    R('h1,'hBF); P("Read PB");

    R('h1,'hBF); P("Read PB");

    R('h1,'hBF); P("Read PB");

    R('h4,'h03); P("Read TAL");

    R('h4,'h03); P("Read TAL");

    R('h4,'h03); P("Read TAL");

    R('h4,'h02); P("Read TAL");

    R('h1,'hBF); P("Read PB");

    R('h1,'hBF); P("Read PB");

    R('h1,'hBF); P("Read PB");

    R('h1,'hBF); P("Read PB");

    R('h4,'h02); P("Read TAL");

    R('h4,'h02); P("Read TAL");

    R('h4,'h02); P("Read TAL");

    R('h4,'h01); P("Read TAL");

    R('h1,'hBF); P("Read PB");

    R('h1,'hBF); P("Read PB");

    R('h1,'hBF); P("Read PB");

    R('h1,'hBF); P("Read PB");

    R('hD,'h9B); P("Read ICR");

  • I have to admit that I don't fully understand the implications of the debug output you provided.

    As I understand it, you are suggesting that a similar behaviour to the "timer b bug" might exist for the SR IRQ? How I understand the "timer b bug" (I had to look it up, please pardon my ignorance...) it means that the IRQ flag is not set if the ICR is read right before the flag would be set?

    That would make a lot of sense: What I did in my tests is that I had some code running on the C64 which checked the ICR in a loop and then put the content of the SR in PB, so the FPGA could read it check if this matched the value it sent.

    And checking the ICR in a tight loop is exactly what the Bitte melde dich an, um diesen Link zu sehen. (that exhibits the bug, that strik is currently investigating) is doing.

  • Well, understanding what the tests are doing is exactly the ongoing trick of course :smile: Its just a list of actions sent to the IC, and observations of the internal state change. Interpretations are always difficult.

    Yes, there may be a bug like the Timer B bug - I would then also only expect those bugs in the so-called "old" 6526R4. But who knows. So far I have not seen this bug in my tests - but if it exists I will be able to find it. But if it is a bug similar to the timer B bug, it would present itself at any speed of operation of the serial port.

    I would currently find it more likely you're facing an improperly reset internal shift counter in some cases.

    In my tests I observe at the end of every 8 bits of transfer, at PHI/2 speeds, one bit is skipped in some as-yet unknown reason.

    At phi2/2 speeds, SP is really still sampled after 3 clocks, so in the same cycle the next CNT edge is created you can set the SP value for the *previous* bit.

    What seems to happen at phi2/2 speed in my tests is that when the shift register is full and needs to move its content to SDR, this overlaps with the same cycle as the next input bit arriving. So the data copied into SDR is actually one bit too late. Subsequently the reset of the shift counter seems to be off.

    This end of a byte internally seems to go wrong at phi/2. At least that is my best current guess from measurements I have.

    I'm fairly sure the IC was not intended to go this fast - the datasheet mentions SP is captured on posedge. That is true only if CNT is lower than PHI2/4. And that aligns with the max speed another 6526 on the same clock frequency is able to produce.

    For completeness here is my current test stream for the SDR input at higher speeds: Note that I observe that switching the SPMODE in CRA to output resets the INPUT shift regsiter. So I use SPMODE out for a few cycles to get into a known state of the internal input shift register.

    It is important to note I connect RS[2] (with resistor) to CNT, and RS[3] (with resistor) to the SP input. So reading or writing anything will set CNT, SP to the highest 2 bits of the 4-bit register address

    Same functions as above.

    P("Test SDR input from SP on CNT");

    W('hE,'h40); P("Write CRA: 40");

    W('hD,'h7F); P("Write ICR: 7F");

    R('hC,'h00); P("Read SDR");

    R('hC,'h00); P("Read SDR");

    R('hC,'h00); P("Read SDR");

    R('hC,'h00); P("Read SDR");

    W('hE,'h00); P("Write CRA: 00");

    R('hD,'h18); P("Read ICR");

    R('h0,'hFF); P("Read PA");

    R('h0,'hFF); P("Read PA");

    R('h0,'hFF); P("Read PA");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('h0,'hFF); P("Read PA");

    R('h0,'hFF); P("Read PA");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h8,'h09); P("Read TDT");

    R('h8,'h09); P("Read TDT");

    R('h8,'h09); P("Read TDT");

    R('hC,'h00); P("Read SDR");

    R('hC,'h00); P("Read SDR");

    R('hC,'h00); P("Read SDR");

    R('h0,'hFF); P("Read PA");

    R('h0,'hFF); P("Read PA");

    R('h0,'hFF); P("Read PA");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h8,'h09); P("Read TDT");

    R('h8,'h09); P("Read TDT");

    R('h8,'h09); P("Read TDT");

    R('hC,'h00); P("Read SDR");

    R('hC,'h00); P("Read SDR");

    R('hC,'h00); P("Read SDR");

    R('h8,'h09); P("Read TDT");

    R('h8,'h09); P("Read TDT");

    R('h8,'h09); P("Read TDT");

    R('hC,'h00); P("Read SDR");

    R('hC,'h00); P("Read SDR");

    R('hC,'h00); P("Read SDR");

    R('h8,'h09); P("Read TDT");

    R('h8,'h09); P("Read TDT");

    R('h8,'h09); P("Read TDT");

    R('hC,'h00); P("Read SDR");

    R('hC,'h00); P("Read SDR");

    R('hC,'h00); P("Read SDR");

    R('h0,'hFF); P("Read PA");

    R('h0,'hFF); P("Read PA");

    R('h0,'hFF); P("Read PA");

    R('h0,'hFF); P("Read PA");

    R('h4,'hFF); P("Read TAL");

    R('hC,'h00); P("Read SDR");

    R('h4,'hFF); P("Read TAL");

    R('hC,'h00); P("Read SDR");

    R('h4,'hFF); P("Read TAL");

    R('hC,'h2E); P("Read SDR");

    R('hC,'h2E); P("Read SDR");

    R('hD,'h18); P("Read ICR");

    R('hC,'h2E); P("Read SDR");

    R('hC,'h2E); P("Read SDR");

    R('hC,'h2E); P("Read SDR");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h8,'h09); P("Read TDT");

    R('hC,'h2E); P("Read SDR");

    R('hC,'h2E); P("Read SDR");

    R('h4,'hFF); P("Read TAL");

    R('hC,'h2E); P("Read SDR");

    R('hC,'h2E); P("Read SDR");

    R('hC,'h2E); P("Read SDR");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('hC,'h2E); P("Read SDR");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h8,'h09); P("Read TDT");

    R('hC,'h2E); P("Read SDR");

    R('hC,'h2E); P("Read SDR");

    R('h4,'hFF); P("Read TAL");

    R('hC,'h2E); P("Read SDR");

    R('hC,'h2E); P("Read SDR");

    R('hC,'h2E); P("Read SDR");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('hC,'h2E); P("Read SDR");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h8,'h00); P("Read TDT");

    R('hC,'h2E); P("Read SDR");

    R('hC,'h2E); P("Read SDR");

    R('h4,'hFF); P("Read TAL");

    R('hC,'h2E); P("Read SDR");

    R('hC,'h2E); P("Read SDR");

    R('hC,'h2E); P("Read SDR");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('hC,'h2E); P("Read SDR");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h8,'h00); P("Read TDT");

    R('hC,'h2E); P("Read SDR");

    R('hC,'h2E); P("Read SDR");

    R('h4,'hFF); P("Read TAL");

    R('hC,'h2E); P("Read SDR");

    R('hC,'h2E); P("Read SDR");

    R('hC,'h2E); P("Read SDR");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('hC,'h2E); P("Read SDR");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h8,'h00); P("Read TDT");

    R('hC,'h55); P("Read SDR");

    R('hC,'h55); P("Read SDR");

    R('h4,'hFF); P("Read TAL");

    R('hC,'h55); P("Read SDR");

    R('hC,'h55); P("Read SDR");

    R('hC,'h55); P("Read SDR");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('hC,'h55); P("Read SDR");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h8,'h01); P("Read TDT");

    R('hC,'h55); P("Read SDR");

    R('hC,'h55); P("Read SDR");

    R('h4,'hFF); P("Read TAL");

    R('hC,'h55); P("Read SDR");

    R('hC,'h55); P("Read SDR");

    R('hC,'h55); P("Read SDR");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('hC,'h55); P("Read SDR");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h8,'h01); P("Read TDT");

    R('hC,'h55); P("Read SDR");

    R('hC,'h55); P("Read SDR");

    R('h4,'hFF); P("Read TAL");

    R('hC,'h55); P("Read SDR");

    R('hC,'h55); P("Read SDR");

    R('hC,'h55); P("Read SDR");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('hC,'h55); P("Read SDR");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h8,'h01); P("Read TDT");

    R('hC,'h55); P("Read SDR");

    R('hC,'h55); P("Read SDR");

    R('h4,'hFF); P("Read TAL");

    R('hC,'h55); P("Read SDR");

    R('hC,'h55); P("Read SDR");

    R('hC,'h55); P("Read SDR");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('hC,'h55); P("Read SDR");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('h0,'hFF); P("Read PA");

    R('h0,'hFF); P("Read PA");

    R('h0,'hFF); P("Read PA");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('h0,'hFF); P("Read PA");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('h0,'hFF); P("Read PA");

    R('hC,'h55); P("Read SDR");

    R('hC,'h55); P("Read SDR");

    R('h8,'h02); P("Read TDT");

    R('h8,'h02); P("Read TDT");

    R('hC,'h55); P("Read SDR");

    R('hC,'h55); P("Read SDR");

    R('h8,'h02); P("Read TDT");

    R('h8,'h02); P("Read TDT");

    R('hC,'h55); P("Read SDR");

    R('hC,'h55); P("Read SDR");

    R('h8,'h02); P("Read TDT");

    R('h8,'h02); P("Read TDT");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('h0,'hFF); P("Read PA");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('h0,'hFF); P("Read PA");

    R('hC,'h55); P("Read SDR");

    R('hC,'h55); P("Read SDR");

    R('h8,'h02); P("Read TDT");

    R('h8,'h02); P("Read TDT");

    R('hD,'h18); P("Read ICR");

    R('h0,'hFF); P("Read PA");

    R('h0,'hFF); P("Read PA");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('hC,'h39); P("Read SDR");

    R('h0,'hFF); P("Read PA");

    R('hC,'h39); P("Read SDR");

    R('h0,'hFF); P("Read PA");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('hC,'h39); P("Read SDR");

    R('h0,'hFF); P("Read PA");

    R('hC,'h39); P("Read SDR");

    R('h0,'hFF); P("Read PA");

    R('hC,'h39); P("Read SDR");

    R('h0,'hFF); P("Read PA");

    R('hC,'hCF); P("Read SDR");

    R('h0,'hFF); P("Read PA");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('hC,'hCF); P("Read SDR");

    R('h0,'hFF); P("Read PA");

    R('hC,'hCF); P("Read SDR");

    R('h0,'hFF); P("Read PA");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('hC,'hCF); P("Read SDR");

    R('h0,'hFF); P("Read PA");

    R('hC,'hCF); P("Read SDR");

    R('h0,'hFF); P("Read PA");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('hC,'h36); P("Read SDR");

    R('h0,'hFF); P("Read PA");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('hC,'h36); P("Read SDR");

    R('h0,'hFF); P("Read PA");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('hC,'h36); P("Read SDR");

    R('h0,'hFF); P("Read PA");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('h0,'hFF); P("Read PA");

    R('hC,'h94); P("Read SDR");

    R('hC,'h94); P("Read SDR");

    R('h8,'h03); P("Read TDT");

    R('h8,'h03); P("Read TDT");

    R('hC,'h94); P("Read SDR");

    R('hC,'h94); P("Read SDR");

    R('h8,'h03); P("Read TDT");

    R('h8,'h03); P("Read TDT");

    W('hC,'h89); P("Write SDR: 89");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('h0,'hFF); P("Read PA");

    R('hC,'h89); P("Read SDR");

    R('hC,'h89); P("Read SDR");

    R('h8,'h03); P("Read TDT");

    R('h8,'h03); P("Read TDT");

    R('hC,'h89); P("Read SDR");

    R('hC,'h89); P("Read SDR");

    R('h8,'h03); P("Read TDT");

    R('h8,'h03); P("Read TDT");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('h0,'hFF); P("Read PA");

    R('hD,'h18); P("Read ICR");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('h0,'hFF); P("Read PA");

    R('hC,'h36); P("Read SDR");

    R('hC,'h36); P("Read SDR");

    R('h8,'h03); P("Read TDT");

    R('h8,'h03); P("Read TDT");

    R('h4,'hFF); P("Read TAL");

    R('h4,'hFF); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('h0,'hFF); P("Read PA");

    R('hD,'h10); P("Read ICR");

    W('hE,'h41); P("Write CRA: 41");

    M(1,1,1,1,0,1); P("lines PCN: 1, IRQN: 1, PB7: 1, PB6: 1, SP: 0, CNT: 1");

    X('hFF,'hFF,'h00,'h00,'hFF,'hFF,'hFF,'hFF,'h03,'h00,'h00,'h12,'h36,'h08,'h41,'h00,1);

    P("ic sc&rd: PA: FF PB: FF DDA: 00 DDB: 00 TAL: FF TAH: FF TBL: FF TBH: FF TDT: 03 TDS: 00 TDM: 00 TDH: 12 SDR: 36 ICR: 08 CRA: 41 CRB: 00 ");

    M(1,1,1,1,0,1); P("lines PCN: 1, IRQN: 1, PB7: 1, PB6: 1, SP: 0, CNT: 1");

    X('hFF,'hFF,'h00,'h00,'hFF,'hFF,'hFF,'hFF,'h03,'h00,'h00,'h12,'h36,'h18,'h41,'h00,1);

    P("ic sc&rd: PA: FF PB: FF DDA: 00 DDB: 00 TAL: FF TAH: FF TBL: FF TBH: FF TDT: 03 TDS: 00 TDM: 00 TDH: 12 SDR: 36 ICR: 18 CRA: 41 CRB: 00 ");

    M(1,1,1,1,0,1); P("lines PCN: 1, IRQN: 1, PB7: 1, PB6: 1, SP: 0, CNT: 1");

    X('hFF,'hFF,'h00,'h00,'hFE,'hFF,'hFF,'hFF,'h03,'h00,'h00,'h12,'h36,'h18,'h41,'h00,1);

    P("ic sc&rd: PA: FF PB: FF DDA: 00 DDB: 00 TAL: FE TAH: FF TBL: FF TBH: FF TDT: 03 TDS: 00 TDM: 00 TDH: 12 SDR: 36 ICR: 18 CRA: 41 CRB: 00 ");

    M(1,1,1,1,0,1); P("lines PCN: 1, IRQN: 1, PB7: 1, PB6: 1, SP: 0, CNT: 1");

    X('hFF,'hFF,'h00,'h00,'hFD,'hFF,'hFF,'hFF,'h03,'h00,'h00,'h12,'h36,'h18,'h41,'h00,1);

    P("ic sc&rd: PA: FF PB: FF DDA: 00 DDB: 00 TAL: FD TAH: FF TBL: FF TBH: FF TDT: 03 TDS: 00 TDM: 00 TDH: 12 SDR: 36 ICR: 18 CRA: 41 CRB: 00 ");

    M(1,1,1,1,0,1); P("lines PCN: 1, IRQN: 1, PB7: 1, PB6: 1, SP: 0, CNT: 1");

    W('hE,'h01); P("Write CRA: 01");

    R('h4,'hFB); P("Read TAL");

    R('h4,'hFA); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('h0,'hFF); P("Read PA");

    R('hC,'h65); P("Read SDR");

    R('hC,'h65); P("Read SDR");

    R('h8,'h03); P("Read TDT");

    R('h8,'h04); P("Read TDT");

    R('h4,'hF3); P("Read TAL");

    R('h4,'hF2); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('h0,'hFF); P("Read PA");

    R('h4,'hEF); P("Read TAL");

    R('h4,'hEE); P("Read TAL");

    R('h0,'hFF); P("Read PA");

    R('h0,'hFF); P("Read PA");

    X('hFF,'hFF,'h00,'h00,'hEB,'hFF,'hFF,'hFF,'h04,'h00,'h00,'h12,'h65,'h18,'h01,'h00,1);

    P("ic sc&rd: PA: FF PB: FF DDA: 00 DDB: 00 TAL: EB TAH: FF TBL: FF TBH: FF TDT: 04 TDS: 00 TDM: 00 TDH: 12 SDR: 65 ICR: 18 CRA: 01 CRB: 00 ");

    X('hFF,'hFF,'h00,'h00,'hEA,'hFF,'hFF,'hFF,'h04,'h00,'h00,'h12,'h65,'h18,'h01,'h00,1);

    P("ic sc&rd: PA: FF PB: FF DDA: 00 DDB: 00 TAL: EA TAH: FF TBL: FF TBH: FF TDT: 04 TDS: 00 TDM: 00 TDH: 12 SDR: 65 ICR: 18 CRA: 01 CRB: 00 ");

    X('hFF,'hFF,'h00,'h00,'hE9,'hFF,'hFF,'hFF,'h04,'h00,'h00,'h12,'h65,'h18,'h01,'h00,1);

    P("ic sc&rd: PA: FF PB: FF DDA: 00 DDB: 00 TAL: E9 TAH: FF TBL: FF TBH: FF TDT: 04 TDS: 00 TDM: 00 TDH: 12 SDR: 65 ICR: 18 CRA: 01 CRB: 00 ");

    X('hFF,'hFF,'h00,'h00,'hE8,'hFF,'hFF,'hFF,'h04,'h00,'h00,'h12,'h65,'h18,'h01,'h00,1);

    P("ic sc&rd: PA: FF PB: FF DDA: 00 DDB: 00 TAL: E8 TAH: FF TBL: FF TBH: FF TDT: 04 TDS: 00 TDM: 00 TDH: 12 SDR: 65 ICR: 18 CRA: 01 CRB: 00 ");

    R('hD,'h18); P("Read ICR");

    X('hFF,'hFF,'h00,'h00,'hE6,'hFF,'hFF,'hFF,'h04,'h00,'h00,'h12,'h65,'h00,'h01,'h00,1);

    P("ic sc&rd: PA: FF PB: FF DDA: 00 DDB: 00 TAL: E6 TAH: FF TBL: FF TBH: FF TDT: 04 TDS: 00 TDM: 00 TDH: 12 SDR: 65 ICR: 00 CRA: 01 CRB: 00 ");

    X('hFF,'hFF,'h00,'h00,'hE5,'hFF,'hFF,'hFF,'h04,'h00,'h00,'h12,'h65,'h10,'h01,'h00,1);

    P("ic sc&rd: PA: FF PB: FF DDA: 00 DDB: 00 TAL: E5 TAH: FF TBL: FF TBH: FF TDT: 04 TDS: 00 TDM: 00 TDH: 12 SDR: 65 ICR: 10 CRA: 01 CRB: 00 ");

    X('hFF,'hFF,'h00,'h00,'hE4,'hFF,'hFF,'hFF,'h04,'h00,'h00,'h12,'h65,'h10,'h01,'h00,1);

    P("ic sc&rd: PA: FF PB: FF DDA: 00 DDB: 00 TAL: E4 TAH: FF TBL: FF TBH: FF TDT: 04 TDS: 00 TDM: 00 TDH: 12 SDR: 65 ICR: 10 CRA: 01 CRB: 00 ");

  • I think either FETs or open-drain with pullup would be fine. In fact, on reflection, I'd most likely go open-drain with pull-up, which is already how we do this on the IEC port etc on the MEGA65.

    Paul.

    Note that the IEC bus is behind 7406 open collector inverters. So knowing that the IEC bus is open collector doesn't meant that the CIA is open collector ;)

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Bitte melde dich an, um diesen Link zu sehen. | Bitte melde dich an, um diesen Link zu sehen.

    Bitte melde dich an, um diesen Link zu sehen.

  • Note that the IEC bus is behind 7406 open collector inverters. So knowing that the IEC bus is open collector doesn't meant that the CIA is open collector ;)

    Hi skoe,

    I would expect the NMOS versions of the 6526 to be very simillar to open-drain with a fairly low valued pull-up resistor (The PMOS) . But I have no experience with the HCMOS version, do you have any reason to believe an open-drain with pullup would not work in practice? Even at 3.3V? (given that the PLA doesn't even go above 3.6V I dont think there will be any issue running at 3.3V with 5V tolerance and maybe a small pulllup)

  • Yes, there may be a bug like the Timer B bug - I would then also only expect those bugs in the so-called "old" 6526R4. But who knows. So far I have not seen this bug in my tests - but if it exists I will be able to find it. But if it is a bug similar to the timer B bug, it would present itself at any speed of operation of the serial port.

    FWIW, my C64 has a 6526R4, so that's what I used. It then probably wouldn't apply to the CIAs in a 1571, though.

    At phi2/2 speeds, SP is really still sampled after 3 clocks, so in the same cycle the next CNT edge is created you can set the SP value for the *previous* bit.

    So here with "clocks" you mean clock changes (not clock cycles), right?

    I'm fairly sure the IC was not intended to go this fast - the datasheet mentions SP is captured on posedge. That is true only if CNT is lower than PHI2/4. And that aligns with the max speed another 6526 on the same clock frequency is able to produce.

    I'm not sure that's what you mean, but in my experience it is *not* possible for the CIA (at least the 6526R4 that I used) to reliably receive from a CIA running at the same clock speed at the highest data rate (ie timer a == 1) . In the worst case it takes 2,5 clock cycles (of the 4 clock cycles for one bit at maximum speed) from the rising edge of CNT until SP is sampled (I just realised in Bitte melde dich an, um diesen Link zu sehen. I wrote that the worst case is 3,5 clock cycles, that is not correct).

    As when sending from the SR the CIA uses a CNT duty cycle of 50% (2 clock cycles), the remaining 2 clock cycles are not enough for the receiving CIA to correctly sample the bit for all possible phase offsets between CNT and PHI2. (To correctly receive a bit, the CIA is happy with a much shorter low CNT phase than 2 clock cycles. The xum1541 firmware for interfacing with the 1571 uses a ~75% duty cycle for CNT, that's why the transfer generally works, even at the highest speed).

  • So here with "clocks" you mean clock changes (not clock cycles), right?

    I mean phi2 clocks (not CNT clocks). Please not I'm running PHi2 from a GPIO of the Arduino, so effectively all my tests are (far slower than) 10kHz. But that is perfectly ok, I have not noticed any issues running 6526 very slow. Leaving the 6526 at DC 0Hz for a very long time like a few seconds or more, I have seen some weird stuff happen though. Like it resetting itself. Not sure if that is an artifact.

    In the test above there is a sequence somewhere halfway showing what I mean: (I hope pasting this works): This is the same information as above, but just run through verilog to create a waveform. At the bottom are 2 registers from my own verilog model, where you can observe the shifter shifting and that the IC sends out CF as value of SDR, which is one cycle too late. The proper value SDR should have been was 67.

    About the rest yes your analysis makes perfect sense. Indeed, like you mention, the output with phase uncertainty wont work between 2 6526's. So thats an IC design oversight I suppose, not taking into account the clock phase issues and capturing edge.

    Bitte melde dich an, um diesen Anhang zu sehen.

  • Note on the diagram: the waveform is not an exact reflection of reality - The D pins of the CIA are sampled just before the negedge of phi2, and after that the D bus is tristate duting phi2=0. It also looks like the A pins arrive after the D change, and that D changes before phi2 even goes high - again this is just a converted version of the actual Arduino tests I'm doing. The places to look what the output of the IC are is on the negedges of phi2. The inputs do change like the graph shows - for this set of the tests at least - while phi2=0.

  • I mean phi2 clocks (not CNT clocks).

    I understand that. The reason why I was asking was your statement "SP is really still sampled after 3 clocks", while my understanding is that it's sampled after 3 half-cycles of PHI2 (see my reasoning in Bitte melde dich an, um diesen Link zu sehen.).

    Leaving the 6526 at DC 0Hz for a very long time like a few seconds or more, I have seen some weird stuff happen though. Like it resetting itself. Not sure if that is an artifact.

    I think that's true for all the NMOS chips. (In contrast to the WDC versions, where I think you can halt and resume the clock at will).

    In the test above there is a sequence somewhere halfway showing what I mean: (I hope pasting this works): This is the same information as above, but just run through verilog to create a waveform. At the bottom are 2 registers from my own verilog model, where you can observe the shifter shifting and that the IC sends out CF as value of SDR, which is one cycle too late. The proper value SDR should have been was 67.

    If I understand that correctly, the Verilog isn't supposed to model the workings of a real CIA but the equivalent of what you're doing with your Arduino code, right? Otherwise I don't understand it because the original chip takes 4 PHI2 cycles per bit when sending, while the waveform you posted seems to have only two cycles per bit.

  • Regarding (lack of) 0Hz operation. The MOS 6526 is probably filled with dynamic flip flops. The VIC-II is full of them, and so is the CPU. In the VIC II (the dieshots I have analyzed), the registers are refreshed by one of the clocks.

    My Bitte melde dich an, um diesen Link zu sehen. and Bitte melde dich an, um diesen Link zu sehen. pages.

  • If I understand that correctly, the Verilog isn't supposed to model the workings of a real CIA but the equivalent of what you're doing with your Arduino code, right? Otherwise I don't understand it because the original chip takes 4 PHI2 cycles per bit when sending, while the waveform you posted seems to have only two cycles per bit.

    > I think that's true for all the NMOS chips. (In contrast to the WDC versions, where I think you can halt and resume the clock at will).

    Ok, I had not realised that...

    Language is hard... Sorry about the confusion about clocks and phases and whatnot.

    The diagram shows an input test, CNT and SP are driven externally from the Arduino. CNT is changing 0->1 and 1->0 every PHI2 cycle as shown in the diagram.

    What I meant with IC "sends out" is that the chip sends CF over its 8-bit data bus to the arduino, so CF is really the value inside the SDR register of the chip. At this CNT rate, you can see the IC still works somewhat for input but is taking the output too late.

    If I am correct, what you are actually seing in that cycle is that the input bit present right on the same cycle the CF is read from the IC, is actually on the external pin at that same instant.

    That must means, during the cycle CF is read, there is a transparent path for 1/2 of the clock cycle through the entire IC direct to the processor's databus for the LSB bit all the way from the SP input.

    This has to be a design mistake or unintended consequence as you really need a minimum of 1/2 phase of PHI2 delay before taking a value from SP to allow for settling of the value after the latch closes. Then another latch while reading to ensure the internal state is streched beyond the end of the PHI2=1 phase.

    From this test it would not surprise me if this particular issue is just a symtom of a more problematic issue where the internal state's minimal internal timing delay is not met for this case when running at 1MHz. So you could get occasionally random incorrect internal state being latched in on a next cycle. Which could cause all sorts of issue. Hard to say. But whether this has any relationship to what you're seing would need a few different samples tested as such types of timing sensitive issues vary significantly between IC batches.

    I have'nt seen if you're looking at sending or receiving bits from the 1571, or both? Do the issues also occur at say lower speeds?

  • Actually that's not a property of NMOS. You can implement dynamic and static logic in NMOS and in CMOS. And it's still used today, since it saves real estate. Just think of DRAM.

    This is an example in CMOS:
    Bitte melde dich an, um dieses Bild zu sehen.

    In NMOS it's done slightly different. The bit is stored in the capacity of the totem pole FETs here when Phi is low. It is fed whenever Phi is high. This is also the reason for what you saw: As long as Phi is high (or low, depending from the implementation), you can change D_in. It is stored when the input FET is switched off. Often you have cascades of these dynamic latches, first gated with Phi2 and the second with Phi1. Phi1 is created internally and is a non-overlapping, inverse clock.

    This is by the way the reason that the datasheets not only state a maximal clock rate but also a minimal. Your screenshot merlintwa shows that you are way below it (if the time axis is correct), but it seems there is enough margin in the design. Nice that you have VCD now ;)

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Bitte melde dich an, um diesen Link zu sehen. | Bitte melde dich an, um diesen Link zu sehen.

    Bitte melde dich an, um diesen Link zu sehen.

  • Hi Skoe,

    Thanks for the heads-up, I've done a lot of designs in CMOS, also with pass gates, but I have never worked with the older NMOS. The oldest technology I worked on was 100nm.

    The diagram I sent above is an approximation of the reality using the actual Arduino vectors I used, I didn't even bother to set a `timescale directive so times are way off. I'll try posting a more accurate reflection of reality, with position of sample moments more accurate, later (still just an interpretation to make diagrams with).

    The actual speed of the Arduino is determined by the USB-serial delay it takes to send the measurement results as printf'ed strings to the PC. I did set the USB baudrate to max (1Mbit) for my setup.

    The full test I'm running right now (gets longer every day) is around 2000 phi2 cycles. It takes about 30 seconds of the Arduino to make one full testrun while also sending the results back to the PC. I setup the arduino to repeat the test after a 10s delay.

    I have not seen any issue running this slow - of course timing is very relaxed and the 6526 is not driving any high loads.

    With Arduino its not really an option to store measurement results in a buffer before sending them to the PC at the end - there isn't enough ram.

  • I have'nt seen if you're looking at sending or receiving bits from the 1571, or both? Do the issues also occur at say lower speeds?

    I actually haven't experienced the problems myself, as I don't even own a 1571. So strik would need to comment if the errors also happen at slower speed (and maybe also when the 1571 is sending).

    I only did some low level tests to learn about the timing requirements of the CIA when receiving at maximum data rate (because that's what the xum1541 firmware is communicating at).

  • Ok, thanks, I had not properly understood al the different software and stuff used. I've just looked up what's inside the xum1541 to figure out what you meant.

    So, I conclude from your FPGA experiments, you've seen max transfer rates close to 2 phi2 clocks per bit using a 6526R4 in a C64 as input, when you first phase-align the external FPGA with the chip. You then also make CNT only high for half of a PHI2 cycle, followed by 1.5 cycles low. Is that correct?

    That should also be possible then in my tests to observe. I'll try that scenario.

    So far I have not seen anything to suggest the length of the CNT high phase and low phase would make a difference, perhaps that is missing in the tests. I'm struggling to come to an IC design structure reason why that would make a difference.

    But what can easily happen when you have clocks running freely and there is a transparent path inside the IC, is that the internal timing is violated towards some parts of the logic like the IRQ capture but is just fast enough to have been seen as a data ready input.

    I'm sure you are fully aware of all metastability protection in modern ICs - the 6526 doesnt seem to have any protection in this case. Even in the 80s you would for sure design in a 1/2 cycle delay on all unsynchronised edges ariving on the IC. Like all the Port A and Port B input have. If you let such uncaptured edges then propagate out of your IC into the rest of your (synchronous) system you are asking for lots of random lockups and crazyness. Applying unsynchronised inputs to pins of chips, for pins that are designed for synchronous inputs only (like the 6510), can easly cause interal illegal states - completely unrelated to the pin connected even.

    When the source and destination clocks drift to just the right phase difference. I'd expect as long as the external sending system has a clock division that is guaranteed under all cases including clock jitter to be 2.5 cycles *or more* then it should work just fine. And in that case, some type of IRQ bug becomes a possible scenario again.