Forum Discussion
Altera_Forum
Honored Contributor
11 years agoAccess serial port for data sent from Nios II's uart for real time plotting graph in
Hi all,
I am able to read data from FPGA to Nios processor, then transmit this data to Uart component created in Qsys using direct register method (IORD_ALTERA_AVALON_UART_STATUS (UART_BASE); IOWR_ALTERA_AVALON_UART_TXDATA(UART_BASE, txdata);etc). Then, I was trying to access serial port data sent from uart in Altera Nios II to plot graph real time in Matlab. I was using this code from Matlab central (http://uk.mathworks.com/matlabcentral/fileexchange/28941-real-time-data-plot-from-serial-port) with minor modification as pasted below: When I run this code I keep getting the following error. What should I do ? ??? In an assignment A(I) = B, the number of elements in B and I must be the same. Error in ==> real_time_data_serial at 80 voltage(count) = fscanf(s,'%f'); I found a few solutions on the web, what I have tried: 1. add pause in .m file so that it has enough time to read the data before the next cycle of data 2. add enough delay at C code where I transmit data to uart 3. make sure the uart has the same setting as comport such as comport number, baud rate, parity, flow control %%real time data plot from a serial port % This matlab script is for ploting a graph by accessing serial port data in % real time. Change the com values and all variable values accroding to % your requirements. Dont forget to add terminator in to your serial device program. % This script can be modified to be used on any platform by changing the % serialPort variable. % Author: Moidu thavot. %%Clear all variables clear all; %%Variables (Edit yourself) SerialPort='com8'; %serial port MaxDeviation = 3;%Maximum Allowable Change from one value to next TimeInterval=0.2;%time interval between each input.0.2 loop=120;%count values %%Set up the serial port object s=serial('com8'); set(s,'BaudRate',9600,'DataBits', 8, 'Parity', 'none','StopBits', 1, 'FlowControl', 'none','Terminator','LF'); set(s, 'terminator', 'LF'); set(s, 'timeout', 10); %%s = serial(SerialPort) fopen(s); time =now; voltage = 0; %% Set up the figure figureHandle = figure('NumberTitle','off',... 'Name','Voltage Characteristics',... 'Color',[0 0 0],'Visible','off'); % Set axes axesHandle = axes('Parent',figureHandle,... 'YGrid','on',... 'YColor',[0.9725 0.9725 0.9725],... 'XGrid','on',... 'XColor',[0.9725 0.9725 0.9725],... 'Color',[0 0 0]); hold on; plotHandle = plot(axesHandle,time,voltage,'Marker','.','LineWidth',1,'Color',[0 1 0]); xlim(axesHandle,[min(time) max(time+0.001)]); % Create xlabel xlabel('Time','FontWeight','bold','FontSize',14,'Color',[1 1 0]); % Create ylabel ylabel('Voltage in V','FontWeight','bold','FontSize',14,'Color',[1 1 0]); % Create title title('Real Time Data','FontSize',15,'Color',[1 1 0]); %% Initializing variables voltage(1)=0; time(1)=0; count = 2; k=1; while ~isequal(count,loop) %%Re creating Serial port before timeout k=k+1; if k==25 fclose(s); delete(s); clear s; s = serial('com8'); fopen(s) k=0; end %%Serial data accessing pause(2); fprintf('here'); voltage(count) = fscanf(s,'%f'); %%For reducing Error Use your own costant voltage(1)=0; if (voltage(count)-voltage(count-1)>MaxDeviation) voltage(count)=voltage(count-1); end time(count) = count; set(plotHandle,'YData',voltage,'XData',time); set(figureHandle,'Visible','on'); datetick('x','mm/DD HH:MM'); pause(5); count = count +1; end %% Clean up the serial port fclose(s); delete(s); clear s; When I check the serial port status, I got the following: Communication Settings Port: COM8 BaudRate: 9600 Terminator: 'LF' Communication State Status: open RecordStatus: off Read/Write State TransferStatus: idle BytesAvailable: 0 ValuesReceived: 0 ValuesSent: 0 I noticed the serial port is ready (since it is open) but no data is sent or receive. Could you please tell me what is wrong so I could try? Please , thank you17 Replies
- Altera_Forum
Honored Contributor
want2know,
I think you don't fully understand how Qsys ties into Quartus and NIOS IDE. When you generate your Qsys system you get a .sopcinfo file. When you start a NIOS project - File New > NIOS II Application and BSP from Template - you import your Qsys file. This generates a system.h file (located in the 'project_name'_bsp folder) that contains all of system configuration parameter that you set up in qsys. Specifically, Uart1_IRQ_INTERRUPT_CONTROLLER_ID is a parameter that is specified in the system.h file. When you first started your project, after importing the .sopcinfo file, you should have seen 2 folders appear ('project_name' and 'project_name'_bsp). If you were to right click the _bsp folder and go to NIOS II > BSP Editor, you could look into the Enable File Generation tab and see that the system.h file is going to be made. Click Generate button and your system.h file will be produced in the _bsp folder. Now you can view your system.h file (you might need to refresh with F5). In there you should see all the qsys parameters and memory mapped address spaces. So to answer question# 2: InitUart knows what Uart_IRQ is supposed to be, because you should always include the system.h file in your code (#include "system.h"). OK. Now let's talk about interrupt enables/register functions (ic_isr_register and irq_enable). In question 3 you ask why the flag is set to 0x0. Please read the documentation for ic_isr_register. It will say to set that parameter to 0x0 since it isn't being used. ---------------------------------------------------------------------------------------------------- The reason I want to separate this section from the one previous is that you seem to be confused on how the interrupt/hardware work together. In question 4 you ask if you can call the ic_isr_register multiple times for the same hardware peripheral (Uart1). This does not make sense. You should only call it once for 1 peripheral... Therefore, you should also have 1 context_uart. The way interrupts work is that when the main thread is interrupted, the state of that main thread is temporarily stored the variable - context_uart - until the interrupt service routine (Isr_Uart1) is completed. Then the main thread will resume where it left off. As you know Uart is a serial protocol - which means only 1 piece of data can be sent at a time. However, uart is fairly fast (although not the fastest comm. protocol). The speed depends on your baud rate. I usually use 115200. So to answer question 4: No, do not call out that line 12 times... Call it out once. Then send your data 1 element at a time. If you have 12 data sets @ 10 elements/data set, you will have to send out 120 elements sequentially. That is ok, because the transfer rate is fast. All the data will come out from 1 uart port which is what you connect to your PC. ---------------------------------------------------------------------------------------------------- Question 5: In the example I linked previously, there where 2 uarts used to talk to each other. That's why they have Get/Put_Uart 1 and 2. But in your case you only have 1 uart so you only need to use the Get_Uart1 and Put_Uart1 functions. You ask, why you need these functions if Isr_Uart is already there. Please examine the Uart code in more detail. You will see that the Isr_Uart is called on an interrupt and it will store data in a buffer (Rx_buffer or Tx_buffer). This is done automatically as the interrupt is triggered. However it is up to you to see what the data actually is. That is what Get_Uart and Put_Uart functions do. Get_Uart reads out of the Rx_buffer while Put_Uart places data in the Tx_buffer. You can think of it as functions that let you interface with the ISR function. Question 6: Yes you still need that Tails and Heads. Don't change this code. In fact you shouldn't have to modify any of the code in the InterruptHandlerforUart file. Question 7: IF you have a fixed baud rate then you don't need the divisor. Actually just change the following function is the InterruptHandlerforUart.c file: void InitUart1() { ALTERA_AVALON_UART_CONTROL_RRDY_MSK); } and in the header void InitUart1(); as you can see I modified the init function to have no inputs since you don't need to set the baud rate - it is already fixed. Hopefully this helps. Let me know if you need anything else. - Altera_Forum
Honored Contributor
1) If you aren't limited by onchip memory, I don't see a reason for you to take out code from the InterruptHandlerforUart files. Even if you never call out GetUart, it won't hurt to have it in your code - for the future...
I can't see why your code (.txt,.stack,.heap, etc) would take up a lot of memory. Normally I allocate at least 26000 bytes to onchip memory in qsys. That is more than enough for the complete Uart code. EmptyUart function is there to check if the data buffers are empty. You can use it if you want. You don't need it to transmit data. But again, even if you don't use it, don't remove it from the code if you have ample memory space. 2) "The way interrupts work is that when the main thread is interrupted, the state of that main thread is temporarily stored the variable - context_uart - until the interrupt service routine (Isr_Uart1) is completed. Then the main thread will resume where it left off." <-- this is from my last reply So in IsrUart, context and id are the what you pass context_uart into. Although it's not used directly in that function, i think its needed for the ic_isr_register function, so don't modify. 3) once again, if you aren't limited by on chip memory, don't delete this code. You might need it in the future. 4) rxhead/tail, txhead/tail are just position markers in the Rxbuffer and Txbuffer. Basically, when the head = tails then the buffer is empty. The code is using these location values to parse through the data buffers. This is needed because Uart data maybe coming in at one rate, but you are reading it in at a different rate (as you need it). 5) See answer 2 and middle section of previous reply. It is just a holder of the main thread's state, while the Uart Interrupt service routine is being processed. Here is a wiki on context switching / interrupt handling: http://en.wikipedia.org/wiki/context_switch#interrupt_handling So in summary, don't fiddle around with the interrupthandlerforuart code. It is more work then it's worth and you might damage the functionality. - Altera_Forum
Honored Contributor
How are you transmitting uart from the fpga? Are you polling or using interrupts?
Here is a thread about using UART with interrupts: http://www.alteraforum.com/forum/showthread.php?t=17224 The code bluegem1 provides (uart interrupt handler) works very well. I've used it to communicate with nios and a Visual c++ program on the pc. Make sure your baud rates match up (i use 115200). The matlab code looks correct. - Altera_Forum
Honored Contributor
--- Quote Start --- Hi all, I am able to read data from FPGA to Nios processor, then transmit this data to Uart component created in Qsys using direct register method (IORD_ALTERA_AVALON_UART_STATUS (UART_BASE); IOWR_ALTERA_AVALON_UART_TXDATA(UART_BASE, txdata);etc). Then, I was trying to access serial port data sent from uart in Altera Nios II to plot graph real time in Matlab. I was using this code from Matlab central (http://uk.mathworks.com/matlabcentral/fileexchange/28941-real-time-data-plot-from-serial-port) with minor modification as pasted below: When I run this code I keep getting the following error. What should I do ? ??? In an assignment A(I) = B, the number of elements in B and I must be the same. Error in ==> real_time_data_serial at 80 voltage(count) = fscanf(s,'%f'); I found a few solutions on the web, what I have tried: 1. add pause in .m file so that it has enough time to read the data before the next cycle of data 2. add enough delay at C code where I transmit data to uart 3. make sure the uart has the same setting as comport such as comport number, baud rate, parity, flow control %%real time data plot from a serial port % This matlab script is for ploting a graph by accessing serial port data in % real time. Change the com values and all variable values accroding to % your requirements. Dont forget to add terminator in to your serial device program. % This script can be modified to be used on any platform by changing the % serialPort variable. % Author: Moidu thavot. %%Clear all variables clear all; %%Variables (Edit yourself) SerialPort='com8'; %serial port MaxDeviation = 3;%Maximum Allowable Change from one value to next TimeInterval=0.2;%time interval between each input.0.2 loop=120;%count values %%Set up the serial port object s=serial('com8'); set(s,'BaudRate',9600,'DataBits', 8, 'Parity', 'none','StopBits', 1, 'FlowControl', 'none','Terminator','LF'); set(s, 'terminator', 'LF'); set(s, 'timeout', 10); %%s = serial(SerialPort) fopen(s); time =now; voltage = 0; %% Set up the figure figureHandle = figure('NumberTitle','off',... 'Name','Voltage Characteristics',... 'Color',[0 0 0],'Visible','off'); % Set axes axesHandle = axes('Parent',figureHandle,... 'YGrid','on',... 'YColor',[0.9725 0.9725 0.9725],... 'XGrid','on',... 'XColor',[0.9725 0.9725 0.9725],... 'Color',[0 0 0]); hold on; plotHandle = plot(axesHandle,time,voltage,'Marker','.','LineWidth',1,'Color',[0 1 0]); xlim(axesHandle,[min(time) max(time+0.001)]); % Create xlabel xlabel('Time','FontWeight','bold','FontSize',14,'Color',[1 1 0]); % Create ylabel ylabel('Voltage in V','FontWeight','bold','FontSize',14,'Color',[1 1 0]); % Create title title('Real Time Data','FontSize',15,'Color',[1 1 0]); %% Initializing variables voltage(1)=0; time(1)=0; count = 2; k=1; while ~isequal(count,loop) %%Re creating Serial port before timeout k=k+1; if k==25 fclose(s); delete(s); clear s; s = serial('com8'); fopen(s) k=0; end %%Serial data accessing pause(2); fprintf('here'); voltage(count) = fscanf(s,'%f'); %%For reducing Error Use your own costant voltage(1)=0; if (voltage(count)-voltage(count-1)>MaxDeviation) voltage(count)=voltage(count-1); end time(count) = count; set(plotHandle,'YData',voltage,'XData',time); set(figureHandle,'Visible','on'); datetick('x','mm/DD HH:MM'); pause(5); count = count +1; end %% Clean up the serial port fclose(s); delete(s); clear s; When I check the serial port status, I got the following: Communication Settings Port: COM8 BaudRate: 9600 Terminator: 'LF' Communication State Status: open RecordStatus: off Read/Write State TransferStatus: idle BytesAvailable: 0 ValuesReceived: 0 ValuesSent: 0 I noticed the serial port is ready (since it is open) but no data is sent or receive. Could you please tell me what is wrong so I could try? Please , thank you --- Quote End --- anyone please even a clue for me to try please? - Altera_Forum
Honored Contributor
How are you UART? are you polling or using interrupts?
I recommend using interrupts: look at the following thread - the code provided in this thread works well... http://www.alteraforum.com/forum/showthread.php?t=17224 I've used this code to communicate with a visual c++ program on the pc. I think the matlab code for accessing the serial port is correct, so the problem is probably on the FPGA side. - Altera_Forum
Honored Contributor
--- Quote Start --- How are you UART? are you polling or using interrupts? I recommend using interrupts: look at the following thread - the code provided in this thread works well... http://www.alteraforum.com/forum/showthread.php?t=17224 I've used this code to communicate with a visual c++ program on the pc. I think the matlab code for accessing the serial port is correct, so the problem is probably on the FPGA side. --- Quote End --- Hi Krasner, Thanks for your reply. I dont understand why it is not working, must it be done with interrupts? Couldn't it be done by using iowr on the uart? I used the following code to access the UART (rs232 serial port) component I created in Qsys, I connected the txdata pin to the oscilloscope and it shows nothing, i am wondering why couldn't I use IOWR_ALTERA_AVALON_UART_TXDATA(UART_BASE, txdata); to transmit data to UART? What I want to do is Nios processor reads data from FPGA, Nios transmits the data to serial port and plot graph real time using Maltab,using de0 nano. I do not need to read data from serial port. #include "altera_avalon_uart_regs.h" #define UART_BASE 0x00002000 int main (void) {alt_u16 status, rxdata=0,aa=0, txdata=0; while (! (status & 0x0040)) // Wait for transmission completion status = IORD_ALTERA_AVALON_UART_STATUS (UART_BASE); printf("status= %.2f V \r\n", (float) status); rxdata = 5; // assuming I get this data by accessing sdram in Nios txdata = rxdata; IOWR_ALTERA_AVALON_UART_TXDATA(UART_BASE, txdata); printf("txdata= %.2f V \r\n", (float) txdata); return 0;} Could you please give me some hints? Thanks - Altera_Forum
Honored Contributor
Yes you have to use interrupts for accurate transmission.
I had the same issue you have when using polling (the while loop in your code). This is because the while loop prevents the nios from doing other tasks. In other words, you are bottlenecking yourself. Interrupts allow you to receive and transmit messages exaclty when you want to, by temporarily pausing the nios to perform the uart task. To do interrupts, you must connect the interrupt (IRQ) column in qsys (that is a hardware enable). Then you must do a software enable (alt_ic_isr_register and alt_ic_irq_enable) --> this is slightly different than in the code provided. He uses alt_irq_register and alt_irq_enable which are outdated... Here is what I suggest: The code i linked to is using 2 uarts - because they are talking to each other. You only need 1. So you must go through the provided code and delete one of the uarts (UART2). To make life easy, make sure your uart module in qsys is named UART1. This is because his code expects system.h names to be Uart1 and Uart2. You can give it a different name, but you will have to scrub through the code to make the appropriate changes. Include InterruptHandlerforUart.h in your code. Now in main you want to initialize the uart and enable the software interrupts: int context_uart; InitUart1( <put in a baud rate if uart module did not have fixed baud rate... see the linked code>); alt_ic_isr_register(Uart1_IRQ_INTERRUPT_CONTROLLER_ID, Uart1_IRQ,IsrUart1,&context_uart,0x0); alt_ic_irq_enable(Uart1_IRQ_INTERRUPT_CONTROLLER_ID, Uart1_IRQ); finally to transmit, you just write: PutUart1( <some character> ); The C code provided takes care of the rest (uart statuses, fifoing, etc.) If you have lots of characters - which you do - then put the PutUart1 into a loop. - Altera_Forum
Honored Contributor
--- Quote Start --- Yes you have to use interrupts for accurate transmission. I had the same issue you have when using polling (the while loop in your code). This is because the while loop prevents the nios from doing other tasks. In other words, you are bottlenecking yourself. Interrupts allow you to receive and transmit messages exaclty when you want to, by temporarily pausing the nios to perform the uart task. To do interrupts, you must connect the interrupt (IRQ) column in qsys (that is a hardware enable). Then you must do a software enable (alt_ic_isr_register and alt_ic_irq_enable) --> this is slightly different than in the code provided. He uses alt_irq_register and alt_irq_enable which are outdated... Here is what I suggest: The code i linked to is using 2 uarts - because they are talking to each other. You only need 1. So you must go through the provided code and delete one of the uarts (UART2). To make life easy, make sure your uart module in qsys is named UART1. This is because his code expects system.h names to be Uart1 and Uart2. You can give it a different name, but you will have to scrub through the code to make the appropriate changes. Include InterruptHandlerforUart.h in your code. Now in main you want to initialize the uart and enable the software interrupts: int context_uart; InitUart1( <put in a baud rate if uart module did not have fixed baud rate... see the linked code>); alt_ic_isr_register(Uart1_IRQ_INTERRUPT_CONTROLLER_ID, Uart1_IRQ,IsrUart1,&context_uart,0x0); alt_ic_irq_enable(Uart1_IRQ_INTERRUPT_CONTROLLER_ID, Uart1_IRQ); finally to transmit, you just write: PutUart1( <some character> ); The C code provided takes care of the rest (uart statuses, fifoing, etc.) If you have lots of characters - which you do - then put the PutUart1 into a loop. --- Quote End --- Thank you very much for your kind reply, krasner... I am now trying to implement the code and need some time to troubleshoot the errors here and there, keep you updated - Altera_Forum
Honored Contributor
--- Quote Start --- Yes you have to use interrupts for accurate transmission. I had the same issue you have when using polling (the while loop in your code). This is because the while loop prevents the nios from doing other tasks. In other words, you are bottlenecking yourself. Interrupts allow you to receive and transmit messages exaclty when you want to, by temporarily pausing the nios to perform the uart task. To do interrupts, you must connect the interrupt (IRQ) column in qsys (that is a hardware enable). Then you must do a software enable (alt_ic_isr_register and alt_ic_irq_enable) --> this is slightly different than in the code provided. He uses alt_irq_register and alt_irq_enable which are outdated... Here is what I suggest: The code i linked to is using 2 uarts - because they are talking to each other. You only need 1. So you must go through the provided code and delete one of the uarts (UART2). To make life easy, make sure your uart module in qsys is named UART1. This is because his code expects system.h names to be Uart1 and Uart2. You can give it a different name, but you will have to scrub through the code to make the appropriate changes. Include InterruptHandlerforUart.h in your code. Now in main you want to initialize the uart and enable the software interrupts: int context_uart; InitUart1( <put in a baud rate if uart module did not have fixed baud rate... see the linked code>); alt_ic_isr_register(Uart1_IRQ_INTERRUPT_CONTROLLER_ID, Uart1_IRQ,IsrUart1,&context_uart,0x0); alt_ic_irq_enable(Uart1_IRQ_INTERRUPT_CONTROLLER_ID, Uart1_IRQ); finally to transmit, you just write: PutUart1( <some character> ); The C code provided takes care of the rest (uart statuses, fifoing, etc.) If you have lots of characters - which you do - then put the PutUart1 into a loop. --- Quote End --- Hi Krasner, My current system is done with polling as mentioned earlier using direct register method (IORD_ALTERA_AVALON_UART_STATUS (UART_BASE); IOWR_ALTERA_AVALON_UART_TXDATA(UART_BASE, txdata);etc)., now I would like to implement with interrupt as you recommended, but I have few issues I need to understand so that I can fix those errors: I am able to read serial port and plot the graph real time in Matlab. However, I am having the issue where the data is not updated as frequent as desired. I am using USB-to-Serial interface to the board FTDI UM245R module. I have a few questions about using interrupt for uart: I want to send data from Nios II to serial port to plot graph real time in Matlab. 1. In function void InitUart(), what is the "Uart1_IRQ_INTERRUPT_CONTROLLER_ID" for? I read in the I read in the Altera documentation (https://www.altera.com/en_us/pdfs/literature/hb/nios2/n2sw_nii52010.pdf), the interrupt controller ID is defined in system.h, but I couldn't find any info about it in system.h, should I generate or do something to get this controller id? 2. I assigned IRQ no.2 in Qsys, I dont understand how doesthe function in InitUart() know that Uart1_IRQ is 2? Is it done automatically or how should I assign? alt_ic_isr_register(Uart1_IRQ_INTERRUPT_CONTROLLER_ID, Uart1_IRQ,IsrUart1,&context_uart,0x0); alt_ic_irq_enable(Uart1_IRQ_INTERRUPT_CONTROLLER_ID, Uart1_IRQ); 3. i can't find how to set the flag to 0x0 as you have written 4. Regarding alt_ic_isr_register(Uart1_IRQ_INTERRUPT_CONTROLLER_ID, Uart1_IRQ,IsrUart1,&context_uart,0x0);, I know this sounds stupicd, can I write the above line twelve times so I can call the function IsrUart1 twelve times? Reason being, I need to send twelve sets of data, imagine I have twelve sets of "context_uart" , each set of data has 10 elements for instance. If it is not possible to call alt_ic_isr_register for 12 times, is there a smart way to do it? 5. In the main function, why do we need the two functions GetUart1() and PutUart2()? I thought in the IsUart1(), we have already transmitted the data 6. My current system is done with polling as mentioned earlier, now I would like to implement with interrupt as you recommended, since the current system can display data in correct value and order, but data is not updated as frequent as desired (I posted the thread here http://www.alteraforum.com/forum/showthread.php?t=48165), so do you think I still need to have those codes for buffer size, head and tail etc? In the function PutUart1(), if (++TxHead_1 > (TX_BUFFER_SIZE_1-1)) TxHead_1 = 0; z = IORD_ALTERA_AVALON_UART_CONTROL(UART1_BASE) | ALTERA_AVALON_UART_CONTROL_TRDY_MSK; IOWR_ALTERA_AVALON_UART_CONTROL(UART1_BASE, z); I am wondering what is the purpose of having the codes checking the buffer size and the head and tail? TxHead_1==TxTail_1 7. divisor = (ALT_CPU_FREQ/BaudRate) +1; I assume I dont need this as I have fixed baud rate 115200, am I right? I know I ask a lot and this is demanding, I really appreciate if you could just give short answer to my questions, really appreciate your help!! - Altera_Forum
Honored Contributor
--- Quote Start --- want2know, I think you don't fully understand how Qsys ties into Quartus and NIOS IDE. When you generate your Qsys system you get a .sopcinfo file. When you start a NIOS project - File New > NIOS II Application and BSP from Template - you import your Qsys file. This generates a system.h file (located in the 'project_name'_bsp folder) that contains all of system configuration parameter that you set up in qsys. Specifically, Uart1_IRQ_INTERRUPT_CONTROLLER_ID is a parameter that is specified in the system.h file. When you first started your project, after importing the .sopcinfo file, you should have seen 2 folders appear ('project_name' and 'project_name'_bsp). If you were to right click the _bsp folder and go to NIOS II > BSP Editor, you could look into the Enable File Generation tab and see that the system.h file is going to be made. Click Generate button and your system.h file will be produced in the _bsp folder. Now you can view your system.h file (you might need to refresh with F5). In there you should see all the qsys parameters and memory mapped address spaces. So to answer question# 2: InitUart knows what Uart_IRQ is supposed to be, because you should always include the system.h file in your code (#include "system.h"). OK. Now let's talk about interrupt enables/register functions (ic_isr_register and irq_enable). In question 3 you ask why the flag is set to 0x0. Please read the documentation for ic_isr_register. It will say to set that parameter to 0x0 since it isn't being used. ---------------------------------------------------------------------------------------------------- The reason I want to separate this section from the one previous is that you seem to be confused on how the interrupt/hardware work together. In question 4 you ask if you can call the ic_isr_register multiple times for the same hardware peripheral (Uart1). This does not make sense. You should only call it once for 1 peripheral... Therefore, you should also have 1 context_uart. The way interrupts work is that when the main thread is interrupted, the state of that main thread is temporarily stored the variable - context_uart - until the interrupt service routine (Isr_Uart1) is completed. Then the main thread will resume where it left off. As you know Uart is a serial protocol - which means only 1 piece of data can be sent at a time. However, uart is fairly fast (although not the fastest comm. protocol). The speed depends on your baud rate. I usually use 115200. So to answer question 4: No, do not call out that line 12 times... Call it out once. Then send your data 1 element at a time. If you have 12 data sets @ 10 elements/data set, you will have to send out 120 elements sequentially. That is ok, because the transfer rate is fast. All the data will come out from 1 uart port which is what you connect to your PC. ---------------------------------------------------------------------------------------------------- Question 5: In the example I linked previously, there where 2 uarts used to talk to each other. That's why they have Get/Put_Uart 1 and 2. But in your case you only have 1 uart so you only need to use the Get_Uart1 and Put_Uart1 functions. You ask, why you need these functions if Isr_Uart is already there. Please examine the Uart code in more detail. You will see that the Isr_Uart is called on an interrupt and it will store data in a buffer (Rx_buffer or Tx_buffer). This is done automatically as the interrupt is triggered. However it is up to you to see what the data actually is. That is what Get_Uart and Put_Uart functions do. Get_Uart reads out of the Rx_buffer while Put_Uart places data in the Tx_buffer. You can think of it as functions that let you interface with the ISR function. Question 6: Yes you still need that Tails and Heads. Don't change this code. In fact you shouldn't have to modify any of the code in the InterruptHandlerforUart file. Question 7: IF you have a fixed baud rate then you don't need the divisor. Actually just change the following function is the InterruptHandlerforUart.c file: void InitUart1() { ALTERA_AVALON_UART_CONTROL_RRDY_MSK); } and in the header void InitUart1(); as you can see I modified the init function to have no inputs since you don't need to set the baud rate - it is already fixed. Hopefully this helps. Let me know if you need anything else. --- Quote End --- Thanks Krasner, you explained very good and it helps me a lot!! I have 6 questions: 1. In the main, I modified by removing the GetUart1() because I dont read data from serial port, I have the data with me (the data is stored at txdata1), I just want to transmit to the serial port, my question is, do I still need the function EmptyUart1()? int main() { unsigned char ch; printf("\n\nHello NiosII!!!!!\n"); InitUart(); while(1) { if(!EmptyUart1()) { unsigned char txdata1 [4]={2, 8, 5,6}; PutUart1(&txdata1); } } //while return 0; } 2. My second question, in the IsrUart1 function, what are the "context" and "int id" for? I didnt see they are used anywhere? 3. in the IsrUart1 function as below, since I am not doing anything with rxbuffer and rrdy_mask (I only need Txbuffer and Trdy_msk), I assume I am going to remove everything for RxHead and RxTail as I comment out the below lines, but what should I do with the last line else IOWR_ALTERA_AVALON_UART_CONTROL(UART1_BASE, ALTERA_AVALON_UART_CONTROL_RRDY_MSK);? void IsrUart1(void* context, unsigned int id) { int sr; sr = IORD_ALTERA_AVALON_UART_STATUS(UART1_BASE); //if(sr & ALTERA_AVALON_UART_STATUS_RRDY_MSK); //{ //rx_buffer_1[RxHead_1] = IORD_ALTERA_AVALON_UART_RXDATA(UART1_BASE); //IOWR_ALTERA_AVALON_UART_STATUS(UART1_BASE, 0); //if (++RxHead_1 > (RX_BUFFER_SIZE_1-1)) RxHead_1 = 0; //} if(sr & ALTERA_AVALON_UART_STATUS_TRDY_MSK) { if(IORD_ALTERA_AVALON_UART_CONTROL(UART1_BASE) & ALTERA_AVALON_UART_CONTROL_TRDY_MSK); { if (TxTail_1 != TxHead_1) { IOWR_ALTERA_AVALON_UART_TXDATA(UART1_BASE, tx_buffer_1[TxTail_1]); if (++TxTail_1 > (TX_BUFFER_SIZE_1 -1)) TxTail_1 = 0; } else IOWR_ALTERA_AVALON_UART_CONTROL(UART1_BASE, ALTERA_AVALON_UART_CONTROL_RRDY_MSK); } } } unsigned char EmptyUart1() { if(RxHead_1 == RxTail_1) return 1; return 0; 4. I tried to understand what is the rxhead, rxtail, txhead,txtail, I dont understand what are they about, if I understand correctly, it saves the received dta in rxhead, then check if txtail and txhead are not same, then transmit, but I dont get the whole idea of using these four terms, forgive me for being stupid 5. In void InitUart1(){ IOWR_ALTERA_AVALON_UART_CONTROL(UART1_BASE, ALTERA_AVALON_UART_CONTROL_RRDY_MSK); }, since I dont want to receive any data from UART, I just want to transmit, I dont know what to be put here since I dont need the rrdy_msk here, please correct me if I am wrong 6. My last question is, alt_ic_isr_register(Uart1_IRQ_INTERRUPT_CONTROLLER_ID, Uart1_IRQ,IsrUart1,&context_uart1,0x0);, what is this &context_uart1? In the documention, it states that it is the input argument points to data structure associated with device driver instance, but I am not quite sure what it actually means... Thank you very much, really appreciate your help, more than I can say