OpenCores

a VHDL 16550 UART core

Issue List
Transmit Interrupt doesn't fire during a Single Byte Send #7
Closed ocghost opened this issue almost 16 years ago
ocghost commented almost 16 years ago

Simulation of the UART shows that the transmit interrupt will be generated, as expected, even with a single byte transfer (the transmit FIFO becoming empty).

ocghost commented almost 16 years ago

Here's some example code for you to get the idea. As you can see, I'm using a Xilinx microblaze system. There are three ports - A, B, and C. A is a uartlite hyperterm console for outputting printf's. I can provide this code as an attachment if desired. Mostly it's just to show how it's being used to produce the problem...

#include "main.h" #include "xio.h"

XUartNs550 UART_Port_C_16550_struct; XUartNs550 UART_Port_B_16550_struct; XUartNs550Format format;

XIntc InterruptController;

/ Variable Creation / Xuint8 uart_buffer16; Xuint16 options;

void PortC_Handler (void CallBackRef, Xuint32 Event, unsigned int EventData) { Xuint8 Errors; XUartNs550 UartNs550Ptr = (XUartNs550 )CallBackRef; char dummy; int asdf; //xil_printf("Entered Port C Interrupt Handler\r\n"); if (Event == XUN_EVENT_SENT_DATA) { / placeholder to allow breaking to occur here / asdf = 42; xil_printf("Entered Port C Send Interrupt Handler\r\n"); } else if (Event == XUN_EVENT_RECV_DATA) { / don't care what happens to the Rx'd byte / XUartNs550_Recv (UartNs550Ptr, &dummy, 1); xil_printf("Entered Port C RECV Interrupt Handler\r\n"); } else { / placeholder to allow breaking to occur here */ asdf = 999; xil_printf("Entered Port C Some other Interrupt Handler\r\n"); } }

void PortB_Handler (void CallBackRef, Xuint32 Event, unsigned int EventData) { Xuint8 Errors; XUartNs550 UartNs550Ptr = (XUartNs550 )CallBackRef; char dummy; int asdf; //xil_printf("Entered Port B Interrupt Handler\r\n"); if (Event == XUN_EVENT_SENT_DATA) { / placeholder to allow breaking to occur here / asdf = 42; xil_printf("Entered Port B Send Interrupt Handler\r\n"); } else if (Event == XUN_EVENT_RECV_DATA) { / don't care what happens to the Rx'd byte / XUartNs550_Recv (UartNs550Ptr, &dummy, 1); xil_printf("Entered Port B RECV Interrupt Handler\r\n"); } else { / placeholder to allow breaking to occur here */ asdf = 999; xil_printf("Entered Port B Some other Interrupt Handler\r\n"); } }

int main() { Xuint16 Options; XStatus Status;

microblaze_enable_interrupts();

//Setup Interrupt System:
Status = XIntc_Initialize(&InterruptController, XPAR_INTERRUPT_CONTROLLER_DEVICE_ID);

/* Start the Interrupt Controller with interrupts enabled.  */
Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);

/* Initialize */
XUartNs550_Initialize(&UART_Port_C_16550_struct, XPAR_PORTC_WISHBONE_BRIDGE_DEVICE_ID);
XUartNs550_Initialize(&UART_Port_B_16550_struct, XPAR_PORTB_WISHBONE_BRIDGE_DEVICE_ID);


Options = XUN_OPTION_DATA_INTR | XUN_OPTION_FIFOS_ENABLE |
	XUN_OPTION_RESET_TX_FIFO | XUN_OPTION_RESET_RX_FIFO;
XUartNs550_SetOptions(&UART_Port_C_16550_struct, Options);
XUartNs550_SetOptions(&UART_Port_B_16550_struct, Options);

//Set defaults for UART Port B, C
format.BaudRate = BAUD_RATE;
format.DataBits = XUN_FORMAT_8_BITS;
format.Parity = XUN_FORMAT_NO_PARITY;
format.StopBits = XUN_FORMAT_1_STOP_BIT;

XUartNs550_SetDataFormat(&UART_Port_C_16550_struct, &format);
XUartNs550_SetDataFormat(&UART_Port_B_16550_struct, &format);

//Connect device driver handlers:
//PortC
Status = XIntc_Connect(&InterruptController, SERC_UART_INTERRUPT_ID,
                       (XInterruptHandler)XUartNs550_InterruptHandler,
                       (void *)&UART_Port_C_16550_struct);
XIntc_Enable(&InterruptController, SERC_UART_INTERRUPT_ID); //PortC

//PortB
Status = XIntc_Connect(&InterruptController, SERB_UART_INTERRUPT_ID,
                       (XInterruptHandler)XUartNs550_InterruptHandler,
                       (void *)&UART_Port_B_16550_struct);
XIntc_Enable(&InterruptController, SERB_UART_INTERRUPT_ID); //PortB

/* Setup the interrupt handlers for the devices */
XUartNs550_SetHandler(&UART_Port_C_16550_struct, PortC_Handler, &UART_Port_C_16550_struct);
XUartNs550_SetHandler(&UART_Port_B_16550_struct, PortB_Handler, &UART_Port_B_16550_struct);

unsigned int i;

xil_printf("Starting Test\r\n");
for (i = 0; i < 100000000; i++) {}


char *test2String = "!!";
char *test1String = "!";
/* send exactly 2 bytes, wait, then send 1 byte.
 * use GDB to confirm that the send interrupt is generated for the former
 * send, but not for the latter */
XUartNs550_Send (&UART_Port_C_16550_struct, test2String, 2);
XUartNs550_Send (&UART_Port_B_16550_struct, test2String, 2);

for (i = 0; i < 100000000; i++) {}

XUartNs550_Send (&UART_Port_C_16550_struct, test1String, 1);
XUartNs550_Send (&UART_Port_B_16550_struct, test1String, 1);

while (1) {}

//end printing Main Menu while loop

}//end main()

/ End of File /

hlefevre was assigned almost 16 years ago
hlefevre closed this almost 16 years ago
ocghost commented almost 16 years ago

Just to clear this one up on my end also -- we were able to figure it out -- the directory was not using the most up-to-date UART release. We were using the old (circa august) release of the UART.

I apologize for the mix-up...

ocghost commented almost 16 years ago

And I forgot to add -- Thanks for the great core!
And on top of that -- thank you for the rapid response! Regards, -Ben


Assignee
hlefevre
Labels
Bug