diff --git a/CubeKeil Example/Core/Src/main.c b/CubeKeil Example/Core/Src/main.c
index baca127..c4cea99 100644
--- a/CubeKeil Example/Core/Src/main.c
+++ b/CubeKeil Example/Core/Src/main.c
@@ -58,7 +58,7 @@ void SystemClock_Config(void);
/* USER CODE BEGIN 0 */
W25_HandleTypeDef hw25;
HAL_StatusTypeDef W25_RES;
-W25_reProgramInitTypeDef writeInit;
+W25_WriteInitTypeDef writeInit;
uint8_t read_buff[20] = {0};
uint8_t write_buff[20] = {0x14,0x13,0x12,0x11,0x10,
@@ -115,16 +115,16 @@ int main(void)
/* Infinite loop */
/* USER CODE BEGIN WHILE */
- // Example for using manufactire info CMD
+ // Example for FLASH: using manufactire info CMD
uint32_t w25_ID = W25_CMD_Read_JEDEC_ID(&hw25);
uint64_t w25_unique_ID = W25_CMD_Read_Device_ID(&hw25);
- // Example for erase/program/read functions
+ // Example for FLASH: erase/program/read functions
W25_RES = W25_FLASH_Erase_Sector(&hw25, 0, 1000);
W25_RES = W25_FLASH_Program_Area(&hw25, 0xf9, write_buff, 15, 100);
W25_CMD_Read_Data(&hw25, 0xf9, read_buff, 15);
- // Example for write area functions
+ // Example for FLASH: write area functions init
writeInit.pDataPtr = write_buff;
writeInit.Data_Address = 0xfb;
writeInit.Data_Size = 1;
@@ -132,6 +132,7 @@ int main(void)
writeInit.Sector_Size = 15;
while (1)
{
+ // Example for FLASH: write area functions
W25_FLASH_Write_Area(&hw25, &writeInit, 1000);
HAL_Delay(10);
W25_CMD_Read_Data(&hw25, 0xf9, read_buff, 15);
diff --git a/CubeKeil Example/MDK-ARM/flash eeprom Example.uvoptx b/CubeKeil Example/MDK-ARM/flash eeprom Example.uvoptx
index b6013b6..de0ccbe 100644
--- a/CubeKeil Example/MDK-ARM/flash eeprom Example.uvoptx
+++ b/CubeKeil Example/MDK-ARM/flash eeprom Example.uvoptx
@@ -154,7 +154,7 @@
0
135
1
-
134230134
+ 134230152
0
0
0
@@ -165,6 +165,22 @@
\\flash_eeprom_Example\../Core/Src/main.c\135
+
+ 1
+ 0
+ 136
+ 1
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ ../Core/Src/main.c
+
+
+
@@ -312,18 +328,6 @@
2
2
- 5
- 0
- 0
- 0
- ..\Core\Inc\stm32f4xx_hal_conf.h
- stm32f4xx_hal_conf.h
- 0
- 0
-
-
- 2
- 3
1
0
0
@@ -335,7 +339,7 @@
2
- 4
+ 3
1
0
0
@@ -347,7 +351,7 @@
2
- 5
+ 4
1
0
0
@@ -359,7 +363,7 @@
2
- 6
+ 5
1
0
0
@@ -371,7 +375,7 @@
2
- 7
+ 6
1
0
0
@@ -383,7 +387,7 @@
2
- 8
+ 7
1
0
0
@@ -393,6 +397,18 @@
0
0
+
+ 2
+ 8
+ 5
+ 0
+ 0
+ 0
+ ..\Core\Inc\stm32f4xx_hal_conf.h
+ stm32f4xx_hal_conf.h
+ 0
+ 0
+
@@ -649,7 +665,7 @@
5
28
1
- 1
+ 0
0
0
..\..\spi_flash\spi_flash.c
@@ -684,7 +700,7 @@
0
0
0
- ..\..\..\.GENERAL\gpio_general.c
+ ..\..\GENERAL\gpio_general.c
gpio_general.c
0
0
@@ -696,7 +712,7 @@
0
0
0
- ..\..\..\.GENERAL\gpio_general.h
+ ..\..\GENERAL\gpio_general.h
gpio_general.h
0
0
@@ -708,7 +724,7 @@
0
0
0
- ..\..\..\.GENERAL\periph_general.h
+ ..\..\GENERAL\periph_general.h
periph_general.h
0
0
diff --git a/CubeKeil Example/MDK-ARM/flash eeprom Example.uvprojx b/CubeKeil Example/MDK-ARM/flash eeprom Example.uvprojx
index 64b6699..445a7e9 100644
--- a/CubeKeil Example/MDK-ARM/flash eeprom Example.uvprojx
+++ b/CubeKeil Example/MDK-ARM/flash eeprom Example.uvprojx
@@ -395,11 +395,6 @@
Application/User/Core
-
- stm32f4xx_hal_conf.h
- 5
- ..\Core\Inc\stm32f4xx_hal_conf.h
-
main.c
1
@@ -430,6 +425,11 @@
1
../Core/Src/stm32f4xx_hal_msp.c
+
+ stm32f4xx_hal_conf.h
+ 5
+ ..\Core\Inc\stm32f4xx_hal_conf.h
+
@@ -609,17 +609,17 @@
gpio_general.c
1
- ..\..\..\.GENERAL\gpio_general.c
+ ..\..\GENERAL\gpio_general.c
gpio_general.h
5
- ..\..\..\.GENERAL\gpio_general.h
+ ..\..\GENERAL\gpio_general.h
periph_general.h
5
- ..\..\..\.GENERAL\periph_general.h
+ ..\..\GENERAL\periph_general.h
diff --git a/GENERAL/flash_general.c b/GENERAL/flash_general.c
deleted file mode 100644
index f904b65..0000000
--- a/GENERAL/flash_general.c
+++ /dev/null
@@ -1,190 +0,0 @@
-#include "flash_general.h"
-FLASH_EraseInitTypeDef EraseInitStruct;
-extern HAL_StatusTypeDef res_hal;
-unsigned CRC_Update;
-//uint32_t PAGE_OFFSET = ((uint32_t)((4-1) * 0x0400));
-uint32_t PAGE_NUMB = 127;
-
-//----------------------------------------------------------
-/*-----------------BOOTLOADER FUNCTIONS-------------------*/
-
-/* Записать в память данные, произвольного размера */
-HAL_StatusTypeDef FLASH_Write_Data(uint32_t* Address, uint8_t* Data, int Data_size)
-{
- int data_cnt = 0;
- uint32_t adr;а
- uint32_t word_data;
-
-
- res_hal = HAL_FLASH_Unlock();
-
- if (res_hal != HAL_OK) return res_hal;
-
- for (adr = *Address; adr < *Address + Data_size; adr = adr + 4)
- {
-
-
- word_data = (
- Data[data_cnt] |
- Data[data_cnt + 1] << 8 |
- Data[data_cnt + 2] << 16 |
- Data[data_cnt + 3] << 24);
-
- if (adr == (0x40+USART2_IRQn*4)+MAIN_APP_START_ADDRESS)
- {
- // check if uart handler is correct
- if (word_data == FLASH_Read_Word(MAIN_APP_START_ADDRESS+4) + 0x1A) // if there is no specific address for uart handler
- {
- word_data = FLASH_Read_Word(UART_HANDLER_ADD); // write address of bootloader uart handler
- CRC_Update = 1;
-
- }
- }
-
- res_hal = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, adr, word_data);
-
- if (res_hal != HAL_OK) return res_hal;
-
- data_cnt += 4;
- }
-
- *Address += Data_size;
- res_hal = HAL_FLASH_Lock();
-
- return res_hal;
-}
-
-/* Очистить приложение */
-HAL_StatusTypeDef FLASH_Erase_App(void) //
-{
- uint32_t PageError = 0x00;
-
- res_hal = HAL_FLASH_Unlock();
-
- if (res_hal != HAL_OK)
- {
- __ASM("");
- return res_hal;
- }
-
- EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;// erase pages
- EraseInitStruct.Banks = FLASH_BANK_1;
- EraseInitStruct.Sector = KEY_FLASH_SECTOR_X+1; //first sector for erase
- EraseInitStruct.NbSectors = 8;// num of sector that need to be erased
-
- res_hal = HAL_FLASHEx_Erase(&EraseInitStruct, &PageError);
-
- if (res_hal != HAL_OK)
- {
- __ASM("");
- return res_hal;
- }
-
- res_hal = HAL_FLASH_Lock();
-
- return res_hal;
-}
-
-/* Записать ключ в память */
-void SetKey(void)
-{
- HAL_FLASH_Unlock();
-
- HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, BOOTLOADER_KEY_SECTOR_ADR, BL_KEY_APP_WRITTEN);
-
- HAL_FLASH_Lock();
-}
-/* Считать ключ из памяти */
-uint32_t ReadKey(void)
-{
- return (*(__IO uint32_t*)BOOTLOADER_KEY_SECTOR_ADR);
-}
-/* Очистить настройки бутлоадера для запуска приложения (CRC) */
-void ResetAppSettings(void)
-{
- HAL_FLASH_Unlock();
- uint32_t PageError = 0x00;
-
- EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;// erase pages
- EraseInitStruct.Banks = APP_SET_FLASH_BANK_X;
- EraseInitStruct.Sector = APP_SET_FLASH_SECTOR_X; //address
- EraseInitStruct.NbSectors = 1;// num of erased pages
-
- HAL_FLASHEx_Erase(&EraseInitStruct, &PageError);
- HAL_FLASH_Lock();
-
-}
-/* Очистить сектор с ключом (ключ, количество перезагрузок из-за WDGT) */
-void ResetKeySector(void)
-{
- HAL_FLASH_Unlock();
- uint32_t PageError = 0x00;
-
- EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;// erase pages
- EraseInitStruct.Banks = KEY_FLASH_BANK_X;
- EraseInitStruct.Sector = KEY_FLASH_SECTOR_X; //address
- EraseInitStruct.NbSectors = 1;// num of erased pages
-
- HAL_FLASHEx_Erase(&EraseInitStruct, &PageError);
- HAL_FLASH_Lock();
-
-}
-/*-----------------BOOTLOADER FUNCTIONS-------------------*/
-//----------------------------------------------------------
-
-
-
-//-----------------ELEMENTARY FUNCTIONS---------------------
-/* functions for reading bytes/halswords/words */
-uint8_t FLASH_Read_Byte(uint32_t add)
-{
- return (*(__IO uint8_t*)(add));
-}
-uint16_t FLASH_Read_HalfWord(uint32_t add)
-{
- return (*(__IO uint16_t*)(add));
-}
-uint32_t FLASH_Read_Word(uint32_t add)
-{
- return (*(__IO uint32_t*)(add));
-}
-/* functions for writing bytes/halswords/words */
-HAL_StatusTypeDef FLASH_Write_Byte(uint32_t Address, uint8_t Data)
-{
- res_hal = HAL_FLASH_Unlock();
-
- if (res_hal != HAL_OK) return res_hal;
-
- res_hal = HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, Address, (uint8_t)(Data));
-
- if (res_hal != HAL_OK) return res_hal;
-
- res_hal = HAL_FLASH_Lock();
- return res_hal;
-}
-HAL_StatusTypeDef FLASH_Write_HalfWord(uint32_t Address, uint16_t Data)
-{
- res_hal = HAL_FLASH_Unlock();
-
- if (res_hal != HAL_OK) return res_hal;
-
- res_hal = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, Address, (uint16_t)(Data));
-
- if (res_hal != HAL_OK) return res_hal;
-
- res_hal = HAL_FLASH_Lock();
- return res_hal;
-}
-HAL_StatusTypeDef FLASH_Write_Word(uint32_t Address, uint32_t Data)
-{
- res_hal = HAL_FLASH_Unlock();
- if (res_hal != HAL_OK) return res_hal;
-
- res_hal = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Address, (uint32_t)(Data));
- if (res_hal != HAL_OK) return res_hal;
-
- res_hal = HAL_FLASH_Lock();
- return res_hal;
-}
-//----------------------------------------------------------
-
diff --git a/GENERAL/flash_general.h b/GENERAL/flash_general.h
deleted file mode 100644
index 4d23041..0000000
--- a/GENERAL/flash_general.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*********************************UART**************************************
-Данный файл содержит объявления базовых функции и дефайны для инициализации
-UART.
-***************************************************************************/
-#ifndef __UART_GENERAL_H_
-#define __UART_GENERAL_H_
-
-//////////////////////////////////////////////////////////////////////
-/////////////////////////---USER SETTINGS---/////////////////////////
-#define HAL_UART_MODULE_ENABLED // need to uncomment these defines in stm32f4xx_hal_conf.h
-#define HAL_USART_MODULE_ENABLED // also need to add hal_uart.c (source code)
-
-//#define USE_USART1
-//#define USE_USART2
-//#define USE_USART3
-//#define USE_UART4
-//#define USE_UART5
-//#define USE_USART6
-/* note: used uart defines in modbus.h */
-
-/////////////////////////---USER SETTINGS---/////////////////////////
-#include "periph_general.h"
-
-
-
-/////////////////////////////////////////////////////////////////////
-////////////////////////////---DEFINES---////////////////////////////
-/**
- * @brief Analog for HAL define. Remade with pointer to structure.
- * @note @ref __HAL_LINKDMA.
- */
-#define __USER_LINKDMA(__HANDLE__, __PPP_DMA_FIELD__, __DMA_HANDLE__) \
-do{ \
-(__HANDLE__)->__PPP_DMA_FIELD__ = (__DMA_HANDLE__); \
-(__DMA_HANDLE__)->Parent = (__HANDLE__);} while(0U)
-
-
-////////////////////////////---DEFINES---////////////////////////////
-
-
-/////////////////////////////////////////////////////////////////////
-///////////////////////---STRUCTURES & ENUMS---//////////////////////
-typedef struct // struct with settings for custom function
-{
- UART_HandleTypeDef huart;
-
- GPIO_TypeDef *GPIOx;
- uint16_t GPIO_PIN_RX;
- uint16_t GPIO_PIN_TX;
-
- DMA_Stream_TypeDef *DMAChannel; // DMAChannel = 0 if doesnt need
- uint32_t DMA_CHANNEL_X; // DMAChannel = 0 if doesnt need
-
-
-}UART_SettingsTypeDef;
-///////////////////////---STRUCTURES & ENUMS---//////////////////////
-
-
-/////////////////////////////////////////////////////////////////////
-///////////////////////////---FUNCTIONS---///////////////////////////
-/**
- * @brief Initialize UART with UART_SettingsTypeDef structure.
- * @param suart - указатель на структуру с настройками UART.
- * @return HAL status.
- * @note Данная структура содержит хендл ЮАРТ и настройки перефирии (GPIO)
- */
-/* functions for reading bytes/halswords/words */
-uint8_t FLASH_Read_Byte(uint32_t add);
-uint16_t FLASH_Read_HalfWord(uint32_t add);
-uint32_t FLASH_Read_Word(uint32_t add);
-/* functions for writing bytes/halswords/words */
-HAL_StatusTypeDef FLASH_Write_Byte(uint32_t Address, uint8_t Data);
-HAL_StatusTypeDef FLASH_Write_HalfWord(uint32_t Address, uint16_t Data);
-HAL_StatusTypeDef FLASH_Write_Word(uint32_t Address, uint32_t Data);
-///////////////////////////---FUNCTIONS---///////////////////////////
-
-#endif // __UART_GENERAL_H_
\ No newline at end of file
diff --git a/GENERAL/gpio_general.c b/GENERAL/gpio_general.c
index 49e6fb5..5e866d0 100644
--- a/GENERAL/gpio_general.c
+++ b/GENERAL/gpio_general.c
@@ -1,4 +1,4 @@
-/**********************************TIM**************************************
+/*********************************GPIO**************************************
Данный файл содержит базовые функции для инициализации портов.
//-------------------Функции-------------------//
@func users
diff --git a/GENERAL/gpio_general.h b/GENERAL/gpio_general.h
index d7a9dea..18b2eb3 100644
--- a/GENERAL/gpio_general.h
+++ b/GENERAL/gpio_general.h
@@ -1,4 +1,4 @@
-/**********************************TIM**************************************
+/*********************************GPIO**************************************
Данный файл содержит объявления базовых функции и дефайны для инициализации
портов.
***************************************************************************/
@@ -7,13 +7,13 @@
#include "periph_general.h"
-
+/* undone
#define SPI_Alternate_Mapping(INSTANCE) ((((INSTANCE) == TIM1) || ((INSTANCE) == TIM2))? GPIO_AF1_TIM1: \
(((INSTANCE) == TIM3) || ((INSTANCE) == TIM4) || ((INSTANCE) == TIM5))? GPIO_AF2_TIM3: \
(((INSTANCE) == TIM8) || ((INSTANCE) == TIM9) || ((INSTANCE) == TIM10) || ((INSTANCE) == TIM11))? GPIO_AF3_TIM8: \
(((INSTANCE) == TIM12) || ((INSTANCE) == TIM13) || ((INSTANCE) == TIM14))? GPIO_AF9_TIM12: \
(0))
-
+*/
#define TIM_Alternate_Mapping(INSTANCE) ((((INSTANCE) == TIM1) || ((INSTANCE) == TIM2))? GPIO_AF1_TIM1: \
(((INSTANCE) == TIM3) || ((INSTANCE) == TIM4) || ((INSTANCE) == TIM5))? GPIO_AF2_TIM3: \
diff --git a/GENERAL/periph_general.h b/GENERAL/periph_general.h
index 1e7db4f..79a5118 100644
--- a/GENERAL/periph_general.h
+++ b/GENERAL/periph_general.h
@@ -1,4 +1,4 @@
-/**********************************TIM**************************************
+/********************************PERIPH*************************************
Данный файл содержит инклюды и дефайны для всех библиотек базовой перефирии.
***************************************************************************/
#ifndef __PERIPH_GENERAL_H_
diff --git a/spi_flash/spi_flash.c b/spi_flash/spi_flash.c
index fde2470..02b0809 100644
--- a/spi_flash/spi_flash.c
+++ b/spi_flash/spi_flash.c
@@ -1,336 +1,48 @@
+/********************************W25 FLASH**********************************
+Данный файл содержит базовые функции для общения с памятью FLASH по SPI.
+//-------------------Функции-------------------//
+@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 "spi_flash.h"
-uint8_t rx_buf[1025];
-uint8_t tx_buf[10];
uint8_t sector_buff[W25_SECTOR_SIZE];
/* USER CODE BEGIN PV */
char str1[30];
-//----------------------FUNCTION FUNCTIONS---------------------
//-------------------------------------------------------------
-HAL_StatusTypeDef W25_FLASH_Read(W25_HandleTypeDef *hw25, uint32_t FLASH_Address, uint8_t *pBuff, uint16_t Size, uint32_t Timeout)
-{
- uint32_t tickstart = HAL_GetTick();
-
- // wait for unbusy
- if(W25_WaitOnFlagUntilTimeout(hw25, W25_SR_BUSY, 0, Timeout, tickstart) != HAL_OK) // if its unbusy for timeout
- return HAL_TIMEOUT; // return timeout error
-
- W25_CMD_Read_Data(hw25, FLASH_Address, pBuff, Size);
- return HAL_OK;
-}
-HAL_StatusTypeDef W25_FLASH_Write_Area(W25_HandleTypeDef *hw25, W25_reProgramInitTypeDef *WriteInit, uint32_t Timeout)
-{
- uint8_t sector_buff[256];
- uint32_t tickstart = HAL_GetTick();
- uint32_t timeoutcnt = Timeout;
- HAL_StatusTypeDef W25_Status;
-
- // WAIT FOR UNBUSY
- if(W25_WaitOnFlagUntilTimeout(hw25, W25_SR_BUSY, 0, Timeout, tickstart) != HAL_OK) // if its unbusy for timeout
- return HAL_TIMEOUT; // return timeout error
-
- // SAVE USER "SECTOR" FROM FLASH
- timeoutcnt = HAL_GetTick() - tickstart; // update timeout
- Timeout -= timeoutcnt;
- tickstart += timeoutcnt;
- // store data from flash
- W25_Status = W25_FLASH_Read(hw25, WriteInit->Sector_Address, sector_buff, WriteInit->Sector_Size, Timeout);
- if(W25_Status != HAL_OK)
- return W25_Status;
-
- // ERASE SECTOR
- timeoutcnt = HAL_GetTick() - tickstart; // update timeout
- Timeout -= timeoutcnt;
- tickstart += timeoutcnt;
- // erase flash
- W25_Status = W25_FLASH_Erase_Sector(hw25, WriteInit->Sector_Address, Timeout);
- if(W25_Status != HAL_OK)
- return W25_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];
- }
-
- // RESTORE UPDATED DATA TO FLASH
- timeoutcnt = HAL_GetTick() - tickstart; // update timeout
- Timeout -= timeoutcnt;
- tickstart += timeoutcnt;
- // restore data to flash
- W25_Status = W25_FLASH_Program_Area(hw25, WriteInit->Sector_Address, sector_buff, WriteInit->Sector_Size, Timeout);
- if(W25_Status != HAL_OK)
- return W25_Status;
-
- return HAL_OK;
-}
-
-HAL_StatusTypeDef W25_FLASH_Program_Area(W25_HandleTypeDef *hw25, uint32_t FLASH_Address, uint8_t *pData, uint16_t Size, uint32_t Timeout)
-{
- uint32_t tickstart = HAL_GetTick();
- HAL_StatusTypeDef W25_Status;
-
- // CALC AREA TO PROGRAM
- uint16_t bytecnt = 0;
- uint16_t firstpage_size = 0;
- uint16_t lastpage_size = Size;
- uint16_t firstpage = (FLASH_Address/256);
- uint16_t lastpage = ((FLASH_Address+Size-1)/256);
- if(firstpage != lastpage) // if area is on several pages
- {
- firstpage_size = (firstpage+1)*256 - FLASH_Address; // set size of data at first page
- lastpage_size = (FLASH_Address+Size) - lastpage*256; // set size of data at last page
- }
-
- // PROGRAM PAGES: FROM FIRST NO THE PREVIOUS TO THE LAST
- for(int i = 0; i < lastpage - firstpage; i++)
- {
- W25_Status = W25_FLASH_Program_Page(hw25, FLASH_Address, &pData[bytecnt], firstpage_size, Timeout, tickstart); // programm page
- if(W25_Status != HAL_OK)
- return W25_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 += firstpage_size;
- FLASH_Address += firstpage_size;
- // and set start size as page size. because next pages will be fully programmed
- firstpage_size = W25_PAGE_SIZE;
- }
-
- // PROGRAM LAST PAGE
- W25_Status = W25_FLASH_Program_Page(hw25, FLASH_Address, &pData[bytecnt], lastpage_size, Timeout, tickstart); // programm page
- if(W25_Status != HAL_OK)
- return W25_Status;
-
- return HAL_OK; // if all ok return HAL_OK
-}
-
-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)
-{
- // enable writting and waiting for unbusy
- if(W25_WriteEnablingUntilTimeout(hw25, Timeout, tickstart) != HAL_OK) // if writting isnt enable
- return HAL_TIMEOUT; // return timeout
-
- // programm page (instruction)
- W25_CMD_Page_Program(hw25, FLASH_Address, pData, Size);
-
- // waiting for ending of writting
- if(W25_WaitOnFlagUntilTimeout(hw25, W25_SR_WEL|W25_SR_BUSY, 0, Timeout, tickstart) != HAL_OK) // if writting isnt done (W25 busy and WEL bit isnt in reset state)
- return HAL_TIMEOUT;
-
- return HAL_OK;
-}
-
-HAL_StatusTypeDef W25_FLASH_Erase_Sector(W25_HandleTypeDef *hw25, uint32_t FLASH_Address, uint32_t Timeout)
-{
- uint32_t tickstart = HAL_GetTick();
-
- // enable writting and waiting for unbusy
- if(W25_WriteEnablingUntilTimeout(hw25, Timeout, tickstart) != HAL_OK) // if writting isnt enable
- return HAL_TIMEOUT; // return timeout
-
- // programm page (instruction)
- W25_CMD_Erase_Sector(hw25, FLASH_Address);
-
- // waiting for ending of erasing
- if(W25_WaitOnFlagUntilTimeout(hw25, W25_SR_WEL|W25_SR_BUSY, 0, Timeout, tickstart) != HAL_OK) // if erase isnt done (W25 busy and WEL bit isnt in reset state)
- return HAL_TIMEOUT; // return timeout because erasing instruction accepted, but arent done
-
- return HAL_OK; // if all ok return HAL_OK
-}
-
-HAL_StatusTypeDef W25_WriteEnablingUntilTimeout(W25_HandleTypeDef *hw25, uint32_t Timeout, uint32_t tickstart)
-{
- // enable writting
- W25_CMD_Read_Status_Register(hw25, W25_SR_WEL|W25_SR_BUSY);
- while((hw25->SR&W25_SR_WEL) != W25_SR_WEL)
- {
- // if flash isnt busy - set WEL flag
- if((hw25->SR&W25_SR_BUSY) == 0)
- W25_CMD_Write_Enable(hw25);
-
- W25_CMD_Read_Status_Register(hw25, W25_SR_WEL);
- if((HAL_GetTick() - tickstart) >= Timeout) // if time is out
- return HAL_TIMEOUT; // set timeout
- }
- return HAL_OK; // if all ok return HAL_OK
-}
-
-HAL_StatusTypeDef W25_WaitOnFlagUntilTimeout(W25_HandleTypeDef *hw25, uint16_t FlagMask, uint16_t FlagStatus, uint32_t Timeout, uint32_t tickstart)
-{
- // enable writting
- W25_CMD_Read_Status_Register(hw25, FlagMask);
- while((hw25->SR&FlagMask) != FlagStatus)
- {
- W25_CMD_Read_Status_Register(hw25, FlagMask);
- if((HAL_GetTick() - tickstart) >= Timeout) // if time is out
- return HAL_TIMEOUT; // set timeout
- }
- return HAL_OK; // if all ok return HAL_OK
-}
-
-
-//-----------------ELEMENTARY COMMAND FUNCTIONS----------------
-//-------------------------------------------------------------
-void W25_CMD_Read_Data(W25_HandleTypeDef *hw25, uint32_t FLASH_Address, uint8_t *pBuff, uint16_t Size)
-{
- uint8_t command[4];
- uint8_t response[2] = {0};
-
- command[0] = W25_READ_DATA;
- command[1] = FLASH_Address >> 16 & 0xFF;
- command[2] = FLASH_Address >> 8 & 0xFF;
- command[3] = FLASH_Address & 0xFF;
-
- W25_CS_Set(hw25);
- W25_SPI_Transmit(hw25, command, 4);
- W25_SPI_Receive(hw25, pBuff, Size);
- W25_CS_Reset(hw25);
-}
-void W25_CMD_Fast_Read(W25_HandleTypeDef *hw25, uint32_t FLASH_Address, uint8_t *pBuff, uint16_t Size)
-{
- uint8_t command[5] = {0};
- uint8_t response[2] = {0};
-
- command[0] = W25_READ_DATA;
- command[1] = FLASH_Address >> 16 & 0xFF;
- command[2] = FLASH_Address >> 8 & 0xFF;
- command[3] = FLASH_Address & 0xFF;
- command[4] = 0xFF;
-
- W25_CS_Set(hw25);
- W25_SPI_Transmit(hw25, command, 5);
- W25_SPI_Receive(hw25, pBuff, Size);
- W25_CS_Reset(hw25);
-}
-void W25_CMD_Page_Program(W25_HandleTypeDef *hw25, uint32_t FLASH_Address, uint8_t *pData, uint16_t Size)
-{
- // 1 command byte + 3 address bytes + 256 data bytes
- uint8_t command[1+3+256];
- FLASH_Address = FLASH_Address & 0xFFFFFF;
-
- command[0] = W25_PAGE_PROGRAM;
- command[1] = FLASH_Address >> 16 & 0xFF;
- command[2] = FLASH_Address >> 8 & 0xFF;
- command[3] = FLASH_Address & 0xFF;
-
- if((FLASH_Address/256) != ((FLASH_Address+Size-1)/256))
- return;
-
- W25_CS_Set(hw25);
- W25_SPI_Transmit(hw25, command, 4); // send insctruction to write
- W25_SPI_Transmit(hw25, pData, Size); // send data to write
- W25_CS_Reset(hw25);
-}
-
-void W25_CMD_Erase_Sector(W25_HandleTypeDef *hw25, uint32_t FLASH_Address)
-{
- uint8_t command[4];
- uint8_t response[8];
- FLASH_Address = FLASH_Address & 0xFFFFFF;
-
- command[0] = W25_ERASE_SECTOR;
- command[1] = FLASH_Address >> 16;
- command[2] = FLASH_Address >> 8;
- command[3] = FLASH_Address;
-
- W25_CS_Set(hw25);
- W25_SPI_Transmit(hw25, command, 4);
- W25_CS_Reset(hw25);
-}
-
-void W25_CMD_Write_Enable(W25_HandleTypeDef *hw25)
-{
- uint8_t command[1];
- command[0] = W25_WRITE_ENABLE;
-
- W25_CS_Set(hw25);
- W25_SPI_Transmit(hw25, command, 1);
- W25_CS_Reset(hw25);
-}
-
-void W25_CMD_Write_Status_Register(W25_HandleTypeDef *hw25, uint16_t WrittenBits)
-{
- uint8_t command[2];
-
- command[0] = W25_WRITE_STATUS_REG;
- command[1] = WrittenBits >> 2;
-
- W25_CS_Set(hw25);
- W25_SPI_Transmit(hw25, command, 1);
- W25_CS_Reset(hw25);
-}
-
-void W25_CMD_Read_Status_Register(W25_HandleTypeDef *hw25, uint16_t RequestedBits)
-{
- uint8_t command[2];
- uint8_t *pSRPtr = 0;
- uint8_t size = 1;
-
- if(RequestedBits >> 8) // if its high byte of status register
- {
- command[0] = W25_READ_STATUS_REG_2;
- pSRPtr = (uint8_t *)(&hw25->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] = W25_READ_STATUS_REG_1;
- }
- }
- else // of its low byte of status register
- {
- command[0] = W25_READ_STATUS_REG_1;
- pSRPtr = (uint8_t *)(&hw25->SR); // set pointer to LO byte of SR register
- size = 1;
- }
-
- W25_CS_Set(hw25);
- W25_SPI_Transmit(hw25, command, 1); // send insctruction to read SR
- W25_SPI_Receive(hw25, pSRPtr, 1); // receive response
- W25_CS_Reset(hw25);
- if(size > 1) // if 2 bytes are requested
- {
- W25_CS_Set(hw25);
- W25_SPI_Transmit(hw25, command+1, 1); // send insctruction to read SR
- W25_SPI_Receive(hw25, pSRPtr-1, 1); // receive response
- W25_CS_Reset(hw25);
- }
-}
-uint32_t W25_CMD_Read_JEDEC_ID(W25_HandleTypeDef *hw25)
-{
- uint8_t dt[4] = {0};
- uint32_t return_val;
-
- tx_buf[0] = W25_READ_JEDEC_ID;
- W25_CS_Set(hw25);
- W25_SPI_Transmit(hw25, tx_buf, 1);
- W25_SPI_Receive(hw25, &dt[1], 3);
- W25_CS_Reset(hw25);
-
- return_val = (*(uint64_t *)dt);
- return __REV(return_val) & 0xFFFFFF;
-}
-
-uint64_t W25_CMD_Read_Device_ID(W25_HandleTypeDef *hw25)
-{
- uint8_t dt[8];
- uint64_t return_val_LO;
- uint64_t return_val_HI;
- tx_buf[0] = W25_READ_UNIQUE_ID;
- W25_CS_Set(hw25);
- W25_SPI_Transmit(hw25, tx_buf, 1);
- W25_SPI_Receive(hw25, dt, 8);
- W25_CS_Reset(hw25);
-
- return_val_LO = (*(uint64_t *)dt) >> 32;
- return_val_HI = (*(uint64_t *)dt) & 0xFFFFFFFF;
- return ((uint64_t)__REV(return_val_HI) << 32) | __REV(return_val_LO);
-}
-//-------------------------------------------------------------
-
+//--------------------------FOR USER---------------------------
+/**
+ * @brief Initialize SPI and GPIO for W25 FLASH.
+ * @param hw25 - указатель на структуру с настройками SPI и GPIO портов.
+ */
void W25_Base_Init(W25_HandleTypeDef *hw25)
{
@@ -395,17 +107,492 @@ void W25_Base_Init(W25_HandleTypeDef *hw25)
HAL_GPIO_Init(hw25->GPIOs.MOSI_GPIOx, &GPIO_InitStruct);
}
-//-------------------------------------------------------------
+
+/**
+ * @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)
+{
+ uint32_t tickstart = HAL_GetTick();
+
+ // wait for unbusy
+ if(W25_WaitOnFlagUntilTimeout(hw25, W25_SR_BUSY, 0, Timeout, tickstart) != HAL_OK) // if its unbusy for timeout
+ return HAL_TIMEOUT; // return timeout error
+
+ W25_CMD_Read_Data(hw25, FLASH_Address, pBuff, Size);
+ return HAL_OK;
+}
+/**
+ * @brief Write data to area in external 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)
+{
+ uint8_t sector_buff[256];
+ uint32_t tickstart = HAL_GetTick();
+ uint32_t timeoutcnt = Timeout;
+ HAL_StatusTypeDef W25_Status;
+
+ // WAIT FOR UNBUSY
+ if(W25_WaitOnFlagUntilTimeout(hw25, W25_SR_BUSY, 0, Timeout, tickstart) != HAL_OK) // if its unbusy for timeout
+ return HAL_TIMEOUT; // return timeout error
+
+ // SAVE USER "SECTOR" FROM FLASH
+ timeoutcnt = HAL_GetTick() - tickstart; // update timeout
+ Timeout -= timeoutcnt;
+ tickstart += timeoutcnt;
+ // store data from flash
+ W25_Status = W25_FLASH_Read(hw25, WriteInit->Sector_Address, sector_buff, WriteInit->Sector_Size, Timeout);
+ if(W25_Status != HAL_OK)
+ return W25_Status;
+
+ // ERASE SECTOR
+ timeoutcnt = HAL_GetTick() - tickstart; // update timeout
+ Timeout -= timeoutcnt;
+ tickstart += timeoutcnt;
+ // erase flash
+ W25_Status = W25_FLASH_Erase_Sector(hw25, WriteInit->Sector_Address, Timeout);
+ if(W25_Status != HAL_OK)
+ return W25_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];
+ }
+
+ // RESTORE UPDATED DATA TO FLASH
+ timeoutcnt = HAL_GetTick() - tickstart; // update timeout
+ Timeout -= timeoutcnt;
+ tickstart += timeoutcnt;
+ // restore data to flash
+ W25_Status = W25_FLASH_Program_Area(hw25, WriteInit->Sector_Address, sector_buff, WriteInit->Sector_Size, Timeout);
+ if(W25_Status != HAL_OK)
+ return W25_Status;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Program area in external 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)
+{
+ uint32_t tickstart = HAL_GetTick();
+ HAL_StatusTypeDef W25_Status;
+
+ // CALC AREA TO PROGRAM
+ uint16_t bytecnt = 0;
+ uint16_t firstpage_size = 0;
+ uint16_t lastpage_size = Size;
+ uint16_t firstpage = (FLASH_Address/256);
+ uint16_t lastpage = ((FLASH_Address+Size-1)/256);
+ if(firstpage != lastpage) // if area is on several pages
+ {
+ firstpage_size = (firstpage+1)*256 - FLASH_Address; // set size of data at first page
+ lastpage_size = (FLASH_Address+Size) - lastpage*256; // set size of data at last page
+ }
+
+ // PROGRAM PAGES: FROM FIRST NO THE PREVIOUS TO THE LAST
+ for(int i = 0; i < lastpage - firstpage; i++)
+ {
+ W25_Status = W25_FLASH_Program_Page(hw25, FLASH_Address, &pData[bytecnt], firstpage_size, Timeout, tickstart); // programm page
+ if(W25_Status != HAL_OK)
+ return W25_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 += firstpage_size;
+ FLASH_Address += firstpage_size;
+ // and set start size as page size. because next pages will be fully programmed
+ firstpage_size = W25_PAGE_SIZE;
+ }
+
+ // PROGRAM LAST PAGE
+ W25_Status = W25_FLASH_Program_Page(hw25, FLASH_Address, &pData[bytecnt], lastpage_size, Timeout, tickstart); // programm page
+ if(W25_Status != HAL_OK)
+ return W25_Status;
+
+ return HAL_OK; // if all ok return HAL_OK
+}
+
+/**
+ * @brief Erase external 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)
+{
+ uint32_t tickstart = HAL_GetTick();
+
+ // enable writting and waiting for unbusy
+ if(W25_WriteEnablingUntilTimeout(hw25, Timeout, tickstart) != HAL_OK) // if writting isnt enable
+ return HAL_TIMEOUT; // return timeout
+
+ // programm page (instruction)
+ W25_CMD_Erase_Sector(hw25, FLASH_Address);
+
+ // waiting for ending of erasing
+ if(Timeout) // if timeout isn zero - wait it.
+ if(W25_WaitOnFlagUntilTimeout(hw25, W25_SR_WEL|W25_SR_BUSY, 0, Timeout, tickstart) != HAL_OK) // if erase isnt done (W25 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 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)
+{
+ // enable writting and waiting for unbusy
+ if(W25_WriteEnablingUntilTimeout(hw25, Timeout, tickstart) != HAL_OK) // if writting isnt enable
+ return HAL_TIMEOUT; // return timeout
+
+ // programm page (instruction)
+ W25_CMD_Page_Program(hw25, FLASH_Address, pData, Size);
+
+ // waiting for ending of writting
+ if(W25_WaitOnFlagUntilTimeout(hw25, W25_SR_WEL|W25_SR_BUSY, 0, Timeout, tickstart) != HAL_OK) // if writting isnt done (W25 busy and WEL bit isnt in reset state)
+ return HAL_TIMEOUT;
+
+ return HAL_OK;
+}
+/**
+ * @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)
+{
+ // enable writting
+ W25_CMD_Read_Status_Register(hw25, W25_SR_WEL|W25_SR_BUSY);
+ while((hw25->SR&W25_SR_WEL) != W25_SR_WEL)
+ {
+ // if flash isnt busy - set WEL flag
+ if((hw25->SR&W25_SR_BUSY) == 0)
+ W25_CMD_Write_Enable(hw25);
+
+ W25_CMD_Read_Status_Register(hw25, W25_SR_WEL);
+ if((HAL_GetTick() - tickstart) >= Timeout) // if time is out
+ return HAL_TIMEOUT; // set timeout
+ }
+ return HAL_OK; // if all ok return HAL_OK
+}
+
+/**
+ * @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)
+{
+ // enable writting
+ W25_CMD_Read_Status_Register(hw25, FlagMask);
+ while((hw25->SR&FlagMask) != FlagStatus)
+ {
+ W25_CMD_Read_Status_Register(hw25, FlagMask);
+ if((HAL_GetTick() - tickstart) >= Timeout) // if time is out
+ return HAL_TIMEOUT; // set timeout
+ }
+ return HAL_OK; // if all ok return HAL_OK
+}
//-------------------------------------------------------------
+//----------------------COMMAND FUNCTIONS----------------------
+/**
+ * @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)
+{
+ uint8_t command[2];
+ uint8_t *pSRPtr = 0;
+ uint8_t size = 1;
+
+ if(RequestedBits >> 8) // if its high byte of status register
+ {
+ command[0] = W25_READ_STATUS_REG_2;
+ pSRPtr = (uint8_t *)(&hw25->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] = W25_READ_STATUS_REG_1;
+ }
+ }
+ else // of its low byte of status register
+ {
+ command[0] = W25_READ_STATUS_REG_1;
+ pSRPtr = (uint8_t *)(&hw25->SR); // set pointer to LO byte of SR register
+ size = 1;
+ }
+
+ W25_Select(hw25);
+ W25_SPI_Transmit(hw25, command, 1); // send insctruction to read SR
+ W25_SPI_Receive(hw25, pSRPtr, 1); // receive response
+ W25_Deselect(hw25);
+ if(size > 1) // if 2 bytes are requested
+ {
+ W25_Select(hw25);
+ W25_SPI_Transmit(hw25, command+1, 1); // send insctruction to read SR
+ W25_SPI_Receive(hw25, pSRPtr-1, 1); // receive response
+ W25_Deselect(hw25);
+ }
+}
+
+/**
+ * @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)
+{
+ uint8_t command[2];
+
+ command[0] = W25_WRITE_STATUS_REG;
+ command[1] = WrittenBits >> 2;
+
+ W25_Select(hw25);
+ W25_SPI_Transmit(hw25, command, 1);
+ W25_Deselect(hw25);
+}
+
+/**
+ * @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)
+{
+ uint8_t command[1];
+ command[0] = W25_WRITE_ENABLE;
+
+ W25_Select(hw25);
+ W25_SPI_Transmit(hw25, command, 1);
+ W25_Deselect(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)
+{
+ uint8_t command[4];
+ uint8_t response[2] = {0};
+
+ command[0] = W25_READ_DATA;
+ command[1] = FLASH_Address >> 16 & 0xFF;
+ command[2] = FLASH_Address >> 8 & 0xFF;
+ command[3] = FLASH_Address & 0xFF;
+
+ W25_Select(hw25);
+ W25_SPI_Transmit(hw25, command, 4);
+ W25_SPI_Receive(hw25, pBuff, Size);
+ W25_Deselect(hw25);
+}
+/**
+ * @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_Fast_Read(W25_HandleTypeDef *hw25, uint32_t FLASH_Address, uint8_t *pBuff, uint16_t Size)
+{
+ uint8_t command[5] = {0};
+ uint8_t response[2] = {0};
+
+ command[0] = W25_READ_DATA;
+ command[1] = FLASH_Address >> 16 & 0xFF;
+ command[2] = FLASH_Address >> 8 & 0xFF;
+ command[3] = FLASH_Address & 0xFF;
+ command[4] = 0xFF;
+
+ W25_Select(hw25);
+ W25_SPI_Transmit(hw25, command, 5);
+ W25_SPI_Receive(hw25, pBuff, Size);
+ W25_Deselect(hw25);
+}
+/**
+ * @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)
+{
+ // 1 command byte + 3 address bytes + 256 data bytes
+ uint8_t command[1+3+256];
+ FLASH_Address = FLASH_Address & 0xFFFFFF;
+
+ command[0] = W25_PAGE_PROGRAM;
+ command[1] = FLASH_Address >> 16 & 0xFF;
+ command[2] = FLASH_Address >> 8 & 0xFF;
+ command[3] = FLASH_Address & 0xFF;
+
+ if((FLASH_Address/256) != ((FLASH_Address+Size-1)/256))
+ return;
+
+ W25_Select(hw25);
+ W25_SPI_Transmit(hw25, command, 4); // send insctruction to write
+ W25_SPI_Transmit(hw25, pData, Size); // send data to write
+ W25_Deselect(hw25);
+}
+
+/**
+ * @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)
+{
+ uint8_t command[4];
+ uint8_t response[8];
+ FLASH_Address = FLASH_Address & 0xFFFFFF;
+
+ command[0] = W25_ERASE_SECTOR;
+ command[1] = FLASH_Address >> 16;
+ command[2] = FLASH_Address >> 8;
+ command[3] = FLASH_Address;
+
+ W25_Select(hw25);
+ W25_SPI_Transmit(hw25, command, 4);
+ W25_Deselect(hw25);
+}
+
+
+/**
+ * @brief Send command to read JEDEC ID.
+ * @param hw25 - указатель на хендл flash.
+ * @return JEDEC ID микросхемы.
+ */
+uint32_t W25_CMD_Read_JEDEC_ID(W25_HandleTypeDef *hw25)
+{
+ uint8_t command[1] = {0};
+ uint8_t receive[4] = {0};
+ uint32_t return_val;
+
+ command[0] = W25_READ_JEDEC_ID;
+ W25_Select(hw25);
+ W25_SPI_Transmit(hw25, command, 1);
+ W25_SPI_Receive(hw25, &receive[1], 3);
+ W25_Deselect(hw25);
+
+ return_val = (*(uint64_t *)receive);
+ return __REV(return_val) & 0xFFFFFF;
+}
+
+/**
+ * @brief Send command to read JEDEC ID.
+ * @param hw25 - указатель на хендл flash.
+ * @return Device ID микросхемы.
+ */
+uint64_t W25_CMD_Read_Device_ID(W25_HandleTypeDef *hw25)
+{
+ uint8_t command[1] = {0};
+ uint8_t receive[8] = {0};
+ uint64_t return_val_LO;
+ uint64_t return_val_HI;
+ command[0] = W25_READ_UNIQUE_ID;
+ W25_Select(hw25);
+ W25_SPI_Transmit(hw25, command, 1);
+ W25_SPI_Receive(hw25, receive, 8);
+ W25_Deselect(hw25);
+
+ 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);
+}
+//-------------------------------------------------------------
+
+//-------------------------------------------------------------
+//---------------------PERIPTH FUNCTIONS-----------------------
+/**
+ * @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)
{
HAL_SPI_Transmit (&hw25->hspi, data, size, 500);
}
-//-------------------------------------------------------------
+/**
+ * @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)
{
HAL_SPI_Receive (&hw25->hspi, data, size, 500);
diff --git a/spi_flash/spi_flash.h b/spi_flash/spi_flash.h
index 5317267..067dbd7 100644
--- a/spi_flash/spi_flash.h
+++ b/spi_flash/spi_flash.h
@@ -1,36 +1,9 @@
-/********************************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)
+/********************************W25 FLASH**********************************
+Данный файл содержит инклюды и дефайны для общения с памятью FLASH по SPI.
***************************************************************************/
+#ifndef __SPI_FLASH_H_
+#define __SPI_FLASH_H_
+
#include "stm32f4xx_hal.h"
#include "gpio_general.h"
@@ -45,10 +18,12 @@
/////////////////////////////////////////////////////////////////////
////////////////////////////---DEFINES---////////////////////////////
/**
- * @brief Defines for CMD.
+ * @brief Defines for W25 chip.
*/
-#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)
+#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.
*/
@@ -79,17 +54,13 @@
#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 /* через мат выражение */
@@ -107,7 +78,7 @@ typedef struct
uint32_t Sector_Address;
uint32_t Sector_Size;
-}W25_reProgramInitTypeDef;
+}W25_WriteInitTypeDef;
typedef struct
{
@@ -134,7 +105,11 @@ extern W25_HandleTypeDef hw25;
///////////////////////---STRUCTURES & ENUMS---//////////////////////
/////////////////////////////////////////////////////////////////////
-///////////////////////////---FUNCTIONS---///////////////////////////
+///////////////////////---FUNCTIONS FOR USER---//////////////////////
+/**
+ * @brief Initialize SPI and GPIO for W25 FLASH.
+ * @param hw25 - указатель на структуру с настройками SPI и GPIO портов.
+ */
void W25_Base_Init(W25_HandleTypeDef *hw25);
/**
@@ -152,18 +127,20 @@ HAL_StatusTypeDef W25_FLASH_Read(W25_HandleTypeDef *hw25, uint32_t FLASH_Address
/**
* @brief Write data to area in FLASH.
* @param hw25 - указатель на хендл flash.
- * @param reProgramInit - указатель на структуру, определяющую участок памяти для записи.
+ * @param WriteInit - указатель на структуру, определяющую участок памяти для записи.
* @param Timeout - время, за которое должно быть осуществлено чтение.
* @return HAL status.
* @note Позволяет перепрограммировать участок памяти. Можно записывать несколько страниц.
* Данные в сектора участка, но за пределами участка не сохраняются.
*/
-HAL_StatusTypeDef W25_FLASH_Write_Area(W25_HandleTypeDef *hw25, W25_reProgramInitTypeDef *reProgramInit, uint32_t Timeout);
+HAL_StatusTypeDef W25_FLASH_Write_Area(W25_HandleTypeDef *hw25, W25_WriteInitTypeDef *WriteInit, uint32_t Timeout);
/**
* @brief Program area in FLASH.
* @param hw25 - указатель на хендл flash.
- * @param reProgramInit - указатель на структуру, определяющую участок памяти для записи.
+ * @param FLASH_Address - адресс куда начинать записывать.
+ * @param pData - откуда брать данные для записи в FLASH.
+ * @param Size - сколько байтов записать.
* @param Timeout - время, за которое должно быть осуществлено чтение.
* @return HAL status.
* @note Позволяет перепрограммировать участок памяти. Можно записывать несколько страниц.
@@ -174,19 +151,52 @@ HAL_StatusTypeDef W25_FLASH_Program_Area(W25_HandleTypeDef *hw25, uint32_t FLASH
/**
* @brief Erase FLASH Sector.
* @param hw25 - указатель на хендл flash.
- * @param reProgramInit - указатель на структуру, определяющую участок памяти для записи.
- * @param Timeout - время, за которое должно быть осуществлено чтение.
+ * @param FLASH_Address - адресс где надо данные стереть.
+ * @param Timeout - время, за которое должно быть осуществлена очистка.
* @return HAL status.
- * @note Позволяет перепрограммировать участок памяти. Можно записывать несколько страниц.
- * Данные в сектора участка, но за пределами участка не сохраняются.
+ * @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);
-HAL_StatusTypeDef W25_WaitOnFlagUntilTimeout(W25_HandleTypeDef *hw25, uint16_t FlagMask, uint16_t FlagStatus, 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.
@@ -236,9 +246,9 @@ void W25_CMD_Fast_Read(W25_HandleTypeDef *hw25, uint32_t FLASH_Address, uint8_t
/**
* @brief Send command to fast page program.
* @param hw25 - указатель на хендл flash.
- * @param FLASH_Address - адресс откуда начинать считывание.
+ * @param FLASH_Address - адресс куда начинать записывать.
* @param pData - откуда брать данные для записи в FLASH.
- * @param Size - сколько байтов считывать.
+ * @param Size - сколько байтов записать.
* @note Программирование FLASH только в пределах одной страницы.
* Т.е. если запись с 0x0, то не больше 256 байт. Если с 0ч40, то не больше 192 байт.
*/
@@ -265,7 +275,10 @@ uint32_t W25_CMD_Read_JEDEC_ID(W25_HandleTypeDef *hw25);
* @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.
@@ -286,5 +299,6 @@ void W25_SPI_Transmit (W25_HandleTypeDef *hw25, uint8_t *data, uint16_t size);
*/
void W25_SPI_Receive (W25_HandleTypeDef *hw25, uint8_t *data, uint16_t size);
-///////////////////////////---FUNCTIONS---///////////////////////////
+//////////////////////---FUNCTION FOR PERIPTH---/////////////////////
+#endif // __SPI_FLASH_H_
\ No newline at end of file