cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
JEJA_Adimec
Visitor
Visitor
291 Views
Registered: ‎11-09-2020

Zync Ultrascale+ MPSoc XSpiPs_SelfTest fails with XST_REGISTER_ERROR on XSPIPS_CR_OFFSET for SPI0

Jump to solution

Hi All,

We have enabled the SPI0 periperial for the Zynq Ultrascale+ MPSoc in Vivado 2018.1 and using EMIO for pin routing. Also the HDF file is loaded into the Xilinx SDK 2018.1 and the xparameters.h are correctly generated. Upon calling XSpiPs_SelfTest it returns XST_REGISTER_ERROR for the XSPIPS_CR_OFFSET. The register reads 0x00000000 and expects XSPIPS_CR_RESET_STATE 0x00020000U.

See https://github.com/Xilinx/embeddedsw/blob/master/XilinxProcessorIPLib/drivers/spips/src/xspips_selftest.c#L89-L94 

This is a snippet from the generated xparameters.h:

/* Canonical definitions for peripheral PSU_SPI_0 */
#define XPAR_XSPIPS_0_DEVICE_ID XPAR_PSU_SPI_0_DEVICE_ID
#define XPAR_XSPIPS_0_BASEADDR 0xFF040000
#define XPAR_XSPIPS_0_HIGHADDR 0xFF04FFFF
#define XPAR_XSPIPS_0_SPI_CLK_FREQ_HZ 200000000

This is our SPI initialize which wraps the XSpiPs functions:

int32_t _SPI_Initialize(void)
{
	s32 Status;
	XSpiPs_Config *cfg;

	cfg = XSpiPs_LookupConfig(XPAR_XSPIPS_0_DEVICE_ID);
	if (cfg == NULL) {
		return 1;
	}

	Status = XSpiPs_CfgInitialize(&SpiInstance, cfg, cfg->BaseAddress);
	if (Status != XST_SUCCESS) {
		return 2;
	}

	Status = XSpiPs_SelfTest(&SpiInstance);
	if (Status != XST_SUCCESS) {
		xil_printf("SPI SelfTest: %d\n", Status);
		return 3;
	}

	Status = XSpiPs_SetOptions(&SpiInstance, XSPIPS_MASTER_OPTION | XSPIPS_FORCE_SSELECT_OPTION);
	if (Status != XST_SUCCESS) {
		return 4;
	}

	Status = XSpiPs_SetClkPrescaler(&SpiInstance, XSPIPS_CLK_PRESCALE_8);
	if (Status != XST_SUCCESS) {
		return 5;
	}
	return 0;
}

 

0 Kudos
1 Solution

Accepted Solutions
JEJA_Adimec
Visitor
Visitor
189 Views
Registered: ‎11-09-2020

I have found the problem, the Ultrascale+ project uses multiboot using the FSBL (first stage bootloader). When loading the hdf file a new psu_init.c is generated which is only included and executed from the FSBL. When flashing the fresh FSBL I was able to pass the selftest and also read the module ID registers of both enabled SPI0 and SPI1 peripherials.

Using the XSCT Console from the debug view gets the correct result:

xsct% mrd 0xff0500fc
FF0500FC:   00090108

xsct% mrd 0xff0400fc
FF0400FC:   00090108

View solution in original post

0 Kudos
3 Replies
JEJA_Adimec
Visitor
Visitor
274 Views
Registered: ‎11-09-2020

I also tried to extend the selftest to read the Mod_id register at 0xFF0400FC  which should contain value 0x00090108. It seems also to read 0x00000000

 

 

 

	Register = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress,
				 0xFC); // Mod_id
	xil_printf("Mod_id(0x%08x): 0x%08x\n", InstancePtr->Config.BaseAddress + 0xFC, Register);
	if (Register != 0x00090108) {
		return (s32)XST_REGISTER_ERROR;
	}
Mod_id(0xFF0400FC): 0x00000000

 

Also i tried the Slave_Idle_count but it also reads 0x00000000

See also register sheet https://www.xilinx.com/html_docs/registers/ug1087/mod___spi.html

0 Kudos
JEJA_Adimec
Visitor
Visitor
238 Views
Registered: ‎11-09-2020

I have also checked the SPI0 reference clock is enabled in the generated psu_init:

    /*
    * Register : SPI0_REF_CTRL @ 0XFF5E007C

    * Clock active signal. Switch to 0 to disable the clock
    *  PSU_CRL_APB_SPI0_REF_CTRL_CLKACT                            0x1

    * 6 bit divider
    *  PSU_CRL_APB_SPI0_REF_CTRL_DIVISOR1                          0x1

    * 6 bit divider
    *  PSU_CRL_APB_SPI0_REF_CTRL_DIVISOR0                          0xf

    * 000 = IOPLL; 010 = RPLL; 011 = DPLL; (This signal may only be toggled af
    * ter 4 cycles of the old clock and 4 cycles of the new clock. This is not
    *  usually an issue, but designers must be aware.)
    *  PSU_CRL_APB_SPI0_REF_CTRL_SRCSEL                            0x0

    * This register controls this reference clock
    * (OFFSET, MASK, VALUE)      (0XFF5E007C, 0x013F3F07U ,0x01010F00U)
    */
	PSU_Mask_Write(CRL_APB_SPI0_REF_CTRL_OFFSET,
		0x013F3F07U, 0x01010F00U);
0 Kudos
JEJA_Adimec
Visitor
Visitor
190 Views
Registered: ‎11-09-2020

I have found the problem, the Ultrascale+ project uses multiboot using the FSBL (first stage bootloader). When loading the hdf file a new psu_init.c is generated which is only included and executed from the FSBL. When flashing the fresh FSBL I was able to pass the selftest and also read the module ID registers of both enabled SPI0 and SPI1 peripherials.

Using the XSCT Console from the debug view gets the correct result:

xsct% mrd 0xff0500fc
FF0500FC:   00090108

xsct% mrd 0xff0400fc
FF0400FC:   00090108

View solution in original post

0 Kudos