CoreUARTapb
Enable FIFO → Edit IO and locked → Run program
Fixed mode vs Programmable
Fixed
在面板上配置參數。運行期間沒辦法更改
Programmable
利用 register 配置,或是用UART_init()在初始化時配置。
TxData: 放傳送的資料
RxData: 放接收的資料
Ctrl1: 設定baud value,利用baud value算出baud rate
Ctrl2: 設定# of bit, parity, parity even/odd, baud value
Ctrl3: 設定baud value fraction
baud value 總共13位元,8位元在Ctrl1,5位元在Ctrl2
FIFO mode
- FIFO buffer
- 必須開啟才會有buffer,沒開的話只收的到1byte的資料
Normal mode
- 資料經過double-buffered 所以不會有loading延遲
Status Register
TXRDY: 等於0時表示FIFO/buffer不再接收新的傳輸資料
RXRDY: 等於1時表示FIFO/buffer裡的資料可以被讀取(取出)
PARITY_ERR: 等於1時表示parity error
OVERFLOW: 等於1時表示Rx FIFO/buffer已經溢位滿出來了
FRAMING_ERR: 等於1時表示接收到的格式錯誤
Driver functions
UART_send
- 不能假設這個函式return的時候對方已經收到資料,此時可能還正在傳輸。可以釋放或再次使用tx buffer的記憶體空間,因為return時就表示tx buffer中的資料已經被轉移到硬體的tx FIFO
UART_get_rx
- 不是在FIFO模式時,這個函式會記錄parity, framimg, and overflow錯誤,在FIFO模式只會紀錄overflow錯誤。因此必須使用interrupt來處理parity, framimg錯誤
UART_fill_tx_fifo
- 用在interrupt-driven 的傳輸
- 不能假設這個函式return的時候對方已經收到資料,此時可能還正在傳輸。可以釋放或再次使用tx buffer的記憶體空間,因為return時就表示tx buffer中的資料已經被轉移到硬體的tx FIFO
UART_get_rx_status
- 用OR 結合rx status跟執行UART_get_rx() 時所累積的錯誤
- 回傳自上次呼叫get_rx_status()以來的所有錯誤
- 先get_rx_status(),確認沒問題再UART_get_rx()
- 如果coreUARTapb是用fixed模式的話,UART_init()中的參數沒有作用
- 也無法修改control register 當中的值
- APB 介面允許存取內部暫存器、FIFO、內部記憶體
Memory Map
應該是兩組位址都可以用,但根據範例程式只有試過0x5開頭的那個位址可以用,0x3開頭的沒有試過。
Default CoreUART pinout
- CoreUART_0
RX → G22 → Not use in SOM
TX → B22 → Not use in SOM - CoreUART_1
RX → E21 → P2-65 → P13-7
TX → F20 → P2-55 → P13-8
Fractional Baudrate
原生的core_uart_apb.c、core_uart_apb.h 以及 coreuartapb_regs.h 似乎沒有提供能夠修改fractional baudrate的function,必須先在Libero中啟用enable extra precision。以下是我依照原廠文件的配置修改的作法與邏輯分析儀的驗證。目標3M baudrate,主頻100MHz。
coreuartapb_regs.h
- 新增 CTRL3_REG_OFFSET 0x14u
- 新增 CTRL3_BAUDVALUE_MASK 0x07u
coreuartapb_regs.h
- 新增 UART_set_frac_baud()
coreuartapb_regs.c
- 新增函式如下
Singal Issue
傳送0x87的資料,但邏輯分析儀收到的是0xC3。推測可能是baud value設定不正確導致baudrate不相符造成資料接收錯誤。
設定baudrate是57600,clk為system clock 50MHz。因此得到baud value = 53.2534,設定為53。baud value原廠說明如下。
The term baudval must be rounded to the nearest integer and must be greater than or equal to 1 or less than or equal to 8191.
solution
- 計算baud value的clock是依照FIC_0_CLK,所以在這邊是100MHz
- 9600, 28800 is good,接近被100MHz整除,baurate的誤差比較小
- 57600 need to set baud value as 107, not 108
ERROR
在CoreUARTapb_1中配置兩組UART,在Place and route時出現以下錯誤,後來改成只各配置一組就解決這個錯誤。
Unable to find a legal assignment of I/O bank voltages which permits all I/Os to be placed
Rx Issue
UART_get_rx() 只能接收到一個byte的資料
Solution
一定要打開 FIFO mode,去IO constrain固定好pin腳,然後lock住腳位
Interrupt Issue — 1
程式無法進入ISR
Solution
範例程式用的是FabricIrq3_IRQHandler,但libero裡的配置是0,1這兩組,對應到coreUART0和coreUART1。
MSS_INT_F2M預設是開啟的,開啟後才能使用FPGA Fabric的interrupt,只有[15:0],共16組可以使用
在 Design Hierarchy 中,右鍵選擇Conver to SmartDesign,即可將system builder建立好的top module平面化(就是攤開來的意思啦),下面第二章圖從左到右。
攤開之後對著MSS點兩下,或是右鍵configure就可以出現下面的microcontroller配置圖,上面講到的interrupt management就是在這裡
如果要包裝回去的話(上圖從右到左),一樣右鍵Conver to System Builder就好,然後別忘記要set as root,不然IO Constrain裡面會是以MSS為目標,而且在place and route的時候會出現錯誤。
Interrupt Issue — 2
程式卡在IRQHandler裡面,沒辦法離開回到main
- 從ISR結束離開之後 (0xFFFFFFF9 EXC_RETURN),PC 會回到 NVIC_EnableIRQ裡面, 然後可能是什麼東西又觸發一次 IRQ
Solution
- Mark the “TXRDY” unused or inverted, since it is high when FIFO is available for transmit data. So it will constantly triggered the interrupt