STM32 SPI Example (feat. Winbond W25Q16JVIM spi flash)

This post shows a few user cases of utilizing the spi flash W25Q16JVIM with STM32. The tests are verified on the NUCELO-F446RE development board.


Initialization and Read ID of the flash

I start with the normal mode of the flash, which is the standard SPI mode 0. The flash is connect to SPI2 of the MCU, the corresponding pinout is:

MCU Flash
PB10 SCK
PC1 MOSI
PC2 MISO
PC3 ~CS

The CubeMX will initialise the SPI interface of the MCU, and we only need to implement functions to manipulate the flash. In my case, the functions are implemented in a separate w25q_flash.h and w25q_flash.c file.

Initially I implement the following functions:

#include "w25q_flash.h"

extern SPI_HandleTypeDef hspi2;

/**
 * @brief Send data to the flash.
 * 
 * @param data 
 * @param size 
 */
void W25Q_Write(uint8_t *data, uint16_t size)
{
    HAL_SPI_Transmit(&hspi2, data, size, 1000); // Send the data
}

/**
 * @brief Read data from the flash.
 * 
 * @param data 
 * @param size 
 */
void W25Q_Read(uint8_t *data, uint16_t size)
{
    HAL_SPI_Receive(&hspi2, data, size, 1000); // Receive the data
}


/**
 * @brief Reset the flash to the initial power-on state.
 * 
 */
void W25Q_Reset(void)
{
    W25Q_CMDTypeDef cmd[2];

    cmd[0] = ENABLE_RESET;
    cmd[1] = RESET_DEVICE;

    W25Q_FLASH_CS_LOW();

    W25Q_Write((uint8_t*)cmd, sizeof(cmd)); // Send the command to enable reset

    W25Q_FLASH_CS_HIGH();

    HAL_Delay(1); // Wait for the reset to complete
}

/**
 * @brief Read JEDEC ID from the flash.
 * 
 * @return W25Q_IDTypeDef 
 */
W25Q_IDTypeDef W25Q_ReadID(void)
{
    W25Q_IDTypeDef id;
    W25Q_CMDTypeDef cmd = JEDEC_ID;

    W25Q_FLASH_CS_LOW(); // CS low

    W25Q_Write((uint8_t*)&cmd, sizeof(cmd)); // Send the command to read ID

    W25Q_Read((uint8_t*)&id, sizeof(id)); // Read the ID
    
    W25Q_FLASH_CS_HIGH(); // CS high

    return id;
}

Back to the main.c file, after calling the function to reset the chip and read the JEDEC id of the chip, and using UART to send back the read id to the serial monitor, I get the expected result of 0xEF7015 as the JEDEC ID of my flash chip.