Files
templates/c/eeprom-ft24c256/ft24c256.h
Andrey Kruchinkin 11bf8b6c11 feat(eeprom-ft24c256): драйвер EEPROM 24Cxx по I2C
Перенесён из KONOR_ds18b20/lib/eeprom; в OpticalTester лежала такая же копия.

Запись режется по границам страниц внутри библиотеки: микросхема
принимает до 64 байт за транзакцию, но при переходе через границу
страницы счётчик адреса заворачивается и затирает уже принятые байты.
Вызывающему коду об этом думать не нужно.
2026-08-23 01:15:12 +03:00

278 lines
14 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @file ft24c256.h
* @brief Портируемый драйвер последовательной EEPROM FT24C256 и её семейства.
*
* Библиотека не привязана к микроконтроллеру: она не включает заголовки
* периферии, не обращается к регистрам и не пользуется прерываниями. Обмен
* идёт через таблицу обратных вызовов FT24C256_Io, которую заполняет порт
* платы (для этой сборки — @c src/eeprom.c поверх I2C1 STM32F103C8T6).
*
* FT24C256 — 32768 байт (256 кбит) с двухбайтовым адресом слова и страницей
* записи 64 байта. Запись выполняется постранично: микросхема принимает до
* 64 байт в одной транзакции, но только внутри страницы — при переходе через
* её границу счётчик адреса заворачивается на начало той же страницы и
* затирает уже принятые байты. Поэтому FT24C256_Write() сама режет запрос по
* границам страниц:
*
* @code
* запись 100 байт с адреса 0x0030
*
* 0x0000 0x0040 0x0080 0x00C0
* | страница 0 | страница 1 | страница 2 |
* +---------------+---------------+---------------+
* [ 16 ][ 64 ][ 20 ]
* 1-я 2-я 3-я транзакция
* @endcode
*
* После каждой транзакции кристалл уходит во внутренний цикл записи (до 5 мс)
* и не отвечает на шину. Готовность определяется опросом подтверждения
* (ACK polling): библиотека шлёт адресный байт без данных, пока микросхема не
* ответит. Порт, который не умеет передавать транзакцию нулевой длины,
* выставляет @c poll_retries в ноль — тогда используется выдержка
* @c write_ms.
*
* Кристалл выбирается тремя адресными выводами A0...A2, поэтому на одной шине
* живут до восьми микросхем с адресами 0x50...0x57. Задавая @c size и
* @c page_size, тем же кодом обслуживаются младшие члены семейства с
* двухбайтовым адресом: FT24C32 (4 КБ, страница 32), FT24C64 (8 КБ, 32),
* FT24C128 (16 КБ, 64), FT24C512 (64 КБ, 128). Микросхемы до FT24C16
* включительно адресуют слово одним байтом и этой библиотекой не
* поддерживаются.
*/
#ifndef FT24C256_H
#define FT24C256_H
#include <stdint.h>
/** Объём FT24C256 в байтах (256 кбит). */
#define FT24C256_SIZE 32768UL
/** Размер страницы записи FT24C256 в байтах. */
#define FT24C256_PAGE_SIZE 64U
/** Предельная страница семейства (FT24C512); задаёт размер буфера транзакции. */
#define FT24C256_PAGE_MAX 128U
/** Базовый адрес на шине при A0 = A1 = A2 = 0. */
#define FT24C256_BASE_ADDRESS 0x50U
/** Число микросхем семейства на одной шине. */
#define FT24C256_MAX_DEVICES 8U
/** Длительность внутреннего цикла записи по даташиту, мс. */
#define FT24C256_WRITE_MS 5U
/** Число опросов подтверждения после записи по умолчанию. */
#define FT24C256_POLL_RETRIES 20U
/** Длина адреса слова в байтах: FT24C32 и старше адресуют двумя байтами. */
#define FT24C256_ADDRESS_SIZE 2U
/**
* @brief Доступ библиотеки к шине I2C.
*
* Обязательны @c write и @c write_read. Адрес в вызовах — семибитный, без
* бита направления: сдвиг и добавление бита выполняет порт.
*/
typedef struct {
/**
* Передаёт транзакцию «старт, адрес, данные, стоп».
* Вызов с @c size, равным нулю, передаёт один адресный байт и применяется
* для опроса готовности; 1 — микросхема ответила подтверждением.
*/
uint8_t (*write)(void *context, uint8_t address, const uint8_t *data,
uint16_t size);
/**
* Передаёт @c tx_size байт, затем без освобождения шины (повторный старт)
* читает @c rx_size байт; 1 — обмен завершён подтверждениями.
*/
uint8_t (*write_read)(void *context, uint8_t address, const uint8_t *tx,
uint16_t tx_size, uint8_t *rx, uint16_t rx_size);
/** Выдержка в миллисекундах; обязателен, если @c poll_retries равен нулю. */
void (*delay_ms)(void *context, uint32_t milliseconds);
/** Управление выводом WP: 1 — запись запрещена. Допускает значение 0. */
void (*set_write_protect)(void *context, uint8_t enabled);
void *context; /**< Контекст порта, передаётся вызовам без изменений. */
} FT24C256_Io;
/**
* @brief Параметры кристалла.
*
* Нулевые поля заменяются значениями по умолчанию вызовом
* FT24C256_ConfigDefault() или самой FT24C256_Init().
*/
typedef struct {
uint32_t size; /**< Объём в байтах; 0 — @ref FT24C256_SIZE. */
uint16_t page_size; /**< Страница записи; 0 — @ref FT24C256_PAGE_SIZE. */
uint8_t address; /**< Семибитный адрес; 0 — @ref FT24C256_BASE_ADDRESS. */
uint8_t write_ms; /**< Выдержка цикла записи; 0 — @ref FT24C256_WRITE_MS. */
uint8_t poll_retries; /**< Опросов готовности; 0 — только выдержка. */
} FT24C256_Config;
/**
* @brief Состояние кристалла: настройки, обратные вызовы и счётчики обмена.
*/
typedef struct {
FT24C256_Io io; /**< Обратные вызовы порта. */
FT24C256_Config config; /**< Параметры кристалла. */
uint8_t ready; /**< 1, если FT24C256_Init() прошла успешно. */
uint32_t written_bytes; /**< Байтов, отправленных на запись. */
uint32_t read_bytes; /**< Байтов, полученных чтением. */
uint32_t write_errors; /**< Транзакций записи, оставшихся без ответа. */
uint32_t read_errors; /**< Транзакций чтения, оставшихся без ответа. */
} FT24C256;
/**
* @brief Заполняет параметры значениями FT24C256 с адресными выводами на GND.
*
* @param config Параметры, принадлежащие вызывающему коду.
*/
void FT24C256_ConfigDefault(FT24C256_Config *config);
/**
* @brief Готовит кристалл к работе.
*
* Обмена с шиной не выполняет: наличие микросхемы проверяется отдельно
* вызовом FT24C256_IsPresent().
*
* @param device Состояние, принадлежащее вызывающему коду.
* @param io Обратные вызовы порта; копируются внутрь состояния.
* @param config Параметры либо 0 для значений по умолчанию.
* @return 1 при успешной настройке, 0 при неполных аргументах.
*/
uint8_t FT24C256_Init(FT24C256 *device, const FT24C256_Io *io,
const FT24C256_Config *config);
/**
* @brief Проверяет отклик микросхемы на её адрес.
*
* @param device Состояние кристалла.
* @return 1, если получено подтверждение, иначе 0.
*/
uint8_t FT24C256_IsPresent(FT24C256 *device);
/**
* @brief Ожидает завершения внутреннего цикла записи.
*
* При ненулевом @c poll_retries шлёт адресные байты, пока микросхема не
* ответит; иначе выдерживает паузу @c write_ms.
*
* @param device Состояние кристалла.
* @return 1, если микросхема готова, иначе 0.
*/
uint8_t FT24C256_WaitReady(FT24C256 *device);
/**
* @brief Читает произвольное число байтов подряд.
*
* Чтение границами страниц не ограничено: счётчик адреса проходит весь
* массив, поэтому запрос выполняется одной транзакцией.
*
* @param device Состояние кристалла.
* @param address Адрес первого байта.
* @param buffer Приёмник данных.
* @param size Число байтов.
* @return 1 при успехе; 0 при выходе за границы массива или отказе шины.
*/
uint8_t FT24C256_Read(FT24C256 *device, uint32_t address, void *buffer,
uint16_t size);
/**
* @brief Записывает произвольное число байтов, разрезая запрос по страницам.
*
* После каждой страницы выполняется ожидание готовности, поэтому вызов
* блокирующий: запись всего массива занимает около 2.6 с.
*
* @param device Состояние кристалла.
* @param address Адрес первого байта.
* @param data Записываемые данные.
* @param size Число байтов.
* @return 1 при успехе; 0 при выходе за границы массива или отказе шины.
*/
uint8_t FT24C256_Write(FT24C256 *device, uint32_t address, const void *data,
uint16_t size);
/**
* @brief Записывает только те страницы, содержимое которых отличается.
*
* Ресурс кристалла — миллион циклов записи на страницу, поэтому сохранение
* настроек, которые меняются редко, выгоднее вести этой функцией: неизменные
* страницы не переписываются.
*
* @param device Состояние кристалла.
* @param address Адрес первого байта.
* @param data Записываемые данные.
* @param size Число байтов.
* @return 1 при успехе, иначе 0.
*/
uint8_t FT24C256_Update(FT24C256 *device, uint32_t address, const void *data,
uint16_t size);
/**
* @brief Читает один байт.
*
* @param device Состояние кристалла.
* @param address Адрес байта.
* @param value Приёмник значения.
* @return 1 при успехе, иначе 0.
*/
uint8_t FT24C256_ReadByte(FT24C256 *device, uint32_t address, uint8_t *value);
/**
* @brief Записывает один байт.
*
* @param device Состояние кристалла.
* @param address Адрес байта.
* @param value Записываемое значение.
* @return 1 при успехе, иначе 0.
*/
uint8_t FT24C256_WriteByte(FT24C256 *device, uint32_t address, uint8_t value);
/**
* @brief Заполняет область одинаковым значением.
*
* @param device Состояние кристалла.
* @param address Адрес первого байта.
* @param value Записываемое значение.
* @param size Число байтов.
* @return 1 при успехе, иначе 0.
*/
uint8_t FT24C256_Fill(FT24C256 *device, uint32_t address, uint8_t value,
uint32_t size);
/**
* @brief Заполняет весь массив значением 0xFF.
*
* @param device Состояние кристалла.
* @return 1 при успехе, иначе 0.
*/
uint8_t FT24C256_Erase(FT24C256 *device);
/**
* @brief Включает или снимает аппаратную защиту записи выводом WP.
*
* @param device Состояние кристалла.
* @param enabled 1 — запись запрещена, 0 — разрешена.
* @return 1, если порт управляет выводом WP, иначе 0.
*/
uint8_t FT24C256_Protect(FT24C256 *device, uint8_t enabled);
/**
* @brief Возвращает объём кристалла.
*
* @param device Состояние кристалла.
* @return Число байтов; 0 для ненастроенного состояния.
*/
uint32_t FT24C256_Size(const FT24C256 *device);
/**
* @brief Возвращает адрес кристалла на шине для указанных выводов A0...A2.
*
* @param index Значение адресных выводов, 0...7.
* @return Семибитный адрес 0x50...0x57.
*/
uint8_t FT24C256_AddressOf(uint8_t index);
#endif /* FT24C256_H */