W25Q128J Part Drivers Documentation

This page presents an overview of the W25Q128J Part Drivers.

A detailed API documentation is also available here: W25Q128J Part Drivers API Documentation.

Introduction

The W25Q128J part driver provides APIs to drive the W25Q128J NOR Flash. The implementation uses the HAL.

The W25Q128J is 3.3V (2.7V to 3.6V volts) 128M-bit Serial NOR SPI flash memory organized into 65536 programmable pages of 256-bytes each. Pages can be erased in groups of 256 (64KB block erase).

The W25Q128J provides a continuous read mode that allows for efficient access to the entire memory array with a single read command.

It is rated for more than 100000 erase/program cycles with more than 20 years data retention.

The W25Q128J part driver provides full asynchronous write functionality, including multi-page writes management through the use of an internal asynchronous state machine.

To use this feature, both USE_HAL_SPI_REGISTER_CALLBACKS and USE_HAL_SPI_USER_DATA must be enabled, and the write complete callback may be registered with the w25q128j_register_write_cplt_callback() API.

The state machine starts with the call to w25q128j_write_dma() and stops when all data has been transmitted. At that point, the previously registered callback function will be called.

The function w25q128j_get_async_write_phase() allows to monitor the current transfer phase.

The driver for the W25Q128J comes as an OpenCMSIS pack. The following section describes its usage and the structure of the pack, providing a comprehensive guide to leveraging this high-performance flash memory device in your applications.

Principles

The driver implements all functions in a single component. It uses the HAL SPI.

It abstracts SPI commands through easy-to-use straightforward APIs.

Programming model

Folder structure

The driver’s folder structure is as follows:

w25q128j
  |- w25q128j.c
  |- w25q128j.h

The files w25q128j.c, w25q128j.h constitute the core of the part driver.

Usage and initialization

The main data structure for this driver is the w25q128j_obj_t object structure, which contains all the internal state needed by the driver. The user application never needs to access that structure’s fields directly. However, unlike with HAL drivers, the user application has full ownership of the data structures used by part driver. It is its duty to ensure timely allocation and de-allocation.

The driver has its own interface object structure, w25q128j_io_t to store its own specific state and link to the underlying (HAL) driver being used.

At initialization, the user application must separately initialize the resources used by the part drivers, including the SPI peripheral as the part interface, the system peripherals, and the DMA peripheral (if using the part driver in DMA mode). Optionally, it can rely on STM32CubeMX2-generated code for the initialization of those HAL resources.

The part driver does not enforce the requirements on the resources, but the user application must respect them to ensure proper functionality. After the user application properly initializes all the required resources (HAL instances), it can call the part driver initialization and provide those resources.

Key part driver’s features:

Read/Write operations in polling mode

The W25Q128J part driver provides read and write APIs, which abstract the various commands involved in the process.

w25q128j_write()

The W25Q128J allows only 256 bytes ( equivalent to one page size ) to be programmed at a time which limits the amount of data that can be written in a single transfer to this size. The w25q128j_write() API overcomes this limitation by dynamically writing multiple pages based on the size provided.

w25q128j_read()

The w25q128j_write() API allows one or more data bytes to be read from the memory. The entire memory can be accessed with a single read instruction.

Asynchronous read/write (DMA)

The W25Q128J part driver provides full asynchronous read/write functionality, including multi-page writes management through the use of an internal asynchronous state machine.

To use the asynchronous write feature, both USE_HAL_SPI_REGISTER_CALLBACKS and USE_HAL_SPI_USER_DATA must be enabled, and the write complete callback function must be registered with the w25q128j_register_write_cplt_callback() API. The asynchronous read API can be used with the overriding of the WEAK callback function of the SPI IP, but similar to the asynchronous write, a read callback function can be registered with the help of the w25q128j_register_read_cplt_callback() function if both USE_HAL_SPI_REGISTER_CALLBACKS and USE_HAL_SPI_USER_DATA are enabled.

Asynchronous read (DMA)

The read state machine starts with the call to w25q128j_read_dma() and stops when all data has been received. At that point, if USE_HAL_SPI_REGISTER_CALLBACKS and USE_HAL_SPI_USER_DATA are enabled and the callback function is registered, it will be called. The state of the transfer can be checked with the help of the blocking w25q128j_get_async_read_phase() function, it can be one of the values defined in the enumeration below

typedef enum
{
  W25Q128J_ASYNC_READ_IDLE = 0,      /*!<  Idle state - No ongoing transfer */
  W25Q128J_ASYNC_READING             /*!<  Read transfer ongoing            */
} w25q128j_async_read_phase_t;

Asynchronous write (DMA)

The write state machine starts with the call to w25q128j_write_dma() and stops when all data has been transmitted. At that point, the application calls the previously registered callback function.

The state of the transfer can be checked with the help of the blocking w25q128j_get_async_write_phase() function, it can be one of the values defined in the enumeration below:

typedef enum
{
  W25Q128J_ASYNC_WRITE_IDLE = 0,      /*!< Idle state - No ongoing transfer                                 */
  W25Q128J_ASYNC_WEL,                 /*!< Send the write enable cmd                                        */
  W25Q128J_ASYNC_WRITE_CMD,           /*!< Send the write page cmd                                          */
  W25Q128J_ASYNC_WRITE_DATA           /*!< Send data to write                                               */
} w25q128j_async_write_phase_t;

For a graphical presentation of this feature refer to the sequence diagram titled “Use Case: Using the w25q128j part drivers to write data with DMA which demonstrates the async write sequence” under the “Sequence Diagram” below.

Resources configuration

The application project must override w25q128j_io_init() to initialize part drivers instances. w25q128j_init() calls this function during the driver initialization step.

The function uses an ID stored in the w25q128j_io_t structure to discriminate the configuration that will be used.

The following constraints apply to the HAL resources used by the part driver:

For the SPI Instance:

  • The mode set to MASTER.

  • The direction set to FULL DUPLEX.

  • The data width set to 8 BIT.

  • The first bit set to MSB.

  • The NSS pin management set to INTERNAL, as it is handled by the part driver through GPIO.

For the GPIO Pin:

  • The mode set as OUTPUT.

  • The speed set as VERY_HIGH.

Sequence Diagram

The diagram below presents a simple use case for this driver.

simple use case for this driver

simple use case for this driver

Dependencies

The diagram below presents the partitioning of this driver into components.

partitioning of this driver into components

This components’ structure translates to the following inclusion graph in terms of C code:

inclusion graph of this driver