AXI Quad SPI를 사용한 SPI Master (MicroBlaze 편)
14522 단어 FPGAMicroBlazexilinxVivadozynq
개요
FPGA에서 외부 IC와 SPI 통신을 하고 싶은 경우가 많다고 생각합니다.
단순히 제어 레지스터를 설정하는 것과 같은 통신 타이밍을 엄격하게 일정하게 할 필요가없는 경우,
HDL로 SPI 컨트롤러를 직접 만들지 않아도 MicroBlaze와 AXI Quad SPI를 사용하여 소프트웨어로 개발하는 것이 편리합니다.
이번에는 MicroBlaze에 AXI Quad SPI를 연결하고 SPI Master Mode에서 쓰기 및 읽기를 수행하는 방법을 소개합니다.
환경
Block Design 만들기
이 기사 의 디자인을 베이스로 작성해 갑니다.
기본적으로 Interrupt Controller가 연결된 MicroBlaze가 있으면 괜찮습니다.
AXI Quad SPI 추가
AXI Quad SPI를 추가하고 IP 설정은 아래 그림과 같이 했습니다.
SPI는 Master Mode로 동작시키고, 데이터 폭은 8bit로 합니다.
슬레이브는 두 개의 IC를 연결한다고 가정하고 슬레이브 번호를 2로 설정합니다.
SPI 버스는 FPGA 핀으로 직접 출력되며 ip2intc_irpt는 MicroBlaze의 인터럽트 입력에 연결된다.
ext_spi_clk는 100MHz 클럭을 입력합니다.
SCLK의 주파수는 다음 식과 같습니다.
f_{SCLK} = \frac{f_{in}}{D_{Frequency Ratio}} = \frac{100 \rm MHz}{16 \times 1} = 6.25 {\rm MHz}
전반적인 디자인은 다음과 같습니다.
샘플 코드
Hello World 템플릿을 기반으로 만들고 아래 코드를 복사합니다.
#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xintc.h"
#include "xspi.h"
// 送受信バッファサイズ
#define BUFFER_SIZE 32
// デバイスドライバのインスタンス
static XIntc Intc;
static XSpi Spi;
// SPI通信中フラグ
volatile static int TransferInProgress;
// 割り込み処理中に起きたエラーをカウント
int Error;
// SPI送受信バッファ
u8 WriteBuffer[BUFFER_SIZE];
u8 ReadBuffer[BUFFER_SIZE];
// SPI割り込みハンドラ
void SpiHandler(void *CallBackRef, u32 StatusEvent, unsigned int ByteCount)
{
// 通信中フラグを降ろす
TransferInProgress = FALSE;
// 通信完了割り込み以外はエラー
if (StatusEvent != XST_SPI_TRANSFER_DONE) {
Error++;
}
}
int main()
{
int Status;
XSpi_Config *ConfigPtr;
init_platform();
// SPIドライバの初期化
ConfigPtr = XSpi_LookupConfig(XPAR_SPI_0_DEVICE_ID);
if (ConfigPtr == NULL) return XST_DEVICE_NOT_FOUND;
Status = XSpi_CfgInitialize(&Spi, ConfigPtr, ConfigPtr->BaseAddress);
if (Status != XST_SUCCESS) return XST_FAILURE;
// SPIコントローラが正しく動作しているかセルフテストを行う
Status = XSpi_SelfTest(&Spi);
if (Status != XST_SUCCESS) return XST_FAILURE;
// XIntcの初期化
Status = XIntc_Initialize(&Intc, XPAR_INTC_0_DEVICE_ID);
if(Status != XST_SUCCESS) return XST_FAILURE;
// SPIの割り込みハンドラを指定
Status = XIntc_Connect(&Intc, XPAR_INTC_0_SPI_0_VEC_ID,
(XInterruptHandler)XSpi_InterruptHandler,
(void *)&Spi);
if(Status != XST_SUCCESS) return XST_FAILURE;
//XIntcをhardware interrupts onlyで開始
Status = XIntc_Start(&Intc, XIN_REAL_MODE);
if(Status != XST_SUCCESS) return XST_FAILURE;
// SPIの割り込みを有効化
XIntc_Enable(&Intc, XPAR_INTC_0_SPI_0_VEC_ID);
// MicroBlazeの割り込み設定を初期化
Xil_ExceptionInit();
// MicroBlazeにXIntcからの割り込みを登録
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XIntc_InterruptHandler,
&Intc);
// MicroBlazeの割り込みを有効化
Xil_ExceptionEnable();
// SPI割り込みハンドラによって呼び出される関数を指定
XSpi_SetStatusHandler(&Spi, &Spi, (XSpi_StatusHandler)SpiHandler);
// SPI動作モードを設定
// XSP_MASTER_OPTION: マスターモードで動作
// XSP_MANUAL_SSELECT_OPTION: SSピンマニュアル選択
Status = XSpi_SetOptions(&Spi, XSP_MASTER_OPTION |
XSP_MANUAL_SSELECT_OPTION);
if (Status != XST_SUCCESS) return XST_FAILURE;
// スレーブを選択する
Status = XSpi_SetSlaveSelect(&Spi, 1);
if (Status != XST_SUCCESS) return XST_FAILURE;
// SPIドライバをスタートし、デバイスと割り込みを有効にする
XSpi_Start(&Spi);
// 送受信バッファの初期化
for(int i=0; i<BUFFER_SIZE; i++){
WriteBuffer[i] = i+0xA0;
ReadBuffer[i] = 0;
}
// 10回送信する
for(int i=0; i<10; i++){
// 通信中フラグを立てる
TransferInProgress = TRUE;
// 送信開始
XSpi_Transfer(&Spi, WriteBuffer, ReadBuffer, BUFFER_SIZE);
// SPI割り込みが入るまで待つ
while (TransferInProgress);
}
xil_printf("SPI Transfer Finished! (Error Count=%d", Error);
cleanup_platform();
return 0;
}
동작 파형
데이터가 연속으로 전송되었습니다. BUFFER_SIZE분의 길이가 연속으로 전송되고 있습니다.
BlockDesign에서 Transaction Width를 8bit로 설정했기 때문에 하위 8bit에만 데이터가 나오고 있네요.
SPI는 간단한 시프트 레지스터이므로, 상위 24bit분은 넘쳐 사용되지 않기 때문에,
8bit 타입의 SPI에서도 기본적으로는 이 프로토콜에서도 문제 없습니다.
다음으로 전송할 길이를 1로 보았습니다.
전송 종료 후 Chip Select가 올라가고 있는 것을 확인할 수 있습니다.
SCLK의 주파수는 설정대로 6.25MHz입니다.
참고
Reference
이 문제에 관하여(AXI Quad SPI를 사용한 SPI Master (MicroBlaze 편)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/s_nkg/items/a8d96db0767993b1f633텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)