I'm writing SPI driver on top of CMSIS for W25Q (25Q64FVSIG) populated on STM32F411 Blackpill board. My problem is that flash memory are not responding to signals via SPI. MCU is configured as master, flash as slave. Clock and MOSI signal are generated, CS is set low. However, I do not observe the answer on MISO, as in picture below.
Pin mapping: (PA4 - CS) (PA5 - SCK) (PA7 - MOSI) (PB4 - MISO)
I suspected problems with the flash chip, but after replacing it with a new one, I observe no improvement. At the same time, I'm looking at the code and waveforms and can't work out what I'm doing wrong. I also don't have anyone by my side to look with me. So I am counting on your help!
Oscilloscope measurement picture - attempt to read JEDEC ID
This is what my driver code looks like:
uint32_t w25_pin_spi_init(void)
{
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
/* setup alternate functions of PA5/PA7/PB4 and output to PA4 (NSS)*/
GPIOA->MODER &= ~GPIO_MODER_MODE4;
GPIOA->MODER &= ~GPIO_MODER_MODE5;
GPIOA->MODER &= ~GPIO_MODER_MODE7;
GPIOB->MODER &= ~GPIO_MODER_MODE4;
GPIOA->MODER |= GPIO_MODER_MODE4_0; //output
GPIOA->MODER |= GPIO_MODER_MODE5_1; //alternate
GPIOA->MODER |= GPIO_MODER_MODE7_1;
GPIOB->MODER |= GPIO_MODER_MODE4_1;
GPIOA->OSPEEDR |= (GPIO_OSPEEDR_OSPEED4_0 | GPIO_OSPEEDR_OSPEED4_1);
/* OTYPER in reset state */
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD5;
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD7;
GPIOB->PUPDR &= ~GPIO_PUPDR_PUPD4;
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD4;
/* pull-up for MISO */
GPIOB->PUPDR |= GPIO_PUPDR_PUPD4_0;
GPIOA->AFR[0] |= (GPIO_AFRL_AFSEL5_0 | GPIO_AFRL_AFSEL5_2);
GPIOA->AFR[0] |= (GPIO_AFRL_AFSEL7_0 | GPIO_AFRL_AFSEL7_2);
GPIOB->AFR[0] |= (GPIO_AFRL_AFSEL4_0 | GPIO_AFRL_AFSEL4_2);
return 0;
}
void w25_CS_enable(void)
{
GPIOA->BSRR |= GPIO_BSRR_BR4;
}
void w25_CS_disable (void)
{
GPIOA->BSRR |= GPIO_BSRR_BS4;
}
uint32_t w25_spi_init(void)
{
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
SPI1->CR1 &= ~SPI_CR1_DFF;
SPI1->CR1 |= (SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0);
SPI1->CR1 |= SPI_CR1_MSTR;
SPI1->CR1 |= SPI_CR1_SSM;
SPI1->CR1 |= SPI_CR1_SSI;
SPI1->CR1 |= SPI_CR1_SPE;
return 0;
}
uint16_t w25_send_receive_data(uint16_t data)
{
while(!(SPI1->SR & SPI_SR_TXE));
SPI1->DR = data;
while(!(SPI1->SR & SPI_SR_RXNE));
return SPI1->DR;
}
And its used this way to read JEDEC ID:
w25_pin_spi_init();
w25_spi_init();
[...]
w25_CS_enable();
w25_send_receive_data(0x9F);
uint16_t manuf = w25_send_receive_data(0x00);
uint16_t mem_type = w25_send_receive_data(0x00);
uint16_t capa = w25_send_receive_data(0x00);
w25_CS_disable();
/WP and /FLASH pins are set up to high by design of board, schematic included below.
STM32F411 Blackpill schematic (flash in bottom left): STM32F411 Blackpill schematic
CodePudding user response:
GPIOA->MODER &= ~GPIO_MODER_MODE4;
GPIOA->MODER &= ~GPIO_MODER_MODE5;
GPIOA->MODER &= ~GPIO_MODER_MODE7;
GPIOB->MODER &= ~GPIO_MODER_MODE4;
three times GPIOA and only one GPIOB. Same when setting. Copy paste error I believe. Check for similar errors in your code.
You should use functions to avoid such problems.
CodePudding user response:
I found the problem. It was that the MISO for flash on my board is connected to pin PA7, not as in the documentation to PB4. I probably have a different version of this board.
Never trust schematics! Check for yourself on a real board!