From fd7d230e10488ce99bc89dea125af0f133139aa6 Mon Sep 17 00:00:00 2001 From: alexey Date: Wed, 14 Aug 2024 18:27:50 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9D=D0=B0=D1=87=D0=B0=D0=BB=D0=BE=20=D1=80?= =?UTF-8?q?=D0=B0=D0=B1=D0=BE=D1=82=D1=8B=20=D0=BD=D0=B0=D0=B4=20=D0=BF?= =?UTF-8?q?=D1=80=D0=B5=D1=80=D1=8B=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=D0=BC?= =?UTF-8?q?=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- GENERAL/periph_general.h | 1 + memory_spi/memory_spi.c | 419 +++++++++++++++++++++++++++++++++++++-- memory_spi/memory_spi.h | 220 +++++++++++++++++--- 3 files changed, 598 insertions(+), 42 deletions(-) diff --git a/GENERAL/periph_general.h b/GENERAL/periph_general.h index 9295cd2..7ec6343 100644 --- a/GENERAL/periph_general.h +++ b/GENERAL/periph_general.h @@ -1,5 +1,6 @@ /********************************PERIPH************************************* Данный файл содержит инклюды и дефайны для всех библиотек базовой перефирии. +Для использования библиотеки для периферии нужно подключить этот файл. ***************************************************************************/ #ifndef __PERIPH_GENERAL_H_ #define __PERIPH_GENERAL_H_ diff --git a/memory_spi/memory_spi.c b/memory_spi/memory_spi.c index 42d562c..98a14ea 100644 --- a/memory_spi/memory_spi.c +++ b/memory_spi/memory_spi.c @@ -34,8 +34,8 @@ #include "memory_spi.h" uint8_t sector_buff[MEMSPI_SECTOR_SIZE]; -//------------------------------------------------------------- -//--------------------------FOR USER--------------------------- +//------------------------------------------------------------------- +//-----------------------------FOR USER------------------------------ /** * @brief Initialize SPI and GPIO for MEMSPI FLASH. * @param hmemspi - указатель на структуру с настройками SPI и GPIO портов. @@ -72,7 +72,29 @@ void MEMSPI_Base_Init(MEMSPI_HandleTypeDef *hmemspi) HAL_GPIO_Init(hmemspi->CS_GPIOx, &GPIO_InitStruct); } +//-----------------------INTERRUPT MODE FUNCTIONS-------------------- +/** + * @brief Read external FLASH/EEPROM with interrupt. + * @param hmemspi - указатель на хендл внешней памяти. + * @param FLASH_Address - адресс откуда начинать считывание. + * @param pBuff - куда записывать данные из FLASH. + * @param Size - сколько байтов считывать. + * @param Timeout - время, за которое должно быть осуществлено чтение. + * @return HAL status. + */ +HAL_StatusTypeDef MEMSPI_Read_Memory_IT(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pBuff, uint16_t Size) +{ + HAL_StatusTypeDef MEMSPI_Status; + uint32_t tickstart = HAL_GetTick(); + MEMSPI_Status = MEMSPI_CMD_Read_Data_IT(hmemspi, FLASH_Address, pBuff, Size); + if(MEMSPI_Status != HAL_OK) + return MEMSPI_Status; + + return HAL_OK; +} + +//-----------------------BLOCKING MODE FUNCTIONS--------------------- /** * @brief Read external FLASH/EEPROM. * @param hmemspi - указатель на хендл внешней памяти. @@ -190,7 +212,6 @@ HAL_StatusTypeDef MEMSPI_FLASH_Write(MEMSPI_HandleTypeDef *hmemspi, MEMSPI_Write // WRITE FLASH WITH SAVING PREVIOUS DATA if(WriteInit->fSavePrevoisData) { -// uint8_t sector_buff[WriteInit->Sector_Size]; // store data from flash MEMSPI_Status = MEMSPI_Read_Memory(hmemspi, WriteInit->Sector_Address, sector_buff, WriteInit->Sector_Size, Timeout); if(MEMSPI_Status != HAL_OK) @@ -346,8 +367,90 @@ HAL_StatusTypeDef MEMSPI_FLASH_Erase(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLA } -//------------------------------------------------------------- -//----------------------SERVICE FUNCTIONS---------------------- +//------------------------------------------------------------------- +//-------------------------SERVICE FUNCTIONS------------------------- +//----------------------INTERRUPT MODE FUNCTIONS--------------------- +/** + * @brief Handler for SPI FLASH/EEPROM. + * @param hmemspi - указатель на хендл внешней памяти. + * @return HAL status. + * @note Включает в себя проверку на доступность памяти (флаг BUSY) + */ +void MEMSPI_Handler(MEMSPI_HandleTypeDef *hmemspi) +{ + HAL_SPI_StateTypeDef active_line = hmemspi->sspi.hspi.State; + HAL_SPI_IRQHandler(&hmemspi->sspi.hspi); + + /* RX Callback */ + if (( hmemspi->sspi.hspi.RxXferCount == 0U) && (hmemspi->MEM_State == MEM_RECEIVE_DATA) && // if all bytes are received and receive is active + hmemspi->sspi.hspi.State != HAL_SPI_STATE_BUSY_RX) // also check that receive "REALLY" isnt busy + MEM_SPI_OperationCplt_Handler(hmemspi); + + /* TX Callback */ + if (( hmemspi->sspi.hspi.TxXferCount == 0U) && (hmemspi->MEM_State == MEM_SEND_COMMAND) && // if all bytes are transmited and transmit is active + hmemspi->sspi.hspi.State != HAL_SPI_STATE_BUSY_TX) // also check that transmit "REALLY" isnt busy + MEM_SPI_TransmitCommandCplt_Handler(hmemspi); + +} +/** + * @brief Handler for transmit SPI command to EEPROM/FLASH. + * @param hmemspi - указатель на хендл внешней памяти. + * @return HAL status. + * @note После отправки комманды - инициализирует прием ответа если надо или завершает команду. + */ +void MEM_SPI_TransmitCommandCplt_Handler(MEMSPI_HandleTypeDef *hmemspi) +{ + __HAL_UNLOCK(&hmemspi->sspi.hspi); + uint8_t endcmd = 0; + hmemspi->MEM_State = MEM_RECEIVE_DATA; + switch(hmemspi->Active_CMD) + { + case WRITE_ENABLE: endcmd = 1; break; + case WRITE_DISABLE: endcmd = 1; break; + case WRITE_STATUS_REG: endcmd = 1; break; + + case ERASE_SECTOR: endcmd = 1; break; + case PAGE_PROGRAM: endcmd = 1; break; + case READ_STATUS_REG: MEMSPI_SPI_Receive_IT(hmemspi, (uint8_t *)&hmemspi->SR, 1); break; + case READ_DATA: MEMSPI_SPI_Receive_IT(hmemspi, hmemspi->pRxBuffPtr, hmemspi->RxXferSize); break; + + case READ_JEDEC_ID: MEMSPI_SPI_Receive_IT(hmemspi, &hmemspi->pRxBuffPtr[1], 3); break; + case READ_UNIQUE_ID: MEMSPI_SPI_Receive_IT(hmemspi, hmemspi->pRxBuffPtr, 8); break; + + default: break; + } +} + +/** + * @brief Handler for receive SPI response from EEPROM/FLASH. + * @param hmemspi - указатель на хендл внешней памяти. + * @return HAL status. + * @note Завершает общение с памятью. + */ +void MEM_SPI_OperationCplt_Handler(MEMSPI_HandleTypeDef *hmemspi) +{ + __HAL_UNLOCK(&hmemspi->sspi.hspi); + uint64_t return_val_LO; + uint64_t return_val_HI; + + switch(hmemspi->Active_CMD) + { + case READ_JEDEC_ID: + *(uint32_t *)hmemspi->pRxBuffPtr = __REV((*(uint64_t *)hmemspi->pRxBuffPtr)) & 0xFFFFFF; + break; + case READ_UNIQUE_ID: + return_val_LO = (*(uint64_t *)hmemspi->pRxBuffPtr) >> 32; + return_val_HI = (*(uint64_t *)hmemspi->pRxBuffPtr) & 0xFFFFFFFF; + *(uint64_t *)hmemspi->pRxBuffPtr = ((uint64_t)__REV(return_val_HI) << 32) | __REV(return_val_LO); + break; + default: break; + } + + hmemspi->Active_CMD = WAIT_FOR_CMD; + MEMSPI_Deselect(hmemspi); +} + +//-----------------------BLOCKING MODE FUNCTIONS-------------------- /** * @brief Write page in external EEPROM. * @param hmemspi - указатель на хендл внешней памяти. @@ -508,6 +611,54 @@ HAL_StatusTypeDef MEMSPI_WriteEnablingUntilTimeout(MEMSPI_HandleTypeDef *hmemspi * @note Считывает флаги до тех пор, пока они не будут в состоянии FlagStatus или до тех пор, пока таймаут не истечет. */ HAL_StatusTypeDef MEMSPI_WaitOnFlagsUntilTimeout(MEMSPI_HandleTypeDef *hmemspi, uint16_t FlagMask, uint16_t FlagStatus, uint32_t *Timeout, uint32_t *tickstart) +{ + HAL_StatusTypeDef MEMSPI_Status; + uint32_t tickstart_reserve; + uint32_t max_delay = HAL_MAX_DELAY; + if(tickstart == NULL) + tickstart = &tickstart_reserve; + if(Timeout == NULL) + Timeout = &max_delay; + + // check flags + do{ + if(hmemspi->sspi.hspi.State == HAL_SPI_STATE_READY) + MEMSPI_Status = MEMSPI_CMD_Read_Status_Register(hmemspi, FlagMask, 0, *Timeout); + }while(((HAL_GetTick() - *tickstart) < *Timeout) && (MEMSPI_Status != HAL_OK)); + + while((hmemspi->SR&FlagMask) != FlagStatus) + { + // check flags +// MEMSPI_Status = MEMSPI_CMD_Read_Status_Register(hmemspi, FlagMask, *Timeout); + MEMSPI_Status = MEMSPI_SPI_Receive(hmemspi, (uint8_t *)&hmemspi->SR, 1, *Timeout); // receive response + if(MEMSPI_Status != HAL_OK) + { + MEMSPI_Deselect(hmemspi); + return MEMSPI_Status; + } + + if((HAL_GetTick() - *tickstart) >= *Timeout) // if time is out + { + MEMSPI_Deselect(hmemspi); + return HAL_TIMEOUT; // set timeout + } + } + MEMSPI_Deselect(hmemspi); + MEMSPI_Update_Timeout_Variables(Timeout, tickstart); + return HAL_OK; // if all ok return HAL_OK +} + +/** + * @brief Wait for flag until timeout in interrupt mode. + * @param hmemspi - указатель на хендл внешней памяти. + * @param FlagMask - маска для флагов, какие флаги считывать. + * @param FlagStatus - какое состояние должно быть у выбранных флагов. + * @param Timeout - время, за которое должно быть осуществлено чтение. + * @param tickstart - время, относительно которого надо отсчитывать таймаут. + * @return HAL status. + * @note Считывает флаги до тех пор, пока они не будут в состоянии FlagStatus или до тех пор, пока таймаут не истечет. + */ +HAL_StatusTypeDef MEMSPI_WaitOnFlagsUntilTimeout_IT(MEMSPI_HandleTypeDef *hmemspi, uint16_t FlagMask, uint16_t FlagStatus, uint32_t *Timeout, uint32_t *tickstart) { HAL_StatusTypeDef MEMSPI_Status; // check flags @@ -547,8 +698,9 @@ void MEMSPI_Update_Timeout_Variables(uint32_t *Timeout, uint32_t *tickstart) *Timeout -= timeoutcnt; *tickstart += timeoutcnt; } -//------------------------------------------------------------- -//----------------------COMMAND FUNCTIONS---------------------- +//------------------------------------------------------------------- +//-------------------------COMMAND FUNCTIONS------------------------- +//------------------------------BLOCKING----------------------------- /** * @brief Send command to read Status Register. * @param hmemspi - указатель на хендл внешней памяти. @@ -617,11 +769,9 @@ HAL_StatusTypeDef MEMSPI_CMD_Write_Status_Register(MEMSPI_HandleTypeDef *hmemspi command[0] = MEMSPI_WRITE_STATUS_REG; command[1] = WrittenBits; command[2] = WrittenBits >> 8; - - size = 3; MEMSPI_Select(hmemspi); - SPI_RES = MEMSPI_SPI_Transmit(hmemspi, command, size, Timeout); + SPI_RES = MEMSPI_SPI_Transmit(hmemspi, command, 3, Timeout); MEMSPI_Deselect(hmemspi); return SPI_RES; @@ -645,7 +795,6 @@ HAL_StatusTypeDef MEMSPI_CMD_Write_Enable(MEMSPI_HandleTypeDef *hmemspi, uint32_ return SPI_RES; } - /** * @brief Send command to read data from FLASH/EEPROM. * @param hmemspi - указатель на хендл внешней памяти. @@ -659,7 +808,6 @@ HAL_StatusTypeDef MEMSPI_CMD_Read_Data(MEMSPI_HandleTypeDef *hmemspi, uint32_t F { HAL_StatusTypeDef SPI_RES; uint8_t command[4]; - uint8_t response[2] = {0}; command[0] = MEMSPI_READ_DATA; command[1] = FLASH_Address >> 16 & 0xFF; @@ -837,5 +985,250 @@ HAL_StatusTypeDef MEMSPI_CMD_Fast_Read(MEMSPI_HandleTypeDef *hmemspi, uint32_t F return SPI_RES; } -//------------------------------------------------------------- +//------------------------------------------------------------------- +//-------------------------COMMAND FUNCTIONS------------------------- +//-----------------------------INTERRUPT----------------------------- +/** + * @brief Send command to read Status Register. + * @param hmemspi - указатель на хендл внешней памяти. + * @param RequestedBits - какие биты запросить. + * @param EndCMD - завершать комманду или нет. (очистка Chip Selected пина) + * @param Timeout - время, за которое должно быть осуществлено чтение. + * @return Заполняет Status Register в hmemspi. + * @note Всего есть две комманды: на запрос верхнего или нижниго байта. + * Функция в соответствии с RequestedBits определяет какой байт запросить, или два байта сразу. + */ +HAL_StatusTypeDef MEMSPI_CMD_Read_Status_Register_IT(MEMSPI_HandleTypeDef *hmemspi, uint16_t RequestedBits, uint8_t EndCMD) +{ + HAL_StatusTypeDef SPI_RES; + uint8_t command[2]; + uint8_t *pSRPtr = 0; + uint8_t size = 1; + + command[0] = MEMSPI_READ_STATUS_REG; + hmemspi->Active_OP = command[0]; + hmemspi->MEM_State = MEM_SEND_COMMAND; + + MEMSPI_Select(hmemspi); + SPI_RES = MEMSPI_SPI_Transmit_IT(hmemspi, command, 1); // send insctruction to read SR + return SPI_RES; +} + +/** + * @brief Send command to write bits in Status Register. + * @param hmemspi - указатель на хендл внешней памяти. + * @param WrittenBits - какие биты запросить. + * @note Данная команда посылает биты, как сдвинутые на 2 вправо. Т.е. 0-й бит в комманде - 2-й бит BP0. + Но биты указываются в также как они расположены и регистре. Функция сама выполняет сдвиг. + */ +HAL_StatusTypeDef MEMSPI_CMD_Write_Status_Register_IT(MEMSPI_HandleTypeDef *hmemspi, uint16_t WrittenBits) +{ + HAL_StatusTypeDef SPI_RES; + uint8_t command[3]; + uint8_t size; + + command[0] = MEMSPI_WRITE_STATUS_REG; + command[1] = WrittenBits; + command[2] = WrittenBits >> 8; + hmemspi->Active_CMD = command[0]; + hmemspi->MEM_State = MEM_SEND_COMMAND; + + MEMSPI_Select(hmemspi); + SPI_RES = MEMSPI_SPI_Transmit_IT(hmemspi, command, 3); + + return SPI_RES; +} + +/** + * @brief Send command to set Write Enable Latch (WEL) in Status Register. + * @param hmemspi - указатель на хендл внешней памяти. + * @note Разрешает запись в FLASH, путем высталения WEL в Status Register + */ +HAL_StatusTypeDef MEMSPI_CMD_Write_Enable_IT(MEMSPI_HandleTypeDef *hmemspi) +{ + HAL_StatusTypeDef SPI_RES; + uint8_t command[1]; + command[0] = MEMSPI_WRITE_ENABLE; + hmemspi->Active_CMD = command[0]; + hmemspi->MEM_State = MEM_SEND_COMMAND; + + MEMSPI_Select(hmemspi); + SPI_RES = MEMSPI_SPI_Transmit_IT(hmemspi, command, 1); + + return SPI_RES; +} + +/** + * @brief Send command to read data from FLASH/EEPROM. + * @param hmemspi - указатель на хендл внешней памяти. + * @param FLASH_Address - адресс откуда начинать считывание. + * @param pBuff - куда записывать данные из FLASH. + * @param Size - сколько байтов считывать. + * @param Timeout - время, за которое должно быть осуществлено чтение. + * @return pBuff. + */ +HAL_StatusTypeDef MEMSPI_CMD_Read_Data_IT(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pBuff, uint16_t Size) +{ + HAL_StatusTypeDef SPI_RES; + uint8_t command[4]; + + command[0] = MEMSPI_READ_DATA; + command[1] = FLASH_Address >> 16 & 0xFF; + command[2] = FLASH_Address >> 8 & 0xFF; + command[3] = FLASH_Address & 0xFF; + hmemspi->Active_CMD = command[0]; + hmemspi->MEM_State = MEM_SEND_COMMAND; + hmemspi->pRxBuffPtr = pBuff; + hmemspi->RxXferSize = Size; + + MEMSPI_Select(hmemspi); + SPI_RES = MEMSPI_SPI_Transmit_IT(hmemspi, command, 4); + + return SPI_RES; +} + +/** + * @brief Send command to write eeprom. + * @param hmemspi - указатель на хендл внешней памяти. + * @param FLASH_Address - адресс куда начинать записывать. + * @param pData - откуда брать данные для записи в FLASH. + * @param Size - сколько байтов записать. + * @param Timeout - время, за которое должна быть осуществлена запись. + * @note Рзамер данных для записи в EEPROM без ограничений. + */ +HAL_StatusTypeDef MEMSPI_CMD_EEPROM_Write_IT(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pData, uint16_t Size) +{ + HAL_StatusTypeDef SPI_RES; + // 1 command byte + 3 address bytes + 256 data bytes + uint8_t command[1+3+MEMSPI_PAGE_SIZE]; + FLASH_Address = FLASH_Address & 0xFFFFFF; + + command[0] = MEMSPI_WRITE_EEPROM; + command[1] = FLASH_Address >> 16 & 0xFF; + command[2] = FLASH_Address >> 8 & 0xFF; + command[3] = FLASH_Address & 0xFF; + // check if data range is placed at one page + if((FLASH_Address/MEMSPI_PAGE_SIZE) != ((FLASH_Address+Size-1)/MEMSPI_PAGE_SIZE)) // if page of first byte isnt equal page of last byte + return HAL_ERROR; // return error + for(int i = 0; i < Size; i++) + command[4+i] = pData[i]; + + hmemspi->Active_CMD = command[0]; + hmemspi->MEM_State = MEM_SEND_COMMAND; + + MEMSPI_Select(hmemspi); + SPI_RES = MEMSPI_SPI_Transmit_IT(hmemspi, command, Size+4); // send insctruction+data to write + + return SPI_RES; +} +/** + * @brief Send command to page program in FLASH. + * @param hmemspi - указатель на хендл внешней памяти. + * @param FLASH_Address - адресс куда начинать записывать. + * @param pData - откуда брать данные для записи в FLASH. + * @param Size - сколько байтов записать. + * @param Timeout - время, за которое должна быть осуществлена запись. + * @note Программирование FLASH только в пределах одной страницы. + * Т.е. если запись с 0x0, то не больше 256 байт. Если с 0ч40, то не больше 192 байт. + */ +HAL_StatusTypeDef MEMSPI_CMD_FLASH_Page_Program_IT(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pData, uint16_t Size) +{ + HAL_StatusTypeDef SPI_RES; + // 1 command byte + 3 address bytes + 256 data bytes + uint8_t command[1+3+MEMSPI_PAGE_SIZE]; + FLASH_Address = FLASH_Address & 0xFFFFFF; + + command[0] = MEMSPI_PAGE_PROGRAM; + command[1] = FLASH_Address >> 16 & 0xFF; + command[2] = FLASH_Address >> 8 & 0xFF; + command[3] = FLASH_Address & 0xFF; + // check if data range is placed at one page + if((FLASH_Address/MEMSPI_PAGE_SIZE) != ((FLASH_Address+Size-1)/MEMSPI_PAGE_SIZE)) // if page of first byte isnt equal page of last byte + return HAL_ERROR; // return error + for(int i = 0; i < Size; i++) + command[4+i] = pData[i]; + + hmemspi->Active_CMD = command[0]; + hmemspi->MEM_State = MEM_SEND_COMMAND; + + MEMSPI_Select(hmemspi); + SPI_RES = MEMSPI_SPI_Transmit_IT(hmemspi, command, Size+4); // send insctruction+data to write + + return SPI_RES; +} + +/** + * @brief Send command to erase sector. + * @param hmemspi - указатель на хендл внешней памяти. + * @param FLASH_Address - адресс где надо данные стереть. + * @param Timeout - время, за которое должна быть осуществлена очистка. + * @note Микросхема вроде сама высчитывает какой сектор ерейзнуть, в соответствии с заданным адресом. + */ +HAL_StatusTypeDef MEMSPI_CMD_FLASH_Erase_Sector_IT(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address) +{ + HAL_StatusTypeDef SPI_RES; + uint8_t command[4]; + uint8_t response[8]; + FLASH_Address = FLASH_Address & 0xFFFFFF; + + command[0] = MEMSPI_ERASE_SECTOR; + command[1] = FLASH_Address >> 16; + command[2] = FLASH_Address >> 8; + command[3] = FLASH_Address; + hmemspi->Active_CMD = command[0]; + hmemspi->MEM_State = MEM_SEND_COMMAND; + + MEMSPI_Select(hmemspi); + SPI_RES = MEMSPI_SPI_Transmit_IT(hmemspi, command, 4); + + return SPI_RES; +} + + +/** + * @brief Send command to read JEDEC ID. + * @param hmemspi - указатель на хендл внешней памяти. + * @param Timeout - время, за которое должно быть осуществлено чтение. + * @return JEDEC ID микросхемы. + */ +HAL_StatusTypeDef MEMSPI_CMD_Read_JEDEC_ID_IT(MEMSPI_HandleTypeDef *hmemspi, uint32_t *JEDEC_ID_var) +{ + HAL_StatusTypeDef SPI_RES; + uint8_t command[1] = {0}; + command[0] = MEMSPI_READ_JEDEC_ID; + + hmemspi->Active_CMD = command[0]; + hmemspi->MEM_State = MEM_SEND_COMMAND; + hmemspi->pRxBuffPtr = (uint8_t *)&JEDEC_ID_var[0]; + hmemspi->RxXferSize = 4; + + MEMSPI_Select(hmemspi); + SPI_RES = MEMSPI_SPI_Transmit_IT(hmemspi, command, 1); + + return SPI_RES; +} + +/** + * @brief Send command to read JEDEC ID. + * @param hmemspi - указатель на хендл внешней памяти. + * @param Timeout - время, за которое должно быть осуществлено чтение. + * @return Device ID микросхемы. + */ +HAL_StatusTypeDef MEMSPI_CMD_Read_Device_ID_IT(MEMSPI_HandleTypeDef *hmemspi, uint64_t *Device_ID_var) +{ + HAL_StatusTypeDef SPI_RES; + uint8_t command[1] = {0}; + uint8_t receive[8] = {0}; + + command[0] = MEMSPI_READ_UNIQUE_ID; + hmemspi->Active_CMD = command[0]; + hmemspi->MEM_State = MEM_SEND_COMMAND; + hmemspi->pRxBuffPtr = (uint8_t *)&Device_ID_var[0]; + hmemspi->RxXferSize = 8; + + MEMSPI_Select(hmemspi); + SPI_RES = MEMSPI_SPI_Transmit_IT(hmemspi, command, 1); + + return SPI_RES; +} diff --git a/memory_spi/memory_spi.h b/memory_spi/memory_spi.h index be711e3..cf0e147 100644 --- a/memory_spi/memory_spi.h +++ b/memory_spi/memory_spi.h @@ -22,20 +22,22 @@ ///////////////////////////////////////////////////////////////////// ////////////////////////////---DEFINES---//////////////////////////// /** - * @brief SPI Transmit. - * @param _hmemspi_ - указатель на хендл внешней памяти. - * @param _data_ - указатель на данные для отправки. - * @param _size_ - размер данных для отправки. - * @param _timeout_ - время, за которое должна быть осуществлена отправка. + * @brief SPI Transmit IT. * @note Здесь вызывается только функция HAL, и ничего больше. */ -#define MEMSPI_SPI_Transmit(_hmemspi_, _data_, _size_, _timeout_) HAL_SPI_Transmit(&_hmemspi_->sspi.hspi, _data_, _size_, _timeout_) +#define MEMSPI_SPI_Transmit_IT(_hmemspi_, _data_, _size_) HAL_SPI_Transmit_IT(&_hmemspi_->sspi.hspi, _data_, _size_) +/** + * @brief SPI Receive IT. + * @note Здесь вызывается только функция HAL, и ничего больше. + */ +#define MEMSPI_SPI_Receive_IT(_hmemspi_, _data_, _size_) HAL_SPI_Receive_IT(&_hmemspi_->sspi.hspi, _data_, _size_) +/** + * @brief SPI Transmit. + * @note Здесь вызывается только функция HAL, и ничего больше. + */ +#define MEMSPI_SPI_Transmit(_hmemspi_, _data_, _size_, _timeout_) HAL_SPI_Transmit(&_hmemspi_->sspi.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_->sspi.hspi, _data_, _size_, _timeout_) @@ -111,30 +113,58 @@ typedef struct unsigned fSavePrevoisData:1; }MEMSPI_WriteInitTypeDef; -typedef struct +typedef enum { - 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; + WAIT_FOR_CMD = 0x00, + WRITE_ENABLE = MEMSPI_WRITE_ENABLE, + WRITE_DISABLE = MEMSPI_WRITE_DISABLE, + WRITE_STATUS_REG = MEMSPI_WRITE_STATUS_REG, + + READ_DATA = MEMSPI_READ_DATA, + + ERASE_SECTOR = MEMSPI_ERASE_SECTOR, + PAGE_PROGRAM = MEMSPI_PAGE_PROGRAM, + WRITE_EEPROM = MEMSPI_WRITE_EEPROM, + READ_STATUS_REG = MEMSPI_READ_STATUS_REG, + + READ_JEDEC_ID = MEMSPI_READ_JEDEC_ID, + READ_UNIQUE_ID = MEMSPI_READ_UNIQUE_ID, +}MEMSPI_CommandsTypeDef; + +typedef enum +{ + WAIT_FOR_UNBUSY, + READ_MEMORY, + EEPROM_WRITE, + FLASH_PROGRAM, + FLASH_ERASE, +}MEM_OperationsTypeDef; + +typedef enum +{ + MEM_READY = 0x00, + MEM_SEND_COMMAND = 0x01, + MEM_RECEIVE_DATA = 0x02, +}MEM_StateTypeDef; typedef struct { uint16_t SR; - SPI_SettingsTypeDef sspi; -// MEMSPI_GPIOTypeDef GPIOs; - GPIO_TypeDef *CS_GPIOx; - uint32_t CS_PIN; - uint32_t hNextAddr; - uint16_t hNextPage; - uint16_t hNextSector; + + SPI_SettingsTypeDef sspi; + GPIO_TypeDef *CS_GPIOx; + uint32_t CS_PIN; + + MEM_OperationsTypeDef Active_OP; + MEMSPI_CommandsTypeDef Active_CMD; + MEM_StateTypeDef MEM_State; + + uint8_t *pRxBuffPtr; + uint16_t RxXferSize; + + uint32_t hNextAddr; + uint16_t hNextPage; + uint16_t hNextSector; }MEMSPI_HandleTypeDef; extern MEMSPI_HandleTypeDef hmemspi; @@ -148,6 +178,17 @@ extern MEMSPI_HandleTypeDef hmemspi; */ void MEMSPI_Base_Init(MEMSPI_HandleTypeDef *hmemspi); +/** + * @brief Read external FLASH/EEPROM with interrupt. + * @param hmemspi - указатель на хендл внешней памяти. + * @param FLASH_Address - адресс откуда начинать считывание. + * @param pBuff - куда записывать данные из FLASH. + * @param Size - сколько байтов считывать. + * @param Timeout - время, за которое должно быть осуществлено чтение. + * @return HAL status. + */ +HAL_StatusTypeDef MEMSPI_Read_Memory_IT(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pBuff, uint16_t Size); + /** * @brief Read external FLASH. * @param hmemspi - указатель на хендл внешней памяти. @@ -285,8 +326,36 @@ HAL_StatusTypeDef MEMSPI_WaitOnFlagsUntilTimeout(MEMSPI_HandleTypeDef *hmemspi, void MEMSPI_Update_Timeout_Variables(uint32_t *Timeout, uint32_t *tickstart); ////////////////////////---SERVICE FUNCTIONS---////////////////////// +///////////////////////////////////////////////////////////////////// +///////////////////////---HANDLERS FUNCTIONS---////////////////////// +/** + * @brief Handler for SPI FLASH/EEPROM. + * @param hmemspi - указатель на хендл внешней памяти. + * @return HAL status. + * @note Включает в себя проверку на доступность памяти (флаг BUSY) + */ +void MEMSPI_Handler(MEMSPI_HandleTypeDef *hmemspi); + +/** + * @brief Handler for transmit SPI command to EEPROM/FLASH. + * @param hmemspi - указатель на хендл внешней памяти. + * @return HAL status. + * @note После отправки комманды - инициализирует прием ответа если надо или завершает команду. + */ +void MEM_SPI_TransmitCommandCplt_Handler(MEMSPI_HandleTypeDef *hmemspi); + +/** + * @brief Handler for receive SPI response from EEPROM/FLASH. + * @param hmemspi - указатель на хендл внешней памяти. + * @return HAL status. + * @note Завершает общение с памятью. + */ +void MEM_SPI_OperationCplt_Handler(MEMSPI_HandleTypeDef *hmemspi); +///////////////////////---HANDLERS FUNCTIONS---////////////////////// + ///////////////////////////////////////////////////////////////////// //////////////////////---FUNCTION FOR COMMAND---///////////////////// +////////////////////////////---BLOCKING---/////////////////////////// /** * @brief Send command to read Status Register. * @param hmemspi - указатель на хендл внешней памяти. @@ -383,7 +452,100 @@ uint64_t MEMSPI_CMD_Read_Device_ID(MEMSPI_HandleTypeDef *hmemspi, uint32_t Timeo * @note Данная функция предполагает отправку одного dummy байта после адресса, но у меня поч не работает пока :( */ HAL_StatusTypeDef MEMSPI_CMD_Fast_Read(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pBuff, uint16_t Size, uint32_t Timeout); +////////////////////////////---BLOCKING---/////////////////////////// //////////////////////---FUNCTION FOR COMMAND---///////////////////// + +///////////////////////////////////////////////////////////////////// +//////////////////////---FUNCTION FOR COMMAND---///////////////////// +///////////////////////////---INTERRUPT---/////////////////////////// +/** + * @brief Send command to read Status Register in interrupt mode. + * @param hmemspi - указатель на хендл внешней памяти. + * @param RequestedBits - какие биты запросить. + * @param Timeout - время, за которое должно быть осуществлено чтение. + * @return Заполняет Status Register в hmemspi. + * @note Всего есть две комманды: на запрос верхнего или нижниго байта. + * Функция в соответствии с RequestedBits определяет какой байт запросить, или два байта сразу. + */ +HAL_StatusTypeDef MEMSPI_CMD_Read_Status_Register_IT(MEMSPI_HandleTypeDef *hmemspi, uint16_t RequestedBits, uint8_t EndCMD); + +/** + * @brief Send command to write bits in Status Register in interrupt mode. + * @param hmemspi - указатель на хендл внешней памяти. + * @param WrittenBits - какие биты запросить. + * @param Timeout - время, за которое должна быть осуществлена запись. + * @note Данная команда посылает биты, как сдвинутые на 2 вправо. Т.е. 0-й бит в комманде - 2-й бит BP0. + Но биты указываются в также как они расположены и регистре. Функция сама выполняет сдвиг. + */ +HAL_StatusTypeDef MEMSPI_CMD_Write_Status_Register_IT(MEMSPI_HandleTypeDef *hmemspi, uint16_t WrittenBits); + +/** + * @brief Send command to set Write Enable Latch (WEL) in Status Register in interrupt mode. + * @param hmemspi - указатель на хендл внешней памяти. + * @param Timeout - время, за которое должна быть осуществлена запись. + * @note Разрешает запись в FLASH, путем высталения WEL в Status Register + */ +HAL_StatusTypeDef MEMSPI_CMD_Write_Enable_IT(MEMSPI_HandleTypeDef *hmemspi); + +/** + * @brief Send command to read data from FLASH/EEPROM in interrupt mode. + * @param hmemspi - указатель на хендл внешней памяти. + * @param FLASH_Address - адресс откуда начинать считывание. + * @param pBuff - куда записывать данные из FLASH. + * @param Size - сколько байтов считывать. + * @param Timeout - время, за которое должно быть осуществлено чтение. + * @return pBuff. + */ +HAL_StatusTypeDef MEMSPI_CMD_Read_Data_IT(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pBuff, uint16_t Size); +/** + * @brief Send command to write eeprom in interrupt mode. + * @param hmemspi - указатель на хендл внешней памяти. + * @param FLASH_Address - адресс куда начинать записывать. + * @param pData - откуда брать данные для записи в FLASH. + * @param Size - сколько байтов записать. + * @param Timeout - время, за которое должна быть осуществлена запись. + * @note Рзамер данных для записи в EEPROM без ограничений. + */ +HAL_StatusTypeDef MEMSPI_CMD_EEPROM_Write_IT(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pData, uint16_t Size); +/** + * @brief Send command to page program in FLASH in interrupt mode. + * @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_IT(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pData, uint16_t Size); + +/** + * @brief Send command to erase sector of FLASH in interrupt mode. + * @param hmemspi - указатель на хендл внешней памяти. + * @param FLASH_Address - адресс где надо данные стереть. + * @param Timeout - время, за которое должна быть осуществлена очистка. + * @note Микросхема вроде сама высчитывает какой сектор ерейзнуть, в соответствии с заданным адресом. + */ +HAL_StatusTypeDef MEMSPI_CMD_FLASH_Erase_Sector_IT(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address); + +/** + * @brief Send command to read JEDEC ID in interrupt mode. + * @param hmemspi - указатель на хендл внешней памяти. + * @param Timeout - время, за которое должно быть осуществлено чтение. + * @return JEDEC ID микросхемы. + */ +HAL_StatusTypeDef MEMSPI_CMD_Read_JEDEC_ID_IT(MEMSPI_HandleTypeDef *hmemspi, uint32_t *JEDEC_ID_var); + +/** + * @brief Send command to read JEDEC ID in interrupt mode. + * @param hmemspi - указатель на хендл внешней памяти. + * @param Timeout - время, за которое должно быть осуществлено чтение. + * @return Device ID микросхемы. + */ +HAL_StatusTypeDef MEMSPI_CMD_Read_Device_ID_IT(MEMSPI_HandleTypeDef *hmemspi, uint64_t *Device_ID_var); +///////////////////////////---INTERRUPT---/////////////////////////// +//////////////////////---FUNCTION FOR COMMAND---///////////////////// + #endif // __SPI_MEMORY_H_ \ No newline at end of file