Files
2026-06-27 00:39:04 +03:00

110 lines
7.3 KiB
Markdown

# Драйвер внешней 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. Подключение подмодуля
Выполните команду в корневом каталоге вашего проекта:
```bash
git submodule add https://domstudent.ru Library/DS_W25X40CL
```
### 2. Автоматическое обновление CMake
Запустите PowerShell-скрипт для автоматического добавления путей `Inc` и файлов `Src` подмодуля памяти в структуру сборки проекта:
```powershell
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: перед записью данных в любую область памяти, этот сектор **обязательно нужно стереть**, иначе новые данные логически смешаются со старыми.
```c
#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`.