FlexSPI issue with one trailing clock and one missing clock

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

FlexSPI issue with one trailing clock and one missing clock

1,141 Views
christoph_fauck
Contributor II

Hi,

we want to use FlexSPI-QSPIB1 to talk to an FPGA and to use DMA. So I configured the FlexSPI and can use CMD_SDR to send a test command.

Then I changed to the LUT command to WRITE_SDR with one MOSI line and found, that there is an issue with the FlexSPI. The Processors reference Manual IMX8MMRM rev 2 tells, that I can fill the txFIFO before and after starting the LUT command.

I found, that the FlexSPI clocks one time and runs into timeout, when

1) I fill the txFIFO after starting FlexSPI_IPCMD_TRG(1)

2) Starting FlexSPI_IPCMD_TRG(1) and don't fill the txFIFO

with exactly the same behavior on the QSPI interface.

Screenshot_20200911_172314.png

Then I changed to start FlexSPI_IPCMD_TRG(1) and then fill  the txFIFO to send two Bytes. But now I get a trailing clock cycle without valid data, then a pause and then 15 additional clocks with proper data (I filled the txFIFO with 0x12345678) but missing last clock.

It seems, that FlexSPI generates a wrong trailing clock and therefore suppress the last data clock.

Screenshot_20200911_172419.png

Since the content of the reference manual seems to be wrong in some things, could you help me please to remove the trailing clock, please.

Thanks and regards
Christoph

Here please find my test code:

#include "halQSpi.h"
#include "fsl_iomuxc.h"
#include "fsl_gpio.h"

#include "MIMX8MM6_cm4.h"

#include "fsl_debug_console.h"

u32_t halQSpiModuleFreq( void )
{
	u32_t u32_pllFreq 			= CLOCK_GetPllFreq( kCLOCK_SystemPll1Ctrl );
	u32_t u32_rootPreDivider	= CLOCK_GetRootPreDivider ( kCLOCK_RootQspi );
	u32_t u32_rootPostDivider	= CLOCK_GetRootPostDivider( kCLOCK_RootQspi );
	
	return u32_pllFreq / 2 / u32_rootPreDivider / u32_rootPostDivider;
}

static inline u32_t halQspiSetReg( u32_t u32_reg, u32_t u32_mask, u32_t  u32_val )
{
	u32_reg &= ~u32_mask;
	u32_reg |=  u32_val;
	
	return u32_reg;
}

static inline u32_t halQspiFlashStartAddrB1( void )
{
	u32_t u32_startAddr = 0;
	
	u32_startAddr += (u32_t)FLEXSPI->FLSHCR0[0] & FlexSPI_FLSHCR0_FLSHSZ_MASK;
	u32_startAddr += (u32_t)FLEXSPI->FLSHCR0[1] & FlexSPI_FLSHCR0_FLSHSZ_MASK;
	
	return u32_startAddr * 1024;
}

void halQSpiPrintLut( void )
{
	// Unlock LUT
	FLEXSPI->LUTKEY		= FlexSPI_LUTKEY_KEY( 0x5AF05AF0 );
	FLEXSPI->LUTCR		= FlexSPI_LUTCR_UNLOCK( 1 );

	// Print LUT
	PRINTF( "	LUT[0]    0x%08x\r\n", (u32_t)FLEXSPI->LUT[0] );                                 
	PRINTF( "	LUT[1]    0x%08x\r\n", (u32_t)FLEXSPI->LUT[1] );                                 
	PRINTF( "	LUT[2]    0x%08x\r\n", (u32_t)FLEXSPI->LUT[2] );                                 
	PRINTF( "	LUT[3]    0x%08x\r\n", (u32_t)FLEXSPI->LUT[3] );                                 
	PRINTF( "	LUT[4]    0x%08x\r\n", (u32_t)FLEXSPI->LUT[4] );                                 
	PRINTF( "	LUT[5]    0x%08x\r\n", (u32_t)FLEXSPI->LUT[5] );                                 
	PRINTF( "	LUT[6]    0x%08x\r\n", (u32_t)FLEXSPI->LUT[6] );                                 
	PRINTF( "	LUT[7]    0x%08x\r\n", (u32_t)FLEXSPI->LUT[7] );                                 
	
	// Lock lut
	FLEXSPI->LUTKEY		= FlexSPI_LUTKEY_KEY( 0x5AF05AF0 );
	FLEXSPI->LUTCR		= FlexSPI_LUTCR_LOCK( 1 );
}

void halQSpiPrintReg( void )
{
	PRINTF( "Debug FlexSPI register:\r\n" );
	
	PRINTF( "	MCR0        0x%08x\r\n", (u32_t)FLEXSPI->MCR0 );                                 
	PRINTF( "	MCR1        0x%08x\r\n", (u32_t)FLEXSPI->MCR1 );                                 
	PRINTF( "	MCR2        0x%08x\r\n", (u32_t)FLEXSPI->MCR2 );                                 
	PRINTF( "	AHBCR       0x%08x\r\n", (u32_t)FLEXSPI->AHBCR );                                 
	PRINTF( "	INTEN       0x%08x\r\n", (u32_t)FLEXSPI->INTEN );                                 
// 	PRINTF( "	INTR        0x%08x\r\n", (u32_t)FLEXSPI->INTR );                                 
// 	PRINTF( "	LUTKEY      0x%08x\r\n", (u32_t)FLEXSPI->LUTKEY );                                 
	PRINTF( "	LUTCR       0x%08x\r\n", (u32_t)FLEXSPI->LUTCR );                                 
// 	PRINTF( "	AHBRXBUFCR0 0x%08x\r\n", (u32_t)FLEXSPI->AHBRXBUFCR0 ); 
// 	
	PRINTF( "	FLSHCR0[0]  0x%08x\r\n", (u32_t)FLEXSPI->FLSHCR0[0] );                                 
	PRINTF( "	FLSHCR0[1]  0x%08x\r\n", (u32_t)FLEXSPI->FLSHCR0[1] );                                 
	PRINTF( "	FLSHCR0[2]  0x%08x\r\n", (u32_t)FLEXSPI->FLSHCR0[2] );                                 
	PRINTF( "	FLSHCR0[3]  0x%08x\r\n", (u32_t)FLEXSPI->FLSHCR0[3] );
	                        
	PRINTF( "	FLSHCR1[0]  0x%08x\r\n", (u32_t)FLEXSPI->FLSHCR1[0] );                                 
	PRINTF( "	FLSHCR1[1]  0x%08x\r\n", (u32_t)FLEXSPI->FLSHCR1[1] );                                 
	PRINTF( "	FLSHCR1[2]  0x%08x\r\n", (u32_t)FLEXSPI->FLSHCR1[2] );                                 
	PRINTF( "	FLSHCR1[3]  0x%08x\r\n", (u32_t)FLEXSPI->FLSHCR1[3] ); 
	                        
// 	PRINTF( "	FLSHCR2[0]  0x%08x\r\n", (u32_t)FLEXSPI->FLSHCR2[0] );                                 
// 	PRINTF( "	FLSHCR2[1]  0x%08x\r\n", (u32_t)FLEXSPI->FLSHCR2[1] );                                 
// 	PRINTF( "	FLSHCR2[2]  0x%08x\r\n", (u32_t)FLEXSPI->FLSHCR2[2] );                                 
// 	PRINTF( "	FLSHCR2[3]  0x%08x\r\n", (u32_t)FLEXSPI->FLSHCR2[3] ); 
// 	                        
// 	PRINTF( "	FLSHCR4     0x%08x\r\n", (u32_t)FLEXSPI->FLSHCR4 );                                 
	PRINTF( "	IPCR0       0x%08x\r\n", (u32_t)FLEXSPI->IPCR0 );                                 
	PRINTF( "	IPCR1       0x%08x\r\n", (u32_t)FLEXSPI->IPCR1 );                                 
// 	PRINTF( "	IPCMD       0x%08x\r\n", (u32_t)FLEXSPI->IPCMD );                                 
// 	PRINTF( "	DLPR        0x%08x\r\n", (u32_t)FLEXSPI->DLPR );                                 
// 	PRINTF( "	IPRXFCR     0x%08x\r\n", (u32_t)FLEXSPI->IPRXFCR );                                 
	PRINTF( "	IPTXFCR     0x%08x\r\n", (u32_t)FLEXSPI->IPTXFCR );                                 
// 	PRINTF( "	DLLCR[0]    0x%08x\r\n", (u32_t)FLEXSPI->DLLCR[0] );                                 
// 	PRINTF( "	DLLCR[1]    0x%08x\r\n", (u32_t)FLEXSPI->DLLCR[1] );                                 
// 	PRINTF( "	STS0        0x%08x\r\n", (u32_t)FLEXSPI->STS0 );                                 
// 	PRINTF( "	STS1        0x%08x\r\n", (u32_t)FLEXSPI->STS1 );                                 
// 	PRINTF( "	STS2        0x%08x\r\n", (u32_t)FLEXSPI->STS2 );                                 
// 	PRINTF( "	AHBSPNDSTS  0x%08x\r\n", (u32_t)FLEXSPI->AHBSPNDSTS );                                 
// 	PRINTF( "	IPRXFSTS    0x%08x\r\n", (u32_t)FLEXSPI->IPRXFSTS );                                 
// 	PRINTF( "	IPTXFSTS    0x%08x\r\n", (u32_t)FLEXSPI->IPTXFSTS ); 
	
// 	halQSpiPrintLut();
}

void halQSpiPrintStatus( void )
{
	u32_t u32_regVal;
	
	PRINTF( "FlexSPI status register:\r\n" );
	
	PRINTF( "	STS0        0x%08x\r\n", (u32_t)FLEXSPI->STS0 );                                 
	PRINTF( "	STS1        0x%08x\r\n", (u32_t)FLEXSPI->STS1 );                                 
// 	PRINTF( "	STS2        0x%08x\r\n", (u32_t)FLEXSPI->STS2 );  
	
	// *******************************************************************
	// IPCMDERRCODE - Indicates the Error Code when IP command Error detected. This field will be
	// cleared when INTR[IPCMDERR] is write-1-clear(w1c).
	// *******************************************************************
	PRINTF( "	STS1 - IPCMDERRCODE: " );
	
	u32_regVal = ( FLEXSPI->STS1 & FlexSPI_STS1_IPCMDERRCODE_MASK ) >> FlexSPI_STS1_IPCMDERRCODE_SHIFT;
	
	switch ( u32_regVal )
	{
		case 0b0000: PRINTF( "No error.\r\n" );																		break;
		case 0b0010: PRINTF( "IP command with JMP_ON_CS instruction used in the sequence.\r\n" );						break;
		case 0b0011: PRINTF( "There is unknown instruction opcode in the sequence.\r\n" );								break;
		case 0b0100: PRINTF( "Instruction DUMMY_SDR/DUMMY_RWDS_SDR used in DDR sequence.\r\n" );						break;
		case 0b0101: PRINTF( "Instruction DUMMY_DDR/DUMMY_RWDS_DDR used in SDR sequence.\r\n" );						break;
		case 0b0110: PRINTF( "Flash access start address exceed the whole flash address range (A1/A2/B1/B2).\r\n" );	break;
		case 0b1110: PRINTF( "Sequence execution timeout.\r\n" );														break;
		case 0b1111: PRINTF( "Flash boundary crossed.\r\n" );															break;
	}
	
	// *******************************************************************
	// Indicates the sequence Index when IPmmand Error detected. This field will be
	// INTR[IPCMDERR] is write-1-clear(w1c).
	// *******************************************************************
	
	u32_regVal = ( FLEXSPI->STS1 & FlexSPI_STS1_IPCMDERRID_MASK ) >> FlexSPI_STS1_IPCMDERRID_SHIFT;
	
	PRINTF( "	STS1 - IPCMDERRID:   %d\r\n", u32_regVal );
	
}

void halQSpiPrintFlashSizes( void )
{
	PRINTF( "Debug FlexSPI flash sizes:\r\n" );
	
	PRINTF( "	flashSize A1        0x%08x kByte\r\n", (u32_t)FLEXSPI->FLSHCR0[0] & FlexSPI_FLSHCR0_FLSHSZ_MASK );                                 
	PRINTF( "	flashSize A2        0x%08x kByte\r\n", (u32_t)FLEXSPI->FLSHCR0[1] & FlexSPI_FLSHCR0_FLSHSZ_MASK );                                 
	PRINTF( "	flashSize B1        0x%08x kByte\r\n", (u32_t)FLEXSPI->FLSHCR0[2] & FlexSPI_FLSHCR0_FLSHSZ_MASK );                                 
	PRINTF( "	flashSize B2        0x%08x kByte\r\n", (u32_t)FLEXSPI->FLSHCR0[3] & FlexSPI_FLSHCR0_FLSHSZ_MASK );                                 

	PRINTF( "	flashStartAddr B1   0x%08x\r\n", halQspiFlashStartAddrB1() );                                 
}

bool halQSpiInit( void )
{
	// *******************************************************************
	// Select and enable clock
	// *******************************************************************
// 	CLOCK_SetRootMux( kCLOCK_RootIpg, kCLOCK_QspiRootmuxSysPll1Div8 );
	
	CLOCK_SetRootMux( kCLOCK_RootQspi, kCLOCK_QspiRootmuxSysPll1Div8 );
	CLOCK_SetRootDivider( kCLOCK_RootQspi, 1U, 2U );
	
//     CLOCK_EnableClock( kCLOCK_AhbClk );
//     CLOCK_EnableClock( kCLOCK_IpgClk );
    CLOCK_EnableClock( kCLOCK_Qspi );
	
	// *******************************************************************
	// Init QSPI_A pins
	// *******************************************************************
	IOMUXC_SetPinMux( IOMUXC_NAND_ALE_QSPI_A_SCLK,     0U );
	IOMUXC_SetPinMux( IOMUXC_NAND_CE0_B_QSPI_A_SS0_B,  0U );
	IOMUXC_SetPinMux( IOMUXC_NAND_DATA00_QSPI_A_DATA0, 0U );
	IOMUXC_SetPinMux( IOMUXC_NAND_DATA01_QSPI_A_DATA1, 0U );
	IOMUXC_SetPinMux( IOMUXC_NAND_DATA02_QSPI_A_DATA2, 0U );
	IOMUXC_SetPinMux( IOMUXC_NAND_DATA03_QSPI_A_DATA3, 0U );
	
	// *******************************************************************
	// Init QSPI
	// *******************************************************************
	{
		// MCR0
		FLEXSPI->MCR0 = halQspiSetReg( FLEXSPI->MCR0, FlexSPI_MCR0_MDIS_MASK,							FlexSPI_MCR0_MDIS( 1 ) );
		                                                                                				
		FLEXSPI->MCR0 = halQspiSetReg( FLEXSPI->MCR0, FlexSPI_MCR0_LEARNEN_MASK,						FlexSPI_MCR0_LEARNEN( 0 ) );
		
		FLEXSPI->MCR0 = halQspiSetReg( FLEXSPI->MCR0, FlexSPI_MCR0_SCKFREERUNEN_MASK,					FlexSPI_MCR0_SCKFREERUNEN( 0 ) );
// 		FLEXSPI->MCR0 = halQspiSetReg( FLEXSPI->MCR0, FlexSPI_MCR0_SCKFREERUNEN_MASK,					FlexSPI_MCR0_SCKFREERUNEN( 1 ) );
		
		FLEXSPI->MCR0 = halQspiSetReg( FLEXSPI->MCR0, FlexSPI_MCR0_COMBINATIONEN_MASK,					FlexSPI_MCR0_COMBINATIONEN( 0 ) );
		FLEXSPI->MCR0 = halQspiSetReg( FLEXSPI->MCR0, FlexSPI_MCR0_DOZEEN_MASK,							FlexSPI_MCR0_DOZEEN( 0 ) );
		
// 		FLEXSPI->MCR0 = halQspiSetReg( FLEXSPI->MCR0, FlexSPI_MCR0_HSEN_MASK,							FlexSPI_MCR0_HSEN( 0 ) );
		FLEXSPI->MCR0 = halQspiSetReg( FLEXSPI->MCR0, FlexSPI_MCR0_HSEN_MASK,							FlexSPI_MCR0_HSEN( 1 ) );
		
		FLEXSPI->MCR0 = halQspiSetReg( FLEXSPI->MCR0, FlexSPI_MCR0_SERCLKDIV_MASK,						FlexSPI_MCR0_SERCLKDIV( 4 ) );
		                                                                                    			
		FLEXSPI->MCR0 = halQspiSetReg( FLEXSPI->MCR0, FlexSPI_MCR0_ATDFEN_MASK,							FlexSPI_MCR0_ATDFEN( 0 ) );
		FLEXSPI->MCR0 = halQspiSetReg( FLEXSPI->MCR0, FlexSPI_MCR0_ARDFEN_MASK,							FlexSPI_MCR0_ARDFEN( 0 ) );
		FLEXSPI->MCR0 = halQspiSetReg( FLEXSPI->MCR0, FlexSPI_MCR0_RXCLKSRC_MASK,						FlexSPI_MCR0_RXCLKSRC( 0 ) );
		                                                                                    			
		// MCR2                                                                         				
		FLEXSPI->MCR2 = halQspiSetReg( FLEXSPI->MCR2, FlexSPI_MCR2_RESUMEWAIT_MASK,						FlexSPI_MCR2_RESUMEWAIT( 0x20 ) );
		FLEXSPI->MCR2 = halQspiSetReg( FLEXSPI->MCR2, FlexSPI_MCR2_SCKBDIFFOPT_MASK,					FlexSPI_MCR2_SCKBDIFFOPT( 0 ) );
		FLEXSPI->MCR2 = halQspiSetReg( FLEXSPI->MCR2, FlexSPI_MCR2_SAMEDEVICEEN_MASK,					FlexSPI_MCR2_SAMEDEVICEEN( 0 ) );
		FLEXSPI->MCR2 = halQspiSetReg( FLEXSPI->MCR2, FlexSPI_MCR2_CLRAHBBUFOPT_SHIFT,					FlexSPI_MCR2_CLRAHBBUFOPT( 0 ) );
		                                                                                				
		// AHBCR                                                                        				
// 		FLEXSPI->AHBCR = halQspiSetReg( FLEXSPI->AHBCR, FlexSPI_AHBCR_READADDROPT_MASK,					FlexSPI_AHBCR_READADDROPT( 0 ) );
// 		FLEXSPI->AHBCR = halQspiSetReg( FLEXSPI->AHBCR, FlexSPI_AHBCR_PREFETCHEN_MASK,					FlexSPI_AHBCR_PREFETCHEN( 0 ) );
// 		FLEXSPI->AHBCR = halQspiSetReg( FLEXSPI->AHBCR, FlexSPI_AHBCR_BUFFERABLEEN_MASK,				FlexSPI_AHBCR_BUFFERABLEEN( 0 ) );
// 		FLEXSPI->AHBCR = halQspiSetReg( FLEXSPI->AHBCR, FlexSPI_AHBCR_CACHABLEEN_MASK,					FlexSPI_AHBCR_CACHABLEEN( 0 ) );
// 		FLEXSPI->AHBCR = halQspiSetReg( FLEXSPI->AHBCR, FlexSPI_AHBCR_APAREN_MASK,						FlexSPI_AHBCR_APAREN( 0 ) );
		
		// Configure FLSHCRB1
		
		// FLSHCR0, Flash size in kByte                                                                      	
// 		FLEXSPI->FLSHCR0[0] = halQspiSetReg( FLEXSPI->FLSHCR0[0], FlexSPI_FLSHCR0_FLSHSZ_MASK,			FlexSPI_FLSHCR0_FLSHSZ( 8 ) );
// 		FLEXSPI->FLSHCR0[1] = halQspiSetReg( FLEXSPI->FLSHCR0[0], FlexSPI_FLSHCR0_FLSHSZ_MASK,			FlexSPI_FLSHCR0_FLSHSZ( 8 ) );
// 		FLEXSPI->FLSHCR0[2] = halQspiSetReg( FLEXSPI->FLSHCR0[0], FlexSPI_FLSHCR0_FLSHSZ_MASK,			FlexSPI_FLSHCR0_FLSHSZ( 8 ) );
// 		FLEXSPI->FLSHCR0[3] = halQspiSetReg( FLEXSPI->FLSHCR0[0], FlexSPI_FLSHCR0_FLSHSZ_MASK,			FlexSPI_FLSHCR0_FLSHSZ( 8 ) );
		
		// FLSHCR1                                                                       	
		FLEXSPI->FLSHCR1[2] = halQspiSetReg( FLEXSPI->FLSHCR1[0], FlexSPI_FLSHCR1_CSINTERVAL_MASK,		FlexSPI_FLSHCR1_CSINTERVAL( 0 ) );
		FLEXSPI->FLSHCR1[2] = halQspiSetReg( FLEXSPI->FLSHCR1[0], FlexSPI_FLSHCR1_CSINTERVALUNIT_MASK,	FlexSPI_FLSHCR1_CSINTERVALUNIT( 0 ) );
		FLEXSPI->FLSHCR1[2] = halQspiSetReg( FLEXSPI->FLSHCR1[0], FlexSPI_FLSHCR1_CAS_MASK,				FlexSPI_FLSHCR1_CAS( 0 ) );
		FLEXSPI->FLSHCR1[2] = halQspiSetReg( FLEXSPI->FLSHCR1[0], FlexSPI_FLSHCR1_WA_MASK,				FlexSPI_FLSHCR1_WA( 0 ) );
		FLEXSPI->FLSHCR1[2] = halQspiSetReg( FLEXSPI->FLSHCR1[0], FlexSPI_FLSHCR1_TCSH_MASK,			FlexSPI_FLSHCR1_TCSH( 3 ) );
		FLEXSPI->FLSHCR1[2] = halQspiSetReg( FLEXSPI->FLSHCR1[0], FlexSPI_FLSHCR1_TCSS_MASK,			FlexSPI_FLSHCR1_TCSS( 3 ) );
		
		
		// FLSHCR2                                                                       	
// 		FLEXSPI->FLSHCR2[2] = halQspiSetReg( FLEXSPI->FLSHCR2[0], FlexSPI_FLSHCR2_CLRINSTRPTR_MASK,		FlexSPI_FLSHCR2_CLRINSTRPTR( 0 ) );
// 		FLEXSPI->FLSHCR2[2] = halQspiSetReg( FLEXSPI->FLSHCR2[0], FlexSPI_FLSHCR2_AWRWAITUNIT_MASK,		FlexSPI_FLSHCR2_AWRWAITUNIT( 0 ) );
// 		FLEXSPI->FLSHCR2[2] = halQspiSetReg( FLEXSPI->FLSHCR2[0], FlexSPI_FLSHCR2_AWRWAIT_MASK,			FlexSPI_FLSHCR2_AWRWAIT( 0 ) );
// 		FLEXSPI->FLSHCR2[2] = halQspiSetReg( FLEXSPI->FLSHCR2[0], FlexSPI_FLSHCR2_ARDSEQNUM_MASK,		FlexSPI_FLSHCR2_ARDSEQNUM( 0 ) );
// 		FLEXSPI->FLSHCR2[2] = halQspiSetReg( FLEXSPI->FLSHCR2[0], FlexSPI_FLSHCR2_AWRSEQID_MASK,		FlexSPI_FLSHCR2_AWRSEQID( 0 ) );
// 		FLEXSPI->FLSHCR2[2] = halQspiSetReg( FLEXSPI->FLSHCR2[0], FlexSPI_FLSHCR2_ARDSEQNUM_MASK,		FlexSPI_FLSHCR2_ARDSEQNUM( 0 ) );
// 		FLEXSPI->FLSHCR2[2] = halQspiSetReg( FLEXSPI->FLSHCR2[0], FlexSPI_FLSHCR2_ARDSEQID_MASK,		FlexSPI_FLSHCR2_ARDSEQID( 0 ) );
		
		// FLSHCR4
		FLEXSPI->FLSHCR4	 = halQspiSetReg( FLEXSPI->FLSHCR4, FlexSPI_FLSHCR4_WMOPT1_MASK,			FlexSPI_FLSHCR4_WMOPT1( 0 ) );
		FLEXSPI->FLSHCR4	 = halQspiSetReg( FLEXSPI->FLSHCR4, FlexSPI_FLSHCR4_WMENA_MASK,				FlexSPI_FLSHCR4_WMENA( 0 ) );
		FLEXSPI->FLSHCR4	 = halQspiSetReg( FLEXSPI->FLSHCR4, FlexSPI_FLSHCR4_WMENB_MASK,				FlexSPI_FLSHCR4_WMENB( 0 ) );
		
		// Set individual mode
		FLEXSPI->IPCR1		= halQspiSetReg( FLEXSPI->IPCR1, FlexSPI_IPCR1_IPAREN_MASK,					FlexSPI_IPCR1_IPAREN( 0 ) );
		
		// Set sequence. ISEQNUM is the operation count n+1
		FLEXSPI->IPCR1		= halQspiSetReg( FLEXSPI->IPCR1, FlexSPI_IPCR1_ISEQID_MASK,					FlexSPI_IPCR1_ISEQID( 0 ) );
		FLEXSPI->IPCR1		= halQspiSetReg( FLEXSPI->IPCR1, FlexSPI_IPCR1_ISEQNUM_MASK,				FlexSPI_IPCR1_ISEQNUM( 0 ) );
		
		FLEXSPI->IPTXFCR	= halQspiSetReg( FLEXSPI->IPTXFCR, FlexSPI_IPTXFCR_TXDMAEN_MASK,			FlexSPI_IPTXFCR_TXDMAEN( 0 ) );
// 		FLEXSPI->IPTXFCR	= halQspiSetReg( FLEXSPI->IPTXFCR, FlexSPI_IPTXFCR_TXDMAEN_MASK,			FlexSPI_IPTXFCR_TXDMAEN( 1 ) );
	
		// Enable
		FLEXSPI->MCR0 = halQspiSetReg( FLEXSPI->MCR0, FlexSPI_MCR0_MDIS_MASK,							FlexSPI_MCR0_MDIS( 0 ) );
	}
	
	// *******************************************************************
	// Configure LUT after MDIS = 0
	// *******************************************************************
	{
		// Unlock LUT
		FLEXSPI->LUTKEY		= FlexSPI_LUTKEY_KEY( 0x5AF05AF0 );
		FLEXSPI->LUTCR		= FlexSPI_LUTCR_UNLOCK( 1 );
		
		// Setup lut
		{
			u32_t u32_reg;
			
			u32_reg = 0;
			
			// WRITE_SDR on single line
			u32_reg	 = FlexSPI_LUT_OPCODE0( 0x08 )	| FlexSPI_LUT_NUM_PADS0( 0 )	| FlexSPI_LUT_OPERAND0( 0 );
			
			// WRITE_SDR on quad line
// 			u32_reg	 = FlexSPI_LUT_OPCODE0( 0x08 )	| FlexSPI_LUT_NUM_PADS0( 2 )	| FlexSPI_LUT_OPERAND0( 0 );
			
			// CMD_SDR on single line
// 			u32_reg	 = FlexSPI_LUT_OPCODE0( 0x01 )	| FlexSPI_LUT_NUM_PADS0( 2 )	| FlexSPI_LUT_OPERAND0( 0xA5 );
			
			// Stop
			u32_reg	|= FlexSPI_LUT_OPCODE1( 0x00 )	| FlexSPI_LUT_NUM_PADS1( 0 )	| FlexSPI_LUT_OPERAND1( 0 );
			
			FLEXSPI->LUT[0]	= u32_reg;
			
			for ( int i_iterator = 1; i_iterator < FlexSPI_LUT_COUNT; ++i_iterator )
				FLEXSPI->LUT[ i_iterator ]	= 0;
		}
		
		// Lock lut
		FLEXSPI->LUTKEY		= FlexSPI_LUTKEY_KEY( 0x5AF05AF0 );
		FLEXSPI->LUTCR		= FlexSPI_LUTCR_LOCK( 1 );
	}
	
	// *******************************************************************
	// Reset controller at last
	// *******************************************************************
// 	halQSpiPrintReg();

	FLEXSPI->MCR0 = halQspiSetReg( FLEXSPI->MCR0, FlexSPI_MCR0_SWRESET_MASK,		FlexSPI_MCR0_SWRESET( 1 ) );
	
	
// 		halQSpiPrintReg();
// 		halQSpiPrintLut();
	
	return true;
}

void halQSpiTest( void )
{
	// Set watermark to ( n + 1 ) * 64 Bit
	FLEXSPI->IPTXFCR	= halQspiSetReg( FLEXSPI->IPTXFCR, FlexSPI_IPTXFCR_TXWMRK_MASK,			FlexSPI_IPTXFCR_TXWMRK( 0 ) );
	
	// *******************************************************************
	// Clear fifo, MUST be done to delete rest data from previous transfer
	// *******************************************************************
	{
		// Clear fifo
		FLEXSPI->IPTXFCR	= halQspiSetReg( FLEXSPI->IPTXFCR, FlexSPI_IPTXFCR_CLRIPTXF_MASK,	FlexSPI_IPTXFCR_CLRIPTXF( 1 ) );

		// Wait until fifo empty
		while ( ! ( FLEXSPI->INTR & FlexSPI_INTR_IPTXWE_MASK ) );
	}
	
	PRINTF( "	INTR pre0       0x%08x\r\n", (u32_t)FLEXSPI->INTR );  
	
	// *******************************************************************
	// Configure transmit
	// *******************************************************************
	
	// Set flash start address without base address
// 	FLEXSPI->IPCR0		= halQspiSetReg( FLEXSPI->IPCR0, FlexSPI_IPCR0_SFAR_MASK,			FlexSPI_IPCR0_SFAR( halQspiFlashStartAddrB1() ) );	// didn't work
	FLEXSPI->IPCR0		= halQspiSetReg( FLEXSPI->IPCR0, FlexSPI_IPCR0_SFAR_MASK,			FlexSPI_IPCR0_SFAR( 0 ) );
	
	// Read / program data size in Bytes
	FLEXSPI->IPCR1		= halQspiSetReg( FLEXSPI->IPCR1, FlexSPI_IPCR1_IDATSZ_MASK,			FlexSPI_IPCR1_IDATSZ( 2 ) );
		
// 	halQSpiPrintReg();
// 	halQSpiPrintFlashSizes();
	halQSpiPrintStatus();
	
	PRINTF( "	INTR pre1       0x%08x\r\n", (u32_t)FLEXSPI->INTR );  
	
	// *******************************************************************
	// Start transfer
	// *******************************************************************
	FLEXSPI->IPCMD	= FlexSPI_IPCMD_TRG( 1 );
	
	// INTR = 0x040
	PRINTF( "	INTR post        0x%08x\r\n", (u32_t)FLEXSPI->INTR ); 
	
	for ( int i_burst = 0; i_burst < 2; ++i_burst )
	{
		// Wait until fifo empty
		while ( ! ( FLEXSPI->INTR & FlexSPI_INTR_IPTXWE_MASK ) );
	
		// Fill data to tx fifo. 
		for ( int i_iterator = 0; i_iterator < 8; ++i_iterator )
			FLEXSPI->TFDR[ i_iterator ]	= 0x12345678;
	
		// Start transfer
		FLEXSPI->INTR	= FlexSPI_INTR_IPTXWE_MASK;
	}
	
	// *******************************************************************
	// Start transfer - didn't work. One clock cycle, then stopping until timeout
	// *******************************************************************
// 	FLEXSPI->IPCMD	= FlexSPI_IPCMD_TRG( 1 );
	
	for ( int i_iterator = 0; i_iterator < 10; ++i_iterator )
		PRINTF( "	INTR post        0x%08x\r\n", (u32_t)FLEXSPI->INTR );                                 
	
	halQSpiPrintStatus();	
	
	// Wait until ip command is done
// 	while( FLEXSPI->INTR & FlexSPI_INTR_IPCMDDONE_MASK );
}

 

Thanks and regards
Christoph 

Labels (1)
0 Kudos
3 Replies

1,078 Views
christoph_fauck
Contributor II

Hi Jimmy,

I am using SDK 2.8. The FlexSPI works since some days. The processor reference manual is incomplete, the Linux driver is a better reference: https://elixir.bootlin.com/linux/v5.9-rc7/source/drivers/spi/spi-nxp-fspi.c

The only thing which didn't work is the addressing nxp_fspi_select_mem() of the driver.

-Christoph

0 Kudos

1,087 Views
christoph_fauck
Contributor II

Hi Jimmy,

SDK 2.8. But it works since some days with exception of  the address selection. I used the Linux driver from newest Linux kernel as reference.

The main problem was, that I MUST send a command before sending data. Then some other things may also be wrong, I've rearranged like the Linux kernel driver.

Only the Address selection didn't work. The Linux kernel configures all four QSPI chip sizes to zero, then changes the address of the only one which have to be addressed to the chip size and then writes the address the IPCR0 register.

For me I left the FLSHCR 0 - 3 registers untouched and write zero to IPCR0. This currently works.

0 Kudos

1,090 Views
jimmychan
NXP TechSupport
NXP TechSupport

Which version of SDK are you using?

0 Kudos