Чет работает
This commit is contained in:
76
AllLibs/ExtMemory/Inc/memspi.h
Normal file
76
AllLibs/ExtMemory/Inc/memspi.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file memspi.h
|
||||
* @brief Работа с внешней памятью
|
||||
******************************************************************************
|
||||
@defgroup MEMSPI API for Memory SPI
|
||||
@brief API для работы с внешней памятью
|
||||
******************************************************************************
|
||||
* @details
|
||||
Модуль предоставляет API для удобной работы с FLASH/EEPROM по SPI:
|
||||
- @ref MEMSPI_Read_Memory Считывание внешней FLASH/EEPROM
|
||||
- @ref MEMSPI_EEPROM_Write Запись данных в внешнюю EEPROM
|
||||
- @ref MEMSPI_FLASH_Write Запись данных в внешнюю FLASH (функция сама очищает нужные сектора, и если надо сохраняет выбранные данные)
|
||||
- @ref MEMSPI_FLASH_Program Программирование внешней FLASH (выбранный участок FLASH должен быть очищен)
|
||||
- @ref MEMSPI_FLASH_Erase Очистка внешней FLASH
|
||||
|
||||
Также есть ряд вспомогательных функций:
|
||||
- @ref MEMSPI_EEPROM_Write_Page Запись страницы в EEPROM *есть более общая функция MEMSPI_EEPROM_Write, которая записывает участки больше страницы
|
||||
- @ref MEMSPI_FLASH_Erase_Sector Очистка сектора FLASH. *есть более общая функция MEMSPI_FLASH_Erase, которая может ощичать несколько секторов
|
||||
- @ref MEMSPI_FLASH_Program_Page Программирование страницы. *есть более общая функция MEMSPI_FLASH_Program, которая программирует участки больше страницы
|
||||
- @ref MEMSPI_WriteEnablingUntilTimeout Разрешение записи, пока не будет ответа или не истек таймаут
|
||||
- @ref MEMSPI_WaitOnFlagsUntilTimeout Ожидание флага пока не истек таймаута
|
||||
|
||||
@section Start Инструкция по подключению
|
||||
```c
|
||||
MEMSPI_HandleTypeDef hmemspi;
|
||||
HAL_StatusTypeDef MEMSPI_RES;
|
||||
|
||||
hmemspi.CS_GPIOx = GPIOC;
|
||||
hmemspi.CS_PIN = GPIO_PIN_4;
|
||||
MEMSPI_Base_Init(&hmemspi, &hspi3);
|
||||
|
||||
MEMSPI_RES = MEMSPI_EEPROM_Write(&hmemspi, mem_adr, write_buff, buff_size, Timeout, 1);
|
||||
MEMSPI_RES = MEMSPI_Read_Memory(&hmemspi, mem_adr, read_buff, buff_size, Timeout);
|
||||
```
|
||||
|
||||
******************************************************************************/
|
||||
#ifndef __SPI_MEMORY_H_
|
||||
#define __SPI_MEMORY_H_
|
||||
|
||||
#include "memspi_core.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
///////////////////////---FUNCTIONS FOR USER---//////////////////////
|
||||
/* Initialize SPI and GPIO for MEMSPI FLASH */
|
||||
void MEMSPI_Base_Init(MEMSPI_HandleTypeDef *hmemspi, SPI_HandleTypeDef *hspi);
|
||||
/* Read external FLASH */
|
||||
HAL_StatusTypeDef MEMSPI_Read_Memory(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pBuff, uint16_t Size, uint32_t Timeout);
|
||||
/* Write external EEPROM */
|
||||
HAL_StatusTypeDef MEMSPI_EEPROM_Write(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pData, uint16_t Size, uint32_t Timeout, uint8_t WaitForEnd);
|
||||
/* Write external FLASH */
|
||||
HAL_StatusTypeDef MEMSPI_FLASH_Write(MEMSPI_HandleTypeDef *hmemspi, MEMSPI_WriteInitTypeDef *WriteInit, uint32_t Timeout, uint8_t WaitForEnd);
|
||||
/* Program external FLASH */
|
||||
HAL_StatusTypeDef MEMSPI_FLASH_Program(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pData, uint16_t Size, uint32_t Timeout, uint8_t WaitForEnd);
|
||||
/* Erase external FLASH */
|
||||
HAL_StatusTypeDef MEMSPI_FLASH_Erase(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint16_t Size, uint32_t Timeout, uint8_t WaitForEnd);
|
||||
///////////////////////---FUNCTIONS FOR USER---//////////////////////
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
////////////////////////---SERVICE FUNCTIONS---//////////////////////
|
||||
/* Write page in external EEPROM */
|
||||
HAL_StatusTypeDef MEMSPI_EEPROM_Write_Page(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pData, uint16_t Size, uint32_t *Timeout, uint32_t *tickstart, uint8_t WaitForEnd);
|
||||
/* Erase external FLASH Sector */
|
||||
HAL_StatusTypeDef MEMSPI_FLASH_Erase_Sector(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint32_t *Timeout, uint32_t *tickstart, uint8_t WaitForEnd);
|
||||
/* Program page in external FLASH */
|
||||
HAL_StatusTypeDef MEMSPI_FLASH_Program_Page(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pData, uint16_t Size, uint32_t *Timeout, uint32_t *tickstart, uint8_t WaitForEnd);
|
||||
/* Setting WEL bit until it setted or until timeout */
|
||||
HAL_StatusTypeDef MEMSPI_WriteEnablingUntilTimeout(MEMSPI_HandleTypeDef *hmemspi, uint32_t *Timeout, uint32_t *tickstart);
|
||||
/* Wait for flag until timeout */
|
||||
HAL_StatusTypeDef MEMSPI_WaitOnFlagsUntilTimeout(MEMSPI_HandleTypeDef *hmemspi, uint16_t FlagMask, uint16_t FlagStatus, uint32_t *Timeout, uint32_t *tickstart);
|
||||
/* Update Timeout variables */
|
||||
void MEMSPI_Update_Timeout_Variables(uint32_t *Timeout, uint32_t *tickstart);
|
||||
////////////////////////---SERVICE FUNCTIONS---//////////////////////
|
||||
|
||||
|
||||
#endif // __SPI_MEMORY_H_
|
||||
165
AllLibs/ExtMemory/Inc/memspi_core.h
Normal file
165
AllLibs/ExtMemory/Inc/memspi_core.h
Normal file
@@ -0,0 +1,165 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file memspi_core.h
|
||||
* @brief Работа с командами для внешней памяти
|
||||
******************************************************************************
|
||||
@defgroup MEMSPI_CORE Memory SPI Core
|
||||
@brief Ядро библиотеки
|
||||
@{
|
||||
******************************************************************************
|
||||
* @details
|
||||
Модуль предоставляет функции и макросы для работы с FLASH/EEPROM по SPI
|
||||
на уровне отдельных команд:
|
||||
- @ref MEMSPI_CMD_Read_Status_Register Отправка комманды Read Status Register / Read Status Register 2 (0x05h / 0x35h)
|
||||
- @ref MEMSPI_CMD_Write_Status_Register Отправка комманды Write Status Register (0x01h)
|
||||
- @ref MEMSPI_CMD_Write_Enable Отправка комманды Write Enable (0x06h)
|
||||
- @ref MEMSPI_CMD_Read_Data Отправка комманды Read Data (0x03h)
|
||||
- @ref MEMSPI_CMD_EEPROM_Write Отправка комманды Write (eeprom) (0x02h)
|
||||
- @ref MEMSPI_CMD_FLASH_Page_Program Отправка комманды Page Program (flash) (0x02h)
|
||||
- @ref MEMSPI_CMD_FLASH_Erase_Sector Отправка комманды Erase Sector (flash) (0x20h)
|
||||
- @ref MEMSPI_CMD_Read_JEDEC_ID Отправка комманды Read JEDEC ID (0x4Bh)
|
||||
- @ref MEMSPI_CMD_Read_Device_ID Отправка комманды Read Manufacture / Device Id (0x90)
|
||||
|
||||
******************************************************************************/
|
||||
#ifndef __SPI_MEMORY_CORE_H_
|
||||
#define __SPI_MEMORY_CORE_H_
|
||||
|
||||
#include "memspi_config.h"
|
||||
|
||||
#ifndef local_time
|
||||
#define local_time() HAL_GetTick() ///< Локальное время
|
||||
#endif
|
||||
|
||||
/** @defgroup MEMSPI_Commands Memory SPI Commands
|
||||
* @brief Определения команд SPI-памяти
|
||||
* @{
|
||||
*/
|
||||
#define MEMSPI_READ_JEDEC_ID 0x9F ///< Команда чтения JEDEC ID
|
||||
#define MEMSPI_READ_UNIQUE_ID 0x4B ///< Команда чтения уникального идентификатора
|
||||
#define MEMSPI_WRITE_ENABLE 0x06 ///< Разрешение записи
|
||||
#define MEMSPI_WRITE_DISABLE 0x04 ///< Запрещение записи
|
||||
#define MEMSPI_WRITE_STATUS_REG 0x01 ///< Запись в регистр состояния
|
||||
#define MEMSPI_ERASE_SECTOR 0x20 ///< Стирание одного сектора
|
||||
#define MEMSPI_PAGE_PROGRAM 0x02 ///< Программирование одной страницы
|
||||
#define MEMSPI_WRITE_EEPROM MEMSPI_PAGE_PROGRAM ///< Псевдоним для программирования EEPROM
|
||||
#define MEMSPI_READ_STATUS_REG 0x05 ///< Чтение регистра состояния
|
||||
|
||||
#if defined(MEMSPI_SEPARATED_STATUS_REGISTER)
|
||||
#define MEMSPI_READ_STATUS_REG_2 0x35 ///< Чтение второго регистра состояния (если поддерживается)
|
||||
#endif
|
||||
|
||||
#define MEMSPI_READ_DATA 0x03 ///< Чтение данных из памяти
|
||||
|
||||
/** //MEMSPI_Commands
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup MEMSPI_StatusFlags Statur Register Flags
|
||||
* @brief Определения битов регистра состояния памяти
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Get Flag of Status Register
|
||||
*/
|
||||
#define MEMSPI_Get_Flag(_hmemspi_,_flag_) (((MEMSPI_StatusRegisterTypeDef)(_hmemspi_->SR))._flag_)
|
||||
|
||||
#define MEMSPI_SR_SUS (1<<15) ///< Suspend (приостановка операций)
|
||||
#define MEMSPI_SR_QE (1<<9) ///< Quad Enable (разрешение четырехпроводного интерфейса)
|
||||
#define MEMSPI_SR_SRP1 (1<<8) ///< Status Register Protect 1
|
||||
#define MEMSPI_SR_SRP0 (1<<7) ///< Status Register Protect 0 / SRWD
|
||||
#define MEMSPI_SR_SEC (1<<6) ///< Sector Protect (защита сектора)
|
||||
#define MEMSPI_SR_TB (1<<5) ///< Top/Bottom Protect
|
||||
#define MEMSPI_SR_BP2 (1<<4) ///< Block Protect бит 2
|
||||
#define MEMSPI_SR_BP1 (1<<3) ///< Block Protect бит 1
|
||||
#define MEMSPI_SR_BP0 (1<<2) ///< Block Protect бит 0
|
||||
#define MEMSPI_SR_WEL (1<<1) ///< Write Enable Latch (бит разрешения записи)
|
||||
#define MEMSPI_SR_BUSY (1<<0) ///< Занято (операция в процессе выполнения)
|
||||
|
||||
|
||||
// Exclusive (by name) EEPROM SR bits
|
||||
#define MEMSPI_SR_SRWD MEMSPI_SR_SRP0 ///< Status Register Write Disable (аналог SRP0)
|
||||
#define MEMSPI_SR_WIP MEMSPI_SR_WEL ///< Write-In-Progress (используется в некоторых EEPROM)
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
////////////////////////////---DEFINES---////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
///////////////////////---STRUCTURES & ENUMS---//////////////////////
|
||||
|
||||
/**
|
||||
* @brief Структура параметров инициализации записи в память MEMSPI.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t *pDataPtr; ///< Указатель на буфер данных, которые будут записаны
|
||||
uint32_t Data_Address; ///< Начальный адрес записи в памяти
|
||||
uint32_t Data_Size; ///< Размер данных для записи в байтах
|
||||
|
||||
uint32_t Sector_Address; ///< Адрес начала сектора, в который будет производиться запись
|
||||
uint32_t Sector_Size; ///< Размер сектора, который может быть затронут при записи
|
||||
|
||||
unsigned fSavePrevoisData:1; ///< Флаг: сохранять ли предыдущие данные сектора (до стирания)
|
||||
} MEMSPI_WriteInitTypeDef;
|
||||
|
||||
/**
|
||||
* @brief Основная структура управления MEMSPI.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t SR; ///< Регистра состояния микросхемы
|
||||
|
||||
SPI_HandleTypeDef *hspi; ///< Указатель на дескриптор SPI, используемый для обмена с памятью
|
||||
GPIO_TypeDef *CS_GPIOx; ///< Порт GPIO для вывода управления CS (chip select)
|
||||
uint32_t CS_PIN; ///< Номер вывода (пина) для CS
|
||||
|
||||
uint32_t hNextAddr; ///< Следующий адрес для автоматической записи/чтения
|
||||
uint16_t hNextPage; ///< Следующая страница памяти
|
||||
uint16_t hNextSector; ///< Следующий сектор памяти
|
||||
} MEMSPI_HandleTypeDef;
|
||||
|
||||
///////////////////////---STRUCTURES & ENUMS---//////////////////////
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
//////////////////////---FUNCTION FOR COMMAND---/////////////////////
|
||||
|
||||
/** @defgroup MEMSPI_CmdFunctiins Functions for Memory SPI CMD
|
||||
* @brief Функции для отправки комманд для памяти по SPI
|
||||
* @{
|
||||
*/
|
||||
/* Send command to read Status Register */
|
||||
HAL_StatusTypeDef MEMSPI_CMD_Read_Status_Register(MEMSPI_HandleTypeDef *hmemspi, uint16_t RequestedBits, uint8_t EndCMD, uint32_t Timeout);
|
||||
/* Send command to write bits in Status Register */
|
||||
HAL_StatusTypeDef MEMSPI_CMD_Write_Status_Register(MEMSPI_HandleTypeDef *hmemspi, uint16_t WrittenBits, uint32_t Timeout);
|
||||
/* Send command to set Write Enable Latch (WEL) in Status Register */
|
||||
HAL_StatusTypeDef MEMSPI_CMD_Write_Enable(MEMSPI_HandleTypeDef *hmemspi, uint32_t Timeout);
|
||||
/* Send command to read data from FLASH/EEPROM */
|
||||
HAL_StatusTypeDef MEMSPI_CMD_Read_Data(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pBuff, uint16_t Size, uint32_t Timeout);
|
||||
/* Send command to write eeprom */
|
||||
HAL_StatusTypeDef MEMSPI_CMD_EEPROM_Write(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pData, uint16_t Size, uint32_t Timeout);
|
||||
/* Send command to page program in FLASH */
|
||||
HAL_StatusTypeDef MEMSPI_CMD_FLASH_Page_Program(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pData, uint16_t Size, uint32_t Timeout);
|
||||
/* Send command to erase sector of FLASH */
|
||||
HAL_StatusTypeDef MEMSPI_CMD_FLASH_Erase_Sector(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint32_t Timeout);
|
||||
/* Send command to read JEDEC ID */
|
||||
uint32_t MEMSPI_CMD_Read_JEDEC_ID(MEMSPI_HandleTypeDef *hmemspi, uint32_t Timeout);
|
||||
/* Send command to read JEDEC ID */
|
||||
uint64_t MEMSPI_CMD_Read_Device_ID(MEMSPI_HandleTypeDef *hmemspi, uint32_t Timeout);
|
||||
/*Send command to fast read data from FLASH */
|
||||
HAL_StatusTypeDef MEMSPI_CMD_Fast_Read(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pBuff, uint16_t Size, uint32_t Timeout);
|
||||
//////////////////////---FUNCTION FOR COMMAND---/////////////////////
|
||||
|
||||
/** //MEMSPI_CmdFunctiins
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif // __SPI_MEMORY_CORE_H_
|
||||
|
||||
/** //MEMSPI_CORE
|
||||
* @}
|
||||
*/
|
||||
71
AllLibs/ExtMemory/README.md
Normal file
71
AllLibs/ExtMemory/README.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# Инструкция по подключению релиза библиотеки для работы с внешними FLASH, EEPROM
|
||||
|
||||
STM32_MemorySPI - это набор библиотек для удобной работы с периферией STM32.
|
||||
Данный субмодуль подключается напрямую из Git и содержит набор вспомогательных библиотек для работы МК, в частности STM32 и SEGGER RTT.
|
||||
|
||||
## Структура библиотеки
|
||||
|
||||
*Note: Файлы начинающиеся с `__` и которых **нет** в этом дереве являются **внутренними/непротестированными/недокументированными***
|
||||
```
|
||||
ProjectRoot/
|
||||
└── STM32_MemorySPI # Работа с внешней памятбю
|
||||
├── inc/
|
||||
│ ├── memspi_core.h
|
||||
│ └── memspi.h
|
||||
│── src/
|
||||
│ ├── memspi_core.c
|
||||
│ └── memspi.c
|
||||
└── __memspi_config.h
|
||||
```
|
||||
|
||||
|
||||
## Функции библиотеки
|
||||
Общение с памятью на уровне железа выполняют [функции для команд](#функции-для-команд).
|
||||
Координацию команд выполняют [функции для внутреннего использования](#функции-для-внутреннего-использования).
|
||||
А запросы на запись/чтение/очистку произвольного кол-ва байт выполняют [функции для пользователя](#функции-для-пользователя).
|
||||
|
||||
|
||||
## Пример
|
||||
|
||||
```c
|
||||
MEMSPI_HandleTypeDef hmemspi;
|
||||
HAL_StatusTypeDef MEMSPI_RES;
|
||||
|
||||
hmemspi.CS_GPIOx = GPIOC;
|
||||
hmemspi.CS_PIN = GPIO_PIN_4;
|
||||
MEMSPI_Base_Init(&hmemspi, &hspi3);
|
||||
|
||||
MEMSPI_RES = MEMSPI_EEPROM_Write(&hmemspi, mem_adr, write_buff, buff_size, Timeout, 1);
|
||||
MEMSPI_RES = MEMSPI_Read_Memory(&hmemspi, mem_adr, read_buff, buff_size, Timeout);
|
||||
```
|
||||
|
||||
|
||||
### Функции для пользователя
|
||||
- MEMSPI_Base_Init() Инициализация переферии SPI и GPIO для внешней памяти
|
||||
- MEMSPI_Read_Memory() Считывание внешней FLASH/EEPROM
|
||||
- MEMSPI_EEPROM_Write() Запись данных в внешнюю EEPROM
|
||||
- MEMSPI_FLASH_Write() Запись данных в внешнюю FLASH (функция сама очищает нужные сектора, и если надо сохраняет выбранные данные)
|
||||
- MEMSPI_FLASH_Program() Программирование внешней FLASH (выбранный участок FLASH должен быть очищен)
|
||||
- MEMSPI_FLASH_Erase() Очистка внешней FLASH
|
||||
|
||||
С помощью данных функций предлагается управлять внещней памятью. Эти функции имеют "неограниченый" доступ к памяти. Т.е. они могут записывать данные размером больше страницы и очищать несколько секторов за один вызов.
|
||||
При вызове этих функций проверяется свободно ли устройство. И если свободно то начинают с ним соответсвующую работу. Возможно также ожидание в конце, когда нужная операция выполниться.
|
||||
|
||||
Функция инициализации **MEMSPI_Base_Init()** содержит базовые настройки для перефирии SPI и GPIO. Пользователь только настраивает SPI Instance, BaudratePrescaler и порты ввода/вывода для общения с памятью.
|
||||
|
||||
### Функции для внутреннего использования
|
||||
- MEMSPI_EEPROM_Write_Page() Запись страницы в EEPROM
|
||||
- MEMSPI_FLASH_Erase_Sector() Очистка сектора FLASH.
|
||||
- MEMSPI_FLASH_Program_Page() Программирование страницы.
|
||||
- MEMSPI_WriteEnablingUntilTimeout() Разрешение записи, пока не будет ответа или не истек таймаут
|
||||
- MEMSPI_WaitOnFlagsUntilTimeout() Ожидание флага пока не истек таймаута
|
||||
|
||||
Функции **Write**, **Erase**, **Program** работают напрямую с командами SPI для памяти. Соответственно имеют те же ограничения, что и команды: запись памяти только в пределах страницы, и очистка памяти только по секторам.
|
||||
Они проверяют свободно ли устройство (бит **BUSY** в **Status Register**). И если да, отправляют команду на разрешение записи. И если запись разрешена (бит **WEL** в **Status Register**), начинают с ней работать. Также эти функциии в конце могут ожидать, пока устройство не выполнит нужную операцию с памятью (бит **BUSY** в **Status Register**) ИЛИ просто выйти из функции не дожидаясь конца операции.
|
||||
|
||||
Функции UntilTimeout нужны для ожидания некоторого события до истечения таймаута:
|
||||
- WriteEnabling: посылает команду для разрешения записи и ожидает когда запись разрешится ИЛИ когда истечет таймаут
|
||||
- WaitOnFlags: ожидает выставления выбранных флагов ИЛИ когда истечет таймаут
|
||||
|
||||
### Функции для команд
|
||||
Данные функции начинаются с **MEMSPI_CMD_...()**. Они посылают соответствующие команды и принимают ответ. Также на время команды все функции выставляют Chip Select для выбранного устройства. А функция **MEMSPI_CMD_Read_Status_Register()** имеет параметр, который позволяет не убирать Chip Select после команды для постоянного мониторинга Status Register. Прием с помощью **MEMSPI_SPI_Receive()**.
|
||||
530
AllLibs/ExtMemory/Src/memspi.c
Normal file
530
AllLibs/ExtMemory/Src/memspi.c
Normal file
@@ -0,0 +1,530 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file memspi.c
|
||||
* @brief Реализация работы с внешней памятью
|
||||
******************************************************************************
|
||||
* @details
|
||||
Модуль реализует функции для удобной работы с FLASH/EEPROM по SPI:
|
||||
- MEMSPI_Read_Memory Считывание внешней FLASH/EEPROM
|
||||
- MEMSPI_EEPROM_Write Запись данных в внешнюю EEPROM
|
||||
- MEMSPI_FLASH_Write Запись данных в внешнюю FLASH (функция сама очищает нужные сектора, и если надо сохраняет выбранные данные)
|
||||
- MEMSPI_FLASH_Program Программирование внешней FLASH (выбранный участок FLASH должен быть очищен)
|
||||
- MEMSPI_FLASH_Erase Очистка внешней FLASH
|
||||
|
||||
А также ряд вспомогательных функций:
|
||||
- MEMSPI_EEPROM_Write_Page Запись страницы в EEPROM *есть более общая функция MEMSPI_EEPROM_Write, которая записывает участки больше страницы
|
||||
- MEMSPI_FLASH_Erase_Sector Очистка сектора FLASH. *есть более общая функция MEMSPI_FLASH_Erase, которая может ощичать несколько секторов
|
||||
- MEMSPI_FLASH_Program_Page Программирование страницы. *есть более общая функция MEMSPI_FLASH_Program, которая программирует участки больше страницы
|
||||
- MEMSPI_WriteEnablingUntilTimeout Разрешение записи, пока не будет ответа или не истек таймаут
|
||||
- MEMSPI_WaitOnFlagsUntilTimeout Ожидание флага пока не истек таймаута
|
||||
******************************************************************************/
|
||||
#include "memspi.h"
|
||||
uint8_t sector_buff[MEMSPI_SECTOR_SIZE];
|
||||
|
||||
//-------------------------------------------------------------
|
||||
//--------------------------FOR USER---------------------------
|
||||
/**
|
||||
* @brief Initialize SPI and GPIO for MEMSPI FLASH.
|
||||
* @param hmemspi Указатель на структуру с настройками SPI и GPIO портов.
|
||||
* @param hspi Указатель на хендл SPI.
|
||||
*/
|
||||
void MEMSPI_Base_Init(MEMSPI_HandleTypeDef *hmemspi, SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
|
||||
// SPI PERIPH INIT
|
||||
if(hspi == NULL)
|
||||
return;
|
||||
|
||||
hmemspi->hspi = hspi;
|
||||
|
||||
// GPIO INIT
|
||||
// CHIP SELECT PIN INIT
|
||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
GPIO_InitStruct.Pin = hmemspi->CS_PIN;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
|
||||
#ifdef GPIO_SPEED_FREQ_VERY_HIGH
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
#else
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
#endif
|
||||
HAL_GPIO_Init(hmemspi->CS_GPIOx, &GPIO_InitStruct);
|
||||
MEMSPI_Deselect(hmemspi);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read external FLASH/EEPROM.
|
||||
* @param hmemspi Указатель на хендл внешней памяти.
|
||||
* @param FLASH_Address Адресс откуда начинать считывание.
|
||||
* @param pBuff Куда записывать данные из FLASH.
|
||||
* @param Size Вколько байтов считывать.
|
||||
* @param Timeout Время, за которое должно быть осуществлено чтение.
|
||||
* @return HAL status.
|
||||
* @note Включает в себя проверку на доступность памяти (флаг BUSY)
|
||||
*/
|
||||
HAL_StatusTypeDef MEMSPI_Read_Memory(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pBuff, uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
HAL_StatusTypeDef MEMSPI_Status;
|
||||
uint32_t tickstart = local_time();
|
||||
|
||||
// wait for unbusy
|
||||
if(MEMSPI_WaitOnFlagsUntilTimeout(hmemspi, MEMSPI_SR_BUSY, 0, &Timeout, &tickstart) != HAL_OK) // if its unbusy for timeout
|
||||
return HAL_TIMEOUT; // return timeout error
|
||||
|
||||
MEMSPI_Status = MEMSPI_CMD_Read_Data(hmemspi, FLASH_Address, pBuff, Size, Timeout);
|
||||
if(MEMSPI_Status != HAL_OK)
|
||||
return MEMSPI_Status;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write external EEPROM.
|
||||
* @param hmemspi Указатель на хендл внешней памяти.
|
||||
* @param FLASH_Address Адресс куда начинать записывать.
|
||||
* @param pData Откуда брать данные для записи в EEPROM.
|
||||
* @param Size Вколько байтов записать.
|
||||
* @param Timeout Время, за которое должна быть осуществлена запись.
|
||||
* @param WaitForEnd Ожидание, пока память не выполненит операцию.
|
||||
* @return HAL status.
|
||||
* @note Позволяет записать участок памяти. Можно записывать несколько страниц.
|
||||
*/
|
||||
HAL_StatusTypeDef MEMSPI_EEPROM_Write(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pData, uint16_t Size, uint32_t Timeout, uint8_t WaitForEnd)
|
||||
{
|
||||
uint32_t tickstart = local_time();
|
||||
HAL_StatusTypeDef MEMSPI_Status;
|
||||
|
||||
// CALC AREA TO WRITE
|
||||
uint16_t bytecnt = 0;
|
||||
uint16_t currentpage_size = 0;
|
||||
uint16_t lastpage_size = Size;
|
||||
uint16_t firstpage = (FLASH_Address/MEMSPI_PAGE_SIZE);
|
||||
uint16_t lastpage = ((FLASH_Address+Size-1)/MEMSPI_PAGE_SIZE);
|
||||
if(firstpage != lastpage) // if area is on several pages
|
||||
{
|
||||
currentpage_size = (firstpage+1)*MEMSPI_PAGE_SIZE - FLASH_Address; // set size of data on first page
|
||||
lastpage_size = (FLASH_Address+Size) - lastpage*MEMSPI_PAGE_SIZE; // set size of data on last page
|
||||
}
|
||||
|
||||
// PROGRAM PAGES: FROM FIRST NO THE PREVIOUS TO THE LAST
|
||||
hmemspi->hNextAddr = FLASH_Address; // address would automatically increase in this variable
|
||||
for(int i = 0; i < lastpage - firstpage; i++)
|
||||
{
|
||||
MEMSPI_Status = MEMSPI_EEPROM_Write_Page(hmemspi, hmemspi->hNextAddr, &pData[bytecnt], currentpage_size, &Timeout, &tickstart, 0); // programm page
|
||||
if(MEMSPI_Status != HAL_OK) // note: no need waiting for end: the next call will wait for unbusy
|
||||
return MEMSPI_Status;
|
||||
|
||||
// note for multiple page program: first we program rest of the first page,
|
||||
// then we shift byte count to data, that shoud be on the next page
|
||||
bytecnt += currentpage_size;
|
||||
// and set current size as page size. because next pages will be fully programmed
|
||||
currentpage_size = MEMSPI_PAGE_SIZE;
|
||||
}
|
||||
|
||||
// PROGRAM LAST PAGE
|
||||
MEMSPI_Status = MEMSPI_FLASH_Program_Page(hmemspi, hmemspi->hNextAddr, &pData[bytecnt], lastpage_size, &Timeout, &tickstart, WaitForEnd); // programm page
|
||||
if(MEMSPI_Status != HAL_OK)
|
||||
return MEMSPI_Status;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
/**
|
||||
* @brief Write external FLASH.
|
||||
* @param hmemspi Указатель на хендл внешней памяти.
|
||||
* @param WriteInit Указатель на структуру, определяющую участок памяти для записи.
|
||||
* @param Timeout Время, за которое должно быть осуществлено чтение.
|
||||
* @param WaitForEnd Ожидание, пока память не выполненит операцию.
|
||||
* @return HAL status.
|
||||
* @note Позволяет перепрограммировать участок памяти. Можно записывать несколько страниц.
|
||||
* Данные в сектора участка, но за пределами участка не сохраняются.
|
||||
*/
|
||||
HAL_StatusTypeDef MEMSPI_FLASH_Write(MEMSPI_HandleTypeDef *hmemspi, MEMSPI_WriteInitTypeDef *WriteInit, uint32_t Timeout, uint8_t WaitForEnd)
|
||||
{
|
||||
uint32_t tickstart = local_time();
|
||||
uint32_t timeoutcnt = Timeout;
|
||||
uint8_t *writebuff = WriteInit->pDataPtr;
|
||||
HAL_StatusTypeDef MEMSPI_Status;
|
||||
|
||||
// CHECK FOR UNDEFINED STRUCTURE
|
||||
if (WriteInit->Sector_Size == 0) // if sector undefined
|
||||
{ // fill it with data init
|
||||
WriteInit->Sector_Address = WriteInit->Data_Address;
|
||||
WriteInit->Sector_Size = WriteInit->Data_Size;
|
||||
}
|
||||
else if (WriteInit->Data_Size == 0) // if data undefined
|
||||
{ // fill it with sector init
|
||||
WriteInit->Data_Address = WriteInit->Sector_Address;
|
||||
WriteInit->Data_Size = WriteInit->Sector_Size;
|
||||
} // if both undefined - return HAL ERR
|
||||
else if ((WriteInit->Sector_Size == 0) && (WriteInit->Data_Size == 0))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
// CHECK FOR CORRECT STRUCTURE
|
||||
// if data is beyound sector
|
||||
if((WriteInit->Data_Address < WriteInit->Sector_Address) ||
|
||||
((WriteInit->Data_Address + WriteInit->Data_Size) > (WriteInit->Sector_Address + WriteInit->Sector_Size)))
|
||||
return HAL_ERROR;
|
||||
|
||||
// WRITE FLASH WITH SAVING PREVIOUS DATA
|
||||
if(WriteInit->fSavePrevoisData)
|
||||
{
|
||||
// uint8_t sector_buff[WriteInit->Sector_Size];
|
||||
// store data from flash
|
||||
MEMSPI_Status = MEMSPI_Read_Memory(hmemspi, WriteInit->Sector_Address, sector_buff, WriteInit->Sector_Size, Timeout);
|
||||
if(MEMSPI_Status != HAL_OK)
|
||||
return MEMSPI_Status;
|
||||
|
||||
// CHANGE DATA IN USER "SECTOR"
|
||||
uint32_t addr_shift = WriteInit->Data_Address - WriteInit->Sector_Address;
|
||||
for(int i = 0; i < WriteInit->Data_Size; i++)
|
||||
{
|
||||
sector_buff[addr_shift+i] = WriteInit->pDataPtr[addr_shift+i];
|
||||
}
|
||||
|
||||
// CALC AREA TO REPROGRAM
|
||||
uint16_t lastsector_size = WriteInit->Sector_Size;
|
||||
uint16_t firstsector = (WriteInit->Sector_Address/MEMSPI_SECTOR_SIZE);
|
||||
uint16_t lastsector = ((WriteInit->Sector_Address+WriteInit->Sector_Size-1)/MEMSPI_SECTOR_SIZE);
|
||||
if(firstsector != lastsector) // if area is on several pages
|
||||
{
|
||||
lastsector_size = (WriteInit->Sector_Address+WriteInit->Sector_Size) - lastsector*MEMSPI_SECTOR_SIZE; // set size of data on last page
|
||||
}
|
||||
// REPROGRAM SECTORS: FROM FIRST SECTOR NO THE PREVIOUS TO THE LAST
|
||||
hmemspi->hNextAddr = WriteInit->Sector_Address; // address would automatically increase in this variable
|
||||
hmemspi->hNextSector = firstsector+1;
|
||||
uint16_t bytescnt = 0;
|
||||
uint16_t bytes_to_next_sector = 0;
|
||||
for(int i = 0; i < (lastsector - firstsector); i++)
|
||||
{
|
||||
// ERASE FLASH
|
||||
MEMSPI_Status = MEMSPI_FLASH_Erase(hmemspi, hmemspi->hNextAddr, 1, Timeout, 0);
|
||||
if(MEMSPI_Status != HAL_OK) // note: no need waiting for end: the next call will wait for unbusy
|
||||
return MEMSPI_Status;
|
||||
|
||||
// PROGRAM FLASH WITH NEW DATA
|
||||
// calc bytes to next sector
|
||||
bytes_to_next_sector = hmemspi->hNextSector*MEMSPI_SECTOR_SIZE - hmemspi->hNextAddr;
|
||||
// program data to flash
|
||||
MEMSPI_Status = MEMSPI_FLASH_Program(hmemspi, hmemspi->hNextAddr, §or_buff[bytescnt], bytes_to_next_sector, Timeout, 0);
|
||||
if(MEMSPI_Status != HAL_OK)
|
||||
return MEMSPI_Status;
|
||||
// shift bytes count to data, that shoud be on the next page
|
||||
bytescnt += bytes_to_next_sector;
|
||||
}
|
||||
|
||||
// ERASE FLASH
|
||||
MEMSPI_Status = MEMSPI_FLASH_Erase(hmemspi, hmemspi->hNextAddr, 1, Timeout, 0);
|
||||
if(MEMSPI_Status != HAL_OK) // note: no need waiting for end: the next call will wait for unbusy
|
||||
return MEMSPI_Status;
|
||||
|
||||
// PROGRAM LAST SECTOR
|
||||
MEMSPI_Status = MEMSPI_FLASH_Program(hmemspi, hmemspi->hNextAddr, §or_buff[bytescnt], lastsector_size, Timeout, WaitForEnd);
|
||||
if(MEMSPI_Status != HAL_OK)
|
||||
return MEMSPI_Status;
|
||||
}
|
||||
// WRITE FLASH WITHOUT SAVING PREVIOUS DATA
|
||||
else
|
||||
{
|
||||
// ERASE FLASH
|
||||
MEMSPI_Status = MEMSPI_FLASH_Erase(hmemspi, WriteInit->Sector_Address, WriteInit->Sector_Size, Timeout, 0);
|
||||
if(MEMSPI_Status != HAL_OK) // note: no need waiting for end: the next call will wait for unbusy
|
||||
return MEMSPI_Status;
|
||||
|
||||
// PROGRAM FLASH WITH NEW DATA
|
||||
// program data to flash
|
||||
MEMSPI_Status = MEMSPI_FLASH_Program(hmemspi, WriteInit->Sector_Address, WriteInit->pDataPtr, WriteInit->Sector_Size, Timeout, WaitForEnd);
|
||||
if(MEMSPI_Status != HAL_OK)
|
||||
return MEMSPI_Status;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Program external FLASH.
|
||||
* @param hmemspi Указатель на хендл внешней памяти.
|
||||
* @param FLASH_Address Адресс куда начинать записывать.
|
||||
* @param pData Откуда брать данные для записи в FLASH.
|
||||
* @param Size Вколько байтов записать.
|
||||
* @param Timeout Время, за которое должно быть осуществлено чтение.
|
||||
* @param WaitForEnd Ожидание, пока память не выполненит операцию.
|
||||
* @return HAL status.
|
||||
* @note Программирование участка памяти, без ограничений на кол-во байт
|
||||
*/
|
||||
HAL_StatusTypeDef MEMSPI_FLASH_Program(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pData, uint16_t Size, uint32_t Timeout, uint8_t WaitForEnd)
|
||||
{
|
||||
uint32_t tickstart = local_time();
|
||||
HAL_StatusTypeDef MEMSPI_Status;
|
||||
|
||||
// CALC AREA TO PROGRAM
|
||||
uint16_t lastpage_size = Size;
|
||||
uint16_t firstpage = (FLASH_Address/MEMSPI_PAGE_SIZE);
|
||||
uint16_t lastpage = ((FLASH_Address+Size-1)/MEMSPI_PAGE_SIZE);
|
||||
if(firstpage != lastpage) // if area is on several pages
|
||||
{
|
||||
lastpage_size = (FLASH_Address+Size) - lastpage*MEMSPI_PAGE_SIZE; // set size of data on last page
|
||||
}
|
||||
|
||||
// PROGRAM PAGES: FROM FIRST NO THE PREVIOUS TO THE LAST
|
||||
hmemspi->hNextAddr = FLASH_Address; // address would automatically increase in this variable
|
||||
hmemspi->hNextPage = firstpage+1; // address would automatically increase in this variable
|
||||
uint16_t bytecnt = 0;
|
||||
uint16_t bytes_to_next_page = 0;
|
||||
for(int i = 0; i < lastpage - firstpage; i++)
|
||||
{
|
||||
// calc bytes to next sector
|
||||
bytes_to_next_page = hmemspi->hNextPage*MEMSPI_PAGE_SIZE - hmemspi->hNextAddr;
|
||||
|
||||
MEMSPI_Status = MEMSPI_FLASH_Program_Page(hmemspi, hmemspi->hNextAddr, &pData[bytecnt], bytes_to_next_page, &Timeout, &tickstart, 0); // programm page
|
||||
if(MEMSPI_Status != HAL_OK) // note: no need waiting for end: the next call will wait for unbusy
|
||||
return MEMSPI_Status;
|
||||
|
||||
// then we shift byte count to data, that shoud be on the next page
|
||||
bytecnt += bytes_to_next_page;
|
||||
}
|
||||
|
||||
// PROGRAM LAST PAGE
|
||||
MEMSPI_Status = MEMSPI_FLASH_Program_Page(hmemspi, hmemspi->hNextAddr, &pData[bytecnt], lastpage_size, &Timeout, &tickstart, WaitForEnd); // programm page
|
||||
if(MEMSPI_Status != HAL_OK)
|
||||
return MEMSPI_Status;
|
||||
|
||||
return HAL_OK; // if all ok return HAL_OK
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Erase external FLASH.
|
||||
* @param hmemspi Указатель на хендл внешней памяти.
|
||||
* @param FLASH_Address Адресс где надо данные стереть.
|
||||
* @param Size Вколько байтов стереть.
|
||||
* @param Timeout Время, за которое должно быть осуществлена очистка.
|
||||
* @param WaitForEnd Ожидание, пока память не выполненит операцию.
|
||||
* @return HAL status.
|
||||
* @note Т.к. очитска происходит по секторам, Size нужен, чтобы определить сколько секторов очистить
|
||||
* И если начальны адресс будет на Sector 0, а последний байт на Sector 1, то произойдет очистка Sector 0 и Sector 1
|
||||
*/
|
||||
HAL_StatusTypeDef MEMSPI_FLASH_Erase(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint16_t Size, uint32_t Timeout, uint8_t WaitForEnd)
|
||||
{
|
||||
uint32_t tickstart = local_time();
|
||||
HAL_StatusTypeDef MEMSPI_Status;
|
||||
|
||||
// CALC AREA TO ERASE
|
||||
uint16_t bytecnt = 0;
|
||||
uint16_t firstsector = (FLASH_Address/MEMSPI_SECTOR_SIZE);
|
||||
uint16_t lastsector = ((FLASH_Address+Size-1)/MEMSPI_SECTOR_SIZE);
|
||||
|
||||
for(int i = 0; i <= (lastsector - firstsector); i++)
|
||||
{
|
||||
MEMSPI_Status = MEMSPI_FLASH_Erase_Sector(hmemspi, FLASH_Address, &Timeout, &tickstart, WaitForEnd); // programm page
|
||||
if(MEMSPI_Status != HAL_OK)
|
||||
return MEMSPI_Status;
|
||||
FLASH_Address += MEMSPI_SECTOR_SIZE;
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------
|
||||
//----------------------SERVICE FUNCTIONS----------------------
|
||||
/**
|
||||
* @brief Write page in external EEPROM.
|
||||
* @param hmemspi Указатель на хендл внешней памяти.
|
||||
* @param FLASH_Address Адресс куда начинать записывать.
|
||||
* @param pData Откуда брать данные для записи в EEPROM.
|
||||
* @param Size Вколько байтов записать.
|
||||
* @param Timeout Время, за которое должно быть осуществлено чтение.
|
||||
* @param tickstart Начальное количество тиков.
|
||||
* @param WaitForEnd Ожидание, пока память не выполненит операцию.
|
||||
* @return HAL status.
|
||||
* @note Позволяет записывать только байты в пределах одной страницы.
|
||||
Для более гибкой записи есть функция MEMSPI_EEPROM_Write, которая программирует участки любой длины (в теории).
|
||||
*/
|
||||
HAL_StatusTypeDef MEMSPI_EEPROM_Write_Page(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pData, uint16_t Size, uint32_t *Timeout, uint32_t *tickstart, uint8_t WaitForEnd)
|
||||
{
|
||||
HAL_StatusTypeDef MEMSPI_Status;
|
||||
// enable writting and waiting for unbusy
|
||||
if(MEMSPI_WriteEnablingUntilTimeout(hmemspi, Timeout, tickstart) != HAL_OK) // if writting isnt enable
|
||||
return HAL_TIMEOUT; // return timeout
|
||||
|
||||
MEMSPI_Status = MEMSPI_CMD_EEPROM_Write(hmemspi, FLASH_Address, pData, Size, *Timeout);
|
||||
if(MEMSPI_Status != HAL_OK)
|
||||
return MEMSPI_Status;
|
||||
|
||||
// waiting for ending of writting if need
|
||||
if(WaitForEnd)
|
||||
if(MEMSPI_WaitOnFlagsUntilTimeout(hmemspi, MEMSPI_SR_WEL|MEMSPI_SR_BUSY, 0, Timeout, tickstart) != HAL_OK) // if writting isnt done (MEMSPI busy and WEL bit isnt in reset state)
|
||||
return HAL_TIMEOUT;
|
||||
|
||||
// update handle variables
|
||||
hmemspi->hNextAddr = (FLASH_Address+Size);
|
||||
hmemspi->hNextPage = (FLASH_Address+Size)/MEMSPI_PAGE_SIZE;
|
||||
hmemspi->hNextSector = (FLASH_Address+Size)/MEMSPI_SECTOR_SIZE;
|
||||
return HAL_OK;
|
||||
}
|
||||
/**
|
||||
* @brief Erase external FLASH Sector.
|
||||
* @param hmemspi Указатель на хендл внешней памяти.
|
||||
* @param FLASH_Address Адресс где надо данные стереть.
|
||||
* @param Timeout Время, за которое должно быть осуществлена очистка.
|
||||
* @param tickstart Время, относительно которого надо отсчитывать таймаут.
|
||||
* @param WaitForEnd Ожидание, пока память не выполненит операцию.
|
||||
* @return HAL status.
|
||||
* @note При Timeout = 0, функция не будет ожидать окончания очистки (выставления в 0 флагов BUSY и WEL)
|
||||
* @note Микросхема вроде сама высчитывает какой сектор ерейзнуть, в соответствии с заданным адресом.
|
||||
*/
|
||||
HAL_StatusTypeDef MEMSPI_FLASH_Erase_Sector(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint32_t *Timeout, uint32_t *tickstart, uint8_t WaitForEnd)
|
||||
{
|
||||
HAL_StatusTypeDef MEMSPI_Status;
|
||||
// enable writting and waiting for unbusy
|
||||
if(MEMSPI_WriteEnablingUntilTimeout(hmemspi, Timeout, tickstart) != HAL_OK) // if writting isnt enable
|
||||
return HAL_TIMEOUT; // return timeout
|
||||
|
||||
// erase sector (instruction)
|
||||
MEMSPI_Status = MEMSPI_CMD_FLASH_Erase_Sector(hmemspi, FLASH_Address, *Timeout);
|
||||
if(MEMSPI_Status != HAL_OK)
|
||||
return MEMSPI_Status;
|
||||
|
||||
// waiting for ending of erasing if need
|
||||
if(WaitForEnd)
|
||||
if(MEMSPI_WaitOnFlagsUntilTimeout(hmemspi, MEMSPI_SR_WEL|MEMSPI_SR_BUSY, 0, Timeout, tickstart) != HAL_OK) // if erase isnt done (MEMSPI busy and WEL bit isnt in reset state)
|
||||
return HAL_TIMEOUT; // return timeout because erasing instruction accepted, but arent done
|
||||
// note: if timeout == 0, erasing wouldnt be checking for ending (check busy flag)
|
||||
|
||||
return HAL_OK; // if all ok return HAL_OK
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Program page in external FLASH.
|
||||
* @param hmemspi Указатель на хендл внешней памяти.
|
||||
* @param FLASH_Address Адресс куда начинать записывать.
|
||||
* @param pData Откуда брать данные для записи в FLASH.
|
||||
* @param Size Вколько байтов записать.
|
||||
* @param Timeout Время, за которое должно быть осуществлено чтение.
|
||||
* @param tickstart Время, относительно которого надо отсчитывать таймаут.
|
||||
* @param WaitForEnd Ожидание, пока память не выполненит операцию.
|
||||
* @return HAL status.
|
||||
* @note Позволяет перепрограммировать только байты в прелелах одной страницы.
|
||||
Для более гибкого программирования есть функция MEMSPI_FLASH_Program, которая программирует участки любой длины (в теории).
|
||||
*/
|
||||
HAL_StatusTypeDef MEMSPI_FLASH_Program_Page(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pData, uint16_t Size, uint32_t *Timeout, uint32_t *tickstart, uint8_t WaitForEnd)
|
||||
{
|
||||
HAL_StatusTypeDef MEMSPI_Status;
|
||||
// enable writting and waiting for unbusy
|
||||
if(MEMSPI_WriteEnablingUntilTimeout(hmemspi, Timeout, tickstart) != HAL_OK) // if writting isnt enable
|
||||
return HAL_TIMEOUT; // return timeout
|
||||
|
||||
// check if flash range is placed at one page
|
||||
if((FLASH_Address/MEMSPI_PAGE_SIZE) != ((FLASH_Address+Size-1)/MEMSPI_PAGE_SIZE)) // if page of first byte isnt equal page of last byte
|
||||
return HAL_ERROR; // return error
|
||||
|
||||
// programm page (instruction)
|
||||
MEMSPI_Status = MEMSPI_CMD_FLASH_Page_Program(hmemspi, FLASH_Address, pData, Size, *Timeout);
|
||||
if(MEMSPI_Status != HAL_OK)
|
||||
return MEMSPI_Status;
|
||||
|
||||
// waiting for ending of writting if need
|
||||
if(WaitForEnd)
|
||||
if(MEMSPI_WaitOnFlagsUntilTimeout(hmemspi, MEMSPI_SR_WEL|MEMSPI_SR_BUSY, 0, Timeout, tickstart) != HAL_OK) // if writting isnt done (MEMSPI busy and WEL bit isnt in reset state)
|
||||
return HAL_TIMEOUT;
|
||||
|
||||
// update handle variables
|
||||
hmemspi->hNextAddr = (FLASH_Address+Size);
|
||||
hmemspi->hNextPage = (hmemspi->hNextAddr+Size)/MEMSPI_PAGE_SIZE;
|
||||
hmemspi->hNextSector = (hmemspi->hNextAddr+Size)/MEMSPI_SECTOR_SIZE;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
/**
|
||||
* @brief Setting WEL bit until it setted or until timeout.
|
||||
* @param hmemspi Указатель на хендл внешней памяти.
|
||||
* @param Timeout Время, за которое должно быть осуществлено чтение.
|
||||
* @param tickstart Время, относительно которого надо отсчитывать таймаут.
|
||||
* @return HAL status.
|
||||
* @note Подает команду на разрешение записи до тех пор, пока она запись не разрешиться или до тех пор, пока таймаут не истечет.
|
||||
*/
|
||||
HAL_StatusTypeDef MEMSPI_WriteEnablingUntilTimeout(MEMSPI_HandleTypeDef *hmemspi, uint32_t *Timeout, uint32_t *tickstart)
|
||||
{
|
||||
HAL_StatusTypeDef MEMSPI_Status;
|
||||
|
||||
// wait for unbusy
|
||||
if(MEMSPI_WaitOnFlagsUntilTimeout(hmemspi, MEMSPI_SR_BUSY, 0, Timeout, tickstart) != HAL_OK) // if its unbusy for timeout
|
||||
return HAL_TIMEOUT;
|
||||
|
||||
// enable writing
|
||||
while((hmemspi->SR&MEMSPI_SR_WEL) != MEMSPI_SR_WEL)
|
||||
{
|
||||
// if flash isnt busy - set WEL flag
|
||||
if((hmemspi->SR&MEMSPI_SR_BUSY) == 0)
|
||||
MEMSPI_CMD_Write_Enable(hmemspi, *Timeout);
|
||||
|
||||
// check is writting enabled
|
||||
MEMSPI_Status = MEMSPI_CMD_Read_Status_Register(hmemspi, MEMSPI_SR_WEL|MEMSPI_SR_BUSY, 1, *Timeout);
|
||||
if(MEMSPI_Status != HAL_OK)
|
||||
{
|
||||
MEMSPI_Deselect(hmemspi);
|
||||
return MEMSPI_Status;
|
||||
}
|
||||
|
||||
if((local_time() - *tickstart) >= *Timeout) // if time is out
|
||||
{
|
||||
MEMSPI_Deselect(hmemspi);
|
||||
return HAL_TIMEOUT; // set timeout
|
||||
}
|
||||
}
|
||||
MEMSPI_Deselect(hmemspi);
|
||||
MEMSPI_Update_Timeout_Variables(Timeout, tickstart);
|
||||
return HAL_OK; // if all ok return HAL_OK
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wait for flag until timeout.
|
||||
* @param hmemspi Указатель на хендл внешней памяти.
|
||||
* @param FlagMask Маска для флагов, какие флаги считывать.
|
||||
* @param FlagStatus Какое состояние должно быть у выбранных флагов.
|
||||
* @param Timeout Время, за которое должно быть осуществлено чтение.
|
||||
* @param tickstart Время, относительно которого надо отсчитывать таймаут.
|
||||
* @return HAL status.
|
||||
* @note Считывает флаги до тех пор, пока они не будут в состоянии FlagStatus или до тех пор, пока таймаут не истечет.
|
||||
*/
|
||||
HAL_StatusTypeDef MEMSPI_WaitOnFlagsUntilTimeout(MEMSPI_HandleTypeDef *hmemspi, uint16_t FlagMask, uint16_t FlagStatus, uint32_t *Timeout, uint32_t *tickstart)
|
||||
{
|
||||
HAL_StatusTypeDef MEMSPI_Status;
|
||||
// check flags
|
||||
MEMSPI_Status = MEMSPI_CMD_Read_Status_Register(hmemspi, FlagMask, 0, *Timeout);
|
||||
if(MEMSPI_Status != HAL_OK)
|
||||
return MEMSPI_Status;
|
||||
while((hmemspi->SR&FlagMask) != FlagStatus)
|
||||
{
|
||||
// check flags
|
||||
// MEMSPI_Status = MEMSPI_CMD_Read_Status_Register(hmemspi, FlagMask, *Timeout);
|
||||
MEMSPI_Status = MEMSPI_SPI_Receive(hmemspi, (uint8_t *)&hmemspi->SR, 1, *Timeout); // receive response
|
||||
if(MEMSPI_Status != HAL_OK)
|
||||
{
|
||||
MEMSPI_Deselect(hmemspi);
|
||||
return MEMSPI_Status;
|
||||
}
|
||||
|
||||
if((local_time() - *tickstart) >= *Timeout) // if time is out
|
||||
{
|
||||
MEMSPI_Deselect(hmemspi);
|
||||
return HAL_TIMEOUT; // set timeout
|
||||
}
|
||||
}
|
||||
MEMSPI_Deselect(hmemspi);
|
||||
MEMSPI_Update_Timeout_Variables(Timeout, tickstart);
|
||||
return HAL_OK; // if all ok return HAL_OK
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update Timeout variables.
|
||||
* @param Timeout Указатель на переменную содержащию значение таймаута
|
||||
* @param tickstart Указатель на переменную содержащию начальное кол-во тиков.
|
||||
*/
|
||||
void MEMSPI_Update_Timeout_Variables(uint32_t *Timeout, uint32_t *tickstart)
|
||||
{
|
||||
uint32_t timeoutcnt = local_time() - *tickstart; // update timeout
|
||||
*Timeout -= timeoutcnt;
|
||||
*tickstart += timeoutcnt;
|
||||
}
|
||||
314
AllLibs/ExtMemory/Src/memspi_core.c
Normal file
314
AllLibs/ExtMemory/Src/memspi_core.c
Normal file
@@ -0,0 +1,314 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file memspi_core.c
|
||||
* @brief Реализация работы с командами для внешней памяти
|
||||
******************************************************************************
|
||||
* @details
|
||||
Модуль реализует функции для работы с FLASH/EEPROM по SPI
|
||||
на уровне отдельных команд:
|
||||
- MEMSPI_CMD_Read_Status_Register Отправка комманды Read Status Register / Read Status Register 2 (0x05h / 0x35h)
|
||||
- MEMSPI_CMD_Write_Status_Register Отправка комманды Write Status Register (0x01h)
|
||||
- MEMSPI_CMD_Write_Enable Отправка комманды Write Enable (0x06h)
|
||||
- MEMSPI_CMD_Read_Data Отправка комманды Read Data (0x03h)
|
||||
- MEMSPI_CMD_EEPROM_Write Отправка комманды Write (eeprom) (0x02h)
|
||||
- MEMSPI_CMD_FLASH_Page_Program Отправка комманды Page Program (flash) (0x02h)
|
||||
- MEMSPI_CMD_FLASH_Erase_Sector Отправка комманды Erase Sector (flash) (0x20h)
|
||||
- MEMSPI_CMD_Read_JEDEC_ID Отправка комманды Read JEDEC ID (0x4Bh)
|
||||
- MEMSPI_CMD_Read_Device_ID Отправка комманды Read Manufacture / Device Id (0x90)
|
||||
******************************************************************************/
|
||||
#include "memspi_core.h"
|
||||
|
||||
//-------------------------------------------------------------
|
||||
//----------------------COMMAND FUNCTIONS----------------------
|
||||
/**
|
||||
* @brief Send command to read Status Register.
|
||||
* @param hmemspi Указатель на хендл внешней памяти.
|
||||
* @param RequestedBits Какие биты запросить.
|
||||
* @param EndCMD Завершать комманду или нет. (очистка Chip Selected пина)
|
||||
* @param Timeout Время, за которое должно быть осуществлено чтение.
|
||||
* @return Заполняет Status Register в hmemspi.
|
||||
* @note Всего есть две комманды: на запрос верхнего или нижниго байта.
|
||||
* Функция в соответствии с RequestedBits определяет какой байт запросить, или два байта сразу.
|
||||
*/
|
||||
HAL_StatusTypeDef MEMSPI_CMD_Read_Status_Register(MEMSPI_HandleTypeDef *hmemspi, uint16_t RequestedBits, uint8_t EndCMD, uint32_t Timeout)
|
||||
{
|
||||
HAL_StatusTypeDef SPI_RES;
|
||||
uint8_t command[2];
|
||||
uint8_t *pSRPtr = 0;
|
||||
uint8_t size = 1;
|
||||
|
||||
if(RequestedBits >> 8) // if its high byte of status register
|
||||
{
|
||||
#ifdef MEMSPI_READ_STATUS_REG_2
|
||||
command[0] = MEMSPI_READ_STATUS_REG_2;
|
||||
pSRPtr = (uint8_t *)(&hmemspi->SR) + 1; // set pointer to HI byte of SR register
|
||||
size = 1;
|
||||
if(RequestedBits & 0xFF) // if low byte also requester
|
||||
{
|
||||
size = 2; // set size to 2 bytes
|
||||
command[1] = MEMSPI_READ_STATUS_REG;
|
||||
}
|
||||
#endif // MEMSPI_READ_STATUS_REG_2
|
||||
}
|
||||
else // of its low byte of status register
|
||||
{
|
||||
command[0] = MEMSPI_READ_STATUS_REG;
|
||||
pSRPtr = (uint8_t *)(&hmemspi->SR); // set pointer to LO byte of SR register
|
||||
size = 1;
|
||||
}
|
||||
MEMSPI_Select(hmemspi);
|
||||
SPI_RES = MEMSPI_SPI_Transmit(hmemspi, command, 1, Timeout); // send insctruction to read SR
|
||||
SPI_RES = MEMSPI_SPI_Receive(hmemspi, pSRPtr, 1, Timeout); // receive response
|
||||
if(size > 1) // if 2 bytes are requested
|
||||
{
|
||||
MEMSPI_Deselect(hmemspi);
|
||||
MEMSPI_Select(hmemspi);
|
||||
SPI_RES = MEMSPI_SPI_Transmit(hmemspi, command+1, 1, Timeout); // send insctruction to read SR
|
||||
SPI_RES = MEMSPI_SPI_Receive(hmemspi, pSRPtr-1, 1, Timeout); // receive response
|
||||
MEMSPI_Deselect(hmemspi);
|
||||
}
|
||||
if(EndCMD)
|
||||
MEMSPI_Deselect(hmemspi);
|
||||
return SPI_RES;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send command to write bits in Status Register.
|
||||
* @param hmemspi Указатель на хендл внешней памяти.
|
||||
* @param WrittenBits Какие биты запросить.
|
||||
* @param Timeout Время, за которое должно быть осуществлена запись.
|
||||
* @note Данная команда посылает биты, как сдвинутые на 2 вправо. Т.е. 0-й бит в комманде - 2-й бит BP0.
|
||||
Но биты указываются в также как они расположены и регистре. Функция сама выполняет сдвиг.
|
||||
*/
|
||||
HAL_StatusTypeDef MEMSPI_CMD_Write_Status_Register(MEMSPI_HandleTypeDef *hmemspi, uint16_t WrittenBits, uint32_t Timeout)
|
||||
{
|
||||
HAL_StatusTypeDef SPI_RES;
|
||||
uint8_t command[3];
|
||||
uint8_t size;
|
||||
|
||||
command[0] = MEMSPI_WRITE_STATUS_REG;
|
||||
command[1] = WrittenBits;
|
||||
command[2] = WrittenBits >> 8;
|
||||
|
||||
size = 3;
|
||||
|
||||
MEMSPI_Select(hmemspi);
|
||||
SPI_RES = MEMSPI_SPI_Transmit(hmemspi, command, size, Timeout);
|
||||
MEMSPI_Deselect(hmemspi);
|
||||
|
||||
return SPI_RES;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send command to set Write Enable Latch (WEL) in Status Register.
|
||||
* @param hmemspi Указатель на хендл внешней памяти.
|
||||
* @param Timeout Время, за которое должно быть осуществлена запись.
|
||||
* @note Разрешает запись в FLASH, путем высталения WEL в Status Register
|
||||
*/
|
||||
HAL_StatusTypeDef MEMSPI_CMD_Write_Enable(MEMSPI_HandleTypeDef *hmemspi, uint32_t Timeout)
|
||||
{
|
||||
HAL_StatusTypeDef SPI_RES;
|
||||
uint8_t command[1];
|
||||
command[0] = MEMSPI_WRITE_ENABLE;
|
||||
|
||||
MEMSPI_Select(hmemspi);
|
||||
SPI_RES = MEMSPI_SPI_Transmit(hmemspi, command, 1, Timeout);
|
||||
MEMSPI_Deselect(hmemspi);
|
||||
|
||||
return SPI_RES;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Send command to read data from FLASH/EEPROM.
|
||||
* @param hmemspi Указатель на хендл внешней памяти.
|
||||
* @param FLASH_Address Адресс откуда начинать считывание.
|
||||
* @param pBuff Куда записывать данные из FLASH.
|
||||
* @param Size Сколько байтов считывать.
|
||||
* @param Timeout Время, за которое должно быть осуществлено чтение.
|
||||
* @return pBuff.
|
||||
*/
|
||||
HAL_StatusTypeDef MEMSPI_CMD_Read_Data(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pBuff, uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
HAL_StatusTypeDef SPI_RES;
|
||||
uint8_t command[4];
|
||||
uint8_t response[2] = {0};
|
||||
|
||||
command[0] = MEMSPI_READ_DATA;
|
||||
command[1] = FLASH_Address >> 16 & 0xFF;
|
||||
command[2] = FLASH_Address >> 8 & 0xFF;
|
||||
command[3] = FLASH_Address & 0xFF;
|
||||
|
||||
MEMSPI_Select(hmemspi);
|
||||
SPI_RES = MEMSPI_SPI_Transmit(hmemspi, command, 4, Timeout);
|
||||
SPI_RES = MEMSPI_SPI_Receive(hmemspi, pBuff, Size, Timeout);
|
||||
MEMSPI_Deselect(hmemspi);
|
||||
|
||||
return SPI_RES;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send command to write eeprom.
|
||||
* @param hmemspi Указатель на хендл внешней памяти.
|
||||
* @param FLASH_Address Адресс куда начинать записывать.
|
||||
* @param pData Откуда брать данные для записи в FLASH.
|
||||
* @param Size Сколько байтов записать.
|
||||
* @param Timeout Время, за которое должна быть осуществлена запись.
|
||||
* @note Рзамер данных для записи в EEPROM без ограничений.
|
||||
*/
|
||||
HAL_StatusTypeDef MEMSPI_CMD_EEPROM_Write(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pData, uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
HAL_StatusTypeDef SPI_RES;
|
||||
// 1 command byte + 3 address bytes + 256 data bytes
|
||||
uint8_t command[1+3+MEMSPI_PAGE_SIZE];
|
||||
FLASH_Address = FLASH_Address & 0xFFFFFF;
|
||||
|
||||
command[0] = MEMSPI_WRITE_EEPROM;
|
||||
command[1] = FLASH_Address >> 16 & 0xFF;
|
||||
command[2] = FLASH_Address >> 8 & 0xFF;
|
||||
command[3] = FLASH_Address & 0xFF;
|
||||
|
||||
MEMSPI_Select(hmemspi);
|
||||
SPI_RES = MEMSPI_SPI_Transmit(hmemspi, command, 4, Timeout); // send insctruction to write
|
||||
SPI_RES = MEMSPI_SPI_Transmit(hmemspi, pData, Size, Timeout); // send data to write
|
||||
MEMSPI_Deselect(hmemspi);
|
||||
|
||||
return SPI_RES;
|
||||
}
|
||||
/**
|
||||
* @brief Send command to page program in FLASH.
|
||||
* @param hmemspi Указатель на хендл внешней памяти.
|
||||
* @param FLASH_Address Адресс куда начинать записывать.
|
||||
* @param pData Откуда брать данные для записи в FLASH.
|
||||
* @param Size Сколько байтов записать.
|
||||
* @param Timeout Время, за которое должна быть осуществлена запись.
|
||||
* @note Программирование FLASH только в пределах одной страницы.
|
||||
* Т.е. если запись с 0x0, то не больше 256 байт. Если с 0ч40, то не больше 192 байт.
|
||||
*/
|
||||
HAL_StatusTypeDef MEMSPI_CMD_FLASH_Page_Program(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pData, uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
HAL_StatusTypeDef SPI_RES;
|
||||
// 1 command byte + 3 address bytes + 256 data bytes
|
||||
uint8_t command[1+3+MEMSPI_PAGE_SIZE];
|
||||
FLASH_Address = FLASH_Address & 0xFFFFFF;
|
||||
|
||||
command[0] = MEMSPI_PAGE_PROGRAM;
|
||||
command[1] = FLASH_Address >> 16 & 0xFF;
|
||||
command[2] = FLASH_Address >> 8 & 0xFF;
|
||||
command[3] = FLASH_Address & 0xFF;
|
||||
|
||||
// check if flash range is placed at one page
|
||||
if((FLASH_Address/MEMSPI_PAGE_SIZE) != ((FLASH_Address+Size-1)/MEMSPI_PAGE_SIZE)) // if page of first byte isnt equal page of last byte
|
||||
return HAL_ERROR; // return error
|
||||
|
||||
MEMSPI_Select(hmemspi);
|
||||
SPI_RES = MEMSPI_SPI_Transmit(hmemspi, command, 4, Timeout); // send insctruction to write
|
||||
SPI_RES = MEMSPI_SPI_Transmit(hmemspi, pData, Size, Timeout); // send data to write
|
||||
MEMSPI_Deselect(hmemspi);
|
||||
|
||||
return SPI_RES;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send command to erase sector.
|
||||
* @param hmemspi Указатель на хендл внешней памяти.
|
||||
* @param FLASH_Address Адресс где надо данные стереть.
|
||||
* @param Timeout Время, за которое должна быть осуществлена очистка.
|
||||
* @note Микросхема вроде сама высчитывает какой сектор ерейзнуть, в соответствии с заданным адресом.
|
||||
*/
|
||||
HAL_StatusTypeDef MEMSPI_CMD_FLASH_Erase_Sector(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint32_t Timeout)
|
||||
{
|
||||
HAL_StatusTypeDef SPI_RES;
|
||||
uint8_t command[4];
|
||||
uint8_t response[8];
|
||||
FLASH_Address = FLASH_Address & 0xFFFFFF;
|
||||
|
||||
command[0] = MEMSPI_ERASE_SECTOR;
|
||||
command[1] = FLASH_Address >> 16;
|
||||
command[2] = FLASH_Address >> 8;
|
||||
command[3] = FLASH_Address;
|
||||
|
||||
MEMSPI_Select(hmemspi);
|
||||
SPI_RES = MEMSPI_SPI_Transmit(hmemspi, command, 4, Timeout);
|
||||
MEMSPI_Deselect(hmemspi);
|
||||
|
||||
return SPI_RES;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Send command to read JEDEC ID.
|
||||
* @param hmemspi Указатель на хендл внешней памяти.
|
||||
* @param Timeout Время, за которое должно быть осуществлено чтение.
|
||||
* @return JEDEC ID микросхемы.
|
||||
*/
|
||||
uint32_t MEMSPI_CMD_Read_JEDEC_ID(MEMSPI_HandleTypeDef *hmemspi, uint32_t Timeout)
|
||||
{
|
||||
HAL_StatusTypeDef SPI_RES;
|
||||
uint8_t command[1] = {0};
|
||||
uint8_t receive[4] = {0};
|
||||
uint32_t return_val;
|
||||
|
||||
command[0] = MEMSPI_READ_JEDEC_ID;
|
||||
MEMSPI_Select(hmemspi);
|
||||
SPI_RES = MEMSPI_SPI_Transmit(hmemspi, command, 1, Timeout);
|
||||
SPI_RES = MEMSPI_SPI_Receive(hmemspi, &receive[1], 3, Timeout);
|
||||
MEMSPI_Deselect(hmemspi);
|
||||
|
||||
return_val = (*(uint64_t *)receive);
|
||||
return __REV(return_val) & 0xFFFFFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send command to read JEDEC ID.
|
||||
* @param hmemspi Указатель на хендл внешней памяти.
|
||||
* @param Timeout Время, за которое должно быть осуществлено чтение.
|
||||
* @return Device ID микросхемы.
|
||||
*/
|
||||
uint64_t MEMSPI_CMD_Read_Device_ID(MEMSPI_HandleTypeDef *hmemspi, uint32_t Timeout)
|
||||
{
|
||||
HAL_StatusTypeDef SPI_RES;
|
||||
uint8_t command[1] = {0};
|
||||
uint8_t receive[8] = {0};
|
||||
uint64_t return_val_LO;
|
||||
uint64_t return_val_HI;
|
||||
command[0] = MEMSPI_READ_UNIQUE_ID;
|
||||
MEMSPI_Select(hmemspi);
|
||||
SPI_RES = MEMSPI_SPI_Transmit(hmemspi, command, 1, Timeout);
|
||||
SPI_RES = MEMSPI_SPI_Receive(hmemspi, receive, 8, Timeout);
|
||||
MEMSPI_Deselect(hmemspi);
|
||||
|
||||
return_val_LO = (*(uint64_t *)receive) >> 32;
|
||||
return_val_HI = (*(uint64_t *)receive) & 0xFFFFFFFF;
|
||||
return ((uint64_t)__REV(return_val_HI) << 32) | __REV(return_val_LO);
|
||||
}
|
||||
/**
|
||||
* @brief Send command to fast read data from FLASH.
|
||||
* @param hmemspi Указатель на хендл внешней памяти.
|
||||
* @param FLASH_Address Адресс откуда начинать считывание.
|
||||
* @param pBuff Куда записывать данные из FLASH.
|
||||
* @param Size Сколько байтов считывать.
|
||||
* @param Timeout Время, за которое должно быть осуществлено чтение.
|
||||
* @note Данная функция предполагает отправку одного dummy байта после адресса, но у меня поч не работает пока :(
|
||||
*/
|
||||
HAL_StatusTypeDef MEMSPI_CMD_Fast_Read(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pBuff, uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
HAL_StatusTypeDef SPI_RES;
|
||||
uint8_t command[5] = {0};
|
||||
uint8_t response[2] = {0};
|
||||
|
||||
command[0] = MEMSPI_READ_DATA;
|
||||
command[1] = FLASH_Address >> 16 & 0xFF;
|
||||
command[2] = FLASH_Address >> 8 & 0xFF;
|
||||
command[3] = FLASH_Address & 0xFF;
|
||||
command[4] = 0xFF;
|
||||
|
||||
MEMSPI_Select(hmemspi);
|
||||
SPI_RES = MEMSPI_SPI_Transmit(hmemspi, command, 5, Timeout);
|
||||
SPI_RES = MEMSPI_SPI_Receive(hmemspi, pBuff, Size, Timeout);
|
||||
MEMSPI_Deselect(hmemspi);
|
||||
|
||||
return SPI_RES;
|
||||
}
|
||||
//-------------------------------------------------------------
|
||||
|
||||
70
AllLibs/ExtMemory/__memspi_config.h
Normal file
70
AllLibs/ExtMemory/__memspi_config.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file memspi_config.h
|
||||
* @brief Конфигурационные параметры для общения с FLASH/EEPROM по SPI
|
||||
******************************************************************************
|
||||
@addtogroup MEMSPI_CONFIGS Memory SPI configs
|
||||
@ingroup MEMSPI
|
||||
@brief Конфигурация библиотеки
|
||||
@{
|
||||
******************************************************************************
|
||||
* @details
|
||||
Файл содержит настройки для работы Memory SPI:
|
||||
Размеры страниц и секторов внешней памяти
|
||||
Включение двойного статус регистра (если соответствующая микросхема)
|
||||
- Низкоуровневые функции для приема/передачи по SPI и выбора чипа ChipSelect
|
||||
******************************************************************************/
|
||||
#ifndef __SPI_MEMORY_CONFIG_H_
|
||||
#define __SPI_MEMORY_CONFIG_H_
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/////////////////////////---USER SETTINGS---/////////////////////////
|
||||
|
||||
//#define MEMSPI_SEPARATED_STATUS_REGISTER ///< Использовать двойной статус регистр
|
||||
|
||||
#define MEMSPI_SECTOR_SIZE (0x1000) ///< Размер одного сектора памяти (4096 байт)
|
||||
#define MEMSPI_PAGE_SIZE (0x100) ///< Размер одной страницы памяти (256 байт)
|
||||
|
||||
|
||||
/** @defgroup MEMSPI_LowLevel Config Hardware SPI
|
||||
* @brief Конфигурация функций для доступа к SPI
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief SPI Transmit.
|
||||
* @param _hmemspi_ Указатель на хендл внешней памяти.
|
||||
* @param _data_ Указатель на данные для отправки.
|
||||
* @param _size_ Размер данных для отправки.
|
||||
* @param _timeout_ Время, за которое должна быть осуществлена отправка.
|
||||
* @note Здесь вызывается только функция HAL, и ничего больше.
|
||||
*/
|
||||
#define MEMSPI_SPI_Transmit(_hmemspi_, _data_, _size_, _timeout_) HAL_SPI_Transmit(_hmemspi_->hspi, _data_, _size_, _timeout_)
|
||||
/**
|
||||
* @brief SPI Receive.
|
||||
* @param _hmemspi_ Указатель на хендл внешней памяти.
|
||||
* @param _data_ Указатель на буффер для прниема данных.
|
||||
* @param _size_ Размер данных для приема.
|
||||
* @param _timeout_ Время, за которое должен быть осуществлен прием.
|
||||
* @note Здесь вызывается только функция HAL, и ничего больше.
|
||||
*/
|
||||
#define MEMSPI_SPI_Receive(_hmemspi_, _data_, _size_, _timeout_) HAL_SPI_Receive(_hmemspi_->hspi, _data_, _size_, _timeout_)
|
||||
|
||||
/**
|
||||
* @brief Select MEMORY chip.
|
||||
*/
|
||||
#define MEMSPI_Select(_hmemspi_) (_hmemspi_->CS_GPIOx->BSRR = _hmemspi_->CS_PIN << 16)
|
||||
/**
|
||||
* @brief Deselect MEMORY chip.
|
||||
*/
|
||||
#define MEMSPI_Deselect(_hmemspi_) (_hmemspi_->CS_GPIOx->BSRR = _hmemspi_->CS_PIN)
|
||||
|
||||
/** //MEMSPI_LowLevel
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif // __SPI_MEMORY_CONFIG_H_
|
||||
|
||||
/** //MEMSPI_CONFIGS
|
||||
* @}
|
||||
*/
|
||||
Reference in New Issue
Block a user