How to create a driver to handle External flash memory using SPI?
This article will guide you through creating the necessary driver code to interface a STM32 with an external SPI flash memory. As an example, we will store audio files in the external flash. You can refer to this previous article on how to playback the audio file using a STM32 MCU.
When we want audio files to be programmed in an external SPI Flash memory and have them played back by an STM32 microcontroller, we need to first establish access to the external SPI memory. To do so, we need to implement a driver for SPI flash memory. Here, we will explain how to create this driver using a pair of source and header files.
The hardware and software components used in this example are:
STM32CubeIDE (latest version 1.9.0)
NUCLEO-G071RB - our STM32 board
STM32CubeG0 - STM32Cube MCU HAL firmware Package for STM32G0 (version 1.4.0)
W25Q64JV - 64Mbit Serial Flash Memory
W25Q64JV Datasheet – Datasheet of W25Q64JV
Proto Board - To have the W25Q64JV connected to STM32 through some wires
The same steps can be used to create the driver for a different STM32 MCU and/or a different external SPI flash memory.
External SPI Flash memory driver is a piece of code that helps our STM32 microcontroller interact with external memory device through the SPI peripheral.
Before we create the flash driver let us get the SPI peripheral configured on our STM32 microcontroller to communicate with the Flash memory.
On this Nucleo board, we will use SPI2 peripheral of the STM32G0 to interface with the external memory. Let’s start by creating a new project for the NUCLEO-G071RB – here it is assumed that you already knowhow to create a project using a given board as the default with a quick recap on the steps needed:
- Open the STM32CubeIDE
- Go to File->New->STM32 Project
- Go to the second tab “Board Selector” and type “NUCLEO-G071RB”
- Click on the board and then “Next”
5. Name the project and click Finish
6. When the pop-up message appears, make sure to accept the peripherals with their defaults
Start by making sure your clock is set as 64MHz, this can be done by going to the “Clock Configuration” tab and asserting the value if needed:
Back to the Pinout & Configuration Tab, let’s configure the SPI2 protocol in Full-Duplex Master mode. With the APB bus clock (PCLK) previously configured to 64 MHz, in order to achieve the Baud rate of 2Mbits/sec, we need to divide the frequency by 32, by setting the prescaler to 32. This sets the SPI clock to 2 MHz. Let us set 8-bits for the data size, as our external SPI flash memory supports 8- or 16-bit data transfers.
Pin PA0, PC2 and PC3 are used as SPI2 CLK, SPI2 MISO and SPI2 MOSI. Configure their modes in the GPIO tab under System Core as shown above.
Chip select Configuration:
GPIO pin PC4 is configured as a GPIO Output signal to drive the SPI Flash Chip Select signal.
For this implementation, we will use the setting shown below to split the source and header files under Project Manager > Code Generator:
![1387.png 1387.png](/t5/image/serverpage/image-id/1485i85CE9FD188050C34/image-size/large?v=v2&px=999)
Now, you are all set to generate your project so either use the short cut “Alt+K” or go to Project->Generate CodeThe following SPI2 Initialization code is generated by the STM32Cube IDE :
void MX_SPI2_Init(void)
{
/* USER CODE BEGIN SPI2_Init 0 */
/* USER CODE END SPI2_Init 0 */
/* USER CODE BEGIN SPI2_Init 1 */
/* USER CODE END SPI2_Init 1 */
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_MASTER;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH;
hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 7;
hspi2.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi2.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
if (HAL_SPI_Init(&hspi2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI2_Init 2 */
/* USER CODE END SPI2_Init 2 */
}
We will now proceed to create the following SPI flash driver functions to enable access to the external SPI flash memory.