Serial port interrupt timings
Posted: Wed Jul 24, 2024 10:56 pm
There were some concerns a few weeks back with at least one person convinced that the serial card's UART had a "slow" interrupt. I finally got around to taking measurements, so I'm presenting them here to lay that to rest, and explain what the actual issues are.
Here's a logic analyzer capture of a 16550 in the X16 receiving a byte: The stop bit begins at 14.315720ms, and INTR goes up at 14.316208ms, which is 488 nanoseconds later. VPB goes low 1168 nanoseconds later (at 14.317376ms). So it takes rather longer for the 65C02 to start grabbing the interrupt handler's address than it does for the '550 to signal the interrupt.
We can zoom out further and catch the processor reading from the UART: This particular interrupt handler needs 8680ns to get to reading from the UART after VPB goes low. (FWIW It's the miditest code from https://github.com/X16-community-experimental/miditest - thanks to m00dawg for that, saved me a bunch of time.)
So, then, why would anyone think the interrupt handler was slow / how would you lose bytes when you've got the FIFO turned on?
Here's a capture when running ROMTERM, and pressing/transmitting "Z": ROMTERM polls the UART for bytes, with a normal gap of 63.272us. When the default KERNAL interrupt handler runs, the gap blows up to 648.4us. So the handler is taking 585.128us. If you're running 8N1, with a 16 byte FIFO, you can have 160 bit periods in that 585us before you exceed the FIFO capacity. That's 3.65us per bit, or ~273kbit/second. If you want to receive data faster than that, you've got to do something fancier than using the default interrupt handler.
The above testing was done with an original National Semiconductor PC16550DN on a serial card of my design, so the interrupt circuit actually works, unlike the currently available TexElec serial card. But timing may vary, very slightly, between that part and the TL16C2550 present on the TexElec card.
If anyone has any questions or spots any errors, I'd be happy to try and address them.
(I'll be release the schematic for my card very soon now, the same as I released the schematic for my cartridge design.)
Here's a logic analyzer capture of a 16550 in the X16 receiving a byte: The stop bit begins at 14.315720ms, and INTR goes up at 14.316208ms, which is 488 nanoseconds later. VPB goes low 1168 nanoseconds later (at 14.317376ms). So it takes rather longer for the 65C02 to start grabbing the interrupt handler's address than it does for the '550 to signal the interrupt.
We can zoom out further and catch the processor reading from the UART: This particular interrupt handler needs 8680ns to get to reading from the UART after VPB goes low. (FWIW It's the miditest code from https://github.com/X16-community-experimental/miditest - thanks to m00dawg for that, saved me a bunch of time.)
So, then, why would anyone think the interrupt handler was slow / how would you lose bytes when you've got the FIFO turned on?
Here's a capture when running ROMTERM, and pressing/transmitting "Z": ROMTERM polls the UART for bytes, with a normal gap of 63.272us. When the default KERNAL interrupt handler runs, the gap blows up to 648.4us. So the handler is taking 585.128us. If you're running 8N1, with a 16 byte FIFO, you can have 160 bit periods in that 585us before you exceed the FIFO capacity. That's 3.65us per bit, or ~273kbit/second. If you want to receive data faster than that, you've got to do something fancier than using the default interrupt handler.
The above testing was done with an original National Semiconductor PC16550DN on a serial card of my design, so the interrupt circuit actually works, unlike the currently available TexElec serial card. But timing may vary, very slightly, between that part and the TL16C2550 present on the TexElec card.
If anyone has any questions or spots any errors, I'd be happy to try and address them.
(I'll be release the schematic for my card very soon now, the same as I released the schematic for my cartridge design.)