Problem with simple char device driver for serial UART 16550
Hi, everybody! I'm woking on a Debian system-image in Vmware which has COM1 and COM2 linked (data transmitted to COM1 is received from COM2 and vice-versa).
Currently i'm trying to write a simple device driver for UART 16550 (using interrupts for communication) and i encountered the following problem : after sending, let's say 256 bytes, at the receiving end i get the first 16 bytes right, and then, it just jumps over the next 15-20 bytes, and gives me the rest of the bytes in the right order. I ran the tests many times in a row but this keeps happening, the only thing that differs slightly is the number of bytes it jumps over. :confused: I really don't get it, i have been knocking my head over this for the last couple of days but can't figure it out.
For each COM i'm using 2 buffers, a read buffer and a write one, which are both circular. Waiting queues are being used for the overall synchronization.
The configuration and flow of program are as folllows:
- the init module function registers the COMs and the interrupts assciated to them; the cleanup function of the module releases the resources
- there's an ioctl function implemented to set the parameters and the settings look like:
outb(config.par | config.stop | config.len, LCR);
where config is a struct passed in the call to ioctl and contains the values for baud, parity, stop bit and length
- in the write function there's a call to "wait_event_interruptible" to make sure i synchronize with the interrupt handler and there's enough space in the write buffer to write the new data received from user space; after being "waked-up" from the wait(there is sure enough space now in the buffer to write at least one byte) i copy the data from the user-space buffer to my write buffer (as much data as space i have in the buffer); then i reactivate the THREI on the current COM.
- in the read function i'm also waiting something in the beginning, that is to have at least one byte to read from the read buffer and paste in the user-space buffer; after that is acomplished i simply copy the data from kernel-space to user-space
- in the interrupt handler, after verifying the nature of the irq received, i test the THREI and the RDAI bits from IIR and depending on which one is set i proceed: if THREI is set then i can send my data through the current COM so i go into a cycle (while the Empty Transmitter Holding Register in the LSR is set i drop bytes into the COM, and when i break the cycle i call a wake_up to let who is interested know that there is now space in the write buffer that awaites to be filled), and if RDAI is set then i do pretty much the same except verfying the DATA READY bit in the LSR and reading with "inb" bytes from COM into my read_buffer (after breaking the cycle there's a wake up call letting know that there is data to be read from the read buffer)
I checked my setting many times and i can't find anythng unusual or wrong. That is also the case for the program flow i chose. :confused:
Your help is appreciated. Thank you in advance.:)