diff --git a/memory_spi/memory_spi.c b/memory_spi/memory_spi.c index a8eadd9..baaa922 100644 --- a/memory_spi/memory_spi.c +++ b/memory_spi/memory_spi.c @@ -12,6 +12,7 @@ - MEMSPI_Base_Init Инициализация SPI и GPIO для FLASH @func service + - MEMSPI_EEPROM_Write_Page Запись страницы в EEPROM *есть более общая функция MEMSPI_EEPROM_Write, которая записывает участки больше страницы - MEMSPI_FLASH_Erase_Sector Очистка сектора FLASH. *есть более общая функция MEMSPI_FLASH_Erase, которая может ощичать несколько секторов - MEMSPI_FLASH_Program_Page Программирование страницы. *есть более общая функция MEMSPI_FLASH_Program, которая программирует участки больше страницы - 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 FLASH_Address - адресс куда начинать записывать. * @param pData - откуда брать данные для записи в EEPROM. * @param Size - сколько байтов записать. - * @param Timeout - время, за которое должно быть осуществлено чтение. + * @param Timeout - время, за которое должна быть осуществлена запись. * @param WaitForEnd - ожидание, пока память не выполненит операцию. * @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) { uint32_t tickstart = HAL_GetTick(); 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 + // CALC AREA TO WRITE + uint16_t bytecnt = 0; + 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) 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; } /** @@ -191,7 +207,7 @@ HAL_StatusTypeDef MEMSPI_FLASH_Write(MEMSPI_HandleTypeDef *hmemspi, MEMSPI_Write // ERASE FLASH 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; // 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++) { 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; // 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; } + +//------------------------------------------------------------- +//----------------------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. * @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_Status; - // enable writting - MEMSPI_Status = MEMSPI_CMD_Write_Enable(hmemspi, *Timeout); - if(MEMSPI_Status != HAL_OK) - return MEMSPI_Status; - // check is writting enabled - MEMSPI_Status = MEMSPI_CMD_Read_Status_Register(hmemspi, MEMSPI_SR_WEL|MEMSPI_SR_BUSY, 0, *Timeout); - if(MEMSPI_Status != HAL_OK) - return MEMSPI_Status; + // wait for unbusy + if(MEMSPI_WaitOnFlagUntilTimeout(hmemspi, MEMSPI_SR_BUSY, 0, Timeout, tickstart) != HAL_OK) // if its unbusy for timeout + return HAL_TIMEOUT; + // enable writing while((hmemspi->SR&MEMSPI_SR_WEL) != MEMSPI_SR_WEL) { // if flash isnt busy - set WEL flag if((hmemspi->SR&MEMSPI_SR_BUSY) == 0) MEMSPI_CMD_Write_Enable(hmemspi, *Timeout); - // check is writting enabled -// MEMSPI_Status = MEMSPI_CMD_Read_Status_Register(hmemspi, MEMSPI_SR_WEL|MEMSPI_SR_BUSY, *Timeout); - MEMSPI_Status = MEMSPI_SPI_Receive(hmemspi, (uint8_t *)&hmemspi->SR, 1, *Timeout); // receive response + // check is writting enabled + MEMSPI_Status = MEMSPI_CMD_Read_Status_Register(hmemspi, MEMSPI_SR_WEL|MEMSPI_SR_BUSY, 1, *Timeout); if(MEMSPI_Status != HAL_OK) { MEMSPI_Deselect(hmemspi); diff --git a/memory_spi/memory_spi.h b/memory_spi/memory_spi.h index edffffb..c27fbc9 100644 --- a/memory_spi/memory_spi.h +++ b/memory_spi/memory_spi.h @@ -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); /** - * @brief Read external FLASH/EEPROM. + * @brief Write external EEPROM. * @param hmemspi - указатель на хендл внешней памяти. * @param FLASH_Address - адресс куда начинать записывать. * @param pData - откуда брать данные для записи в EEPROM. * @param Size - сколько байтов записать. - * @param Timeout - время, за которое должно быть осуществлено чтение. + * @param Timeout - время, за которое должна быть осуществлена запись. * @param WaitForEnd - ожидание, пока память не выполненит операцию. * @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); @@ -208,6 +208,20 @@ HAL_StatusTypeDef MEMSPI_FLASH_Erase(MEMSPI_HandleTypeDef *hmemspi, uint32_t FLA ///////////////////////////////////////////////////////////////////// ////////////////////////---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. * @param hmemspi - указатель на хендл внешней памяти. @@ -227,7 +241,7 @@ HAL_StatusTypeDef MEMSPI_FLASH_Erase_Sector(MEMSPI_HandleTypeDef *hmemspi, uint3 * @param FLASH_Address - адресс куда начинать записывать. * @param pData - откуда брать данные для записи в FLASH. * @param Size - сколько байтов записать. - * @param Timeout - время, за которое должно быть осуществлено чтение. + * @param Timeout - время, за которое должна быть осуществлена запись. * @param tickstart - время, относительно которого надо отсчитывать таймаут. * @param WaitForEnd - ожидание, пока память не выполненит операцию. * @return HAL status.