Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- pwm
- LED
- test bench
- Recursion
- ATMEGA128A
- KEYPAD
- gpio
- FND
- ring counter
- Algorithm
- verilog
- behavioral modeling
- java
- dataflow modeling
- prescaling
- soc 설계
- Edge Detector
- BASYS3
- structural modeling
- hc-sr04
- atmega 128a
- Linked List
- half adder
- Pspice
- DHT11
- D Flip Flop
- i2c 통신
- uart 통신
- stop watch
- vivado
Archives
- Today
- Total
거북이처럼 천천히
xspi_slave_intr_example.c 분석 본문
1. xspi_slave_intr_example.c
/******************************************************************************
*
* Copyright (C) 2008 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
* @file xspi_slave_intr_example.c
*
*
* This file contains a design example using the Spi driver (XSpi) and the Spi
* device as a Slave, in interrupt mode.
*
* This example fills the Spi Tx buffer with the number of data bytes it expects
* to receive from the master and then Spi device waits for an external master to
* initiate the transfer. When the master initiates the transfer, the Spi device
* receives data from the master and simultaneously sends the data in Tx buffer
* to the master. Once the transfer is complete, a transfer complete interrupt is
* generated and this example prints the data received from the master. The
* number of bytes to be received by the Spi slave is defined by the constant
* BUFFER_SIZE in this file.
*
* The external SPI devices that are present on the Xilinx boards don't support
* the Master functionality. This example has been tested with Aardvark I2C/SPI
* Host Adapter, an off board external SPI Master device and the Xilinx SPI
* device configured as a Slave. This example has been tested for byte-wide SPI
* transfers.
*
* @note
*
* This example assumes that there is a STDIO device in the system.
*
*<pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- ---------------------------------------------------------
* 1.00a psk 09/05/08 First Release
* 3.00a ktn 10/22/09 Converted all register accesses to 32 bit access.
* Updated to use the HAL APIs/macros. Replaced call to
* XSpi_Initialize API with XSpi_LookupConfig and
* XSpi_CfgInitialize.
* 3.01a sdm 04/23/10 Enabled DTR Half_empty interrupt so that Tx FIFO is
* not empty during a transfer in slave mode.
* 4.2 ms 01/23/17 Added xil_printf statement in main function to
* ensure that "Successfully ran" and "Failed" strings
* are available in all examples. This is a fix for
* CR-965028.
*
*</pre>
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* XPAR parameters */
#include "xspi.h" /* SPI device driver */
#include "xintc.h" /* Interrupt controller devive driver */
#include "stdio.h"
#include "xil_exception.h"
#include "xil_printf.h"
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
#define SPI_IRPT_INTR XPAR_INTC_0_SPI_0_VEC_ID
/*
* This is the size of the buffer to be transmitted/received in this example.
*/
#define BUFFER_SIZE 32
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int SpiSlaveIntrExample(XSpi *SpiInstancePtr, u16 SpiDeviceId);
static int SetupInterruptSystem(XSpi *SpiInstance);
static void SpiHandler(void *CallBackRef, u32 StatusEvent,
unsigned int ByteCount);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they are
* initialized to zero each time the program runs. They could be local but
* should at least be static so that they are zeroed.
*/
static XSpi SpiInstance; /* Instance of the SPI device */
static XIntc IntcInstance; /* Instance of the Interrupt controller device */
/*
* The following variables are used to read/write from the Spi device, these
* are global to avoid having large buffers on the stack.
*/
u8 ReadBuffer[BUFFER_SIZE];
u8 WriteBuffer[BUFFER_SIZE];
/*
* The following variable allows a test value to be added to the values that
* are sent in reflection to the Master transmission such that unique values can
* be generated to guarantee the transfer from Slave to Master is successful.
*/
int Test;
/*
* The following variables are shared between non-interrupt processing and
* interrupt processing such that they must be global.
*/
static volatile int TransferInProgress;
/*****************************************************************************/
/**
*
* Main function to call the Spi Slave example in interrupt mode.
*
* @param None
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main(void)
{
int Status;
/*
* Run the Spi Slave interrupt example.
*/
Status = SpiSlaveIntrExample(&SpiInstance, SPI_DEVICE_ID);
if (Status != XST_SUCCESS) {
xil_printf("Spi slave interrupt Example Failed\r\n");
return XST_FAILURE;
}
xil_printf("Successfully ran Spi slave interrupt Example\r\n");
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function does a minimal test on the Spi device and driver as a design
* example. The purpose of this function is to illustrate the device slave
* functionality in interrupt mode. This function receives data from a master and
* prints the received data.
*
* @param SpiInstancePtr is a pointer to the instance of Spi component.
* @param SpiDeviceId is the Device ID of the Spi Device and is the
* XPAR_<SPI_instance>_DEVICE_ID value from xparameters.h.
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note This function contains an infinite loop such that if the Spi
* device doesn't receive any data or if the interrupts are not
* working, it may never return.
*
******************************************************************************/
static int SpiSlaveIntrExample(XSpi *SpiInstancePtr, u16 SpiDeviceId)
{
XSpi_Config *ConfigPtr;
int Status;
u32 Count;
xil_printf("\r\nEntering the Spi Slave Interrupt Example.\r\n");
xil_printf("Waiting for data from SPI master\r\n");
/*
* Initialize the SPI driver so that it's ready to use, specify the
* device ID that is generated in xparameters.h.
*/
ConfigPtr = XSpi_LookupConfig(SpiDeviceId);
if (ConfigPtr == NULL) {
return XST_FAILURE;
}
Status = XSpi_CfgInitialize(SpiInstancePtr, ConfigPtr,
ConfigPtr->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect the SPI driver to the interrupt subsystem such that
* interrupts can occur. This function is application specific.
*/
Status = SetupInterruptSystem(SpiInstancePtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup the handler for the SPI that will be called from the interrupt
* context when an SPI status occurs, specify a pointer to the SPI
* driver instance as the callback reference so the handler is able to
* access the instance data.
*/
XSpi_SetStatusHandler(SpiInstancePtr,SpiInstancePtr,(XSpi_StatusHandler)
SpiHandler);
/*
* The SPI device is a slave by default and the clock phase and polarity
* have to be set according to its master. In this example, CPOL is set
* to active low and CPHA is set to 1.
*/
Status = XSpi_SetOptions(SpiInstancePtr, XSP_CLK_PHASE_1_OPTION |
XSP_CLK_ACTIVE_LOW_OPTION);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the SPI driver so that the device is enabled.
*/
XSpi_Start(SpiInstancePtr);
/*
* Enable the DTR half-empty interrupt while transfering more than
* FIFO_DEPTH number of bytes in slave mode, so that the Tx FIFO
* is never empty during a transfer. If the Tx FIFO is empty during
* a transfer, it results in master receiving invalid data.
*/
XSpi_IntrEnable(SpiInstancePtr, XSP_INTR_TX_HALF_EMPTY_MASK);
/*
* Initialize the write buffer with pattern to write, initialize the
* read buffer to zero so it can be verified after the read.
*/
Test = 0x50;
for (Count = 0; Count < BUFFER_SIZE; Count++) {
WriteBuffer[Count] = (u8)(Count + Test);
ReadBuffer[Count] = 0;
}
/*
* Transmit data as a slave, when the master starts sending data.
*/
TransferInProgress = TRUE;
Status = XSpi_Transfer(SpiInstancePtr, WriteBuffer, ReadBuffer,
BUFFER_SIZE);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the transfer is complete.
*/
while (TransferInProgress == TRUE);
/*
* Print all the data received from the master.
*/
xil_printf("\r\nReceived data is:\r\n");
for (Count = 0; Count < BUFFER_SIZE; Count++) {
xil_printf("0x%x \r\n", ReadBuffer[Count]);
}
xil_printf("\r\nExiting the Spi Slave Interrupt Example.\r\n");
return XST_SUCCESS;
}
/****************************************************************************/
/**
*
* This function setups the interrupt system such that interrupts can occur
* for the SPI driver. This function is application specific since the actual
* system may or may not have an interrupt controller. The SPI device could
* be directly connected to a processor without an interrupt controller. The
* user should modify this function to fit the application.
*
* @param SpiInstance contains a pointer to the instance of the XSpi
* component which is going to be connected to the interrupt
* controller.
*
* @return XST_SUCCESS if successful, else XST_FAILURE.
*
* @note None.
*
****************************************************************************/
static int SetupInterruptSystem(XSpi *SpiInstance)
{
int Status;
/*
* Initialize the interrupt controller driver so that it's ready to use,
* specify the device ID that is generated in "xparameters.h".
*/
Status = XIntc_Initialize(&IntcInstance, INTC_DEVICE_ID);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect a device driver handler that will be called when an interrupt
* for the device occurs, the device driver handler performs the
* specific interrupt processing for the device.
*/
Status = XIntc_Connect(&IntcInstance,
SPI_IRPT_INTR,
(XInterruptHandler)XSpi_InterruptHandler,
(void *)SpiInstance);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the interrupt controller such that interrupts are enabled for
* all devices that cause interrupts, specific real mode so that the SPI
* can cause interrupts through the interrupt controller.
*/
Status = XIntc_Start(&IntcInstance, XIN_REAL_MODE);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Enable the interrupt for the Spi device.
*/
XIntc_Enable(&IntcInstance, SPI_IRPT_INTR);
/*
* Initialize the exception table.
*/
Xil_ExceptionInit();
/*
* Register the interrupt controller handler with the exception table.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XIntc_InterruptHandler,
&IntcInstance);
/*
* Enable non-critical exceptions.
*/
Xil_ExceptionEnable();
return XST_SUCCESS;
}
/******************************************************************************/
/**
*
* This function is the handler which performs processing for the SPI driver. It
* is called from an interrupt context such that the amount of processing to be
* performed should be minimized. This handler provides an example of how to
* handle SPI interrupts but is application specific.
*
* @param CallBackRef is a reference passed to the handler.
* @param StatusEvent is the status of the SPI.
* @param ByteCount is the number of bytes transferred.
*
* @return None.
*
* @note None.
*
******************************************************************************/
static void SpiHandler(void *CallBackRef, u32 StatusEvent,
unsigned int ByteCount)
{
if (StatusEvent == XST_SPI_TRANSFER_DONE) {
/*
* Indicate the transfer on the SPI bus is no longer in
* progress.
*/
TransferInProgress = FALSE;
}
}
2. 각각의 변수의 역활 및 의미
2.1) SPI_DEVICE_ID (=XPAR_SPI_0_DEVICE_ID)
#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
- FPGA 시스템에서 SPI 모듈을 식별하기 위한 SPI 모듈 식별자
2.2) ConfigPtr
XSpi_Config *ConfigPtr;
ConfigPtr = XSpi_LookupConfig(SpiDeviceId);
- SPI 모듈에 대한 정보를 담고 있는 XSpi_Config 자료형 포인터 변수
- 해당 포인터 변수를 통해 SPI 모듈을 제어할 수 있는 포인터 변수를 획득에 사용
3. 각 함수의 역활
3.1) XSpi_LookupConfig
/*
* Initialize the SPI driver so that it's ready to use, specify the
* device ID that is generated in xparameters.h.
*/
ConfigPtr = XSpi_LookupConfig(SpiDeviceId);
if (ConfigPtr == NULL) {
return XST_FAILURE;
}
- XSpi_LookupConfig 함수는 argument로 전달 받은 SPI Device ID를 토대로 해당 SPI 모듈에 대한 정보를 조회하여 해당 SPI 모듈에 대한 정보를 XSpi_Config 자료형 포인터 변수로 반환한다.
- 이렇게 반환받은 XSpi_Config 형 포인터 변수인 ConfigPtr은 SPI 모듈을 제어하는 XSpi 객체 인스턴스를 초기화하는 작업에 사용된다.
3.2) XSpi_CfgInitialize
Status = XSpi_CfgInitialize(SpiInstancePtr, ConfigPtr,
ConfigPtr->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
- SPI 모듈의 정보를 담고 있는 포인터 변수인 ConfigPtr와 XSpi_CfgInitialize 함수를 활용하여 SPI 모듈을 제어하는 XSpi 객체의 포인터 변수인 SpiInstancePtr를 획득할 수 있다.
3.3) XSpi_SetStatusHandler
/*
* Setup the handler for the SPI that will be called from the interrupt
* context when an SPI status occurs, specify a pointer to the SPI
* driver instance as the callback reference so the handler is able to
* access the instance data.*/
XSpi_SetStatusHandler(SpiInstancePtr,SpiInstancePtr,(XSpi_StatusHandler)
SpiHandler);
- SPI 장치가 Slave 모드 입장에서 Master으로부터 데이터를 송신 완료되었을 때, 발생하는 Interrupt를 처리하기 위한 Interrupt Handler를 등록하는 과정이다.
3.4) XSpi_SetOptions
/*
* The SPI device is a slave by default and the clock phase and polarity
* have to be set according to its master. In this example, CPOL is set
* to active low and CPHA is set to 1. */
Status = XSpi_SetOptions(SpiInstancePtr, XSP_CLK_PHASE_1_OPTION |
XSP_CLK_ACTIVE_LOW_OPTION);
if (Status != XST_SUCCESS) {
return XST_FAILURE; }
- XSpi_SetOptions 함수는 SPI 모듈의 동작 조건을 설정하는 역할을 합니다.
- 이 코드에서 수행하는 작업은 다음과 같습니다:
- SPI 동작 모드 설정:
- SPI 통신에서 클럭의 위상(CPHA)와 극성(CPOL)은 데이터 송수신 시 중요한 요소입니다. 이 설정은 마스터 장치의 클럭 신호에 맞춰 슬레이브 장치가 올바르게 동작할 수 있도록 합니다.
- 이 코드에서는:
- XSP_CLK_ACTIVE_LOW_OPTION: 클럭 극성을 Active Low로 설정합니다. 즉, 클럭 신호가 LOW일 때 유효하다는 의미입니다.
- XSP_CLK_PHASE_1_OPTION: 클럭 위상을 1로 설정합니다. 이는 클럭의 첫 번째 엣지(즉, 상승 또는 하강 엣지)에 데이터가 유효하다는 것을 의미합니다.
3.5) XSpi_IntrEnable
/*
* Enable the DTR half-empty interrupt while transfering more than
* FIFO_DEPTH number of bytes in slave mode, so that the Tx FIFO
* is never empty during a transfer. If the Tx FIFO is empty during
* a transfer, it results in master receiving invalid data.
*/
XSpi_IntrEnable(SpiInstancePtr, XSP_INTR_TX_HALF_EMPTY_MASK);
- Slave SPI 모듈의 Interrupt를 활성화시켜주는 동시에 Slave SPI 모듈의 Interrupt 발생 시점을 정의하는 과정이다.
- Interrupt 발생 시점은 두 번째 Parameter를 통해 정의할 수 있다.
'FPGA 정리 > Xilinx SDK Example 분석' 카테고리의 다른 글
xuartlite_intr_example.c 분석 (0) | 2025.01.15 |
---|---|
xintc_example.c 분석 (0) | 2025.01.15 |