標籤:for efi script 遇到 因此 ase style bubuko png
我在研究NIOS的UART時有遇到一些問題,做一下分享。
Nios II在讀取周邊設備資訊時,可以用輪詢跟中斷方式兩種方式來讀取資料。
測試前的前置作業:
1.在Qsys中加入一個UART,並在Quartus中將新增的UART裝置的RX、TX對接。
問題一: 使用輪詢方式讀程式
當我用以下程式碼去輪詢時,會發現須等到第62筆資料傳完後,status暫存器的RRDY才會正常判斷。
1 /* 2 * UART test: polling test, design by Shih-An Li 3 * 4 */ 5 6 #include <stdio.h> 7 #include <system.h> 8 #include "altera_avalon_uart.h" 9 #include "altera_avalon_uart_regs.h"10 #include "alt_types.h"11 #include "sys/alt_irq.h"12 #include <unistd.h>13 #include <io.h>14 15 16 int main(void)17 {18 int rxdata=0,k=0,t=0;19 unsigned int status;20 21 IOWR_ALTERA_AVALON_UART_CONTROL(UART_TX_BASE, 0x1C0); // clear status22 23 while(1)24 {25 status =IORD_ALTERA_AVALON_UART_STATUS(UART_TX_BASE); // read status register26 if(status & ALTERA_AVALON_UART_STATUS_TRDY_MSK){ // check trdy flag27 if(status & 0x040){// transmit shift register is empty28 printf("Uart ready (0x%2x) and send %3d ", status, t);29 IOWR(UART_TX_BASE,1, t++); // send tx data30 }31 }32 33 usleep(100000);34 status =IORD_ALTERA_AVALON_UART_STATUS(UART_TX_BASE);35 printf(" status=0x%x %d\n", status,k++);36 if (status & ALTERA_AVALON_UART_STATUS_RRDY_MSK) // check RRDY flag37 {38 rxdata = IORD(UART_TX_BASE,0);39 printf("Your character rxd is:\t%d %d\n", rxdata, k);40 }41 42 }43 return 0;44 }
執行結果如下:
1 Uart ready (0x60) and send 59 status=0x60 59 2 Uart ready (0x60) and send 60 status=0x60 60 3 Uart ready (0x60) and send 61 status=0x60 61 4 Uart ready (0x60) and send 62 status=0xe0 62 5 Your character rxd is: 62 63 6 Uart ready (0x60) and send 63 status=0xe0 63 7 Your character rxd is: 63 64 8 Uart ready (0x60) and send 64 status=0xe0 64 9 Your character rxd is: 64 6510 Uart ready (0x60) and send 65
讓我覺得很好奇的是去抓他硬體波形來看,發現只讀一次
status =IORD_ALTERA_AVALON_UART_STATUS(UART_TX_BASE);
結果硬體居然送出了好幾次的chip_select訊號,而Fig.1最後那次的chip_select居然是讀取addr 0 位置RXDATA暫存器,因此會把rx_char_ready訊號拉下,之後Fig2會在連續讀取幾次address 2位置的status暫存器,此時已經變成0x60了。
一直要到62筆之後才會正常收值。
Fig 1. UART波形
Fig 2. 接續Fig 1. 波形
方法二: 使用中斷方式
程式碼如下,使用Nios II HAL模式來讀寫資料。
此模式會用ISR函數來判斷RRDY旗標使否為1,是則去收值,因此判斷上比較準確。
1 /* 2 * Nios使用HAL指令,開啟以及讀寫UART設備, design by Shih-An Li 3 */ 4 5 #include <stdio.h> 6 #include <system.h> 7 #include <unistd.h> // define usleep() 8 #include <stddef.h> // define NULL 9 #include <fcntl.h> // define O_NONBLOCK10 #define BUF_SIZE 12811 12 13 int main()14 {15 int iCount, iUart_rxcount;16 int fdterm; // FILEDESCRIPTOR RETURNED BY OPEN17 FILE *fpterm; // FILE pointer returned by fdopen18 unsigned char uCUart1_rxbuffer[255], ucTX[128];19 // O_ACCMODE all access mode20 fdterm = open("/dev/uart_tx", O_ACCMODE | O_NONBLOCK);21 fpterm = fdopen(fdterm,"rw+");22 if(fpterm){23 fprintf(fpterm,"uart_tx STARTED\r\n"); // check initial output24 iUart_rxcount = fread(&uCUart1_rxbuffer, 1, sizeof(uCUart1_rxbuffer), fpterm);25 usleep(100000);26 printf("received:%s\r\n",uCUart1_rxbuffer);27 }28 ucTX[0]=0;29 while(1) {30 write(fdterm, &ucTX[0], 1); // write tx value to uart31 ucTX[0]++; // tx value + 132 // read uart data to rxbuffer and return receive data number33 iUart_rxcount = read(fdterm, &uCUart1_rxbuffer, sizeof(uCUart1_rxbuffer));34 for(iCount=0; iCount<iUart_rxcount; iCount++) {35 // fprintf(fpterm,"received:%s\r\n",uart1_rxbuffer);36 printf("%d\n",uCUart1_rxbuffer[iCount]);37 }38 usleep(10000);39 }40 return 0;41 }
執行結果如下
received:uart_tx STARTED012345678
因此推薦還是以HAL方式來讀取周邊資料比較不會有資料lost問題。
[Nios][UART] 使用UART 的一些問題?