Files
DS_Library_Docs/docs/DS_W25X40CL.md
T
2026-06-27 00:39:04 +03:00

7.3 KiB

Драйвер внешней Flash-памяти DS_W25X40CL

Низкоуровневая библиотека на Си для работы с энергонезависимой NOR Flash-памятью Winbond W25X40CL (объем 4 Мбит / 512 Килобайт) по интерфейсу SPI. Память разбита на 8 блоков, 128 секторов по 4 КБ и 2048 страниц по 256 байт.

📌 Особенности реализации

  • Блочная очистка и запись: Реализована поддержка постраничной записи (Page Program, до 256 байт) и посекторного стирания (Sector Erase, 4 КБ), что является обязательным требованием для NOR Flash архитектуры.
  • Контроль занятости (Busy Checking): Функции записи и стирания автоматически опрашивают первый регистр статуса памяти (Status Register 1, бит BUSY), блокируя выполнение до тех пор, пока чип физически не завершит операцию во внутренней памяти.
  • Идентификация чипа: Наличие функции чтения JEDEC ID позволяет программно проверить подлинность микросхемы и успешность подключения по шине SPI при старте системы.

🚀 Способ добавления в проект (Git Submodule)

Драйвер подключается к вашему текущему проекту как подмодуль Git, изолируя код управления памятью от прикладной логики.

1. Подключение подмодуля

Выполните команду в корневом каталоге вашего проекта:

git submodule add https://domstudent.ru Library/DS_W25X40CL

2. Автоматическое обновление CMake

Запустите PowerShell-скрипт для автоматического добавления путей Inc и файлов Src подмодуля памяти в структуру сборки проекта:

cd tools/
./UpdateCMakeList.ps1

🔌 Схема подключения (SPI)

Интерфейс SPI настраивается в CubeMX в режиме Full-Duplex Master (или Transmit Only, если чтение не требуется, но для памяти чтение обязательно), Data Size: 8 Bits, First Bit: MSB First. Режим SPI: CPOL = Low (0), CPHA = 1 Edge (0) (SPI Mode 0) или CPOL = High, CPHA = 2 Edge (SPI Mode 3).

Вывод микросхемы W25X40CL Вывод STM32 Назначение
/CS (Pin 1) Любой GPIO_Output Выбор чипа (Chip Select, активен в 0)
DO (IO1) (Pin 2) SPIx_MISO Выход данных (Master Input Slave Output)
/WP (Pin 3) 3.3V или GPIO Защита от записи (Write Protect, притянуть к 3.3В)
GND (Pin 4) GND Общая земля
DI (IO0) (Pin 5) SPIx_MOSI Вход данных (Master Output Slave Input)
CLK (Pin 6) SPIx_SCK Тактовая линия шины SPI
/HOLD (Pin 7) 3.3V или GPIO Удержание шины (Hold, притянуть к 3.3В)
VCC (Pin 8) 3.3V Питание микросхемы (2.3V — 3.6V)

💻 Пример использования в main.c

Помните специфику NOR Flash: перед записью данных в любую область памяти, этот сектор обязательно нужно стереть, иначе новые данные логически смешаются со старыми.

#include "DS_W25X40CL.h"

extern SPI_HandleTypeDef hspi1;
DS_W25X40CL external_flash;

uint8_t write_buffer[256];
uint8_t read_buffer[256];

int main(void) {
    // ... Автоматическая инициализация HAL, GPIO, SPI ...

    /* 1. Инициализация дескриптора памяти */
    DS_W25X40CL_Init(&external_flash, &hspi1, GPIOA, GPIO_PIN_4);

    /* 2. Проверка связи с чипом (Чтение Manufacturer и Device ID) */
    uint32_t jedec_id = DS_W25X40CL_ReadID(&external_flash);
    if (jedec_id == 0xEF3013) { // 0xEF - Winbond, 0x3013 - W25X40CL
        // Память успешно опознана контроллером!
    }

    /* 3. Запись и чтение данных (Пример работы с Сектором 0, Адрес 0x000000) */
    // Подготовка тестовых данных
    for(uint16_t i=0; i<256; i++) write_buffer[i] = i;

    // ШАГ A: Стираем сектор (4 КБ) перед записью
    DS_W25X40CL_EraseSector(&external_flash, 0x000000);

    // ШАГ Б: Записываем страницу памяти (макс 256 байт)
    DS_W25X40CL_WritePage(&external_flash, 0x000000, write_buffer, 256);

    // ШАГ В: Считываем данные обратно для проверки
    DS_W25X40CL_ReadData(&external_flash, 0x000000, read_buffer, 256);

    while (1) {
        // Основной цикл
    }
}

📋 Справочник API функций

void DS_W25X40CL_Init(DS_W25X40CL *flash, SPI_HandleTypeDef *hspi, GPIO_TypeDef *CS_Port, uint16_t CS_Pin)

Выполняет логическую инициализацию структуры драйвера, привязывает к ней шину SPI и программный пин управления защелкой /CS.

uint32_t DS_W25X40CL_ReadID(DS_W25X40CL *flash)

Отправляет команду 0x9F (Read JEDEC ID) и вычитывает 3 байта ответа. Возвращает упакованное 24-битное число, содержащее ID производителя и емкость чипа.

void DS_W25X40CL_EraseSector(DS_W25X40CL *flash, uint32_t SectorAddress)

Отправляет команду разрешения записи 0x06 (Write Enable), затем команду стирания сектора 0x20 и его 24-битный адрес. Ожидает окончания процесса стирания через опрос регистра статуса.

void DS_W25X40CL_WritePage(DS_W25X40CL *flash, uint32_t PageAddress, uint8_t *pData, uint16_t Size)

Записывает массив данных размером до 256 байт в пределах одной физической страницы памяти (команда 0x02). Автоматически контролирует бит готовности чипа.

void DS_W25X40CL_ReadData(DS_W25X40CL *flash, uint32_t Address, uint8_t *pData, uint16_t Size)

Выполняет непрерывное чтение данных любого объема, начиная с указанного 24-битного адреса памяти (команда 0x03). Автоматически инкрементирует адрес на стороне чипа во время удержания линии /CS.