- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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;
}
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi
Could you try out the example design below on your board?
The example design is using uart in interrupt mode.
Regards
Jingyang, Teh
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi
Sorry that i did not attached to the link.
Please find it below:
Regards
Jingyang, Teh
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi
Did you managed to try the suggested change?
Regards
Jingyang, Teh
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I’m currently on vacation and have no access to my computer. I’ll get back to you next week.
Best regards
Vincent
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
reopening the case
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
To use the interrupt you should consider the fast implementation of using the HAL Software.
Regards
Jingyang, Teh
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi
Do you have any follow up question for this case?
Regards
Jingyang, Teh
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Vincent
Could you try not accessing the tx register directly?
Try using the fwrite function like the example here?
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi
Did my previous suggestion of writing and reading using the fwrite and fread work on your end?
Regards
Jingyang, Teh
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page