Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
12679 Discussions

UART stops working when interrupts are enabled

Altera_Forum
Honored Contributor II
2,184 Views

Hi all, 

 

I have used the NIOS II environment for several years, but am at a loss at the following problem: The UART stops working (no more output) when I enable UART RX interrupts. I have tested it with both the JTAG UART and a regular UART routed to some pins on the FPGA. This has been working on previous designs, but I recently changed my PC and installed Quartus II 12.1 Build 177. Not sure if this is a version issue, but it sure is a weird behavior. Also note that I did step through in the debugger and the "alt_irq_register" function returned 0, meaning that it was successful. 

 

Here's the code that I'm using to enable the JTAG UART interrupt and register the ISR function: 

 

void JTAG_UART_init(){ printf("Enable interrupt\n"); IOWR_ALTERA_AVALON_JTAG_UART_CONTROL(JTAG_UART_BASE, ALTERA_AVALON_JTAG_UART_CONTROL_RE_MSK); // enable interrupt printf("Register interrupt\n"); int a = alt_irq_register(JTAG_UART_IRQ,0,JTAG_UART_ISR); // setup handler printf("Initialize ringbuffer\n"); Ringbuffer_init(); } 

 

When I step through the code I get UART output right until where the IRQ is registered (setup handler), so I get the "Register interrupt" output, but not the "Initialize ringbuffer" message. Did anyone else run into this issue or have an idea what the issue could be? Any comments/feedback is highly appreciated. 

 

Thanks, 

Adrian
0 Kudos
7 Replies
Altera_Forum
Honored Contributor II
1,459 Views

Update: 

I did some more debugging and it turns out that as soon as the UART RX interrupt is enabled and its ISR function is registered, the ISR gets called over and over again, even though that there is nothing being received. 

What's strange here is that the code I'm using (see post above) is what I've been successfully using for a while and it is what I find online as well. The only change is that I'm now using a DE0 Nano board instead of a Cyclone III DSP development kit, but that should not matter as NIOS II is still the same. On the other hand, I'm using Quartus II 12.1 instead of the 11.1 version earlier. 

 

Some additional info: 

I am toggling an LED every time the ISR executes and it looks like a 1s on and 1s off blink when I run the code. When I send characters to the UART (which should trigger the ISR), I do see some extra blinks, meaning that the ISR is getting called upon UART receive. 

So the question remains: What causes the UART ISR to be triggered and why does that bring the UART transmit functionality to an immediate halt??? 

 

Any comments or insight is highly appreciated!!!
0 Kudos
Vincent_F
Beginner
872 Views

Hi,

I'm reopening this old post that apparently never got a reply.

I'm facing the same problem. I have a small NIOS II system (used as a demo for my students) that features a jTAG UART and a standard UART. I use the jTAG UART as my stdin/out etc. and run the program from a terminal (either Eclipse or NIOS command shell) to send and receive data from the standard UART. When I use the file mode (i.e. open a file to the UART to use fprintf, fgets, etc.) everything works well, I can send and receive data to and from the UART. But when I register an IRQ for the UART, the file mode doesn't work anymore. Note that my program checks the status register until the UART is ready to send or receive data before calling fprintf. I tried to disable the UART IRQ before fprintf and event tried to unregister the IRQ (using alt_ac_irq_register(UART_ID, UART_IRQ, NULL, NULL, NULL);). Nothing would work.

 

Below is the program. I run it on a DE10-Lite board interfaced with an RFS2 board, which features the UART. In this configuration (no IRQ registered) I'm able to send data. When the RFS2_UART_init(); line is uncommented (in main), the program gets stuck in an interrupt, even when no data is received by the UART. Uncommenting the following lines has no effect:

//alt_ic_irq_disable(RFS2_UART_IRQ_INTERRUPT_CONTROLLER_ID,RFS2_UART_IRQ);
//alt_ic_isr_register(RFS2_UART_IRQ_INTERRUPT_CONTROLLER_ID, RFS2_UART_IRQ, NULL, NULL, NULL);
//IOWR_ALTERA_AVALON_UART_CONTROL(RFS2_UART_BASE, 0);

Note that, when using the direct TX macro, everything works like a charm. Still, I would like to understand why fprintf won't work when registering (and unregistering...!) the IRQ. Any advice, solution or explanation would be appreciated.

Best regards

Vincent

 

// Test program

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <io.h>
#include "system.h"
#include "altera_avalon_uart_regs.h"
#include "altera_avalon_uart.h"
#include "sys/alt_irq.h"
#include "terasic_includes.h"

#define MAX_BUFFER_SIZE 1024

FILE *fJTAG;
FILE *fUART;

char buffer[MAX_BUFFER_SIZE];
static volatile int buffer_index = 0;

// Définition du contexte
static volatile int context;
volatile int uart_flag;

// Fonction d'interruption de service (ISR)
#ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT
static void UART_ISR(void* context)
#else
static void UART_ISR(void* context, alt_u32 id)
#endif
//void UART_ISR(void* context)
{
// Read data received by UART
char received = IORD_ALTERA_AVALON_UART_RXDATA(RFS2_UART_BASE);
// printf("carac %c\r\n",received);

// Check interrupt acknowledgement
// if ((IORD_ALTERA_AVALON_UART_STATUS(RFS2_UART_BASE) & ALTERA_AVALON_UART_STATUS_RRDY_MSK) == 0) {
// printf("IRQ acknowledged.\n");
// NULL;
// } else {
// printf("IRQ error.\n");
// }

// Store data in buffer
if (buffer_index < MAX_BUFFER_SIZE - 1) {
buffer[buffer_index++] = received;
}

// Check end of chain
if (received == '\0') {
uart_flag = 1;
// printf("End of chain received.\n");
}
}

// Initialize UART
void RFS2_UART_init(void) {
void *uart_context = (void *) context;

// Configure UART, activate RX IRQ
IOWR_ALTERA_AVALON_UART_CONTROL(RFS2_UART_BASE, ALTERA_AVALON_UART_CONTROL_RRDY_MSK);

// Deactivate TX IRQ
int control = IORD_ALTERA_AVALON_UART_CONTROL(RFS2_UART_BASE);
control &= ~ALTERA_AVALON_UART_CONTROL_TRDY_MSK;
IOWR_ALTERA_AVALON_UART_CONTROL(RFS2_UART_BASE, control);

// Configure IRQ
alt_ic_isr_register(RFS2_UART_IRQ_INTERRUPT_CONTROLLER_ID, RFS2_UART_IRQ, UART_ISR, uart_context, 0);
}

// Send chain to UART
void UART_write(char * out_data, int length) {

int control;
int status;

bool token = false;
// Open UART file
if (fUART != NULL) {
NULL;
} else {
printf("Opening fUART\n");
fUART = fopen(RFS2_UART_NAME, "w");
token = true;
}

// Read part of file to send
char *out_buffer = malloc(length + 3);
out_buffer = out_data;
out_buffer[length] = '\0'; // add "End of chain" character
/
// Using direct TX macro (works like a charm…!)
/* while (*out_buffer) {
// Send character on UART
IOWR_ALTERA_AVALON_UART_TXDATA(RFS2_UART_BASE, *out_buffer++);
// Wait until character has been sent
while ((IORD_ALTERA_AVALON_UART_STATUS(RFS2_UART_BASE) & ALTERA_AVALON_UART_STATUS_TRDY_MSK) == 0);
} */

// TX via fprintf (does not work :-(..!)
while(IORD_ALTERA_AVALON_UART_STATUS(RFS2_UART_NAME) & ALTERA_AVALON_UART_STATUS_RRDY_MSK) {
// Read the data to clear the IRQ
(void)IORD_ALTERA_AVALON_UART_RXDATA(RFS2_UART_NAME);
}
while ((IORD_ALTERA_AVALON_UART_STATUS(RFS2_UART_BASE) & ALTERA_AVALON_UART_STATUS_TRDY_MSK) == 0) {
IOWR_ALTERA_AVALON_UART_TXDATA(RFS2_UART_BASE, '\0');
}
if (fflush(fUART) == 0) {
printf("fflush succeeded\n");
} else {
printf("fflush failed\n");
}
fflush(stdout);
// Check if ready for TX
if (IORD_ALTERA_AVALON_UART_STATUS(RFS2_UART_BASE) & ALTERA_AVALON_UART_STATUS_TRDY_MSK) {
printf("UART is ready to accept data\n");
status = IORD_ALTERA_AVALON_UART_STATUS(RFS2_UART_BASE);
control = IORD_ALTERA_AVALON_UART_CONTROL(RFS2_UART_BASE);
printf("status %x\r\n",status);
printf("control %x\r\n",control);
// TX chain via file ==> THAT WERE THINGS GO BAD..!
fprintf(fUART, "%s\r\n", out_buffer);
} else {
printf("UART is not ready to accept data\n");
}
// alt_ic_irq_enable(RFS2_UART_IRQ_INTERRUPT_CONTROLLER_ID,RFS2_UART_IRQ);

// Close UART file
if (token == true) {
fflush(fUART);
fclose(fUART);
if (fclose(fUART) != EOF) {
printf("fUART closed\n");
fUART = NULL; // Successfully closed the file
} else {
printf("Failed to close file: %s\n", strerror(errno));
}
token = false;
}

}

int main() {

bool token = false;
int length = 0;
int length_of_str = 0;
int control;
int status;
char WFT_buffer[MAX_BUFFER_SIZE];

uart_flag = 0;
printf("Hello NIOS!\r\n");

// Initialize UART
//RFS2_UART_init();

if (fJTAG != NULL) {
NULL;
} else {
printf("Opening fJTAG\n");
fJTAG = fopen(JTAG_UART_NAME, "rw+");
token = true;
}

while (1){

if (uart_flag == 1) {
printf("Received data: %s\r\n", buffer);
buffer_index = 0;
uart_flag = 0;
} else {
printf("Enter text:");
if (fgets(WFT_buffer + length, sizeof(WFT_buffer) - length,
fJTAG) != NULL)
{
if (strstr(WFT_buffer + length, "\n") != NULL)
{
status = IORD_ALTERA_AVALON_UART_STATUS(RFS2_UART_BASE);
control = IORD_ALTERA_AVALON_UART_CONTROL(RFS2_UART_BASE);
printf("status %x\r\n",status);
printf("control %x\r\n",control);
// strcat(WFT_buffer, "\r\n");
length_of_str = strlen(WFT_buffer);
//alt_ic_irq_disable(RFS2_UART_IRQ_INTERRUPT_CONTROLLER_ID,RFS2_UART_IRQ);
//alt_ic_isr_register(RFS2_UART_IRQ_INTERRUPT_CONTROLLER_ID, RFS2_UART_IRQ, NULL, NULL, NULL);
//IOWR_ALTERA_AVALON_UART_CONTROL(RFS2_UART_BASE, 0);
UART_write(WFT_buffer, length_of_str);
length = 0;
} else length += strlen(WFT_buffer + length);
}
}


}

if (token == true) {
fflush(fJTAG);
fclose(fJTAG);
if (fclose(fJTAG) != EOF) {
fJTAG = NULL; // Successfully closed the file
} else {
printf("Failed to close file: %s\n", strerror(errno));
}
token = false;
}

return 0;
}

0 Kudos
JingyangTeh
Employee
525 Views

Hi


We sincerely apologize for the inconvenience caused by the delay in addressing your Forum queries. Due to an unexpected back-end issue in our system, your Forum cases, along with others, did not get through as intended. As a result, we have a backlog of cases that we are currently working through one by one.

Please be assured that we are doing everything we can to resolve this issue as quickly as possible. However, this process will take some time, and we kindly ask for your patience and understanding during this period. The cases will be attended by AE shortly.

We appreciate your patience and understanding, and we are committed to providing you with the best support possible. 

Thank you for your understanding.


I remember your posting the same question regarding the Interrupt.

It seems like you are not the only person having this issue.

Let me try out on my devkit that I have and get back to you.


Regards

Jingyang, Teh


0 Kudos
JingyangTeh
Employee
464 Views

Hi


Could you give me some more time to work on this case?

I am trying to run an example to see if the IRQ is working as expected.

Will get back to you latest by this week.


Regards

Jingyang, Teh


0 Kudos
JingyangTeh
Employee
440 Views

Hi


I have managed to run the example design on a DE0-Nano board and managed to run the UART in interrupt mode with the example design int he link below:



The HAL API was used in the example design.

Tried using the method you shared of using the C Library method of (fOpen and fWrite), I have see the same behavior like you mentioned.

The UART could not write when I enable the interrupt when I am using the C library when interfacing the UART.


After looking around, it seems like the C library method of fWrite and fRead do not support interrupt mode of reading and writing . So I would say it is an expected behavior when we enable the interrupt when using the C library method.


If you are looking at using the UART with interrupt mode, I woud suggest you to use the HAL API to interface with the UART.


Regards

Jingyang, Teh


0 Kudos
Vincent_F
Beginner
368 Views

Hi Jingyang, Teh,

 

Thanks! At last, this provides an answer to the issue.

I will inform my students and colleagues about it and advice them to use the HAL API from now on.

 

Best regards

 

Pr. Vincent Frick

0 Kudos
JingyangTeh
Employee
293 Views

Hi


I’m glad that your question has been addressed, I now transition this thread to community support. If you have a new question, Please login to ‘https://supporttickets.intel.com/s/?language=en_US’, view details of the desire request, and post a feed/response within the next 15 days to allow me to continue to support you. After 15 days, this thread will be transitioned to community support. The community users will be able to help you on your follow-up questions.



Regards

Jingyang, Teh


0 Kudos
Reply