cancel
Showing results for 
Search instead for 
Did you mean: 

QSPI not responding anymore on STM32F746G-DISCO

Otavio Borges
Associate III

I am trying to communicate with the QSPI memory on the discovery board STM32F746G-DISCO. I was able to properly read the memory ID (through instruction 0x9E) once. After that any read attempt on the flash memory returned 0xFF, I've tried reading the ID again, nonvolatile conf. register.

I used a oscilloscope to check the signals to the memory and all seemed to be fine, CS, CLK and DQ0. But couldn't see any activity on DQ1 (I was using single data lines, so DQ1 = SO).

QUADSPI internal flags in SR seems to be working as expected, but no data is reaching the MCU.

Am I missing any configuration on the peripheral to justify such behaviour?

I have attached some of my code below:

#define EXMEM_QSPI_FUNC_MODE_IND_WRITE	0
#define EXMEM_QSPI_FUNC_MODE_IND_READ	0x01
#define EXMEM_QSPI_FUNC_MODE_AUT_POOL	0x02
#define EXMEM_QSPI_FUNC_MODE_MEM_MAP	0x03
 
#define EXMEM_QSPI_DATA_NONE			0
#define EXMEM_QSPI_DATA_ONE				0x01
#define EXMEM_QSPI_DATA_DUAL			0x02
#define EXMEM_QSPI_DATA_QUAD			0x03
 
#define EXMEM_QSPI_LENGTH			0x01000000	// Total QSPI size 16MB
 
typedef enum{
	EXMEM_COMMAND_FLAGS_DDR					= 0x08,
	EXMEM_COMMAND_FLAGS_DDR_QUARTER_HOLD	= 0x04,
	EXMEM_COMMAND_FLAGS_INSTR_ONCE			= 0x01
}exmem_command_flags_t;
 
typedef struct{
	uint8_t instruction;
	uint32_t address;
 
	uint8_t flags;
	uint8_t dummyCycles;
 
	uint8_t dataMode;
	uint8_t functionalMode;
 
	uint8_t alternateMode;
	uint8_t alternateSize;
	uint8_t alternateBytes[4];
 
	uint8_t addressMode;
	uint8_t addressSize;
 
	uint8_t instructionMode;
}exmem_command_t;
 
typedef struct{
	uint8_t poolingMatchOR;
	uint8_t automaticPoolStop;
	uint32_t poolingMask;
	uint32_t poolingMatch;
	uint32_t interval;
}exmem_match_t;

result_t EXMEM_QSPIInit(void){
	// QSPI pins: NCS: PB6 ,CLK: PB2 ,D0: PD11 ,D1: PD12 ,D2: PE2 ,D3: PD13
	RCC->AHB1ENR |= (RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIODEN | RCC_AHB1ENR_GPIOEEN);
 
	PORT_Reset(GPIOB, EXMEM_QSPI_GPIOB_MASK);
	PORT_Reset(GPIOD, EXMEM_QSPI_GPIOD_MASK);
	GPIO_Reset(GPIOE, 2);
 
	GPIO_SetAF(GPIOB, 2, 9, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_VERY_HIGH, GPIO_PULL_NO_PULL);
	GPIO_SetAF(GPIOB, 6, 10, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_VERY_HIGH, GPIO_PULL_PULL_UP);
 
	PORT_SetAF(GPIOD, EXMEM_QSPI_GPIOD_MASK, 9, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_VERY_HIGH, GPIO_PULL_NO_PULL);
	GPIO_SetAF(GPIOD, 12, 9, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_VERY_HIGH, GPIO_PULL_NO_PULL);
	GPIO_SetAF(GPIOE, 2, 9, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_VERY_HIGH, GPIO_PULL_NO_PULL);
 
	RCC->AHB3ENR |= RCC_AHB3ENR_QSPIEN;
 
	QUADSPI->CR = ((2 << QUADSPI_CR_PRESCALER_Pos) | QUADSPI_CR_SSHIFT);
	QUADSPI->DCR = ((23 << QUADSPI_DCR_FSIZE_Pos) | (2 << QUADSPI_DCR_CSHT_Pos));
	QUADSPI->CR |= QUADSPI_CR_EN;
 
	// Config DMA (DMA2, Stream 7 Channel 3)
	RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;
 
	return RESULT_OK;
}
result_t EXMEM_QSPICommand(exmem_command_t command, uint32_t dataToTransfer, uint8_t *buffer){
	uint32_t ccrValue = 0;
 
	if(UTIL_WaitOrTimeout(EXMEM_BUSY_TIMEOUT, &(QUADSPI->SR), QUADSPI_SR_BUSY, 1) != DELAY_WAIT_OK)
		return RESULT_TIMEOUT;
 
	if(command.dataMode){
		// Init and configure the DMA transfer
		if(buffer){
			DMA2_Stream7->CR = ((3 << DMA_SxCR_CHSEL_Pos) | DMA_SxCR_MBURST_1 | DMA_SxCR_PL | DMA_SxCR_MINC | DMA_SxCR_PFCTRL);
			DMA2_Stream7->NDTR = dataToTransfer;
			DMA2_Stream7->PAR = (uint32_t)(&(QUADSPI->DR));
			DMA2_Stream7->M0AR = (uint32_t)(&(buffer));
 
			DMA2->HIFCR = 0xF400000;
		}
 
		QUADSPI->DLR = dataToTransfer - 1;
		ccrValue |= (((uint32_t)(command.dataMode & 0x03) << 24) | ((uint32_t)(command.dummyCycles & 0x1F) << 18));
	}else{
		QUADSPI->DLR = 0;
	}
 
	if(command.instructionMode){
		ccrValue |= (((uint32_t)(command.instructionMode & 0x03) << 8) | command.instruction);
	}
 
	if(command.alternateMode){
		QUADSPI->ABR = *((uint32_t *)command.alternateBytes);
		ccrValue |= ((uint32_t)(command.alternateSize & 0x03) << 16) | ((uint32_t)(command.alternateSize & 0x03) << 14);
	}
 
	if(command.addressMode){
		QUADSPI->AR = command.address;
		ccrValue |= (((uint32_t)(command.addressSize & 0x03) << 12) | ((uint32_t)(command.addressMode & 0x03) << 10));
	}
 
	QUADSPI->FCR = 0x1B;
	ccrValue |= (((uint32_t)(command.flags & 0x0D) << 28) | ((uint32_t)(command.functionalMode & 0x03) << 26));
	QUADSPI->CCR = ccrValue;
 
	if(command.dataMode == EXMEM_QSPI_DATA_NONE){
		if(UTIL_WaitOrTimeout(EXMEM_BUSY_TIMEOUT, &(QUADSPI->SR), QUADSPI_SR_TCF, 0) != DELAY_WAIT_OK)
			return RESULT_TIMEOUT;
 
		QUADSPI->FCR = QUADSPI_FCR_CTCF;
	}else{
		// init DMA if configured
		if(buffer){
			DMA2_Stream7->CR |= DMA_SxCR_EN;
			// wait for transfer to be done
			if(UTIL_WaitOrTimeout(EXMEM_BUSY_TIMEOUT, &(DMA2->HISR), 0xF400000, 0) != DELAY_WAIT_OK)
				return RESULT_TIMEOUT;
 
			if((DMA2->HISR & 0x3400000)){
				// error flag raised
				DMA2->HIFCR = 0xF400000;
				return RESULT_ERROR;
			}else{
				DMA2->HIFCR = 0xF400000;
				return RESULT_OK;
			}
		}
	}
 
	return RESULT_OK;
}
result_t EXMEM_QSPIConfig(void){
	result_t opResult;
	exmem_command_t com;
	exmem_match_t match;
 
	uint32_t length;
	uint8_t data[40];
 
	com.flags = 0; // no flags
 
	// no address, no alternate, no dummy cycles
	com.dummyCycles = 0;
	com.dataMode = EXMEM_QSPI_DATA_NONE;
	com.alternateMode = EXMEM_QSPI_DATA_NONE;
	com.addressMode = EXMEM_QSPI_DATA_NONE;
 
	com.functionalMode = EXMEM_QSPI_FUNC_MODE_IND_WRITE;
	com.instructionMode = EXMEM_QSPI_DATA_ONE;
 
//	com.instruction = QSPI_REG_READ_STATUS_REGISTER;
//	com.dataMode = EXMEM_QSPI_DATA_ONE;
//	EXMEM_QSPICommand(com, 20, 1);
//	QSPIReadData(data, &length);
 
//	Test Peripheral with a ID match
	com.functionalMode = EXMEM_QSPI_FUNC_MODE_IND_READ;
	com.dataMode = EXMEM_QSPI_DATA_ONE;
	com.instruction = 0x9E;
	memset(data, 0xAA, 40);
	EXMEM_QSPICommand(com, 20, NULL);
	QSPIReadData(data, &length);
 
	return RESULT_OK;
}

1 REPLY 1

Custom libraries and register level code, probably not going to get any bites on the forum.

If the HAL BSP works you'll need to compare/contrast registers and see what's amiss

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..