Forum Discussion
Altera_Forum
Honored Contributor
11 years ago --- 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