Files
STM32_MemorySPI/spi_flash/spi_flash.h
alexey 7dfb95b9f1 init commit
SPI FLASH only, I2C eeprom later
2024-08-12 17:09:48 +03:00

291 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***********************************
Данный файл содержит базовые функции для общения с SPI Flash.
//-------------------Функции-------------------//
@func users
- W25_FLASH_Read Считывание FLASH
- W25_FLASH_Write_Area Запись данных в заданный участок FLASH (с потерей данных в выбраном сектора за пределами этого участка)
- W25_FLASH_Erase_Sector Очистка сектора FLASH
- W25_FLASH_Program_Area Программирование FLASH
@func initialization
- W25_Base_Init Инициализация SPI и GPIO для FLASH
@func process interaction with flash
- W25_FLASH_Program_Page Программирование страницы. *есть более общая функция W25_FLASH_Program_Area, которая программирует участки больше страницы
- W25_WriteEnablingUntilTimeout Разрешение записи, пока не будет ответа или не истек таймаут
- W25_WaitOnFlagUntilTimeout Ожидание флага пока не истек таймаута
@func cmd functions
- W25_CMD_Read_Status_Register Отправка комманд Read Status Register 1 / Read Status Register 1 (0x05h / 0x35h)
- W25_CMD_Write_Status_Register Отправка комманды Write Status Register (0x01h)
- W25_CMD_Write_Enable Отправка комманды Write Enable (0x06h)
- W25_CMD_Write_Disable Отправка комманды Write Disable (0x04h)
- W25_CMD_Read_Data Отправка комманды Read Data (0x03h)
- W25_CMD_Fast_Read Отправка комманды Fast Read (0x0Bh)
- W25_CMD_Page_Program Отправка комманды Page Program (0x02h)
- W25_CMD_Erase_Sector Отправка комманды Erase Sector (0x20h)
- W25_CMD_Read_JEDEC_ID Отправка комманды Read JEDEC ID (0x4Bh)
- W25_CMD_Read_Device_ID Отправка комманды Read Manufacture / Device Id (0x90)
@func SPI functions
- W25_SPI_Transmit Функция отправки по SPI (содержит только HAL_SPI_Transmit)
- W25_SPI_Receive Функция приема по SPI (содержит только HAL_SPI_Receive)
***************************************************************************/
#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 CMD.
*/
#define W25_CS_Set(_hw25_) (_hw25_->GPIOs.CS_GPIOx->BSRR = _hw25_->GPIOs.CS_PIN << 16)
#define W25_CS_Reset(_hw25_) (_hw25_->GPIOs.CS_GPIOx->BSRR = _hw25_->GPIOs.CS_PIN)
/**
* @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 Defines for W25 chip.
*/
#define W25_SECTOR_SIZE (0x1000)
#define W25_PAGE_SIZE (0x100)
/**
* @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_reProgramInitTypeDef;
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---///////////////////////////
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 reProgramInit - указатель на структуру, определяющую участок памяти для записи.
* @param Timeout - время, за которое должно быть осуществлено чтение.
* @return HAL status.
* @note Позволяет перепрограммировать участок памяти. Можно записывать несколько страниц.
* Данные в сектора участка, но за пределами участка не сохраняются.
*/
HAL_StatusTypeDef W25_FLASH_Write_Area(W25_HandleTypeDef *hw25, W25_reProgramInitTypeDef *reProgramInit, uint32_t Timeout);
/**
* @brief Program area in FLASH.
* @param hw25 - указатель на хендл flash.
* @param reProgramInit - указатель на структуру, определяющую участок памяти для записи.
* @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 reProgramInit - указатель на структуру, определяющую участок памяти для записи.
* @param Timeout - время, за которое должно быть осуществлено чтение.
* @return HAL status.
* @note Позволяет перепрограммировать участок памяти. Можно записывать несколько страниц.
* Данные в сектора участка, но за пределами участка не сохраняются.
*/
HAL_StatusTypeDef W25_FLASH_Erase_Sector(W25_HandleTypeDef *hw25, uint32_t FLASH_Address, uint32_t Timeout);
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);
HAL_StatusTypeDef W25_WriteEnablingUntilTimeout(W25_HandleTypeDef *hw25, uint32_t Timeout, uint32_t tickstart);
HAL_StatusTypeDef W25_WaitOnFlagUntilTimeout(W25_HandleTypeDef *hw25, uint16_t FlagMask, uint16_t FlagStatus, uint32_t Timeout, uint32_t tickstart);
/**
* @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);
/**
* @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);
///////////////////////////---FUNCTIONS---///////////////////////////