Page 3 of 3

Re: Integrated debugger inside kernel

Posted: Fri Jun 25, 2021 4:21 pm
by Bonfra
vvaltchev wrote:Just pick up an old Linux and try a two-way communication using minicom.
Just tested, I didn't use minicom 'cause it's not installed on the Linux distro I used for testing and I don't want to search for a long enough ethernet cable but echo and cat works both ways so the cable and the configuration on the other side is perfect
vvaltchev wrote:
nexos wrote:Anyway, @Bonfra, try testing the serial code in QEMU and see if anything gets sent to the serial monitor.
In my understanding, his code already works on QEMU. The problem is only with real hardware.
Exactly, QEMU works perfectly.


The problem must be in the initialization code, this one:

Code: Select all

#define PORT 0x3f8          // COM1
 
static int init_serial() {
   outb(PORT + 1, 0x00);    // Disable all interrupts
   outb(PORT + 3, 0x80);    // Enable DLAB (set baud rate divisor)
   outb(PORT + 0, 0x03);    // Set divisor to 3 (lo byte) 38400 baud
   outb(PORT + 1, 0x00);    //                  (hi byte)
   outb(PORT + 3, 0x03);    // 8 bits, no parity, one stop bit
   outb(PORT + 2, 0xC7);    // Enable FIFO, clear them, with 14-byte threshold
   outb(PORT + 4, 0x0B);    // IRQs enabled, RTS/DSR set
   outb(PORT + 4, 0x1E);    // Set in loopback mode, test the serial chip
   outb(PORT + 0, 0xAE);    // Test serial chip (send byte 0xAE and check if serial returns same byte)
 
   // Check if serial is faulty (i.e: not same byte as sent)
   if(inb(PORT + 0) != 0xAE) {
      return 1; // <---- here it returns error
   }
 
   // If serial is not faulty set it in normal operation mode
   // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
   outb(PORT + 4, 0x0F);
   return 0;
}

Re: Integrated debugger inside kernel

Posted: Fri Jun 25, 2021 4:48 pm
by vvaltchev
Bonfra wrote:Just tested, I didn't use minicom 'cause it's not installed on the Linux distro I used for testing and I don't want to search for a long enough ethernet cable but echo and cat works both ways so the cable and the configuration on the other side is perfect
OK, It's great that it works as expected.
Bonfra wrote:The problem must be in the initialization code, this one:
It's good that you triaged the problem down to a single place. Now, I'm not sure why that fails, but I can still offer some help.

First, check the 8250 UART programming page on wikibooks: https://en.wikibooks.org/wiki/Serial_Pr ... rogramming
It explains a lot of useful stuff about how to configure the 8250 chip. Also, at this point I guess you'll now have to play with the hardware and tweak the initialization parameters to discover what causes the problem. To save you some time in manually calculating the hex constants, can I point you to this simple file with definitions (and very little code) that I wrote, based on that wikibook:
https://github.com/vvaltchev/tilck/blob ... art_8250.c

Given those definitions, my code for initializing the serial port looks like this:

Code: Select all

void init_serial_port(u16 port)
{
   outb(port + UART_IER, IER_NO_INTR);

   uart_set_divisor_latch(port, 1 /* 115200 baud */);

   outb(port + UART_LCR, LCR_8_BITS | LCR_1_STOP_BIT | LCR_NO_PARITY);

   outb(port + UART_FCR, FCR_ENABLE_FIFOs |
                         FCR_CLEAR_RECV_FIFO |
                         FCR_CLEAR_TR_FIFO |
                         FCR_INT_TRIG_LEVEL_3);

   outb(port + UART_MCR, MCR_DTR | MCR_RTS | MCR_AUX_OUTPUT_2);
   outb(port + UART_IER, IER_RCV_AVAIL_INTR);
}
I don't claim at all that will work in your case, as that was one of the few things that unfortunately I couldn't test on real hardware but, it will be easier for you to tweak, by OR-ing human-readable defines after you studied what each of one them does.

I'd be SUPER curious to see what was the problem in your case, once you discover it. Another random guess: have you tried just skipping that the lookback mode and its test and directly trying to send something to the other side?

Re: Integrated debugger inside kernel

Posted: Fri Jun 25, 2021 5:03 pm
by Bonfra
Thanks a lot for the resources! They'll come in super handy!
vvaltchev wrote: Another random guess: have you tried just skipping that the lookback mode and its test and directly trying to send something to the other side?
Yes: receiving data works, the problem is with sending data. I can use another pc to `echo "Hello There" > /dev/ttyUSB0` to the serial port and it's successfully received but when a response is sent back, nothing is caught by `cat /dev/ttyUSB0` (this exact procedure worked with the two machines running Linux).

It's time to make this thing work, thanks again. I'll let you know if something happens

Re: Integrated debugger inside kernel

Posted: Sat Jun 26, 2021 1:20 am
by bzt
Bonfra wrote:Yes: receiving data works, the problem is with sending data. I can use another pc to `echo "Hello There" > /dev/ttyUSB0` to the serial port and it's successfully received but when a response is sent back, nothing is caught by `cat /dev/ttyUSB0` (this exact procedure worked with the two machines running Linux).
This could be an issue with the Linux device. Have you configured it properly using setserial? With FIFO for example it could be that the received bytes are sitting in the queue and not returned by the device. Or that the received bytes are sitting in the kernel buffer, and again, not returned by the device. With "echo" you have explicitly also sent a "\n" which might flush the buffer on the other side, but your code probably doesn't do that.

I'd strongly recommend to install minicom, as others have already suggested. sudo apt-get install minicom or something. It should be a standard package, no trickery needed to install. One of the many benefits of minicom is that it calls the termios system calls to configure the serial device in raw, buffer-less mode (also turns off buffering in the kernel for the device). Or you could also use my raspbootcom.c version, which compiles on a modern Linux without a fuzz and does all that termios setup I've mentioned. By default it prints all bytes it receives, and you don't have to worry about the other things it can do if you don't send 3 times Ctrl+C in a row.

About detection, in my experience many boards which does not have a 16550, and does not emulate it either, will return 0xFF on the status port. It's a good thing to check for that, because normally the status port can never return that value (that would mean byte received, able to receive, send buffer full and send buffer empty all at the same time, which is not possible with real hardware).

Finally about initialization, this code has been tested on real hardware and known to work, feel free to use it.

Cheers,
bzt

Re: Integrated debugger inside kernel

Posted: Sat Jun 26, 2021 3:06 am
by Bonfra
bzt wrote:This could be an issue with the Linux device. Have you configured it properly using setserial?
The Linux device is the one with the USB end plugged, I used stty to configure it, do I also need setserial?
bzt wrote: With FIFO for example it could be that the received bytes are sitting in the queue and not returned by the device. Or that the received bytes are sitting in the kernel buffer, and again, not returned by the device. With "echo" you have explicitly also sent a "\n" which might flush the buffer on the other side, but your code probably doesn't do that.
Well yes, in the majority of the cases I do not send a "\n" but for some specific command I do and even testing them returns nothing.
bzt wrote: I'd strongly recommend to install minicom, as others have already suggested. sudo apt-get install minicom or something. It should be a standard package, no trickery needed to install.
I already tried with minicom and it just sits there with "port offline" or something like that, it never receives something neither lets me send something.
bzt wrote:Or you could also use my raspbootcom.c version, which compiles on a modern Linux without a fuzz and does all that termios setup I've mentioned. By default it prints all bytes it receives, and you don't have to worry about the other things it can do if you don't send 3 times Ctrl+C in a row.
Thanks for the code, I already tried with termios and it didn't work but to be sure I tested also your code, and still, nothing is received :(
bzt wrote: Finally about initialization, this code has been tested on real hardware and known to work, feel free to use it.
Before switching to the wiki's C implementation I was using your code from there, sadly even this does not work.

Before getting crazy against this code I think I'm going to try it on another computer maybe I'll be luckier.