OSDev.org
https://forum.osdev.org/

Communication via serial port
https://forum.osdev.org/viewtopic.php?f=1&t=32926
Page 1 of 1

Author:  guidono [ Thu May 10, 2018 8:47 am ]
Post subject:  Communication via serial port

Hello,

I have developed a small driver that can transmit information via the COM1 port between a small kernel and a host machine.
By telling Bochs to record what comes out of the serial port from the kernel, it works fine (so with bochs set to com1: enabled=1, mode=file, dev=serial.txt).
My goal now is to transmit information from my host machine to the kernel. I tried to write to the file without too much hope, I then tested with the use of a pipe but it just doesn't seem possible under Linux... someone to confirm? If so, is there another way? (I tested with this but strangely no error, nothing happens... com1: enabled=1, mode=pipe, dev=/tmp/myfifo).

I also checked the pic's configuration, the COM1 interrupt shouldn't be masked :
Code:
mov al, 0xEC ; ; clock, keyboard and COM1
out 0x21, al


I checked my IDT, and I found the adress of the function that should be executed (at least, a default routine could be executed... but nothing happens...) :
Code:
IDT[0x20]=32-Bit Interrupt Gate target=0x0008:0x000016b0, DPL=0 // clock (IRQ0)
IDT[0x21]=32-Bit Interrupt Gate target=0x0008:0x000016d0, DPL=0 // keyboard (IRQ1)
IDT[0x22]=32-Bit Interrupt Gate target=0x0008:0x00001690, DPL=0 // default routine
IDT[0x23]=32-Bit Interrupt Gate target=0x0008:0x00001690, DPL=0
IDT[0x24]=32-Bit Interrupt Gate target=0x0008:0x000016f0, DPL=0  // COM1 port (IRQ4)
IDT[0x25]=32-Bit Interrupt Gate target=0x0008:0x00001690, DPL=0


Have a nice day

Edit : I tried with qemu : I managed to receive a message from my kernel in my pipe, but I'm still not able to send bytes to my kernel from the host by using this same pipe...
(here is the command I used to launch qemu : qemu-system-i386 -boot a -fda floppyA -serial pipe:/tmp/myfifo)

Author:  max [ Thu May 10, 2018 5:30 pm ]
Post subject:  Re: Communication via serial port

Hey,

how did you initialize the COM port and did you actually enable the interrupts on it? Did you try to just read something from the port without actually waiting for an interrupt to occur?

If you are sure that everything is fine and it just won't work with a pipe, you could also tell QEMU to connect to a specific TCP address, and on your local PC set up a small program that opens a server socket at that port and sends out some bytes.

Author:  guidono [ Fri May 11, 2018 4:33 am ]
Post subject:  Re: Communication via serial port

Hey !

Thank you for your answer !

I guess I did initialize the COM port correctly, here is the code :
Code:
void init_serial ()
{
    outb (COM1_PORT + 1, 0x00); // Desactive les interruptions
    outb (COM1_PORT + 3, 0x80); // Active le DLAB (Divisor Latch Access Bit)
    outb (COM1_PORT + 0, 0x03); // 38400 baud (115200 / 3), bits de poid faible
    outb (COM1_PORT + 1, 0x00); //                                       fort
    outb (COM1_PORT + 3, 0x02); // 8 bits, pas de parite, un bit de stop
    outb (COM1_PORT + 2, 0xC7);
    outb (COM1_PORT + 4, 0x0B);
}


Thank you for you idea (tcp...), I will try that this weekend !

Author:  max [ Fri May 11, 2018 8:01 am ]
Post subject:  Re: Communication via serial port

Well not really, with this line in the start
Code:
outb (COM1_PORT + 1, 0x00);
the interrupts are disabled (as the comment behind it says)

After configuring the rest you will have to enable them again by writing the correct value to that same port, consider having a look at the documentation or this section in the wiki. Could look like this (would enable the status change interrupt):
Code:
outb (COM1_PORT + 1, 0x02);

Author:  guidono [ Sat May 12, 2018 3:01 am ]
Post subject:  Re: Communication via serial port

Thank you for your help !

I set this register to 0x02 like you suggested, and my interrupt routine linked to COM1 interrupt is executed once at the kernel launch (weird ?).
0x02 means the transmitter is empty, isn't enough to set this register correctly ?
This time, I tried with the udp protocol between netcat and qemu, and like before, I'm just able to receive bytes from the kernel but not the contrary.

Moreover, I took a look at your OS (very interesting/great :) ), and I found something weird :
Code:
/ Enable the interrupts
      // 0: 1  Receiver has data interrupt on
      // 1: 1  Transmitter empty interrupt on
      // 2: 0  Error/break interrupt off
      // 3: 0  Status change interrupt off
g_io_ports::writeByte(port + G_SERIAL_PORT_OFFSET_INTERRUPT_ENABLE, 0x02);


Why 0x02 instead of 0x03 ? (in your schema, the two first bits are set to 1 ! (anyway... it doesn't fix my problem...)

Author:  justinian [ Mon May 14, 2018 3:29 pm ]
Post subject:  Re: Communication via serial port

guidono wrote:
I set this register to 0x02 like you suggested, and my interrupt routine linked to COM1 interrupt is executed once at the kernel launch (weird ?).


It sounds like maybe you're not sending the EOI (End of Interrupt) to tell the interrupt controller that you've handled it, and are ready to receive another? See this page if you're using PIC-style interrupts.

Author:  max [ Tue May 15, 2018 5:50 am ]
Post subject:  Re: Communication via serial port

guidono wrote:
Why 0x02 instead of 0x03 ? (in your schema, the two first bits are set to 1 ! (anyway... it doesn't fix my problem...)
I think that should be 0x03 and you found a bug :mrgreen: Usually in my OS, the kernel log is written out over the serial port, and occasionally I use it to send debug data into the kernel with some software. But there I always know how many bytes will come, so I didn't need the interrupt version :P

Page 1 of 1 All times are UTC - 6 hours
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/