cstm32spicortex-mcmsis

Winbond W25Q and STM32F411 Blackpill - SPI not respond


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


Solution

  • 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!