Исправлено запись eeprom: теперь возможна запись большей одной страницы

This commit is contained in:
alexey
2024-08-13 14:56:45 +03:00
parent a862a135f3
commit 0b206dabdd
2 changed files with 95 additions and 33 deletions

View File

@@ -12,6 +12,7 @@
- MEMSPI_Base_Init Инициализация SPI и GPIO для FLASH - MEMSPI_Base_Init Инициализация SPI и GPIO для FLASH
@func service @func service
- MEMSPI_EEPROM_Write_Page Запись страницы в EEPROM *есть более общая функция MEMSPI_EEPROM_Write, которая записывает участки больше страницы
- MEMSPI_FLASH_Erase_Sector Очистка сектора FLASH. *есть более общая функция MEMSPI_FLASH_Erase, которая может ощичать несколько секторов - MEMSPI_FLASH_Erase_Sector Очистка сектора FLASH. *есть более общая функция MEMSPI_FLASH_Erase, которая может ощичать несколько секторов
- MEMSPI_FLASH_Program_Page Программирование страницы. *есть более общая функция MEMSPI_FLASH_Program, которая программирует участки больше страницы - MEMSPI_FLASH_Program_Page Программирование страницы. *есть более общая функция MEMSPI_FLASH_Program, которая программирует участки больше страницы
- MEMSPI_WriteEnablingUntilTimeout Разрешение записи, пока не будет ответа или не истек таймаут - MEMSPI_WriteEnablingUntilTimeout Разрешение записи, пока не будет ответа или не истек таймаут
@@ -134,38 +135,53 @@ HAL_StatusTypeDef MEMSPI_Read_Memory(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLA
} }
/** /**
* @brief Read external FLASH/EEPROM. * @brief Write external EEPROM.
* @param hmemspi - указатель на хендл внешней памяти. * @param hmemspi - указатель на хендл внешней памяти.
* @param FLASH_Address - адресс куда начинать записывать. * @param FLASH_Address - адресс куда начинать записывать.
* @param pData - откуда брать данные для записи в EEPROM. * @param pData - откуда брать данные для записи в EEPROM.
* @param Size - сколько байтов записать. * @param Size - сколько байтов записать.
* @param Timeout - время, за которое должно быть осуществлено чтение. * @param Timeout - время, за которое должна быть осуществлена запись.
* @param WaitForEnd - ожидание, пока память не выполненит операцию. * @param WaitForEnd - ожидание, пока память не выполненит операцию.
* @return HAL status. * @return HAL status.
* @note Включает в себя проверку на доступность памяти (флаг BUSY) * @note Позволяет записать участок памяти. Можно записывать несколько страниц.
*/ */
HAL_StatusTypeDef MEMSPI_EEPROM_Write(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pData, uint16_t Size, uint32_t Timeout, uint8_t WaitForEnd) HAL_StatusTypeDef MEMSPI_EEPROM_Write(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pData, uint16_t Size, uint32_t Timeout, uint8_t WaitForEnd)
{ {
uint32_t tickstart = HAL_GetTick(); uint32_t tickstart = HAL_GetTick();
HAL_StatusTypeDef MEMSPI_Status; HAL_StatusTypeDef MEMSPI_Status;
// enable writting and waiting for unbusy // CALC AREA TO WRITE
if(MEMSPI_WriteEnablingUntilTimeout(hmemspi, &Timeout, &tickstart) != HAL_OK) // if writting isnt enable uint16_t bytecnt = 0;
return HAL_TIMEOUT; // return timeout uint16_t currentpage_size = 0;
uint16_t lastpage_size = Size;
uint16_t firstpage = (FLASH_Address/MEMSPI_PAGE_SIZE);
uint16_t lastpage = ((FLASH_Address+Size-1)/MEMSPI_PAGE_SIZE);
if(firstpage != lastpage) // if area is on several pages
{
currentpage_size = (firstpage+1)*MEMSPI_PAGE_SIZE - FLASH_Address; // set size of data on first page
lastpage_size = (FLASH_Address+Size) - lastpage*MEMSPI_PAGE_SIZE; // set size of data on last page
}
MEMSPI_Status = MEMSPI_CMD_EEPROM_Write(hmemspi, FLASH_Address, pData, Size, Timeout); // PROGRAM PAGES: FROM FIRST NO THE PREVIOUS TO THE LAST
hmemspi->hNextAddr = FLASH_Address; // address would increase automatically in this variable
for(int i = 0; i < lastpage - firstpage; i++)
{
MEMSPI_Status = MEMSPI_EEPROM_Write_Page(hmemspi, hmemspi->hNextAddr, &pData[bytecnt], currentpage_size, &Timeout, &tickstart, 0); // programm page
if(MEMSPI_Status != HAL_OK) // note: no need waiting for end: the next call will wait for unbusy
return MEMSPI_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 += currentpage_size;
// and set current size as page size. because next pages will be fully programmed
currentpage_size = MEMSPI_PAGE_SIZE;
}
// PROGRAM LAST PAGE
MEMSPI_Status = MEMSPI_FLASH_Program_Page(hmemspi, hmemspi->hNextAddr, &pData[bytecnt], lastpage_size, &Timeout, &tickstart, WaitForEnd); // programm page
if(MEMSPI_Status != HAL_OK) if(MEMSPI_Status != HAL_OK)
return MEMSPI_Status; return MEMSPI_Status;
// waiting for ending of writting if need
if(WaitForEnd)
if(MEMSPI_WaitOnFlagUntilTimeout(hmemspi, MEMSPI_SR_WEL|MEMSPI_SR_BUSY, 0, &Timeout, &tickstart) != HAL_OK) // if writting isnt done (MEMSPI busy and WEL bit isnt in reset state)
return HAL_TIMEOUT;
// update handle variables
hmemspi->hNextAddr = (FLASH_Address+Size);
hmemspi->hNextPage = (FLASH_Address+Size)/MEMSPI_PAGE_SIZE;
hmemspi->hNextSector = (FLASH_Address+Size)/MEMSPI_SECTOR_SIZE;
return HAL_OK; return HAL_OK;
} }
/** /**
@@ -191,7 +207,7 @@ HAL_StatusTypeDef MEMSPI_FLASH_Write(MEMSPI_HandleTypeDef *hmemspi, MEMSPI_Write
// ERASE FLASH // ERASE FLASH
MEMSPI_Status = MEMSPI_FLASH_Erase(hmemspi, WriteInit->Sector_Address, WriteInit->Sector_Size, Timeout, 0); MEMSPI_Status = MEMSPI_FLASH_Erase(hmemspi, WriteInit->Sector_Address, WriteInit->Sector_Size, Timeout, 0);
if(MEMSPI_Status != HAL_OK) // note: no need waiting for end if(MEMSPI_Status != HAL_OK) // note: no need waiting for end: the next call will wait for unbusy
return MEMSPI_Status; return MEMSPI_Status;
// WRITE FLASH WITH SAVING PREVIOUS DATA // WRITE FLASH WITH SAVING PREVIOUS DATA
@@ -266,7 +282,7 @@ HAL_StatusTypeDef MEMSPI_FLASH_Program(MEMSPI_HandleTypeDef *hmemspi, uint32_t F
for(int i = 0; i < lastpage - firstpage; i++) for(int i = 0; i < lastpage - firstpage; i++)
{ {
MEMSPI_Status = MEMSPI_FLASH_Program_Page(hmemspi, hmemspi->hNextAddr, &pData[bytecnt], currentpage_size, &Timeout, &tickstart, 0); // programm page MEMSPI_Status = MEMSPI_FLASH_Program_Page(hmemspi, hmemspi->hNextAddr, &pData[bytecnt], currentpage_size, &Timeout, &tickstart, 0); // programm page
if(MEMSPI_Status != HAL_OK) // note: no need waiting for end if(MEMSPI_Status != HAL_OK) // note: no need waiting for end: the next call will wait for unbusy
return MEMSPI_Status; return MEMSPI_Status;
// note for multiple page program: first we program rest of the first page, // note for multiple page program: first we program rest of the first page,
@@ -316,6 +332,43 @@ HAL_StatusTypeDef MEMSPI_FLASH_Erase(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLA
return HAL_OK; return HAL_OK;
} }
//-------------------------------------------------------------
//----------------------SERVICE FUNCTIONS----------------------
/**
* @brief Write page in external EEPROM.
* @param hmemspi - указатель на хендл внешней памяти.
* @param FLASH_Address - адресс куда начинать записывать.
* @param pData - откуда брать данные для записи в EEPROM.
* @param Size - сколько байтов записать.
* @param Timeout - время, за которое должно быть осуществлено чтение.
* @param WaitForEnd - ожидание, пока память не выполненит операцию.
* @return HAL status.
* @note Позволяет записывать только байты в пределах одной страницы.
Для более гибкой записи есть функция MEMSPI_EEPROM_Write, которая программирует участки любой длины (в теории).
*/
HAL_StatusTypeDef MEMSPI_EEPROM_Write_Page(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pData, uint16_t Size, uint32_t *Timeout, uint32_t *tickstart, uint8_t WaitForEnd)
{
HAL_StatusTypeDef MEMSPI_Status;
// enable writting and waiting for unbusy
if(MEMSPI_WriteEnablingUntilTimeout(hmemspi, Timeout, tickstart) != HAL_OK) // if writting isnt enable
return HAL_TIMEOUT; // return timeout
MEMSPI_Status = MEMSPI_CMD_EEPROM_Write(hmemspi, FLASH_Address, pData, Size, *Timeout);
if(MEMSPI_Status != HAL_OK)
return MEMSPI_Status;
// waiting for ending of writting if need
if(WaitForEnd)
if(MEMSPI_WaitOnFlagUntilTimeout(hmemspi, MEMSPI_SR_WEL|MEMSPI_SR_BUSY, 0, Timeout, tickstart) != HAL_OK) // if writting isnt done (MEMSPI busy and WEL bit isnt in reset state)
return HAL_TIMEOUT;
// update handle variables
hmemspi->hNextAddr = (FLASH_Address+Size);
hmemspi->hNextPage = (FLASH_Address+Size)/MEMSPI_PAGE_SIZE;
hmemspi->hNextSector = (FLASH_Address+Size)/MEMSPI_SECTOR_SIZE;
return HAL_OK;
}
/** /**
* @brief Erase external FLASH Sector. * @brief Erase external FLASH Sector.
* @param hmemspi - указатель на хендл внешней памяти. * @param hmemspi - указатель на хендл внешней памяти.
@@ -400,25 +453,20 @@ HAL_StatusTypeDef MEMSPI_FLASH_Program_Page(MEMSPI_HandleTypeDef *hmemspi, uint3
HAL_StatusTypeDef MEMSPI_WriteEnablingUntilTimeout(MEMSPI_HandleTypeDef *hmemspi, uint32_t *Timeout, uint32_t *tickstart) HAL_StatusTypeDef MEMSPI_WriteEnablingUntilTimeout(MEMSPI_HandleTypeDef *hmemspi, uint32_t *Timeout, uint32_t *tickstart)
{ {
HAL_StatusTypeDef MEMSPI_Status; HAL_StatusTypeDef MEMSPI_Status;
// enable writting
MEMSPI_Status = MEMSPI_CMD_Write_Enable(hmemspi, *Timeout);
if(MEMSPI_Status != HAL_OK)
return MEMSPI_Status;
// check is writting enabled // wait for unbusy
MEMSPI_Status = MEMSPI_CMD_Read_Status_Register(hmemspi, MEMSPI_SR_WEL|MEMSPI_SR_BUSY, 0, *Timeout); if(MEMSPI_WaitOnFlagUntilTimeout(hmemspi, MEMSPI_SR_BUSY, 0, Timeout, tickstart) != HAL_OK) // if its unbusy for timeout
if(MEMSPI_Status != HAL_OK) return HAL_TIMEOUT;
return MEMSPI_Status;
// enable writing
while((hmemspi->SR&MEMSPI_SR_WEL) != MEMSPI_SR_WEL) while((hmemspi->SR&MEMSPI_SR_WEL) != MEMSPI_SR_WEL)
{ {
// if flash isnt busy - set WEL flag // if flash isnt busy - set WEL flag
if((hmemspi->SR&MEMSPI_SR_BUSY) == 0) if((hmemspi->SR&MEMSPI_SR_BUSY) == 0)
MEMSPI_CMD_Write_Enable(hmemspi, *Timeout); MEMSPI_CMD_Write_Enable(hmemspi, *Timeout);
// check is writting enabled // check is writting enabled
// MEMSPI_Status = MEMSPI_CMD_Read_Status_Register(hmemspi, MEMSPI_SR_WEL|MEMSPI_SR_BUSY, *Timeout); MEMSPI_Status = MEMSPI_CMD_Read_Status_Register(hmemspi, MEMSPI_SR_WEL|MEMSPI_SR_BUSY, 1, *Timeout);
MEMSPI_Status = MEMSPI_SPI_Receive(hmemspi, (uint8_t *)&hmemspi->SR, 1, *Timeout); // receive response
if(MEMSPI_Status != HAL_OK) if(MEMSPI_Status != HAL_OK)
{ {
MEMSPI_Deselect(hmemspi); MEMSPI_Deselect(hmemspi);

View File

@@ -155,15 +155,15 @@ void MEMSPI_Base_Init(MEMSPI_HandleTypeDef *hmemspi);
HAL_StatusTypeDef MEMSPI_Read_Memory(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pBuff, uint16_t Size, uint32_t Timeout); HAL_StatusTypeDef MEMSPI_Read_Memory(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pBuff, uint16_t Size, uint32_t Timeout);
/** /**
* @brief Read external FLASH/EEPROM. * @brief Write external EEPROM.
* @param hmemspi - указатель на хендл внешней памяти. * @param hmemspi - указатель на хендл внешней памяти.
* @param FLASH_Address - адресс куда начинать записывать. * @param FLASH_Address - адресс куда начинать записывать.
* @param pData - откуда брать данные для записи в EEPROM. * @param pData - откуда брать данные для записи в EEPROM.
* @param Size - сколько байтов записать. * @param Size - сколько байтов записать.
* @param Timeout - время, за которое должно быть осуществлено чтение. * @param Timeout - время, за которое должна быть осуществлена запись.
* @param WaitForEnd - ожидание, пока память не выполненит операцию. * @param WaitForEnd - ожидание, пока память не выполненит операцию.
* @return HAL status. * @return HAL status.
* @note Включает в себя проверку на доступность памяти (флаг BUSY) * @note Позволяет записать участок памяти. Можно записывать несколько страниц.
*/ */
HAL_StatusTypeDef MEMSPI_EEPROM_Write(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pData, uint16_t Size, uint32_t Timeout, uint8_t WaitForEnd); HAL_StatusTypeDef MEMSPI_EEPROM_Write(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pData, uint16_t Size, uint32_t Timeout, uint8_t WaitForEnd);
@@ -208,6 +208,20 @@ HAL_StatusTypeDef MEMSPI_FLASH_Erase(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLA
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
////////////////////////---SERVICE FUNCTIONS---////////////////////// ////////////////////////---SERVICE FUNCTIONS---//////////////////////
/**
* @brief Write page in external EEPROM.
* @param hmemspi - указатель на хендл внешней памяти.
* @param FLASH_Address - адресс куда начинать записывать.
* @param pData - откуда брать данные для записи в EEPROM.
* @param Size - сколько байтов записать.
* @param Timeout - время, за которое должна быть осуществлена запись.
* @param tickstart - время, относительно которого надо отсчитывать таймаут.
* @param WaitForEnd - ожидание, пока память не выполненит операцию.
* @return HAL status.
* @note Позволяет записывать только байты в пределах одной страницы.
Для более гибкой записи есть функция MEMSPI_EEPROM_Write, которая программирует участки любой длины (в теории).
*/
HAL_StatusTypeDef MEMSPI_EEPROM_Write_Page(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLASH_Address, uint8_t *pData, uint16_t Size, uint32_t *Timeout, uint32_t *tickstart, uint8_t WaitForEnd);
/** /**
* @brief Erase external FLASH Sector. * @brief Erase external FLASH Sector.
* @param hmemspi - указатель на хендл внешней памяти. * @param hmemspi - указатель на хендл внешней памяти.
@@ -227,7 +241,7 @@ HAL_StatusTypeDef MEMSPI_FLASH_Erase_Sector(MEMSPI_HandleTypeDef *hmemspi, uint3
* @param FLASH_Address - адресс куда начинать записывать. * @param FLASH_Address - адресс куда начинать записывать.
* @param pData - откуда брать данные для записи в FLASH. * @param pData - откуда брать данные для записи в FLASH.
* @param Size - сколько байтов записать. * @param Size - сколько байтов записать.
* @param Timeout - время, за которое должно быть осуществлено чтение. * @param Timeout - время, за которое должна быть осуществлена запись.
* @param tickstart - время, относительно которого надо отсчитывать таймаут. * @param tickstart - время, относительно которого надо отсчитывать таймаут.
* @param WaitForEnd - ожидание, пока память не выполненит операцию. * @param WaitForEnd - ожидание, пока память не выполненит операцию.
* @return HAL status. * @return HAL status.