SOLVED: UART not firing interrupt on real hardware

Programming, for all ages and all languages.
Post Reply
User avatar
BASICFreak
Member
Member
Posts: 284
Joined: Fri Jan 16, 2009 8:34 pm
Location: Louisiana, USA

SOLVED: UART not firing interrupt on real hardware

Post by BASICFreak »

This is working well on bochs but on real H/W I get nothing.
I can send and receive on hardware (if not relying on IRQ)
I narrowed down my UART model to a 16550A.

Here is my Init Code

Code: Select all

void setBaudRate(uint16_t COM, uint32_t RATE)
{
	uint8_t LO_RATE, HI_RATE;
	
	LO_RATE = (uint8_t) ((115200 / RATE) & 0xFF);
	HI_RATE = (uint8_t) ((115200 / RATE) >> 8);
	
	IER_handle(COM, false, false, false, false);							//Disable IRQ
	write(COM, FCR, (FCR_ClearRX | FCR_ClearTX));							//Disable FIFO
	write(COM, LCR, LCR_DLAB);												//DLAB
	write(COM, DLL, LO_RATE);												//Data Rate Low
	write(COM, DLH, HI_RATE);												//Data Rate High
	write(COM, LCR, LCR_8Bits);												//Line Control
	write(COM, FCR,(FCR_Enable | FCR_ClearRX | FCR_ClearTX | FCR_16_1));	//Enable FIFO - 1 BYTE BUFFER NOTIFY
	write(COM, MCR, (MCR_DataTermRdy | MCR_RequestSend | MCR_AuxOut2));
	IER_handle(COM, true, true, true, true);								
}
Which breaks down to (assuming 3F8 Base COM1)

Code: Select all

outb(0x3F9, 0);
outb(0x3FA, 6);
outb(0x3FB, 0x80);
outb(0x3F8, 1);    //DATA RATE = 115200
outb(0x3F9, 0);
outb(0x3FB, 3);
outb(0x3FA, 7);
outb(0x3FC, 0xB);
outb(0x3F9, 0xF);    //ENABLE ALL INT
Currently I have debug information coming out COM1 and I really need input so I can modify and FIX my 8042 drivers (which as you all know will disable my keyboard)

If you need more information ask or check the link in signature (DRIVERSRC/HARDWARE/RS232.C\H)

I've been comparing to many others on the forum and I cannot, as of yet, find what is wrong.
Last edited by BASICFreak on Sun Jun 22, 2014 6:43 am, edited 1 time in total.
BOS Source Thanks to GitHub
BOS Expanded Commentary
Both under active development!
Sortie wrote:
  • Don't play the role of an operating systems developer, be one.
  • Be truly afraid of undefined [behavior].
  • Your operating system should be itself, not fight what it is.
User avatar
BASICFreak
Member
Member
Posts: 284
Joined: Fri Jan 16, 2009 8:34 pm
Location: Louisiana, USA

Re: UART not firing interrupt on real hardware

Post by BASICFreak »

Well, if anyone is interested I believe my problem is faulty hardware, as a second test system worked with flying colors... I will still continue to look and see if maybe I missed something important before I claim 100% H/W issue.
BOS Source Thanks to GitHub
BOS Expanded Commentary
Both under active development!
Sortie wrote:
  • Don't play the role of an operating systems developer, be one.
  • Be truly afraid of undefined [behavior].
  • Your operating system should be itself, not fight what it is.
User avatar
ChosenOreo
Member
Member
Posts: 25
Joined: Sun May 29, 2011 5:16 pm
Location: Inside A Computer
Contact:

Re: UART not firing interrupt on real hardware

Post by ChosenOreo »

Just to be on the safe side I would make sure that 0x3f8 is actually your serial port, as I have heard of a few systems (don't have any sources, sorry!) that don't actually use 0x3f8 as the first serial port. However, I'm pretty sure that the port number can be found at physical address 0x400, which is located in the BDA.

- Adrian
User avatar
BASICFreak
Member
Member
Posts: 284
Joined: Fri Jan 16, 2009 8:34 pm
Location: Louisiana, USA

Re: UART not firing interrupt on real hardware

Post by BASICFreak »

ChosenOreo wrote:Just to be on the safe side I would make sure that 0x3f8 is actually your serial port, as I have heard of a few systems (don't have any sources, sorry!) that don't actually use 0x3f8 as the first serial port. However, I'm pretty sure that the port number can be found at physical address 0x400, which is located in the BDA.

- Adrian
Don't Worry about this :D (I have a BIOS probe which gives me all the info on COM LPT etc.)

Code: Select all

COM1 = _BIOS_COM(1);
COM2 = _BIOS_COM(2);
COM3 = _BIOS_COM(3);
COM4 = _BIOS_COM(4);
Which on this system in particular is 3F8 COM1 and 2F8 COM2 COM3&4 don't exist

Now, if only I can find an IDE CD drive to live boot ubuntu and really test the COM port...
BOS Source Thanks to GitHub
BOS Expanded Commentary
Both under active development!
Sortie wrote:
  • Don't play the role of an operating systems developer, be one.
  • Be truly afraid of undefined [behavior].
  • Your operating system should be itself, not fight what it is.
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: UART not firing interrupt on real hardware

Post by gerryg400 »

Hi. I'm not sure what your bug is, it may be hardware, however the order that you initialise things may cause you problems.
Generally speaking the order should be more like this:

Code: Select all

1. Disable all interrupts on device
2. Initialise device (set baud rate etc.)
3. Clear (or acknowledge) pending interrupts on device
4. Install interrupts handler
5. Enable interrupts on device.
If you don't do things in this order you can miss an interrupt, permanently.
This same sequence applies to other devices too.

I had a quick look at your code. It doesn't seem to follow these steps. In particular I couldn't see where you acknowledged potentially pending interrupts.
If a trainstation is where trains stop, what is a workstation ?
User avatar
BASICFreak
Member
Member
Posts: 284
Joined: Fri Jan 16, 2009 8:34 pm
Location: Louisiana, USA

SOLVED: UART not firing interrupt on real hardware

Post by BASICFreak »

Well, after finally thinking to look at Linux 0.96c Source #-o on the manner I changed my init routine to the following:

Code: Select all

uint8_t LO_RATE, HI_RATE;
	
LO_RATE = (uint8_t) ((115200 / RATE) & 0xFF);
HI_RATE = (uint8_t) ((115200 / RATE) >> 8);
	
IER_handle(COM, false, false, false, false);							//Disable IRQ
write(COM, FCR, (FCR_ClearRX | FCR_ClearTX));							//Disable FIFO
write(COM, LCR, LCR_DLAB);												//DLAB
write(COM, DLL, LO_RATE);												//Data Rate Low
write(COM, DLH, HI_RATE);												//Data Rate High
write(COM, LCR, LCR_8Bits);												//Line Control
write(COM, FCR,(FCR_Enable | FCR_ClearRX | FCR_ClearTX | FCR_16_1));	//Enable FIFO - 1 BIT BUFFER NOTIFY
write(COM, MCR, (MCR_DataTermRdy | MCR_RequestSend | MCR_AuxOut2));
IER_handle(COM, true, false, false, false);								//Enable IRQ for RX only
(void) read(COM, RBR);	//read to clear things up? - linux 0.96c code idea (seemed to fix my irq issues)
Which I just added a (void) inb(3f8);
Now I have a very stable Driver, I managed to crash the Kernel and was still getting the echos back :D

@gerryg400
I clear Tx and Rx buffer what else should I do here?




Off-Topic:
I have finally switch back to a cross compiler on a lubuntu (virtual) PC fixed about 2000 warnings I was not getting with DJGPP, compiling to ELF32-i386, and unfortunately using Grub 0.92 (not that Grub is bad just I need to work on my boot code now)

In the process I broke my Phys Mem Manager, and lost my FDC (is unstable and I knew Grub would break it) So I disabled my physical and virtual mem managers, thread manager, FDC driver, and FAT12 driver... (hopefully I'll get everything back up and I'll upload to repo soon)

But on the plus side I now have a steady I/O source which is logged and can test, debug, and build drivers live (well at least the first 2)
AND FINALLY A WORKING MAKEFILE!!!!
BOS Source Thanks to GitHub
BOS Expanded Commentary
Both under active development!
Sortie wrote:
  • Don't play the role of an operating systems developer, be one.
  • Be truly afraid of undefined [behavior].
  • Your operating system should be itself, not fight what it is.
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: SOLVED: UART not firing interrupt on real hardware

Post by gerryg400 »

@gerryg400
I clear Tx and Rx buffer what else should I do here?
Hi. I'm glad you got it working.

To make your driver bullet proof you should

1. Disable all interrupts on the device. You already do this with IER_handle(COM, false, false, false, false);

2. Read the IIR and acknowledge all pending interrupts until the IIR == 1
You already the read the RBR to clear an RX interrupt, but there may be others. In fact I'm not sure but I think that reading the RBR may only clear the RX interrupt if that is the highest pending interrupt. Not 100% sure about that. Never tried it.

3. Install a handler routine so that if another interrupt occurs you can handle it.

4. Enable Interrupts in the device.
If a trainstation is where trains stop, what is a workstation ?
Post Reply