This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Is there a SPI Flash library that supports the TM4C123?

I am trying to interface a Winbond W25X20CL SPI flash chip to a TM4C123 MCU. I was excited to find that the Tiva Utility Library that apparently got installed with Code Composer Studio includes a SPI flash driver with an API that looks perfect for my application. I compiled it in and found that it attempts to utilize SSI features that the TM4C123 doesn't support (although the TM4C129 apparently does).

First I found that it attempts to utilize SSIAdvFrameHoldEnable() to hold the SPI slave/chip select active while it transfers multiple bytes. That function isn't supported on the TM4C123, so I changed the slave select to a GPIO and toggled it manually.

Then I found that the data received in a call to SPIFlashReadID() is delayed by 8 bits. I think that is because it attempts to use MAP_SSIAdvModeSet(ui32Base, SSI_ADV_MODE_WRITE) to prevent the first byte sent from also causing a byte to be received. That also isn't supported on the TM4C123.

I think I could go through the SPI flash source file and adapt it to work with the TM4C123, but I wanted to first check if someone else had already done so, or if there was a better option to use with the TM4C123. Switching to the TM4C129 is one option, but not an easy one for me at this point.

Thanks for any suggestions.

Steve

  • May I offer, "Bravo" for a very well composed & detailed posting? Very good job.

    Feel your pain - my firm encountered similar issues - I doubt that I can advise/rescue in your specific case.

    Might it be that the SPI chip you've chosen is bit "too advanced" for the 4C123? It's been over a year - but iirc - we found (another) SPI Flash (perhaps Atmel) which did "attach" w/only (some) special handling/efforts...
  • Hi Steve,

    I am also unaware of any porting of the utility to TM4C123 and don't see any similar topics by doing a search of the E2E. I would lay odds that it has not yet been ported. If you do take the porting on, please post your results so others may also benefit in the future.
  • Thanks CB1 and Chuck. I modified SPIFlashReadID(), which was easy enough, and took at look at some of the other code. It looks like modifying the blocking routines should be pretty straightforward. The non-blocking routines may be significantly harder. I am still hoping for someone to offer a better solution as I don't have time to do a full port at the moment. If I get back to it, I will be glad to share the result.
  • Again - iirc the flash device you've chosen is more complex than the (other) flash device mentioned. We succeeded w/multi-byte reads & writes w/that (other) device.
  • CB1, it is certainly possible that a different flash chip would be easier to work with. In an attempt to follow up on your Atmel suggestion, I took at look at the AT45DB041E (a somewhat arbitrary choice). It does seem to use a different SPI protocol, but it appears that it still requires the SS (CS) to be held active as multiple bytes are transferred, which on the TM4C123 (I believe) requires controlling the SS line as a GPIO. Not hard to do, but different than how the Tiva Utility Library spi_flash library was written (thus my original question about porting that library).

    The other limitation I have run into with the TM4C123 has nothing to do with the flash chip itself; it is that the MCU doesn't support a "write only" mode assumed by that library. If it were supported, MCU would automatically discard bytes which are received while in that mode. Adding code to pop those bytes from the RX FIFO and discard them also isn't difficult in principle, but when it interacts with the big state machine in the driver's SPIFlashIntHandler(), it isn't immediately obvious (at least to me) where to add those pop instructions.

    I would love to find a less complicated path to a working driver. Is there any chance you could suggest a specific SPI flash that I could compare with? Maybe the better question is if you could refer me to a library that already supports the TM4C123; I think the complications I am dealing with have more to do with the library not supporting that MCU than with the flash chip itself. If there is a TM4C123 library available for any SPI flash, I would be interested.

    Thanks for your help,
    Steve
  • That's the family of the device we used. I believe our part - being older - had less capacity & thus may have been simpler to address.

    Believe you are correct re: "write only." (I don't believe that's (ever) been mentioned here - or other forums my firm attends.)

    And yes - just as you state - the CS pin flows from GPIO - manually controlled.

    Realize that (only) one vendor may not best satisfy (all) client needs - for (all) devices - (all) of the time. (thus my firm employs ARM MCUs from four vendors - based upon performance, feature, price, availability matrix.) You may benefit by searching the SPI libraries of other (ARM vendors) - or venturing to the "Flash or Component" forums/pages of Flash device makers.   This vendor's 123 is bit, "long in the tooth" and it may be that other devices better meet/fit your need...

  • After many detours to put out other fires, I got a chance to port all but the non-blocking routines in the SPI flash library to the TM4C123.  It was relatively straightforward, requiring just manipulating the SS line as a GPIO and discarding data received while in the unsupported SSI_ADV_MODE_WRITE.  The API as defined in the header file is completely unchanged, but there are a couple of functions local to the C file that may need changed in other applications to make GPIOPinWrite() will manipulate the correct CS/SS pin.  An alternative implementation would let you specify that pin using additional arguments to SPIFlashInit().  Macros are used to stub out the added function calls when compiled for other processors, so the changes should have no effect on code size or speed when the added function calls aren't needed.

    I tried to minimize changes to the original source code and to follow its formatting conventions with the added code in order to make it easy to compare side-by-side with the original.

    I also wrote tests for all of the ported functions except for SPIFlashWriteStatus() which I ported but didn't test.  The modified library code, the test code, and the output from the test code are all included in attached files.

    I did not attempt to port the non-blocking routines.  I believe that doing so will require adding states to the state machine in SPIFlashIntHandler() and possibly setting up additional uDMA transfers to discard unwanted received data.  I did leave some source code comments with more specifics about how to start that effort in case someone needs it later.

    If someone makes further changes to this or puts it into a version control repository online, please drop me a message so I can see if the further improvements might be useful to me as well.  Thanks.

    Steve

    spi_flash.cspi_flash.h

    #include <stdint.h>
    #include <stdbool.h>
    #include <string.h>							// for memcmp()
    
    #include "inc/hw_memmap.h"					// for SSI1_BASE
    #include "driverlib/sysctl.h" 				// for SysCtlClockGet()
    
    #include "uartstdio2.h"						// our customized "2" version, not the original.  For UARTprintf()
    #include "spi_flash.h"						// utility library file
    
    #define SPI_FLASH_SSI_BASE SSI1_BASE
    #define BIT_BANG_SPI_SS						/* TM4C123 doesn't support holding SS active during multi-byte transfer */
    #ifdef BIT_BANG_SPI_SS
    	#include "PinMux.h"
    #endif
    
    #include "spiFlashTest.h"
    
    void printBuffer( const uint8_t *buffer, uint32_t bufferSize);
    void printWhetherBufferMatchesExpected( const uint8_t *buffer, const uint8_t *expectedBuffer, uint32_t compareSize);
    void readAndCompareWithExpected(uint32_t ui32Base, uint32_t flashAddressToReadFrom, const uint8_t *expectedBuffer, uint32_t compareSize );
    void readAndSeeIfBlank(uint32_t ui32Base, uint32_t flashAddressToReadFrom, uint32_t compareSize );
    void testProgramming(uint32_t ui32Base, uint32_t ui32Addr, const uint8_t *pui8Data, uint32_t ui32Count);
    void testErase(uint32_t ui32Base, uint32_t ui32Addr, uint32_t eraseCmd);
    
    void spiFlashTest( void )
    {
    
    	/////////////////////////////
    
    	UARTprintf( "\n" "--------- Test reading the flash ID" );
    	{
    		// todo:  add a test for the flash ID to the self-test.
    		uint8_t manufacturerID = 0;
    		uint16_t deviceID = 0;
    		SPIFlashReadID( SPI_FLASH_SSI_BASE, &manufacturerID, &deviceID );
    		UARTprintf( "\n" "SPI flash manufacturer: 0x%02X, device: 0x%02X", manufacturerID, deviceID );
    		UARTprintf( "\n" "  Expected for W25X20:  0x%02X, device: 0x%02X", 0xEF, 0x3012 );
    	}
    	UARTFlushTx( false );
    
    	//////////////////////////////////////////////////////////
    	// Setup needed for testing other features of the library.
    	uint32_t flashAddressToReadFrom = 0x0;
    	uint8_t readBuffer[12];
    	uint32_t readBufferSize = sizeof( readBuffer );
    	uint32_t flashAddressToWriteTo = 0x0;
    
    	////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    	// This may not do anything if flash is already erased.
    
    	UARTprintf( "\n" "--------- Making sure flash is erased so can test programming it" );
    	{
    		// SPIFlashWriteEnable()
    		UARTprintf( "\n" "Enabling flash erasing..." );
    		SPIFlashWriteEnable( SPI_FLASH_SSI_BASE );
    
    		// SPIFlashBlockErase32()
    		{
    		UARTprintf( "\n" "Starting flash erase (32KB)..." );
    		UARTFlushTx( false );
    		SPIFlashBlockErase32( SPI_FLASH_SSI_BASE, flashAddressToWriteTo );
    		}
    
    		// SPIFlashReadStatus()
    		// Run this while erasing so can tell when it is done
    		{
    		uint8_t status;
    		UARTprintf( "\n" "SPI flash status (0x03 expected while erasing, 0x00 when finished): " );
    		do
    		{
    			status = SPIFlashReadStatus( SPI_FLASH_SSI_BASE );
    			UARTprintf( "0x%02X, ", status );
    			UARTFlushTx( false );
    		} while( status != 0 );
    		UARTprintf( "\n" "Finished flash erase..." );
    		UARTFlushTx( false );
    		}
    
    		// Check the erase
    		readAndSeeIfBlank( SPI_FLASH_SSI_BASE, flashAddressToWriteTo, 12 );
    	}
    	UARTFlushTx( false );
    
    	////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    	UARTprintf( "\n" "--------- Testing flash programming" );
    	{
    		// SPIFlashWriteEnable()
    		UARTprintf( "\n" "Enabling flash programming..." );
    		SPIFlashWriteEnable( SPI_FLASH_SSI_BASE );
    
    		// SPIFlashPageProgram()
    		uint8_t writeBuffer[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xAA, 0xAA, 0x55, 0x55 };
    		uint32_t writeBufferSize = sizeof( writeBuffer );
    		SPIFlashPageProgram( SPI_FLASH_SSI_BASE, flashAddressToWriteTo, writeBuffer, writeBufferSize );
    		UARTprintf( "\n" "Writing data   starting at address 0x%X: ", flashAddressToWriteTo );
    		printBuffer( writeBuffer, writeBufferSize );
    	}
    	UARTFlushTx( false );
    
    	////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    	UARTprintf( "\n" "--------- Testing SPIFlashRead()" );
    	{
    		SPIFlashRead( SPI_FLASH_SSI_BASE, flashAddressToReadFrom, readBuffer, readBufferSize );
    		UARTprintf( "\n" "Data      read starting at address 0x%X: ", flashAddressToReadFrom );
    		printBuffer( readBuffer, readBufferSize );
    		uint8_t expectedResult[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xAA, 0xAA, 0x55, 0x55, 0xFF, 0xFF, 0xFF, 0xFF };
    		printWhetherBufferMatchesExpected( readBuffer, expectedResult, sizeof(expectedResult) );
    	}
    	UARTFlushTx( false );
    
    	////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    	// Test SPIFlashFastRead()
    	UARTprintf( "\n" "--------- Testing SPIFlashFastRead()" );
    	{
    		SPIFlashFastRead( SPI_FLASH_SSI_BASE, flashAddressToReadFrom, readBuffer, readBufferSize );
    		UARTprintf( "\n" "Data fast read starting at address 0x%X: ", flashAddressToReadFrom );
    		printBuffer( readBuffer, readBufferSize );
    		uint8_t expectedResult[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xAA, 0xAA, 0x55, 0x55, 0xFF, 0xFF, 0xFF, 0xFF };
    		printWhetherBufferMatchesExpected( readBuffer, expectedResult, sizeof(expectedResult) );
    	}
    	UARTFlushTx( false );
    
    	//////////////////////////////////////////////////////////////////////////////
    	// Clear some additional bits in the same address range without erasing first.
    
    	UARTprintf( "\n" "--------- Testing that programming without erasing clears additional bits" );
    	{
    		// SPIFlashPageProgram()
    		uint8_t writeBuffer[] = { 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF };
    		uint32_t writeBufferSize = sizeof( writeBuffer );
    		testProgramming( SPI_FLASH_SSI_BASE, flashAddressToWriteTo, writeBuffer, writeBufferSize );
    
    		// Check result
    		uint8_t expectedResult[] = { 0x00, 0x00, 0xbe, 0xef, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff };
    		readAndCompareWithExpected( SPI_FLASH_SSI_BASE, flashAddressToWriteTo, expectedResult, sizeof(expectedResult) );
    	}
    	UARTFlushTx( false );
    
    	////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    	// Erase flash (test 32KB erase).  We did this before, but didn't know if the flash was already erased.
    
    	UARTprintf( "\n" "--------- Testing 32KB erase" );
    	{
    		testErase( SPI_FLASH_SSI_BASE, flashAddressToWriteTo, 64 );
    		readAndSeeIfBlank( SPI_FLASH_SSI_BASE, flashAddressToWriteTo, 12 );
    	}
    	UARTFlushTx( false );
    
    	///////////////////////////////////////////////////////////////////////////////
    	// Show that can't program if don't enable programming each time.
    
    	UARTprintf( "\n" "--------- Testing that have to enable programming or it doesn't work" );
    	{
    		// SPIFlashPageProgram()
    		uint8_t writeBuffer[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
    		uint32_t writeBufferSize = sizeof( writeBuffer );
    		SPIFlashPageProgram( SPI_FLASH_SSI_BASE, flashAddressToWriteTo, writeBuffer, writeBufferSize );
    		UARTprintf( "\n" "Overwriting data w/o enabling prog    : " );
    		printBuffer( writeBuffer, writeBufferSize );
    		UARTFlushTx( false );
    
    		// Check result
    		readAndSeeIfBlank( SPI_FLASH_SSI_BASE, flashAddressToWriteTo, 12 );
    	}
    	UARTFlushTx( false );
    
    	/////////////////////////////////////////////////////////////////
    	// Test that SPIFlashWriteDisable() undoes SPIFlashWriteEnable().
    
    	UARTprintf( "\n" "--------- Testing that SPIFlashWriteDisable() prevents programming" );
    	{
    		// SPIFlashWriteEnable()
    		UARTprintf( "\n" "Enabling flash programming..." );
    		SPIFlashWriteEnable( SPI_FLASH_SSI_BASE );
    
    		// SPIFlashWriteDisable()
    		UARTprintf( "\n" "Disabling flash programming..." );
    		SPIFlashWriteDisable( SPI_FLASH_SSI_BASE );
    
    		// SPIFlashPageProgram()
    		uint8_t writeBuffer[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
    		uint32_t writeBufferSize = sizeof( writeBuffer );
    		SPIFlashPageProgram( SPI_FLASH_SSI_BASE, flashAddressToWriteTo, writeBuffer, writeBufferSize );
    
    		UARTprintf( "\n" "Overwriting after en/disabling writing: " );
    		printBuffer( writeBuffer, writeBufferSize );
    
    		// Check result
    		readAndSeeIfBlank( SPI_FLASH_SSI_BASE, flashAddressToWriteTo, 12 );
    	}
    	UARTFlushTx( false );
    
    	/////////////////////////////////////////////////////////////////
    	// Write something and test 64KB erase
    
    	UARTprintf( "\n" "--------- Testing 64KB erase" );
    	{
    		uint8_t writeBuffer[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xAA, 0xAA, 0x55, 0x55 };
    		testProgramming( SPI_FLASH_SSI_BASE, flashAddressToWriteTo, writeBuffer, sizeof( writeBuffer ) );
    
    		uint8_t expectedResult[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xAA, 0xAA, 0x55, 0x55, 0xFF, 0xFF, 0xFF, 0xFF };
    		readAndCompareWithExpected( SPI_FLASH_SSI_BASE, flashAddressToWriteTo, expectedResult, sizeof(expectedResult) );
    
    		testErase( SPI_FLASH_SSI_BASE, flashAddressToWriteTo, 64 );
    		readAndSeeIfBlank( SPI_FLASH_SSI_BASE, flashAddressToWriteTo, 12 );
    	}
    	UARTFlushTx( false );
    
    	/////////////////////////////////////////////////////////////////
    	// Write something and test chip erase
    
    	UARTprintf( "\n" "--------- Testing chip erase" );
    	{
    		uint8_t writeBuffer[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xAA, 0xAA, 0x55, 0x55 };
    		testProgramming( SPI_FLASH_SSI_BASE, flashAddressToWriteTo, writeBuffer, sizeof( writeBuffer ) );
    
    		uint8_t expectedResult[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xAA, 0xAA, 0x55, 0x55, 0xFF, 0xFF, 0xFF, 0xFF };
    		readAndCompareWithExpected( SPI_FLASH_SSI_BASE, flashAddressToWriteTo, expectedResult, sizeof(expectedResult) );
    
    		testErase( SPI_FLASH_SSI_BASE, flashAddressToWriteTo, 0 );				// last arg of 0 causes chip erase
    		readAndSeeIfBlank( SPI_FLASH_SSI_BASE, flashAddressToWriteTo, 12 );
    	}
    	UARTFlushTx( false );
    
    	/////////////////////////////////////////////////////////////////
    	// Write something and test 4KB sector erase
    
    	UARTprintf( "\n" "--------- Testing 4KB erase" );
    	{
    		uint8_t writeBuffer[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xAA, 0xAA, 0x55, 0x55 };
    		testProgramming( SPI_FLASH_SSI_BASE, flashAddressToWriteTo, writeBuffer, sizeof( writeBuffer ) );
    
    		uint8_t expectedResult[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xAA, 0xAA, 0x55, 0x55, 0xFF, 0xFF, 0xFF, 0xFF };
    		readAndCompareWithExpected( SPI_FLASH_SSI_BASE, flashAddressToWriteTo, expectedResult, sizeof(expectedResult) );
    
    		testErase( SPI_FLASH_SSI_BASE, flashAddressToWriteTo, 4 );				// last arg of 4 causes sector erase
    		readAndSeeIfBlank( SPI_FLASH_SSI_BASE, flashAddressToWriteTo, 12 );
    	}
    	UARTFlushTx( false );
    
    	/////////////////////////////////////
    	// Not testing SPIFlashWriteStatus().
    
    	/////////////////////
    	// End of flash tests
    
    	UARTprintf( "\n" "============ Done with Flash Tests ==============" );
    	UARTFlushTx( false );
    }
    
    void printBuffer( const uint8_t *buffer, uint32_t bufferSize)
    {
    	int i;
    	for( i = 0; i < bufferSize-1; ++i )
    		UARTprintf( "0x%02X, ", buffer[i] );
    
    	UARTprintf( "0x%02X", buffer[i] );			// don't follow this last item with ", "
    }
    
    #if 0		// not used?
    void printMessageAddrAndBuffer( const char* message, uint32_t addr, const uint8_t *buffer, uint32_t bufferSize)
    {
    	UARTprintf( message, addr );
    	printBuffer( buffer, bufferSize );
    }
    #endif
    
    void printWhetherBufferMatchesExpected( const uint8_t *buffer, const uint8_t *expectedBuffer, uint32_t compareSize)
    {
    	bool expected = ( memcmp( buffer, expectedBuffer, sizeof(compareSize) ) == 0 );
    	UARTprintf( expected ? " (as expected)" : " (ERROR?)" );
    }
    
    #define MIN(a,b) (((a)<(b))?(a):(b))
    #define MAX(a,b) (((a)>(b))?(a):(b))
    
    void readAndCompareWithExpected(uint32_t ui32Base, uint32_t flashAddressToReadFrom, const uint8_t *expectedBuffer, uint32_t compareSize )
    {
    	uint8_t readBuffer[40];
    	uint32_t readBufferSize = sizeof( readBuffer );
    	uint32_t compareSize2 = MIN(compareSize, readBufferSize);
    	SPIFlashFastRead( ui32Base, flashAddressToReadFrom, readBuffer, compareSize2 );
    	UARTprintf( "\n" "Data fast read starting at address 0x%X: ", flashAddressToReadFrom );
    	printBuffer( readBuffer, compareSize2 );
    	printWhetherBufferMatchesExpected( readBuffer, expectedBuffer, compareSize2 );
    	UARTFlushTx( false );
    }
    
    void readAndSeeIfBlank(uint32_t ui32Base, uint32_t flashAddressToReadFrom, uint32_t compareSize )
    {
    	uint8_t expectedResult[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
    	uint32_t compareSize2 = MIN(compareSize, sizeof(expectedResult));
    	readAndCompareWithExpected( ui32Base, flashAddressToReadFrom, expectedResult, compareSize2 );
    }
    
    void testProgramming(uint32_t ui32Base, uint32_t flashAddressToWriteTo, const uint8_t *writeBuffer, uint32_t writeBufferSize)
    {
    	// SPIFlashWriteEnable()
    	UARTprintf( "\n" "Enabling flash programming..." );
    	SPIFlashWriteEnable( ui32Base );
    
    	// SPIFlashPageProgram()
    	{
    	SPIFlashPageProgram( ui32Base, flashAddressToWriteTo, writeBuffer, writeBufferSize );
    	UARTprintf( "\n" "Writing data   starting at address 0x%X: ", flashAddressToWriteTo );
    	printBuffer( writeBuffer, writeBufferSize );
    	UARTFlushTx( false );
    	}
    }
    
    // eraseCmd = 4 for 4K sector erase, 32 for 32K erase, 64 for 64K erase, 0 to erase whole chip (in which case ui32Addr is ignored)
    void testErase(uint32_t ui32Base, uint32_t flashAddressToErase, uint32_t eraseCmd)
    {
    	// SPIFlashWriteEnable()
    	UARTprintf( "\n" "Enabling flash erasing..." );
    	SPIFlashWriteEnable( ui32Base );
    
    	// SPIFlashBlockErase32()
    	{
    		switch( eraseCmd )
    		{
    		case 4:
    			UARTprintf( "\n" "Starting flash erase (4KB sector)..." );
    			UARTFlushTx( false );
    			SPIFlashSectorErase( ui32Base, flashAddressToErase );
    		break;
    		case 32:
    			UARTprintf( "\n" "Starting flash erase (32KB)..." );
    			UARTFlushTx( false );
    			SPIFlashBlockErase64( ui32Base, flashAddressToErase );
    		break;
    		case 64:
    			UARTprintf( "\n" "Starting flash erase (64KB)..." );
    			UARTFlushTx( false );
    			SPIFlashBlockErase64( ui32Base, flashAddressToErase );
    		break;
    		case 0:
    			UARTprintf( "\n" "Starting flash erase (whole chip)..." );
    			UARTFlushTx( false );
    			SPIFlashChipErase( ui32Base );
    		break;
    		default:
    			UARTprintf( "\n" "Error:  invalid flash erase command" );
    		return;
    		}
    	}
    
    	// SPIFlashReadStatus()
    	// Run this while erasing so can tell when it is done
    	{
    	uint8_t status;
    	uint8_t lastStatus = 0xA5;			// arbitrary, hopefully never used value
    	int repeatCount = 0;
    	UARTprintf( "\n" "SPI flash status (0x03 expected while erasing, 0x00 when finished): " );
    	do
    	{
    		status = SPIFlashReadStatus( ui32Base );
    
    		if( status != lastStatus )
    		{
    			UARTprintf( "0x%02X ", status );
    			repeatCount = 1;
    			UARTprintf( "(%4d times), ", repeatCount );
    			lastStatus = status;
    		}
    		else
    		{
    			++repeatCount;
    			UARTprintf( "\b\b\b\b\b\b\b\b\b\b\b\b\b\b" );
    			UARTprintf( "(%4d times), ", repeatCount );
    		}
    		UARTFlushTx( false );
    	} while( status != 0 );
    	UARTprintf( "\n" "Finished flash erase..." );
    	UARTFlushTx( false );
    	}
    }
    
    --------- Test reading the flash ID
    SPI flash manufacturer: 0xef, device: 0x3012
      Expected for W25X20:  0xef, device: 0x3012
    --------- Making sure flash is erased so can test programming it
    Enabling flash erasing...
    Starting flash erase (32KB)...
    SPI flash status (0x03 expected while erasing, 0x00 when finished): 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00,
    Finished flash erase...
    Data fast read starting at address 0x0: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff (as expected)
    --------- Testing flash programming
    Enabling flash programming...
    Writing data   starting at address 0x0: 0xde, 0xad, 0xbe, 0xef, 0xaa, 0xaa, 0x55, 0x55
    --------- Testing SPIFlashRead()
    Data      read starting at address 0x0: 0xde, 0xad, 0xbe, 0xef, 0xaa, 0xaa, 0x55, 0x55, 0xff, 0xff, 0xff, 0xff (as expected)
    --------- Testing SPIFlashFastRead()
    Data fast read starting at address 0x0: 0xde, 0xad, 0xbe, 0xef, 0xaa, 0xaa, 0x55, 0x55, 0xff, 0xff, 0xff, 0xff (as expected)
    --------- Testing that programming without erasing clears additional bits
    Enabling flash programming...
    Writing data   starting at address 0x0: 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff
    Data fast read starting at address 0x0: 0x00, 0x00, 0xbe, 0xef, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff (as expected)
    --------- Testing 32KB erase
    Enabling flash erasing...
    Starting flash erase (64KB)...
    SPI flash status (0x03 expected while erasing, 0x00 when finished): 0x03 (  50 times), 0x00 (   1 times),
    Finished flash erase...
    Data fast read starting at address 0x0: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff (as expected)
    --------- Testing that have to enable programming or it doesn't work
    Overwriting data w/o enabling prog    : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
    Data fast read starting at address 0x0: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff (as expected)
    --------- Testing that SPIFlashWriteDisable() prevents programming
    Enabling flash programming...
    Disabling flash programming...
    Overwriting after en/disabling writing: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    Data fast read starting at address 0x0: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff (as expected)
    --------- Testing 64KB erase
    Enabling flash programming...
    Writing data   starting at address 0x0: 0xde, 0xad, 0xbe, 0xef, 0xaa, 0xaa, 0x55, 0x55
    Data fast read starting at address 0x0: 0xde, 0xad, 0xbe, 0xef, 0xaa, 0xaa, 0x55, 0x55, 0xff, 0xff, 0xff, 0xff (as expected)
    Enabling flash erasing...
    Starting flash erase (64KB)...
    SPI flash status (0x03 expected while erasing, 0x00 when finished): 0x03 (  51 times), 0x00 (   1 times),
    Finished flash erase...
    Data fast read starting at address 0x0: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff (as expected)
    --------- Testing chip erase
    Enabling flash programming...
    Writing data   starting at address 0x0: 0xde, 0xad, 0xbe, 0xef, 0xaa, 0xaa, 0x55, 0x55
    Data fast read starting at address 0x0: 0xde, 0xad, 0xbe, 0xef, 0xaa, 0xaa, 0x55, 0x55, 0xff, 0xff, 0xff, 0xff (as expected)
    Enabling flash erasing...
    Starting flash erase (whole chip)...
    SPI flash status (0x03 expected while erasing, 0x00 when finished): 0x03 ( 133 times), 0x00 (   1 times),
    Finished flash erase...
    Data fast read starting at address 0x0: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff (as expected)
    --------- Testing 4KB erase
    Enabling flash programming...
    Writing data   starting at address 0x0: 0xde, 0xad, 0xbe, 0xef, 0xaa, 0xaa, 0x55, 0x55
    Data fast read starting at address 0x0: 0xde, 0xad, 0xbe, 0xef, 0xaa, 0xaa, 0x55, 0x55, 0xff, 0xff, 0xff, 0xff (as expected)
    Enabling flash erasing...
    Starting flash erase (4KB sector)...
    SPI flash status (0x03 expected while erasing, 0x00 when finished): 0x03 (  14 times), 0x00 (   1 times),
    Finished flash erase...
    Data fast read starting at address 0x0: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff (as expected)
    ============ Done with Flash Tests ==============
    

  • May I commend you for your skill, time & effort in adding functionality to this library? Well done!

    Minimizing (or avoiding) changes to the original code makes great sense - it may even prove worthwhile to label your code such that it is called and runs "free" from the "normal" library - to preclude any (unwanted/unanticipated) interactions.

    I'm sensing that your SPI Flash chip is among "high end" - I know that the AT45DB family is a "Big Seller" and its inclusion w/in "Steve's Improved SPI lib." would appear to make great sense.

    Thanks for your unique & public-serving effort - much appreciated...
  • Steve,

    Many thanks for your efforts and for posting for the enlightenment and use of our E2E audience.

    Greatly appreciated!!