Files
STM32_MemorySPI/memory_spi/memory_spi.h
alexey 8fd8c03119 minor
2024-08-13 16:01:45 +03:00

387 lines
23 KiB
C
Raw 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.
/********************************SPI MEMORY*********************************
Данный файл содержит инклюды и дефайны для общения с FLASH/EEPROM по SPI.
***************************************************************************/
#ifndef __SPI_MEMORY_H_
#define __SPI_MEMORY_H_
#include "stm32f4xx_hal.h"
#include "gpio_general.h"
/////////////////////////---USER SETTINGS---/////////////////////////
//#define EXT_FLASH
#define EXT_EEPROM
#if defined(EXT_FLASH) & defined(EXT_EEPROM)
#error Choose only one memory
#endif
//#define SEPARATED_STATUS_REGISTER
/////////////////////////////////////////////////////////////////////
////////////////////////////---DEFINES---////////////////////////////
/**
* @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 Defines for MEMORY chip.
*/
#define MEMSPI_Select(_hmemspi_) (_hmemspi_->GPIOs.CS_GPIOx->BSRR = _hmemspi_->GPIOs.CS_PIN << 16)
#define MEMSPI_Deselect(_hmemspi_) (_hmemspi_->GPIOs.CS_GPIOx->BSRR = _hmemspi_->GPIOs.CS_PIN)
#define MEMSPI_SECTOR_SIZE (0x1000)
#define MEMSPI_PAGE_SIZE (0x100)
/**
* @brief Defines for CMD.
*/
#define MEMSPI_READ_JEDEC_ID 0x9F
#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
#define MEMSPI_READ_STATUS_REG 0x05
#if defined(SEPARATED_STATUS_REGISTER)
#define MEMSPI_READ_STATUS_REG_2 0x35
#endif
#define MEMSPI_READ_DATA 0x03
/**
* @brief Defines for Status Register.
*/
#define MEMSPI_Get_Flag(_hmemspi_,_flag_) (((MEMSPI_StatusRegisterTypeDef)(_hmemspi_->SR))._flag_)
// FLASH SR
#define MEMSPI_SR_SUS (1<<15)
#define MEMSPI_SR_QE (1<<9)
#define MEMSPI_SR_SRP1 (1<<8)
#define MEMSPI_SR_SRP0 (1<<7)
#define MEMSPI_SR_SEC (1<<6)
#define MEMSPI_SR_TB (1<<5)
#define MEMSPI_SR_BP2 (1<<4)
#define MEMSPI_SR_BP1 (1<<3)
#define MEMSPI_SR_BP0 (1<<2)
#define MEMSPI_SR_WEL (1<<1)
#define MEMSPI_SR_BUSY (1<<0)
// Exclusive (only by name) EEPROM SR bits
#define MEMSPI_SR_SRWD MEMSPI_SR_SRP0
#define MEMSPI_SR_WIP MEMSPI_SR_WEL
/**
* @brief Calc dividing including remainder (divide and ceil)
* @param _val_ - делимое.
* @param _div_ - делитель.
* @note Если результат деления без остатка: он возвращается как есть
* Если с остатком - округляется вверх
*/
//#define Divide_Up(_val_, _div_) (((_val_)%(_div_))? (_val_)/(_div_)+1 : (_val_)/_div_) /* через тернарный оператор */
#define Divide_Up(_val_, _div_) ((_val_ - 1) / _div_) + 1 /* через мат выражение */
////////////////////////////---DEFINES---////////////////////////////
/////////////////////////////////////////////////////////////////////
///////////////////////---STRUCTURES & ENUMS---//////////////////////
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;
typedef struct
{
uint16_t SR;
SPI_HandleTypeDef hspi;
GPIO_TypeDef *CS_GPIOx;
uint32_t CS_PIN;
GPIO_TypeDef *CLK_GPIOx;
uint32_t CLK_PIN;
GPIO_TypeDef *MISO_GPIOx;
uint32_t MISO_PIN;
GPIO_TypeDef *MOSI_GPIOx;
uint32_t MOSI_PIN;
}MEMSPI_GPIOTypeDef;
typedef struct
{
uint16_t SR;
SPI_HandleTypeDef hspi;
MEMSPI_GPIOTypeDef GPIOs;
uint32_t hNextAddr;
uint16_t hNextPage;
uint16_t hNextSector;
}MEMSPI_HandleTypeDef;
extern MEMSPI_HandleTypeDef hmemspi;
///////////////////////---STRUCTURES & ENUMS---//////////////////////
/////////////////////////////////////////////////////////////////////
///////////////////////---FUNCTIONS FOR USER---//////////////////////
/**
* @brief Initialize SPI and GPIO for MEMSPI FLASH.
* @param hmemspi - указатель на структуру с настройками SPI и GPIO портов.
*/
void MEMSPI_Base_Init(MEMSPI_HandleTypeDef *hmemspi);
/**
* @brief Read external FLASH.
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
///////////////////////---FUNCTIONS FOR USER---//////////////////////
/////////////////////////////////////////////////////////////////////
////////////////////////---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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @brief Update Timeout variables.
* @param Timeout - указатель на переменную содержащию значение таймаута
* @param tickstart - указатель на переменную содержащию начальное кол-во тиков.
*/
void MEMSPI_Update_Timeout_Variables(uint32_t *Timeout, uint32_t *tickstart);
////////////////////////---SERVICE FUNCTIONS---//////////////////////
/////////////////////////////////////////////////////////////////////
//////////////////////---FUNCTION FOR COMMAND---/////////////////////
/**
* @brief Send command to read Status Register.
* @param hmemspi - указатель на хендл внешней памяти.
* @param RequestedBits - какие биты запросить.
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @brief Send command to erase sector of FLASH.
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
//////////////////////---FUNCTION FOR COMMAND---/////////////////////
#endif // __SPI_MEMORY_H_