Files
STM32_MemorySPI/spi_flash/spi_flash.h

304 lines
15 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.
/********************************W25 FLASH**********************************
Данный файл содержит инклюды и дефайны для общения с памятью FLASH по SPI.
***************************************************************************/
#ifndef __SPI_FLASH_H_
#define __SPI_FLASH_H_
#include "stm32f4xx_hal.h"
#include "gpio_general.h"
/////////////////////////---USER SETTINGS---/////////////////////////
#define W25_Internal_Flash_Buffer_For_reProgram_BankNumber FLASH_BANK_1
#define W25_Internal_Flash_Buffer_For_reProgram_SectNumber FLASH_SECTOR_11
#define W25_Internal_Flash_Buffer_For_reProgram_Address 0x08E000000
/////////////////////////////////////////////////////////////////////
////////////////////////////---DEFINES---////////////////////////////
/**
* @brief Defines for W25 chip.
*/
#define W25_Select(_hw25_) (_hw25_->GPIOs.CS_GPIOx->BSRR = _hw25_->GPIOs.CS_PIN << 16)
#define W25_Deselect(_hw25_) (_hw25_->GPIOs.CS_GPIOx->BSRR = _hw25_->GPIOs.CS_PIN)
#define W25_SECTOR_SIZE (0x1000)
#define W25_PAGE_SIZE (0x100)
/**
* @brief Defines for CMD.
*/
#define W25_READ_JEDEC_ID 0x9F
#define W25_READ_UNIQUE_ID 0x4B
#define W25_WRITE_ENABLE 0x06
#define W25_WRITE_DISABLE 0x04
#define W25_WRITE_STATUS_REG 0x01
#define W25_ERASE_SECTOR 0x20
#define W25_PAGE_PROGRAM 0x02
#define W25_READ_STATUS_REG_1 0x05
#define W25_READ_STATUS_REG_2 0x35
#define W25_READ_DATA 0x03
/**
* @brief Defines for Status Register.
*/
#define W25_Get_Flag(_hw25_,_flag_) (((W25_StatusRegisterTypeDef)(_hw25_->SR))._flag_)
#define W25_SR_SUS (1<<15)
#define W25_SR_QE (1<<9)
#define W25_SR_SRP1 (1<<8)
#define W25_SR_SRP0 (1<<7)
#define W25_SR_SEC (1<<8)
#define W25_SR_TB (1<<5)
#define W25_SR_BP2 (1<<4)
#define W25_SR_BP1 (1<<3)
#define W25_SR_BP0 (1<<2)
#define W25_SR_WEL (1<<1)
#define W25_SR_BUSY (1<<0)
/**
* @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;
}W25_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;
}W25_GPIOTypeDef;
typedef struct
{
uint16_t SR;
SPI_HandleTypeDef hspi;
W25_GPIOTypeDef GPIOs;
}W25_HandleTypeDef;
extern W25_HandleTypeDef hw25;
///////////////////////---STRUCTURES & ENUMS---//////////////////////
/////////////////////////////////////////////////////////////////////
///////////////////////---FUNCTIONS FOR USER---//////////////////////
/**
* @brief Initialize SPI and GPIO for W25 FLASH.
* @param hw25 - указатель на структуру с настройками SPI и GPIO портов.
*/
void W25_Base_Init(W25_HandleTypeDef *hw25);
/**
* @brief Read data from external FLASH.
* @param hw25 - указатель на хендл flash.
* @param FLASH_Address - адресс откуда начинать считывание.
* @param pBuff - куда записывать данные из FLASH.
* @param Size - сколько байтов считывать.
* @param Timeout - время, за которое должно быть осуществлено чтение.
* @return HAL status.
* @note Включает в себя проверку на доступность памяти (флаг BUSY)
*/
HAL_StatusTypeDef W25_FLASH_Read(W25_HandleTypeDef *hw25, uint32_t FLASH_Address, uint8_t *pBuff, uint16_t Size, uint32_t Timeout);
/**
* @brief Write data to area in FLASH.
* @param hw25 - указатель на хендл flash.
* @param WriteInit - указатель на структуру, определяющую участок памяти для записи.
* @param Timeout - время, за которое должно быть осуществлено чтение.
* @return HAL status.
* @note Позволяет перепрограммировать участок памяти. Можно записывать несколько страниц.
* Данные в сектора участка, но за пределами участка не сохраняются.
*/
HAL_StatusTypeDef W25_FLASH_Write_Area(W25_HandleTypeDef *hw25, W25_WriteInitTypeDef *WriteInit, uint32_t Timeout);
/**
* @brief Program area in FLASH.
* @param hw25 - указатель на хендл flash.
* @param FLASH_Address - адресс куда начинать записывать.
* @param pData - откуда брать данные для записи в FLASH.
* @param Size - сколько байтов записать.
* @param Timeout - время, за которое должно быть осуществлено чтение.
* @return HAL status.
* @note Позволяет перепрограммировать участок памяти. Можно записывать несколько страниц.
* Данные в сектора участка, но за пределами участка не сохраняются.
*/
HAL_StatusTypeDef W25_FLASH_Program_Area(W25_HandleTypeDef *hw25, uint32_t FLASH_Address, uint8_t *pData, uint16_t Size, uint32_t Timeout);
/**
* @brief Erase FLASH Sector.
* @param hw25 - указатель на хендл flash.
* @param FLASH_Address - адресс где надо данные стереть.
* @param Timeout - время, за которое должно быть осуществлена очистка.
* @return HAL status.
* @note При Timeout = 0, функция не будет ожидать окончания очистки (выставления в 0 флагов BUSY и WEL)
* @note Микросхема вроде сама высчитывает какой сектор ерейзнуть, в соответствии с заданным адресом.
*/
HAL_StatusTypeDef W25_FLASH_Erase_Sector(W25_HandleTypeDef *hw25, uint32_t FLASH_Address, uint32_t Timeout);
/**
* @brief Program page in FLASH.
* @param hw25 - указатель на хендл flash.
* @param FLASH_Address - адресс куда начинать записывать.
* @param pData - откуда брать данные для записи в FLASH.
* @param Size - сколько байтов записать.
* @param Timeout - время, за которое должно быть осуществлено чтение.
* @param tickstart - время, относительно которого надо отсчитывать таймаут.
* @return HAL status.
* @note Позволяет перепрограммировать только байты в прелелах одной страницы.
Для более гибкого программирования есть функция W25_FLASH_Program_Area, которая программирует участки любой длины (в теории).
*/
HAL_StatusTypeDef W25_FLASH_Program_Page(W25_HandleTypeDef *hw25, uint32_t FLASH_Address, uint8_t *pData, uint16_t Size, uint32_t Timeout, uint32_t tickstart);
/**
* @brief Setting WEL bit until it setted or until timeout.
* @param hw25 - указатель на хендл flash.
* @param Timeout - время, за которое должно быть осуществлено чтение.
* @param tickstart - время, относительно которого надо отсчитывать таймаут.
* @return HAL status.
* @note Подает команду на разрешение записи до тех пор, пока она запись не разрешиться или до тех пор, пока таймаут не истечет.
*/
HAL_StatusTypeDef W25_WriteEnablingUntilTimeout(W25_HandleTypeDef *hw25, uint32_t Timeout, uint32_t tickstart);
/**
* @brief Wait for flag until timeout.
* @param hw25 - указатель на хендл flash.
* @param FlagMask - маска для флагов, какие флаги считывать.
* @param FlagStatus - какое состояние должно быть у выбранных флагов.
* @param Timeout - время, за которое должно быть осуществлено чтение.
* @param tickstart - время, относительно которого надо отсчитывать таймаут.
* @return HAL status.
* @note Считывает флаги до тех пор, пока они не будут в состоянии FlagStatus или до тех пор, пока таймаут не истечет.
*/
HAL_StatusTypeDef W25_WaitOnFlagUntilTimeout(W25_HandleTypeDef *hw25, uint16_t FlagMask, uint16_t FlagStatus, uint32_t Timeout, uint32_t tickstart);
///////////////////////---FUNCTIONS FOR USER---//////////////////////
/////////////////////////////////////////////////////////////////////
//////////////////////---FUNCTION FOR COMMAND---/////////////////////
/**
* @brief Send command to read Status Register.
* @param hw25 - указатель на хендл flash.
* @param RequestedBits - какие биты запросить.
* @return Заполняет Status Register в hw25.
* @note Всего есть две комманды: на запрос верхнего или нижниго байта.
* Функция в соответствии с RequestedBits определяет какой байт запросить, или два байта сразу.
*/
void W25_CMD_Read_Status_Register(W25_HandleTypeDef *hw25, uint16_t RequestedBits);
/**
* @brief Send command to write bits in Status Register.
* @param hw25 - указатель на хендл flash.
* @param WrittenBits - какие биты запросить.
* @note Данная команда посылает биты, как сдвинутые на 2 вправо. Т.е. 0-й бит в комманде - 2-й бит BP0.
Но биты указываются в также как они расположены и регистре. Функция сама выполняет сдвиг.
*/
void W25_CMD_Write_Status_Register(W25_HandleTypeDef *hw25, uint16_t WrittenBits);
/**
* @brief Send command to set Write Enable Latch (WEL) in Status Register.
* @param hw25 - указатель на хендл flash.
* @note Разрешает запись в FLASH, путем высталения WEL в Status Register
*/
void W25_CMD_Write_Enable(W25_HandleTypeDef *hw25);
/**
* @brief Send command to read data from FLASH.
* @param hw25 - указатель на хендл flash.
* @param FLASH_Address - адресс откуда начинать считывание.
* @param pBuff - куда записывать данные из FLASH.
* @param Size - сколько байтов считывать.
* @return pBuff.
*/
void W25_CMD_Read_Data(W25_HandleTypeDef *hw25, uint32_t FLASH_Address, uint8_t *pBuff, uint16_t Size);
/**
* @brief Send command to fast read data from FLASH.
* @param hw25 - указатель на хендл flash.
* @param FLASH_Address - адресс откуда начинать считывание.
* @param pBuff - куда записывать данные из FLASH.
* @param Size - сколько байтов считывать.
* @note Данная функция предполагает отправку одного dummy байта после адресса, но у меня поч не работает пока :(
*/
void W25_CMD_Fast_Read(W25_HandleTypeDef *hw25, uint32_t FLASH_Address, uint8_t *pBuff, uint16_t Size);
/**
* @brief Send command to fast page program.
* @param hw25 - указатель на хендл flash.
* @param FLASH_Address - адресс куда начинать записывать.
* @param pData - откуда брать данные для записи в FLASH.
* @param Size - сколько байтов записать.
* @note Программирование FLASH только в пределах одной страницы.
* Т.е. если запись с 0x0, то не больше 256 байт. Если с 0ч40, то не больше 192 байт.
*/
void W25_CMD_Page_Program(W25_HandleTypeDef *hw25, uint32_t FLASH_Address, uint8_t *pData, uint16_t Size);
/**
* @brief Send command to erase sector.
* @param hw25 - указатель на хендл flash.
* @param FLASH_Address - адресс где надо данные стереть.
* @note Микросхема вроде сама высчитывает какой сектор ерейзнуть, в соответствии с заданным адресом.
*/
void W25_CMD_Erase_Sector(W25_HandleTypeDef *hw25, uint32_t FLASH_Address);
/**
* @brief Send command to read JEDEC ID.
* @param hw25 - указатель на хендл flash.
* @return JEDEC ID микросхемы.
*/
uint32_t W25_CMD_Read_JEDEC_ID(W25_HandleTypeDef *hw25);
/**
* @brief Send command to read JEDEC ID.
* @param hw25 - указатель на хендл flash.
* @return Device ID микросхемы.
*/
uint64_t W25_CMD_Read_Device_ID(W25_HandleTypeDef *hw25);
//////////////////////---FUNCTION FOR COMMAND---/////////////////////
/////////////////////////////////////////////////////////////////////
//////////////////////---FUNCTION FOR PERIPTH---/////////////////////
/**
* @brief SPI Transmit.
* @param hw25 - указатель на хендл flash.
* @param data - указатель на данные для отправки.
* @param size - размер данных для отправки.
* @return Device ID микросхемы.
* @note Здесь вызывается только функция HAL, и ничего больше.
*/
void W25_SPI_Transmit (W25_HandleTypeDef *hw25, uint8_t *data, uint16_t size);
/**
* @brief SPI Receive.
* @param hw25 - указатель на хендл flash.
* @param data - указатель на буффер для прниема данных.
* @param size - размер данных для приема.
* @return Device ID микросхемы.
* @note Здесь вызывается только функция HAL, и ничего больше.
*/
void W25_SPI_Receive (W25_HandleTypeDef *hw25, uint8_t *data, uint16_t size);
//////////////////////---FUNCTION FOR PERIPTH---/////////////////////
#endif // __SPI_FLASH_H_