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++
12727 Discussions

UART gets stuck when enabling IRQ (NIOS II)

Vincent_F
Beginner
2,376 Views

Hi,

I'm reopening an old post from 2013 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
20 Replies
JingyangTeh_Altera
2,278 Views

HI


From the code I see that you are are enabling the interrupt for transmit ready.

Could you try to enable disable that and enable the Read ready mask instead.

ALTERA_AVALON_UART_CONTROL_TRDY_MSK <--- Transmit Ready Mask

ALTERA_AVALON_UART_CONTROL_RRDY_MSK < ---- Read Ready Mask


Regards

Jingyang, Teh


0 Kudos
Vincent_F
Beginner
2,250 Views

Hi,

Thanks for your suggestion. Unfortunately, I've already tried it and it won't work either. Whatever the interrupt (transmit or read) the symptoms are the same.

Best regards

Vincent

0 Kudos
JingyangTeh_Altera
2,214 Views

Hi


Could you try out the example design below on your board?

The example design is using uart in interrupt mode.


Regards

Jingyang, Teh


0 Kudos
Vincent_F
Beginner
2,205 Views

Hi,

Thanks for your reply. I can try your example but I can't see any source file. Could you check if the files or code were attached to your reply?

Best regards

Vincent

0 Kudos
JingyangTeh_Altera
2,174 Views

Hi


Sorry that i did not attached to the link.

Please find it below:

https://www.intel.com/content/www/us/en/design-example/715139/cyclone-v-fpga-uart-rs-232-maximum-baud-rate-reference-design.html


Regards

Jingyang, Teh


0 Kudos
Vincent_F
Beginner
2,139 Views

Hi Jingyang, Teh,

Thank you for trying to help. Yet, the above example is based on the nios-dedicated macros for sending/reading data from a UART, which obviously work, and I also successfully used them as previously mentioned. But it still does not answer my original question/issue: why is the use of the fprintf instruction incompatible with the interrupts on the UART, even when the interrupt is disabled prior to using fprintf?

To summarize the context and symptoms:

Context:  System that features a UART

Symptoms:
1. Program that manages to send/receive data from that UART without IRQ using fprintf (via a FILE)
2. Program that gets stuck whenever the IRQ of the UART is registered, even when no data is sent or received
3. Program that gets stuck even when no data is sent or received AND trying to unregister or disable the IRQ of the UART

I know the solution and workaround exist, but I still would like to understand the cause of this issue. We tried an equivalent code on other microcontrollers and no issues were detected. I hope my request is clearer.

Best regards

Vincent

0 Kudos
JingyangTeh_Altera
2,079 Views

Hi


Sorry for the slow response.

Kept going through your code and it looks fine.

I found out that you are accessing the JTAG UART.

It is slightly different from the UART IP.


The control registers are different compared to the UART IP.

https://www.intel.com/content/www/us/en/docs/programmable/683130/24-1/control-register-17391.html


Could you try the following code to register the interrupt ?


 sp->irq_enable = ALTERA_AVALON_JTAG_UART_CONTROL_RE_MSK;

 IOWR_ALTERA_AVALON_JTAG_UART_CONTROL(sp->base, sp->irq_enable); 

 alt_ic_isr_register(irq_controller_id, irq, altera_avalon_jtag_uart_irq,  sp, NULL);



Regards

Jingyang, Teh


0 Kudos
Vincent_F
Beginner
2,055 Views

Hi Jingyang, Teh,

No worries, we're all busy.

Thanks for your reply! Yet, the problem has nothing to do with the JTAG UART (i.e. the IRQ for this IP is never registered nor unregistered) I use it as my stdio interface.

The problem occurs on the RS232 UART (RFS2 UART in my project), i.e. when I enable/disable the IRQ on this interface.

Best regards

Vincent

0 Kudos
JingyangTeh_Altera
2,014 Views

Hi


From the code you are opening the JTAG_UART device instead of the UART IP.

For the UART IP the fOpen should be "#define UART_0_NAME "/dev/UART_0"" instead of "#define JTAG_UART_NAME "/dev/JTAG_UART""



Regards

Jingyang, Teh


0 Kudos
JingyangTeh_Altera
1,893 Views

Hi


Did you managed to try the suggested change?


Regards

Jingyang, Teh


0 Kudos
Vincent_F
Beginner
1,851 Views
Hi Jingyang, Teh,

I’m currently on vacation and have no access to my computer. I’ll get back to you next week.
Best regards
Vincent
0 Kudos
Vincent_F
Beginner
1,718 Views

Hi,

If you look carefully at the code, when I call the function "void UART_write(char * out_data, int length)" I do open the UART.

>> See line fUART=fopen(RFS2_UART_NAME, "w"); where RFS2_UART_NAME defines "/dev/RFS2_UART" in my system.h file.

I also open the JTAG_UART in the main program, but that's only for stdio operations, and I don't do anything that involves the JTAG_UART interrupt.

Best regards

Vincent

0 Kudos
JingyangTeh_Altera
1,868 Views

Hi


As we do not receive any response from you on the previous question/reply/answer that we have provided. 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
KennyTan_Altera
Moderator
1,766 Views

reopening the case


0 Kudos
JingyangTeh_Altera
1,637 Views

Hi


I sorry for the mistake. You are right.

You are opening the UART Core instead of the JTAG Uart.

After digging around. The method you are using is considered the small implementation of the driver which does not support interrupt.


https://www.intel.com/content/www/us/en/docs/programmable/683130/24-1/driver-options-fast-vs-small-implementations-27729.html


To use the interrupt you should consider the fast implementation of using the HAL Software.


Regards

Jingyang, Teh


0 Kudos
JingyangTeh_Altera
1,585 Views

Hi


Do you have any follow up question for this case?


Regards

Jingyang, Teh


0 Kudos
Vincent_F
Beginner
1,563 Views

Hi Jingyang, Teh,

Thank you for your message. The documentation you suggest does not give any further help on how to configure fast implementation except from setting the HAL environment to default. By "fast" or "small" implementation, do you mean the "small driver" option that can be found in the BSP tool, which can be accessed via Eclipse? If so, my system does not use the small implementation of the driver, (i.e. I always use the default settings, which is the "fast" driver according to the documentation).

I would appreciate you provide me with more specific information on how to use fast implementation of the HAL Software.

Best regards

Vincent

 

0 Kudos
JingyangTeh_Altera
1,486 Views

Hi Vincent


Could you try not accessing the tx register directly?

Try using the fwrite function like the example here?

https://www.intel.com/content/www/us/en/docs/programmable/683130/24-1/hal-system-library-support-37443.html

For the fprint, you should not use that as it is used to print to the jtag uart.


Yes you are right, by default it is fast implementation instead of small. The only difference between them is fast support interrupt and small do not.


Regards

Jingyang, Teh



0 Kudos
JingyangTeh_Altera
1,432 Views

Hi


Did my previous suggestion of writing and reading using the fwrite and fread work on your end?


Regards

Jingyang, Teh


0 Kudos
JingyangTeh_Altera
1,361 Views

Hi


As we do not receive any response from you on the previous question/reply/answer that we have provided. 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