Vivado/Vitis v2020.1でArtyのArduino/chipKIT Shield Connectorからシリアルデータを取り込んだ時のメモです。
Vivado
ArtyのArduino/chipKIT Shield Connectorからシリアルデータを取り込むには、VivadoのBlock DesignでAXI UART Liteをインスタンス化します。通常、ArtyのデザインではUSB UARTをインスタンス化するので、それに加えてもう一つUARTを追加することになります。
追加したUARTのピンに、次のようなArduino/chipKIT Shield Connector制約条件を指定します。
# IO0
set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33} [get_ports {Arduino_UART_rxd}]
# IO1
set_property -dict {PACKAGE_PIN U16 IOSTANDARD LVCMOS33} [get_ports {Arduino_UART_txd}]
ピンアサインの資料がなかなか見つからないので苦労しましたが、ここにありました。
Vitis
Vitisでは、AXI UART LiteのレジスタをアクセスしてUARTの受信を行います。具体的には、初期化時にCTRL_REGでFIFOをクリアしてから、STAT_REGを確認して、受信データがあればRxFIFOからデータを取得します。UART用にいろいろ便利なヘルパーAPIが用意されているようですが、シンプルなAPIだけを試しました。用意されているAPIを使用しなくても、*(volatile u32 *) AddrでAXIのアドレスに直接アクセスすることもできます。
#include <stdio.h>
#include "platform.h"
#include "xil_types.h"
#include "xil_assert.h"
#include "xstatus.h"
#include "xuartlite.h"
#include "xuartlite_i.h"
#include "xil_io.h"
#define UARTLITE_DEVICE_ID XPAR_UARTLITE_1_DEVICE_ID
XUartLite UartLite;
int main()
{
init_platform();
int status;
int rx;
// グローバル変数の初期化
status = XUartLite_Initialize(&UartLite, UARTLITE_DEVICE_ID);
if (status != XST_SUCCESS) {
return XST_FAILURE;
}
// UARTのFIFOをクリア
XUartLite_WriteReg(UartLite.RegBaseAddress,
XUL_CONTROL_REG_OFFSET,
XUL_CR_FIFO_RX_RESET|XUL_CR_FIFO_TX_RESET);
// 1000回受信する
for (int i = 0; i<1000;i++) {
// Statusレジスタのビット0を確認
do {
status = XUartLite_ReadReg(UartLite.RegBaseAddress,
XUL_STATUS_REG_OFFSET);
} while (!(status & XUL_SR_RX_FIFO_VALID_DATA));
// 受信データを取得
rx = XUartLite_ReadReg(UartLite.RegBaseAddress,
XUL_RX_FIFO_OFFSET);
printf("RX %c\n",rx);
}
cleanup_platform();
return 0;
}
VitisのRun Configurations->Target Setupを見ると、プログラム実行前にbitstreamが自動的にロードされるようなので、正しいbitstreamが設定されているかを確認してからプログラムを実行する必要があります。
Vivado/Vitisv2020.1で試した場合、なんとなく電源導入後しばらくはUARTの動作が安定しないような気がする(基板が温まると安定するような気がする)ので、何かタイミング制約を追加する必要があるのかもしれません。Vivado/XilinxSDK v2017.2の方がUARTの動作が安定しているような気もします。