Перейти на компактные 12-словные записи v4 и сохранять 10 процентов банка после отключения. Добавить трёхсекундное ожидание роста ЗПТ и настраиваемый лимит пусков. Явно инициализировать состояние UART и гарантировать публикацию параметров EEPROM перед запуском Timer2. Сохранить воспроизводимые сборки, регрессионные проверки, документацию и обновлённые результаты сборки; исключить временные артефакты.
195 lines
14 KiB
C
195 lines
14 KiB
C
/* Драйвер SPI EEPROM, адресация, страницы и автомат завершения операций. Русские пояснения сохранены в UTF-8. */
|
||
/* Начинает условие: __SPISE2P_H__ ещё не определён; защищает повторное включение или задаёт значение сборки. */
|
||
#ifndef __SPISE2P_H__
|
||
|
||
/* Определяет защитный символ или переключатель __SPISE2P_H__ для последующей компиляции. */
|
||
#define __SPISE2P_H__
|
||
|
||
/* Physical EEPROM layout shared with the linker and SETGUI. */
|
||
/* Подключает "eeprom_config.h": выбор профиля физически установленной EEPROM при сборке. */
|
||
#include "eeprom_config.h"
|
||
/* Подключает "include/balsam167_eeprom_layout.h": настройки и интерфейс balsam167_eeprom_layout. */
|
||
#include "include/balsam167_eeprom_layout.h"
|
||
|
||
// Ёмкость памати в байтах
|
||
/* Preserve compact 16-bit arithmetic for the original 32-KiB build.
|
||
* Only the large part needs 32-bit word addresses and transfer lengths. */
|
||
/* Условие компиляции EEPROM_M95M02: выбранный блок включается в текущий вариант прошивки. */
|
||
#if EEPROM_M95M02
|
||
/* Начинает объявление типа, используемого структурами и интерфейсами этого модуля. */
|
||
typedef unsigned long SE2P_SIZE;
|
||
/* Выбирает альтернативный блок текущего условия компиляции. */
|
||
#else
|
||
/* Начинает объявление типа, используемого структурами и интерфейсами этого модуля. */
|
||
typedef unsigned int SE2P_SIZE;
|
||
/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */
|
||
#endif
|
||
/* Задаёт SEEPROM_LEN = BALSAM167_EEPROM_BYTES; данные SEEPROM_LEN. */
|
||
#define SEEPROM_LEN BALSAM167_EEPROM_BYTES
|
||
|
||
/* Задаёт NULL = 0; данные NULL. */
|
||
#define NULL 0
|
||
|
||
/* Задаёт SIXTEEN_BIT = 15; SIXTEEN бит. */
|
||
#define SIXTEEN_BIT 15
|
||
/* Задаёт EIGHT_BIT = 07; EIGHT бит. */
|
||
#define EIGHT_BIT 07
|
||
|
||
/***************************************************************/
|
||
/* Configurable Parameter for SPI bus Serial EEPROM */
|
||
/***************************************************************/
|
||
/* Задаёт SPISE2P_DATA_WIDTH = SIXTEEN_BIT; 2 P данные WIDTH. */
|
||
#define SPISE2P_DATA_WIDTH SIXTEEN_BIT//EIGHT_BIT
|
||
/* Задаёт SPISE2P_ADDR_WIDTH = SIXTEEN_BIT; данные SPISE2P_ADDR_WIDTH. */
|
||
#define SPISE2P_ADDR_WIDTH SIXTEEN_BIT
|
||
/* Задаёт SPIBAUD_REG_VAL = 1; данные SPIBAUD_REG_VAL. */
|
||
#define SPIBAUD_REG_VAL 1//12
|
||
/* Задаёт SPICLK_PHASE = 1; SPICLK фаза. */
|
||
#define SPICLK_PHASE 1
|
||
/* Задаёт SPICLK_POLARITY = 0; данные SPICLK_POLARITY. */
|
||
#define SPICLK_POLARITY 0
|
||
|
||
/* Задаёт SPIBAUD_RATE = 100000; данные SPIBAUD_RATE. */
|
||
#define SPIBAUD_RATE 100000
|
||
//10000000
|
||
|
||
/**************************************************************/
|
||
/**************************************************************/
|
||
|
||
/* Serial EEPROM Command words, left justified */
|
||
/* Задаёт SPISE2P_READ_CMD = 0x0300; 2 P чтение CMD. */
|
||
#define SPISE2P_READ_CMD 0x0300
|
||
/* Задаёт SPISE2P_WRITE_CMD = 0x0200; 2 P запись CMD. */
|
||
#define SPISE2P_WRITE_CMD 0x0200
|
||
/* Задаёт SPISE2P_WRDI_CMD = 0x0400; данные SPISE2P_WRDI_CMD. */
|
||
#define SPISE2P_WRDI_CMD 0x0400
|
||
/* Задаёт SPISE2P_WREN_CMD = 0x0600; данные SPISE2P_WREN_CMD. */
|
||
#define SPISE2P_WREN_CMD 0x0600
|
||
/* Задаёт SPISE2P_RDSR_CMD = 0x0500; данные SPISE2P_RDSR_CMD. */
|
||
#define SPISE2P_RDSR_CMD 0x0500
|
||
/* Задаёт SPISE2P_WRSR_CMD = 0x0100; данные SPISE2P_WRSR_CMD. */
|
||
#define SPISE2P_WRSR_CMD 0x0100
|
||
|
||
/* Задаёт SPISE2P_RDID_CMD = 0x0A00; данные SPISE2P_RDID_CMD. */
|
||
#define SPISE2P_RDID_CMD 0x0A00
|
||
|
||
/* Задаёт SPISE2P_DUMMY_DATA = 0x0000; 2 P DUMMY данные. */
|
||
#define SPISE2P_DUMMY_DATA 0x0000
|
||
/* Задаёт SPISE2P_BUSY_MASK = 0x01; 2 P BUSY маска. */
|
||
#define SPISE2P_BUSY_MASK 0x01
|
||
|
||
/* Symbolic constant for SPICCR to transfer 8bit or 16 bit value*/
|
||
/* Задаёт SPISE2P_TFR16BIT = 0x80|(SPICLK_POLARITY<<6)|SIXTEEN_BIT; 2 P 16 бит. */
|
||
#define SPISE2P_TFR16BIT 0x80|(SPICLK_POLARITY<<6)|SIXTEEN_BIT
|
||
/* Задаёт SPISE2P_TFR8BIT = 0x80|(SPICLK_POLARITY<<6)|EIGHT_BIT; 2 P 8 бит. */
|
||
#define SPISE2P_TFR8BIT 0x80|(SPICLK_POLARITY<<6)|EIGHT_BIT
|
||
|
||
/* Status valus */
|
||
#define SPISE2P_WRRQ 1 /* Write Requset */ /* Задаёт SPISE2P_WRRQ = 1; данные SPISE2P_WRRQ. */
|
||
#define SPISE2P_RDRQ 2 /* Read request */ /* Задаёт SPISE2P_RDRQ = 2; данные SPISE2P_RDRQ. */
|
||
#define SPISE2P_WRIP 4 /* Write in progress */ /* Задаёт SPISE2P_WRIP = 4; данные SPISE2P_WRIP. */
|
||
#define SPISE2P_RDIP 8 /* Read in progress */ /* Задаёт SPISE2P_RDIP = 8; данные SPISE2P_RDIP. */
|
||
|
||
/* Message declaration */
|
||
/* Начинает объявление типа, используемого структурами и интерфейсами этого модуля. */
|
||
typedef struct {
|
||
unsigned int * volatile dataPtr; /* Указатель буфера публикуется до csr: volatile запрещает перенос его записи за ожидание Timer2. */
|
||
volatile unsigned long nrData; /* Число 16-битных слов записывается до флага запуска; Timer2 использует его для завершения передачи. */
|
||
volatile unsigned long se2pAddr; /* Байтовый адрес EEPROM публикуется до csr; прерывание должно получить адрес текущего задания. */
|
||
/* Продолжает список аргументов, полей или выражение }SE2P_DATA;; порядок элементов сохраняется. */
|
||
}SE2P_DATA;
|
||
|
||
|
||
/* Object declaration */
|
||
/* Начинает объявление типа, используемого структурами и интерфейсами этого модуля. */
|
||
typedef struct {
|
||
/* Главный цикл заполняет volatile-поля задания, затем msgPtr и csr; Timer2 читает их после запроса.
|
||
* Одного volatile у msgPtr недостаточно: он защищает указатель, но не содержимое задания. */
|
||
/* Продолжает список аргументов, полей или выражение SE2P_DATA * volatile msgPtr;; порядок элементов сохраняется. */
|
||
SE2P_DATA * volatile msgPtr;
|
||
volatile unsigned int csr; /* control/status register */ /* Объявляет csr — данные csr. volatile требует фактического чтения или записи при каждом доступе. */
|
||
/* Вызывает void с аргументами (*init)(void *) в текущей последовательности операций. */
|
||
void (*init)(void *);
|
||
/* Вызывает void с аргументами (*tick)(void *) в текущей последовательности операций. */
|
||
void (*tick)(void *);
|
||
/* Вызывает void с аргументами (*csset)(void) в текущей последовательности операций. */
|
||
void (*csset)(void);
|
||
/* Вызывает void с аргументами (*csclr)(void) в текущей последовательности операций. */
|
||
void (*csclr)(void);
|
||
/* Продолжает список аргументов, полей или выражение }SPISE2P_DRV;; порядок элементов сохраняется. */
|
||
}SPISE2P_DRV;
|
||
|
||
/* Задаёт SPISE2P_DRV_DEFAULTS = { NULL,; данные SPISE2P_DRV_DEFAULTS. */
|
||
#define SPISE2P_DRV_DEFAULTS { NULL,\
|
||
0,/* Элемент постоянной таблицы 0,; порядок значений совпадает с порядком индексов потребителя. */ \
|
||
(void (*)(void *))SPISE2P_DRV_init,/* Продолжает список аргументов, полей или выражение (void (*)(void *))SPISE2P_DRV_init,; порядок элементов сохраняется. */ \
|
||
(void (*)(void *))SPISE2P_DRV_tick,/* Продолжает список аргументов, полей или выражение (void (*)(void *))SPISE2P_DRV_tick,; порядок элементов сохраняется. */ \
|
||
(void (*)(void))SPISE2P_DRV_csset,/* Продолжает список аргументов, полей или выражение (void (*)(void))SPISE2P_DRV_csset,; порядок элементов сохраняется. */ \
|
||
(void (*)(void))SPISE2P_DRV_csclr} /* Продолжает список аргументов, полей или выражение (void (*)(void))SPISE2P_DRV_csclr}; порядок элементов сохраняется. */
|
||
|
||
/* Начинает объявление типа, используемого структурами и интерфейсами этого модуля. */
|
||
typedef SPISE2P_DRV *SPISE2P_DRV_handle;
|
||
|
||
/* Объявляет интерфейс функции SPISE2P_DRV_init; реализация вызывается через этот прототип. */
|
||
void SPISE2P_DRV_init(SPISE2P_DRV * );
|
||
/* Продвигает неблокирующий автомат SPI EEPROM: команда, адрес, данные и ожидание завершения записи. */
|
||
void SPISE2P_DRV_tick(SPISE2P_DRV *);
|
||
/* Объявляет интерфейс функции SPISE2P_DRV_csset; реализация вызывается через этот прототип. */
|
||
void SPISE2P_DRV_csset(void);
|
||
/* Объявляет интерфейс функции SPISE2P_DRV_csclr; реализация вызывается через этот прототип. */
|
||
void SPISE2P_DRV_csclr(void);
|
||
|
||
/* Проверяет завершение текущего задания SPI EEPROM перед постановкой следующего. */
|
||
unsigned int spiSe2pFree(SPISE2P_DRV *se2p);
|
||
/* Ставит задание записи в SPI-драйвер с учётом состояния занятости EEPROM. */
|
||
void spiSe2pWrite(SPISE2P_DRV *se2p, SE2P_DATA *data);
|
||
/* Ставит задание чтения в SPI-драйвер с указателем буфера, длиной и физическим адресом. */
|
||
void spiSe2pRead(SPISE2P_DRV *se2p, SE2P_DATA *data);
|
||
|
||
/* Условие компиляции (SPISE2P_DATA_WIDTH==SIXTEEN_BIT): выбранный блок включается в текущий вариант прошивки. */
|
||
#if(SPISE2P_DATA_WIDTH==SIXTEEN_BIT)
|
||
/* Задаёт PROM_LEN = BALSAM167_EEPROM_WORDS; данные PROM_LEN. */
|
||
#define PROM_LEN BALSAM167_EEPROM_WORDS
|
||
/* Задаёт PAGE_LEN = (BALSAM167_EEPROM_PAGE_BYTES / 2); данные PAGE_LEN. */
|
||
#define PAGE_LEN (BALSAM167_EEPROM_PAGE_BYTES / 2)
|
||
/* Задаёт WORD_LEN = 2; слово LEN. */
|
||
#define WORD_LEN 2
|
||
/* Выбирает альтернативный блок текущего условия компиляции. */
|
||
#else
|
||
/* Задаёт PROM_LEN = BALSAM167_EEPROM_BYTES; данные PROM_LEN. */
|
||
#define PROM_LEN BALSAM167_EEPROM_BYTES
|
||
/* Задаёт PAGE_LEN = BALSAM167_EEPROM_PAGE_BYTES; данные PAGE_LEN. */
|
||
#define PAGE_LEN BALSAM167_EEPROM_PAGE_BYTES
|
||
/* Задаёт WORD_LEN = 1; слово LEN. */
|
||
#define WORD_LEN 1
|
||
/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */
|
||
#endif
|
||
|
||
/* Установка драйвера сериальной EEPROM. **
|
||
** Инициализациа SPI и проч. Также настройка таймера. **
|
||
** Драйвер работает на прерываниах от таймера 2! */
|
||
/* Объявляет интерфейс функции InitSeeprom; реализация вызывается через этот прототип. */
|
||
void InitSeeprom(void);
|
||
|
||
/* Запись блока в SEEPROM. Параметры таковы: **
|
||
** adres - адрес в епромке, куда писать. **
|
||
** adres = 0..0x8000, если длина слова 8 бит **
|
||
** adres = 0..0x4000, если длина слова 16 бит **
|
||
** buf - указатель на памать, откуда писать. **
|
||
** size - длина блока в байтах. По-любому в байтах! */
|
||
/* Пишет EEPROM с разделением по физическим страницам; область параметров не пересекает образ прошивки. */
|
||
void Seeprom_write(SE2P_SIZE adres, unsigned int buf[], SE2P_SIZE size);
|
||
|
||
/* Чтение блока из SEEPROM. Параметры таковы: **
|
||
** adres - адрес в епромке, откуда читать. **
|
||
** adres = 0..0x8000, если длина слова 8 бит **
|
||
** adres = 0..0x4000, если длина слова 16 бит **
|
||
** buf - указатель на памать, куда читать. **
|
||
** size - длина блока в байтах. По-любому в байтах! */
|
||
/* Читает EEPROM порциями; адрес задаётся словами C28x, размер переводится в число передаваемых слов. */
|
||
void Seeprom_read(SE2P_SIZE adres, unsigned int buf[], SE2P_SIZE size);
|
||
|
||
/* Закрывает условный блок препроцессора; дальнейшие строки относятся к внешнему уровню. */
|
||
#endif
|
||
|