Skip to content

Commit

Permalink
introduce 'SFM_WIP_RETRY_IDLE' to emulate WIP after write access (Era…
Browse files Browse the repository at this point in the history
…se/Page Write)
  • Loading branch information
akaeba committed Apr 1, 2023
1 parent 8975896 commit 10e9ae7
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 16 deletions.
32 changes: 32 additions & 0 deletions spi_flash_model.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ int sfm_init (t_sfm *self, char flashType[])
self->uint8PtrMem = NULL; // not initialized
self->uint32SelFlash = (uint32_t) ~0; // make invalid
self->uint8StatusReg1 = 0; // status register
self->uint8WipRdAfterWriteCnt = 0; // ready for write access
/* determine SPI flash by name */
for ( i = 0; i < sizeof(SPI_FLASH)/sizeof(SPI_FLASH[0]) - 1; i++ ) {
if ( 0 == strcasecmp(flashType, SPI_FLASH[i].charFlashName) ) { // match
Expand Down Expand Up @@ -744,12 +745,21 @@ int sfm (t_sfm *self, uint8_t* spi, uint32_t len)
}
return 16; // write protected
}
/* Write in progress? */
if ( 0 != self->uint8WipRdAfterWriteCnt ) {
if ( 0 != self->uint8MsgLevel ) {
printf(" ERROR:%s: WIP still in progress, read %i times for write access\n", __FUNCTION__, self->uint8WipRdAfterWriteCnt);
}
return 32; // Write in progress
}
/* erase */
memset(self->uint8PtrMem, 0xff, SPI_FLASH[self->uint32SelFlash].uint32FlashTopoTotalSizeByte);
/* clear write enable */
self->uint8StatusReg1 &= (uint8_t) ~(SPI_FLASH[self->uint32SelFlash].uint8FlashMngWrEnaMsk);
/* spi response */
memset(spi, 0, len);
/* set wait for write in progres */
self->uint8WipRdAfterWriteCnt = SFM_WIP_RETRY_IDLE;
/* exit */
return 0;

Expand All @@ -774,6 +784,13 @@ int sfm (t_sfm *self, uint8_t* spi, uint32_t len)
}
return 16; // write protected
}
/* Write in progress? */
if ( 0 != self->uint8WipRdAfterWriteCnt ) {
if ( 0 != self->uint8MsgLevel ) {
printf(" ERROR:%s: WIP still in progress, read %i times for write access\n", __FUNCTION__, self->uint8WipRdAfterWriteCnt);
}
return 32; // Write in progress
}
/* assemble address */
flashAdr = sfm_spi_to_adr (spi+1, SPI_FLASH[self->uint32SelFlash].uint8FlashTopoAdrBytes); // spi packet to address
flashAdr &= (uint32_t) ~(SPI_FLASH[self->uint32SelFlash].uint32FlashTopoSectorSizeByte - 1); // allign to sector
Expand All @@ -790,6 +807,8 @@ int sfm (t_sfm *self, uint8_t* spi, uint32_t len)
self->uint8StatusReg1 &= (uint8_t) ~(SPI_FLASH[self->uint32SelFlash].uint8FlashMngWrEnaMsk);
/* spi response */
memset(spi, 0, len);
/* set wait for write in progres */
self->uint8WipRdAfterWriteCnt = SFM_WIP_RETRY_IDLE;
/* exit */
return 0;

Expand All @@ -809,6 +828,10 @@ int sfm (t_sfm *self, uint8_t* spi, uint32_t len)
/* response */
spi[0] = 0;
spi[1] = self->uint8StatusReg1;
/* state reg 1 has WIP flag */
if ( 0 < self->uint8WipRdAfterWriteCnt ) { // no write (erase/page programm) possible, more WIP polls are necessary
--(self->uint8WipRdAfterWriteCnt);
}
/* exit */
return 0;

Expand Down Expand Up @@ -859,6 +882,13 @@ int sfm (t_sfm *self, uint8_t* spi, uint32_t len)
}
return 16; // write protected
}
/* Write in progress? */
if ( 0 != self->uint8WipRdAfterWriteCnt ) {
if ( 0 != self->uint8MsgLevel ) {
printf(" ERROR:%s: WIP still in progress, read %i times for write access\n", __FUNCTION__, self->uint8WipRdAfterWriteCnt);
}
return 32; // Write in progress
}
/* spi packet to address */
flashAdr = sfm_spi_to_adr (spi+1, SPI_FLASH[self->uint32SelFlash].uint8FlashTopoAdrBytes);
flashAdrBase = flashAdr;
Expand All @@ -873,6 +903,8 @@ int sfm (t_sfm *self, uint8_t* spi, uint32_t len)
flashAdr++;
flashAdr &= (uint32_t) SPI_FLASH[self->uint32SelFlash].uint32FlashTopoPageSizeByte - 1; // page overroll
}
/* set wait for write in progres */
self->uint8WipRdAfterWriteCnt = SFM_WIP_RETRY_IDLE;
/* exit */
return 0;

Expand Down
23 changes: 19 additions & 4 deletions spi_flash_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,20 @@
#define __SPI_FLASH_MODEL_H


/**
* @defgroup SFM_HELP constants
*
* Commen used help definitions.
*
* @{
*/
#ifndef SFM_WIP_RETRY_IDLE
#define SFM_WIP_RETRY_IDLE (3) /**< Number of WIP registers poll until after Page write / Erase the SFM is ready for new requests */
#endif
/** @} */



/* C++ compatibility */
#ifdef __cplusplus
extern "C"
Expand Down Expand Up @@ -72,10 +86,11 @@ typedef struct t_sfm_type {
* @author Andreas Kaeberlein
*/
typedef struct {
uint8_t uint8MsgLevel; /**< Message Level, 0: no messages */
uint8_t* uint8PtrMem; /**< Flash memory, allocated memory corresponds to flash size */
uint32_t uint32SelFlash; /**< Flash Type is selected */
uint8_t uint8StatusReg1; /**< Status Register */
uint8_t uint8MsgLevel; /**< Message Level, 0: no messages */
uint8_t* uint8PtrMem; /**< Flash memory, allocated memory corresponds to flash size */
uint32_t uint32SelFlash; /**< Flash Type is selected */
uint8_t uint8StatusReg1; /**< Status Register */
uint8_t uint8WipRdAfterWriteCnt; /**< Number of WIP Flag Reads until new write i spossible, emulates timing behaviour of flash */
} t_sfm;


Expand Down
52 changes: 40 additions & 12 deletions test/spi_flash_model_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,19 @@ int main ()
goto ERO_END;
}

/* sfm: Read Status Register */
printf("INFO:%s:sfm: Read Status Register\n", __FUNCTION__);
spiLen = 2;
spi[0] = 0x05;
if ( 0 != sfm(&spiFlash, spi, spiLen) ) {
printf("ERROR:%s:sfm: Read Status Register\n", __FUNCTION__);
goto ERO_END;
}
if ( 0 != spi[1] ) {
printf("ERROR:%s:sfm: Invalid Status Register value\n", __FUNCTION__);
goto ERO_END;
}

/* sfm: chip erase */
printf("INFO:%s:sfm: Chip erase\n", __FUNCTION__);
spiLen = 1;
Expand All @@ -111,6 +124,15 @@ int main ()
printf("ERROR:%s:sfm: chip erase\n", __FUNCTION__);
goto ERO_END;
}
// poll for WIP
for ( uint8_t i = 0; i < SFM_WIP_RETRY_IDLE; i++ ) {
spiLen = 2;
spi[0] = 0x05;
if ( 0 != sfm(&spiFlash, spi, spiLen) ) {
printf("ERROR:%s:sfm: Read Status Register\n", __FUNCTION__);
goto ERO_END;
}
}

/* sfm: Sector erase */
printf("INFO:%s:sfm: Sector erase\n", __FUNCTION__);
Expand All @@ -129,18 +151,14 @@ int main ()
printf("ERROR:%s:sfm: sector erase\n", __FUNCTION__);
goto ERO_END;
}

/* sfm: Read Status Register */
printf("INFO:%s:sfm: Read Status Register\n", __FUNCTION__);
spiLen = 2;
spi[0] = 0x05;
if ( 0 != sfm(&spiFlash, spi, spiLen) ) {
printf("ERROR:%s:sfm: Read Status Register\n", __FUNCTION__);
goto ERO_END;
}
if ( 0 != spi[1] ) {
printf("ERROR:%s:sfm: Invalid Status Register value\n", __FUNCTION__);
goto ERO_END;
// poll for WIP
for ( uint8_t i = 0; i < SFM_WIP_RETRY_IDLE; i++ ) {
spiLen = 2;
spi[0] = 0x05;
if ( 0 != sfm(&spiFlash, spi, spiLen) ) {
printf("ERROR:%s:sfm: Read Status Register\n", __FUNCTION__);
goto ERO_END;
}
}

/* sfm: Read Data */
Expand Down Expand Up @@ -188,6 +206,16 @@ int main ()
printf("ERROR:%s:sfm: Invalid Read Data value\n", __FUNCTION__);
goto ERO_END;
}
// poll for WIP
for ( uint8_t i = 0; i < SFM_WIP_RETRY_IDLE; i++ ) {
spiLen = 2;
spi[0] = 0x05;
if ( 0 != sfm(&spiFlash, spi, spiLen) ) {
printf("ERROR:%s:sfm: Read Status Register\n", __FUNCTION__);
goto ERO_END;
}
}
// store to file
sfm_dump( &spiFlash, 0x1010, 0x1030 );

/* sfm_store */
Expand Down

0 comments on commit 10e9ae7

Please sign in to comment.