uart; interrupt driven receive doesn't work

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
mtbro
Member
Member
Posts: 54
Joined: Fri Apr 08, 2022 3:12 pm

uart; interrupt driven receive doesn't work

Post by mtbro »

Previously I set the serial console (com0) in my bootloader and "kernel" to log messages there. In PM I'm using poll_uart_write to poll write to the port. Initialization was done by early_uart_init.
All works as expected, client can see the output. Printing is done by printk() which relies on cputc() which is just navigating/writing in memory starting at 0xb8000. If serial console is enabled data is written via above mentioned poll_uart_write().

I was playing around with the interrupt driven receive as next step. I've uart_init that sets "Received Data Available Interrupt" in IER, sets the proper ISR for irq4 and enables it.
This works just fine in qemu. On real HW nothing is happening. According to my stats no interrupt is requested for irq4. PIC's IMR is set properly. Other IRQs work fine (time,kbd).

I thought maybe there's a problem that I'm using poll write and interrupt to read. Tests I did show it's not true.
Cables I'm using are ok (tested on the test HW with actual OS).

I must be missing something ..
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: uart; interrupt driven receive doesn't work

Post by Octocontrabass »

You need to set OUT2 in the Modem Control Register to connect the IRQ line.

Make sure you don't connect multiple ISA UARTs to the same IRQ line at the same time. That won't work, and it could damage some hardware. (PCI UARTs don't have this limitation.)
mtbro
Member
Member
Posts: 54
Joined: Fri Apr 08, 2022 3:12 pm

Re: uart; interrupt driven receive doesn't work

Post by mtbro »

Thank you for pointing that out. When I came back to wiki about this I see it's even written there under MCR/MSR registers.
That modem got me a bit confused. I thought it's about the actual modem. But even wiki says: "modem that uses a UART as an interface to the computer".

OUT2 was set. I did modify this in uart_init and have more information printed about it main main loop.

I have two ways of connecting to this old testing HW - either via other rs232 port on my new-ish box or using usb2rs232 cable (both were tested and worked ok when old HW was running FreeBSD).

This code doesn't work with USB cable on my primary desktop. It has even problems "catching up" with the console output during boot for some reason. It disconnects the session when I'm setting MCR. While MCR is set to 0x8 it doesn't work. I was able to trigger interrupt when I was attempting to kill cu session with ~ ( ~. was not ending the session for some reason (not in ssh session)).

However using my new-ish computer I was able to boot it just fine:

Code: Select all

.>MIOS boot1
Loading kernel

kernel @ 0x200000
__init_kbd_module: about to enable irq1
uart_init: current MCR: 0x3
uart_init: about to enable irq4
welcome to kernel_main
main: master: IRR: 0 (pending ACKs), IMR: e8 (mask), ISR: 0 (EOI waiting)
main: slave: IRR: 0 (pending ACKs), IMR: 0 (mask), ISR: 0 (EOI waiting)
irq0: 00000000000006a8                ; <-- 's' pressed on the keyboard
irq1: 0000000000000001
irq2: 0000000000000000
irq3: 0000000000000000
irq4: 0000000000000000
0x3f8: MCR: 0x8, MSR: 0xb0
uart_isr_handler: hi                  ; <-- 'm' pressed in cu session
IRR: 4
uart_isr_handler: RBR: 0x6d
As I was writing this reply I got an idea that maybe terminal is messing up something and data is not being sent. But it worked with actual OS. I connected this USB cable to this new-ish box and used that to connect to the box. It worked.
Octocontrabass wrote:Make sure you don't connect multiple ISA UARTs to the same IRQ line at the same time.
Please can you help me understand this a bit more? I thought there is (usually) only one UART chip on board and that's why I should check which device actually triggered the interrupt in all IIRs (something I'm not yet doing in my code).

edit: Looking at my board I do see two GD75232D chips. I'm assuming one would be for irq3 and one for irq4. If I understood you correctly you told me not to cause irq conflict with these two as it can create even damage to HW. Did I get that right?
In my code I'm still assuming what is where. The big next step would be to parse ACPI tables probably to see what I've got on the system.
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: uart; interrupt driven receive doesn't work

Post by Octocontrabass »

mtbro wrote:This code doesn't work with USB cable on my primary desktop.
If your terminal or USB adapter is expecting hardware handshaking, you may also need to set DTR and RTS to establish communication.
mtbro wrote:Please can you help me understand this a bit more? I thought there is (usually) only one UART chip on board and that's why I should check which device actually triggered the interrupt in all IIRs (something I'm not yet doing in my code).
Back in the early PC days, it was pretty common to have four UARTS, with two connected to IRQ3 and two connected to IRQ4. Software would use OUT2 to prevent IRQ conflicts.
mtbro wrote:If I understood you correctly you told me not to cause irq conflict with these two as it can create even damage to HW. Did I get that right?
Yes, but IRQ conflicts won't happen unless both are assigned to the same IRQ (and modern hardware won't be damaged by IRQ conflicts).
mtbro
Member
Member
Posts: 54
Joined: Fri Apr 08, 2022 3:12 pm

Re: uart; interrupt driven receive doesn't work

Post by mtbro »

Octocontrabass wrote:If your terminal or USB adapter is expecting hardware handshaking, you may also need to set DTR and RTS to establish communication.
I used yet another client machine and booted both Ubuntu and FreeBSD. So in total I tested that USB cable on 3 hosts (desktop is osx). It behaves the same way under osx/Linux - connection gets dropped when I'm setting MCR. Same "catching up" issues. On FreeBSD however it all works as expected. I guess uplcom driver there is compensating for something I'm doing wrong (possibly that missing handshake you mentioned).

Octocontrabass wrote:Back in the early PC days, it was pretty common to have four UARTS, with two connected to IRQ3 and two connected to IRQ4. Software would use OUT2 to prevent IRQ conflicts.
That would be probably my situation on the test HW - I have two GD75232D with standard assignment, e.g. FreeBSD sees it as:

Code: Select all

uart0: console (9600,n,8,1)> at port 0x3f8-0x3ff irq 4 flags 0x10 pnpid PNP0501 on isa0
uart1: <16550 or compatible> at port 0x2f8-0x2ff irq 3 pnpid PNP0501 on isa0
I thought by "UART" one means the chip itself. And this one uart chip has two ports //channels// (first one being com1,com3). OUT2 is controlling the uart itself, meaning I can't control if interrupt is for com1 or com3, I need to get this information from IIR.
However I could mess up if I assigned one IRQ # to both chips.
Did I get that correctly?
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: uart; interrupt driven receive doesn't work

Post by Octocontrabass »

mtbro wrote:That would be probably my situation on the test HW - I have two GD75232D with standard assignment, e.g. FreeBSD sees it as:
You have two UARTs, not four.
mtbro wrote:I thought by "UART" one means the chip itself.
It does. (Although the GD75232D is actually a voltage converter...)
mtbro wrote:And this one uart chip has two ports //channels// (first one being com1,com3).
No, each UART controls only one serial port. Your board doesn't have COM3. If it did, you would use OUT2 to prevent IRQ conflicts between COM1 and COM3.
mtbro
Member
Member
Posts: 54
Joined: Fri Apr 08, 2022 3:12 pm

Re: uart; interrupt driven receive doesn't work

Post by mtbro »

Octocontrabass wrote:(Although the GD75232D is actually a voltage converter...)
I found it as "dual high-speed universal asynchronous receiver/transmitter". That does confuse me a bit then as I thought "dual" means two UARTs on a chip.
Octocontrabass wrote:Your board doesn't have COM3. If it did, you would use OUT2 to prevent IRQ conflicts between COM1 and COM3.
You are correct, there are only com1 and com2 according to BDA (and BIOS settings).
I think I understand now, at least I think I do.
mtbro
Member
Member
Posts: 54
Joined: Fri Apr 08, 2022 3:12 pm

Re: uart; interrupt driven receive doesn't work

Post by mtbro »

Octocontrabass wrote:It does. (Although the GD75232D is actually a voltage converter...)
This stuck in my head. While it's not that important to the problem I was having I am curious to learn more so I was googling around. I really though this chip also includes uart in it but you are right (not that I questioned that) - it's just a voltage converter, or as I got to know rs232 driver/receiver.
I like these detours during OS development to actually get more familiar with the HW.
Thanks.
Post Reply