/*****************************************************************************
*
* The purpose of this function is to illustrate how to use the XSpiPs
* device driver in interrupt mode. This function writes and reads data
* from a serial FLASH.
*
* @param	None.
*
* @return	XST_SUCCESS if successful else XST_FAILURE.
*
* @note
*
* This function calls other functions which contain loops that may be infinite
* if interrupts are not working such that it may not return. If the device
* slave select is not correct and the device is not responding on bus it will
* read a status of 0xFF for the status register as the bus is pulled up.
*
*****************************************************************************/
int SpiFlashIntrExample(XScuGic *IntcInstancePtr, XSpiPs *SpiInstancePtr,
			 u16 SpiDeviceId, u16 SpiIntrId)
{
	int Status;
	u8 *BufferPtr;
	u8 UniqueValue;
	u32 Count;
	XSpiPs_Config *ConfigPtr;	/* Pointer to Configuration ROM data */
	u32 TempAddress;
	u32 MaxSize = MAX_DATA;
	u32 ChipSelect = FLASH_SPI_SELECT_1;

	if (XGetPlatform_Info() == XPLAT_ZYNQ_ULTRA_MP) {
		MaxSize = 1024 * 10;
		ChipSelect = FLASH_SPI_SELECT_0;	/* Device is on CS 0 */
		SpiIntrId = XPAR_XSPIPS_0_INTR;
	}

	/*
	 * Lookup the device configuration in the temporary CROM table. Use this
	 * configuration info down below when initializing this component.
	 */
	ConfigPtr = XSpiPs_LookupConfig(SpiDeviceId);
	if (ConfigPtr == NULL) {
		return XST_DEVICE_NOT_FOUND;
	}

	XSpiPs_CfgInitialize(SpiInstancePtr, ConfigPtr,
				  ConfigPtr->BaseAddress);

	/* Initialize the XILISF Library */
	XIsf_Initialize(&Isf, SpiInstancePtr, ChipSelect,
                       IsfWriteBuffer);

	XIsf_SetTransferMode(&Isf, XISF_INTERRUPT_MODE);

	/*
	 * Connect the Spi device to the interrupt subsystem such that
	 * interrupts can occur. This function is application specific
	 */
	Status = SpiSetupIntrSystem(IntcInstancePtr, SpiInstancePtr,
				     SpiIntrId);
	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
	 */
	XIsf_SetStatusHandler(&Isf, SpiInstancePtr,
				 (XSpiPs_StatusHandler) SpiHandler);


	memset(WriteBuffer, 0x00, sizeof(WriteBuffer));
	memset(ReadBuffer, 0x00, sizeof(ReadBuffer));

	/* Unprotect Sectors */
	FlashWrite(&Isf, 0, 0, XISF_WRITE_STATUS_REG);

	FlashErase(&Isf, TEST_ADDRESS, MaxSize);

	/*
	 * Initialize the write buffer for a pattern to write to the FLASH
	 * and the read buffer to zero so it can be verified after the read, the
	 * test value that is added to the unique value allows the value to be
	 * changed in a debug environment to guarantee
	 */
	TempAddress = TEST_ADDRESS;
	for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MaxSize;
		 Count++, UniqueValue++, TempAddress++) {
		WriteBuffer[0] = (u8)(UniqueValue);
		FlashWrite(&Isf, TempAddress, 1, XISF_WRITE);
	}

	/*
	 * Read the contents of the FLASH from TEST_ADDRESS, using Normal Read
	 * command
	 */
	FlashRead(&Isf, TEST_ADDRESS, MaxSize, XISF_READ);

	/*
	 * Setup a pointer to the start of the data that was read into the read
	 * buffer and verify the data read is the data that was written
	 */
	BufferPtr = &ReadBuffer[DATA_OFFSET];

	for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MaxSize;
			 Count++, UniqueValue++) {
		if (BufferPtr[Count] != (u8)(UniqueValue)) {
			return XST_FAILURE;
		}
	}

	SpiDisableIntrSystem(IntcInstancePtr, SpiIntrId);
	return XST_SUCCESS;
}
Пример #2
0
/**
*
* This function does a minimal test on the Spi device and driver as a
* design example. The purpose of this function is to illustrate how to use
* the XSpi component using the interrupt mode.
*
* This function sends data and expects to receive the same data.
*
*
* @param	IntcInstancePtr is a pointer to the instance of the INTC
* 		component.
* @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.
* @param	SpiIntrId is the interrupt Id and is typically
*		XPAR_<INTC_instance>_<SPI_instance>_VEC_ID value from
*		xparameters.h .
*
* @return	XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note
*
* This function contains an infinite loop such that if interrupts are not
* working it may never return.
*
******************************************************************************/
int SpiIntrExample(XIntc *IntcInstancePtr, XSpi *SpiInstancePtr,
			u16 SpiDeviceId, u16 SpiIntrId)
{
	int Status;
	u32 Count;
	u8 Test;
	XSpi_Config *ConfigPtr;	/* Pointer to Configuration data */

	/*
	 * Initialize the SPI driver so that it is  ready to use.
	 */
	ConfigPtr = XSpi_LookupConfig(SpiDeviceId);
	if (ConfigPtr == NULL) {
		return XST_DEVICE_NOT_FOUND;
	}

	Status = XSpi_CfgInitialize(SpiInstancePtr, ConfigPtr,
				  ConfigPtr->BaseAddress);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Perform a self-test to ensure that the hardware was built correctly.
	 */
	Status = XSpi_SelfTest(SpiInstancePtr);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Run loopback test only in case of standard SPI mode.
	 */
	if (SpiInstancePtr->SpiMode != XSP_STANDARD_MODE) {
		return XST_SUCCESS;
	}

	/*
	 * Connect the Spi device to the interrupt subsystem such that
	 * interrupts can occur. This function is application specific.
	 */
	Status = SpiSetupIntrSystem(IntcInstancePtr,
					SpiInstancePtr,
				 	SpiIntrId);
	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) SpiIntrHandler);

	/*
	 * Set the Spi device as a master and in loopback mode.
	 */
	Status = XSpi_SetOptions(SpiInstancePtr, XSP_MASTER_OPTION |
 					XSP_LOOPBACK_OPTION);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}


	/*
	 * Start the SPI driver so that interrupts and the device are enabled.
	 */
	XSpi_Start(SpiInstancePtr);

	/*
	 * Initialize the write buffer with pattern to write, initialize the
	 * read buffer to zero so it can be verified after the read, the
	 * Test value that is added to the unique value allows the value to be
	 * changed in a debug environment.
	 */
	Test = 0x10;
	for (Count = 0; Count < BUFFER_SIZE; Count++) {
		WriteBuffer[Count] = (u8)(Count + Test);
		ReadBuffer[Count] = 0;
	}


	/*
	 * Transmit the data.
	 */
	TransferInProgress = TRUE;
	XSpi_Transfer(SpiInstancePtr, WriteBuffer, ReadBuffer, BUFFER_SIZE);

	/*
	 * Wait for the transmission to be complete.
	 */
	while (TransferInProgress);


	/*
	 * Disable the Spi interrupt.
	 */
	SpiDisableIntrSystem(IntcInstancePtr, SpiIntrId);

	/*
	 * Compare the data received with the data that was transmitted.
	 */
	for (Count = 0; Count < BUFFER_SIZE; Count++) {
		if (WriteBuffer[Count] != ReadBuffer[Count]) {
			return XST_FAILURE;
		}
	}

	return XST_SUCCESS;
}
Пример #3
0
int main() {

  xil_printf("Master SPI oRSC echo test\n");

  // initialize stdout.
  init_platform();

  tx_buffer = cbuffer_new();
  rx_buffer = cbuffer_new();

  spi_stream = spi_stream_init(
      tx_buffer, rx_buffer, 
      DoSpiTransfer, // callback which triggers a SPI transfer
      0);

  int Status;
  XSpi_Config *ConfigPtr;	/* Pointer to Configuration data */

  /*
   * Initialize the SPI driver so that it is  ready to use.
   */
  ConfigPtr = XSpi_LookupConfig(SPI_DEVICE_ID);
  if (ConfigPtr == NULL) {
    xil_printf ("Error: could not lookup SPI configuration\n");
    return XST_DEVICE_NOT_FOUND;
  }

  Status = XSpi_CfgInitialize(&SpiInstance, ConfigPtr,
      ConfigPtr->BaseAddress);
  if (Status != XST_SUCCESS) {
    xil_printf("Error: could not initialize the SPI device\n");
    return XST_FAILURE;
  }

  Status = XSpi_SelfTest(&SpiInstance);
  if (Status != XST_SUCCESS) {
    xil_printf("Error: The SPI self test failed.\n");
    return XST_FAILURE;
  }

  /*
   * Connect the Spi device to the interrupt subsystem such that
   * interrupts can occur. This function is application specific.
   */
  Status = SpiSetupIntrSystem(&IntcInstance, &SpiInstance, SPI_IRPT_INTR);
  if (Status != XST_SUCCESS) {
    xil_printf("Error: Could not setup interrupt system.\n");
    return XST_FAILURE;
  }

  /*
   * Set the Spi device as a master.
   */
  Status = XSpi_SetOptions(&SpiInstance, XSP_MASTER_OPTION);
  if (Status != XST_SUCCESS) {
    xil_printf("Error: Could not set as master\n");
    return XST_FAILURE;
  }

  // Go!
  XSpi_Start(&SpiInstance);

  // Note: to disable interrupt, do: XIntc_Disconnect(&IntcInstance,
  // SPI_IRPT_INTR);

  u32 expected_rx = 0;
  u32 current_tx = 0;

  while (1) {
    // fill up the transmit buffer
    while (cbuffer_freespace(tx_buffer)) {
      cbuffer_push_back(tx_buffer, current_tx++);
    }
    // check to make sure the received buffer is what we expect
    while (cbuffer_size(rx_buffer)) {
      u32 front = cbuffer_value_at(rx_buffer, 0);
      if (front != expected_rx) {
        //xil_printf("Error: expected %lx, got %lx!\n", expected_rx, front);
        xil_printf("Error: data value\n");
      }
      expected_rx++;
      cbuffer_deletefront(rx_buffer, 1);
    }
  }

  return 0;
}
/*****************************************************************************
*
* The purpose of this function is to illustrate how to use the XSpiPs
* device driver in interrupt mode . This test writes and reads data from a
* serial EEPROM.
* This part must be present in the hardware to use this example.
*
* @param	IntcInstancePtr is a pointer to the GIC driver to use.
* @param	SpiInstancePtr is a pointer to the SPI driver to use.
* @param	SpiDeviceId is the DeviceId of the Spi device.
* @param	SpiIntrId is the Spi Interrupt Id.
*
* @return	XST_SUCCESS if successful else XST_FAILURE.
*
* @note
*
* This function calls functions which contain loops that may be infinite
* if interrupts are not working such that it may not return. If the device
* slave select is not correct and the device is not responding on bus it will
* read a status of 0xFF for the status register as the bus is pulled up.
*
*****************************************************************************/
int SpiPsEepromIntrExample(XScuGic *IntcInstancePtr, XSpiPs *SpiInstancePtr,
			 u16 SpiDeviceId, u16 SpiIntrId)
{
	int Status;
	u8 *BufferPtr;
	u8 UniqueValue;
	int Count;
	int Page;
	XSpiPs_Config *SpiConfig;

	/*
	 * Initialize the SPI driver so that it's ready to use
	 */
	SpiConfig = XSpiPs_LookupConfig(SpiDeviceId);
	if (NULL == SpiConfig) {
		return XST_FAILURE;
	}

	Status = XSpiPs_CfgInitialize(SpiInstancePtr, SpiConfig,
				       SpiConfig->BaseAddress);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Perform a self-test to check hardware build
	 */
	Status = XSpiPs_SelfTest(SpiInstancePtr);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Connect the Spi device to the interrupt subsystem such that
	 * interrupts can occur. This function is application specific
	 */
	Status = SpiSetupIntrSystem(IntcInstancePtr, SpiInstancePtr, SpiIntrId);
	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
	 */
	XSpiPs_SetStatusHandler(SpiInstancePtr, SpiInstancePtr,
				 (XSpiPs_StatusHandler) SpiHandler);

	/*
	 * Set the Spi device as a master. External loopback is required.
	 */
	XSpiPs_SetOptions(SpiInstancePtr, XSPIPS_MASTER_OPTION |
			   XSPIPS_FORCE_SSELECT_OPTION);

	XSpiPs_SetClkPrescaler(SpiInstancePtr, XSPIPS_CLK_PRESCALE_64);

	/*
	 * Initialize the write buffer for a pattern to write to the EEPROM
	 * and the read buffer to zero so it can be verified after the read, the
	 * test value that is added to the unique value allows the value to be
	 * changed in a debug environment to guarantee
	 */
	for (UniqueValue = 13, Count = 0; Count < MAX_DATA;
					Count++, UniqueValue++) {
		WriteBuffer[WRITE_DATA_OFFSET + Count] =
					(u8)(UniqueValue + Test);
		ReadBuffer[READ_DATA_OFFSET + Count] = 0xA5;
	}

	/*
	 * Assert the EEPROM chip select
	 */
	XSpiPs_SetSlaveSelect(SpiInstancePtr, EEPROM_SPI_SELECT);

	/*
	 * Write the data in the write buffer to the serial EEPROM a page at a
	 * time
	 */
	for (Page = 0; Page < PAGE_COUNT; Page++) {
		EepromWrite(SpiInstancePtr, Page * PAGE_SIZE, PAGE_SIZE,
				&WriteBuffer[Page * PAGE_SIZE]);
	}

	/*
	 * Read the contents of the entire EEPROM from address 0, since this
	 * function reads the entire EEPROM it will take some amount of time to
	 * complete
	 */
	EepromRead(SpiInstancePtr, 0, MAX_DATA, ReadBuffer);

	/*
	 * Setup a pointer to the start of the data that was read into the read
	 * buffer and verify the data read is the data that was written
	 */
	BufferPtr = &ReadBuffer[READ_DATA_OFFSET];

	for (UniqueValue = 13, Count = 0; Count < MAX_DATA;
					Count++, UniqueValue++) {
		if (BufferPtr[Count] != (u8)(UniqueValue + Test)) {
			return XST_FAILURE;
		}
	}

	SpiDisableIntrSystem(IntcInstancePtr, SpiIntrId);
	return XST_SUCCESS;
}