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.

DK-TM4C129x SPI - EEPROM Problem

Hi,

I am trying to communicate with the on board EEPROM flash MX66L51235F. I'm just sending RDID command which will give me Manufature's ID and Device ID in return.

Here is the code.

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_memmap.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/ssi.h"
#include "driverlib/sysctl.h"
#include "inc/hw_ssi.h"
#include "inc/hw_types.h"

void Config_Master(uint32_t);

int main()
{
	uint32_t ui32SysClk;
	static uint32_t dummy[3] = {0};
	uint32_t i=0;

	// define data that you want to receive
	uint32_t rx_data;

	// set the system clock to be 25MHz
	ui32SysClk = SysCtlClockFreqSet(SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_25MHZ, 25000000);

	//Configure Master Module and system Parameters.
	Config_Master(ui32SysClk);

	// Issue RDID command 9F
	SSIDataPut(SSI3_BASE,0x9F); 	// Read ID
	SSIDataPut(SSI3_BASE,0x00);

	SSIDataGet(SSI3_BASE,&dummy[0]);

	SSIDataPut(SSI3_BASE,0x00);
	SSIDataGet(SSI3_BASE,&dummy[1]);

	SSIDataPut(SSI3_BASE,0x00);
	SSIDataGet(SSI3_BASE,&dummy[2]);

	for (i=0; i<2000; i++){}
	while(1);
}

void Config_Master(uint32_t clk)
{
	uint32_t SysClk = clk;

	// Enable system peripheral
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOQ);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI3);

	// Enable GPIO Ports pin types as SPI
	GPIOPinTypeSSI(GPIO_PORTQ_BASE,(GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2));
	GPIOPinTypeSSI(GPIO_PORTF_BASE,GPIO_PIN_0);

	// Configure GPIO pins
	GPIOPinConfigure(GPIO_PQ0_SSI3CLK);
	GPIOPinConfigure(GPIO_PQ1_SSI3FSS);
	GPIOPinConfigure(GPIO_PQ2_SSI3XDAT0);
	GPIOPinConfigure(GPIO_PF0_SSI3XDAT1);

	// Provide colck to the module.
	SSIConfigSetExpClk(SSI3_BASE, SysClk, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 2000000, 8);

	SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_LEGACY);
	SSIAdvFrameHoldEnable(SSI3_BASE);
	// SSI Module 0 Enable

//	SysCtlPeripheralReset(SYSCTL_PERIPH_SSI3);
	SSIEnable(SSI3_BASE);
}

Problem:

1. If I use following code then I'm not getting any data. it gets stuck in while busy loop. According to my understanding we have to wait for the untill the transmission is finished. But strange thing is that if i'm not using SSIbusy() then I'm getting the data.

SSIDataPut(SSI3_BASE,0x9F);
while(SSIBusy(SSI3_BASE));
SSIDataGet(SSI3_BASE,&dummy[0]);

2. Slave will send me total 3 bytes in return. and I'm reading those bytes in dummy[ ]. Without using the SSIbusy its working fine, but sometimes it misses first byte.

3. I dont know how to flush the receive FIFO. at the very beginning I will receive some garbage and then I have to read the data sent by slave. can anyone tell me how to reset the Rx FIFO?

Thanks

  • Hello Spandan89,

    You are in luck (99%) that I have the code that you can use as reference.

    1145.TM4C129_SSI3_MacronixFlash.7z

    However mandate is to explain why

    1. The PF0 is a locked pin so you would need to unlock the same to use it as SSI-3 RX Pad.

    2. The Flash access requires the user to play with the setting of the SSI-3 Advanced Mode for which I have done some custom and some TivaWare API's and handled the SW overhead.

    3. Do make sure that the CS is connected to the Flash on the board and not to the SD Card

    Regards

    Amit

  • Hi Amit,

    Thanks for the code. Yes, looks like I'm lucky one.

    I havent unlocked the PF0 pin and still I was getting the Manufacture's ID and Device ID. How is that possible?

    I am operating in Legacy mode which is very basic and suitable for beginners like me to start with.

    I just wrote two lines as follows and nothing else and still it gets stuck in busy loop.

    SSIDataPut(SSI3_BASE,0x9F); 	// Read ID
    while(SSIBusy(SSI3_BASE)){}

    I noticed that in your code you are reading the device ID in main(). however according to datasheet you need to send 0x9F command. But its not there in your code anywhere.

    any suggestion on clearing the Rx FIFO first and then reading the values sent by slave?

    Thanks

  • Hi Amit,

    Need to clear few things with you.

    According to datasheet of MCU, it says there are 3 modes possible.  Advanced, Bi and Quad. There are APIs mostly for Advanced mode. Even Legacy mode is characterized as SSI_ADV_MODE_LEGACY. So does that mean that user doesnt have any choice but to work in Advanced mode only. Why cant we have Simple SPI legacy mode? So how many submodes are there in advanced mode?

    Still my code gets stuck whenever I use SSIbusy(). Dont know why. I looked into many forum posts and they all are using SSIBusy(). What am I doing wrong?

    Thanks

  • Hello Spandan89,

    The Advanced mode and Legacy are two different modes. Legacy mode is the same as TM4C123 SSI Mode. The Advanced modes are meant especially for communicating with Serial/Bi/Quad Flash like the one on the DK-TM4C129.

    Regards

    Amit

  • Hello Spandan89,

    Both 0x9F and 0x90 are valid for reading Device ID. The OPCODE 0x90 allows me to change the order of the byte reads based on the 3rd dummy byte value.

    In Legacy mode you need to be aware of the fact that the CS will toggle which will break the transaction to the SPI Flash. Hence you "must" use the Advanced mode or change the CS to GPIO control where you can have control to do a complete transaction.

    I would suggest doing a SysCtlPeripheralReset of the SSI before doing the SysCtlPeripheralEnable to ensure the state machine is reset cleanly between runs. Secondly to flush out data, you can do a SSIDataGetNotBlocking while the RXFE is not set. The example for SSI in in TivaWare's example/peripheral/ssi shows you how to do it.

    Regards

    Amit

  • Hi Amit,

    Over the weekend I was trying to write data into sector. First I checked that sector is erased correctly by reading FF once the sector is erased  correctly. It works fine. But when I try to write any data into the sector by using Page Program instruction it doesnt work. I have checked the waveforms also. Howver oscilloscope is only 2 channels so i had to look at the waveform partially. Here is the code. I have studied your code many times and looks like I am not doing wrong or I'm missing the key point. I will really appreciate if you can point a mistake.

    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_memmap.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/ssi.h"
    #include "driverlib/sysctl.h"
    #include "inc/hw_ssi.h"
    #include "inc/hw_types.h"
    #include "inc/hw_gpio.h"
    
    
    #define FLASH_BUSY_BIT				0x01
    #define FLASH_WRITE_EN_LATCH_BIT	0x02
    
    uint32_t ReadID(uint32_t ui32Base)
    {
        uint32_t ui32MfgID,ui32DevID,Device_ID;
    
    	// First set the master in write mode only. any data sent by slave will be discarded by master.
    	// since dlave may send upto 3 bytes in return, write 3 dummy bytes and slave's sent data will be discarded by master.
    	// untill the next command is issued, slave will keep sending the 3 bytes in sequence
    	// After 3 dummy write start the real communication by setting the master in READ_WRITE_MODE
    	// Now provide one dummy write and slave will send the first of 3 bytes.
    	// provide second dummy write and slave will send the second byte and so on...
    
    
    	SSIDataPut(ui32Base, 0x9F); // Instead of issuing 4 instruction, use only one.
    	SSIDataPut(ui32Base, 0x00);
    	SSIDataPut(ui32Base, 0x00);
    	SSIDataPut(ui32Base, 0x00);
    
    /* ---------  Untill this point discard the data sent by slave. So set the master in Write_mode only. --------------*/
    
    	SSIAdvModeSet(ui32Base,SSI_ADV_MODE_READ_WRITE);
    	SSIDataPut(ui32Base, 0x00);
    	SSIDataGet(ui32Base, &ui32MfgID);	// Read Manufacture ID
    
    	SSIAdvDataPutFrameEnd(ui32Base,0x00); // Puts data into Tx FIFO with end of frame bits
    
    	SSIDataGet(ui32Base, &ui32DevID);
    
    	Device_ID = (ui32MfgID<<8) | ui32DevID;
    	SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE);
    
    	return Device_ID;
    }
    
    uint8_t ReadStatusReg(uint32_t ui32Base, uint8_t ui8FlashCommand)
    {
    	uint32_t ui32Status = 0;
    	uint8_t ui8FlashStatus,ui32Trash;
    
    	SSIAdvFrameHoldEnable(ui32Base);
    	SSIDataPut(ui32Base,ui8FlashCommand);
    	SSIAdvModeSet(ui32Base,SSI_ADV_MODE_READ_WRITE);
    	SSIAdvDataPutFrameEnd(ui32Base,0x00);
    	while(SSIBusy(ui32Base));
    	SSIDataGet(ui32Base, &ui32Status);
    	ui8FlashStatus = (uint8_t)ui32Status;
    	SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE);
    
    	return ui8FlashStatus;
    }
    
    void DeviceBusyCheck(uint32_t ui32Base)
    {
    	uint8_t ui8TempData=0xFF;
    
    	ui8TempData = ReadStatusReg(ui32Base,0x05);
    
    	while((ui8TempData & FLASH_BUSY_BIT) == FLASH_BUSY_BIT)
     	{
    		ui8TempData = ReadStatusReg(ui32Base,0x05);
     	}
    }
    
    void Sector_Erase(uint32_t ui32Base, uint32_t ui32Address, uint8_t ui8FlashCommand)
    {
    	uint32_t getstatus;
        SSIAdvModeSet(ui32Base, SSI_ADV_MODE_WRITE);
        SSIAdvFrameHoldEnable(ui32Base);
        SSIAdvDataPutFrameEnd(ui32Base,0x06);
        while(SSIBusy(ui32Base));
    
        //check for the WIP bit.
        getstatus = ReadStatusReg(SSI3_BASE,0x05);
        while((getstatus & 0x02) != 0x02)
        {
        	getstatus = ReadStatusReg(SSI3_BASE,0x05);
        }
    
        SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE);
    	SSIAdvFrameHoldEnable(ui32Base);
    
        SSIDataPut(ui32Base, 0x20);	// send the sector erase command.
        SSIDataPut(ui32Base, (ui32Address >> 16) & 0xff);
        SSIDataPut(ui32Base, (ui32Address >> 8) & 0xff);
        SSIAdvDataPutFrameEnd(ui32Base, ui32Address & 0xff);
        while(SSIBusy(SSI3_BASE));
        DeviceBusyCheck(SSI3_BASE);
    }
    
    void Read_Data(uint32_t ui32Base, uint32_t ui32Address, uint8_t ui8FlashCommand)
    {
    	uint32_t ui32TempAddr,ui32Trash;
    
    	while(SSIDataGetNonBlocking(ui32Base, &ui32Trash) != 0);	// Get the useless data
    
    	SSIAdvModeSet(ui32Base,SSI_ADV_MODE_WRITE);
    	SSIAdvFrameHoldEnable(ui32Base);
    
    	SSIDataPut(ui32Base,ui8FlashCommand);
    	SSIDataPut(ui32Base, (ui32Address >> 16) & 0xff);
    	SSIDataPut(ui32Base, (ui32Address >> 8) & 0xff);
    	SSIDataPut(ui32Base, ui32Address & 0xff);
    
    	SSIAdvModeSet(ui32Base,SSI_ADV_MODE_READ_WRITE);
    }
    
    void Page_program(uint32_t ui32Base, uint32_t ui32Address, uint8_t ui8FlashCommand)
    {
    	uint32_t getstatus;
    
    	SSIAdvModeSet(ui32Base, SSI_ADV_MODE_WRITE);
    	SSIAdvFrameHoldEnable(ui32Base);
    	SSIAdvDataPutFrameEnd(ui32Base, 0x06);	// send the WREN command
    	while(SSIBusy(SSI3_BASE));
    
    	// Get the status register and check the WEL bit. It gets cleared when the Page Program cycle gets completed
    	getstatus = ReadStatusReg(SSI3_BASE,0x05);
    	while((getstatus & 0x02) != 0x02)
    	{
    		getstatus = ReadStatusReg(SSI3_BASE,0x05);
    	}
    
    	SSIAdvModeSet(ui32Base,SSI_ADV_MODE_WRITE);
    	SSIAdvFrameHoldEnable(SSI3_BASE);
    	SSIDataPut(ui32Base,0x02);	// send the Page Program Command
    	SSIDataPut(ui32Base, (ui32Address >> 16) & 0xff);
    	SSIDataPut(ui32Base, (ui32Address >> 8) & 0xff);
    	SSIDataPut(ui32Base, ui32Address & 0xff);
    }
    
    int main()
    {
    	uint32_t ui32SysClk, ui32Index;
    	uint32_t rx_data[20] = 0x00;
    	// define data that you want to receive
    	uint32_t ui32Trash, ID_check, data_page[20];
    
    
    	// set the system clock to be 25MHz
    	ui32SysClk = SysCtlClockFreqSet(SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_25MHZ, 25000000);
    
    	//Configure Master Module and system Parameters.
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI3);
    
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOQ);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    
    
    	HWREG(GPIO_PORTF_BASE+GPIO_O_LOCK) = GPIO_LOCK_KEY;
    	HWREG(GPIO_PORTF_BASE+GPIO_O_CR)   |= GPIO_PIN_0;
    
    	// Configure GPIO pins
    	GPIOPinConfigure(GPIO_PQ0_SSI3CLK);
    	GPIOPinConfigure(GPIO_PQ1_SSI3FSS);
    	GPIOPinConfigure(GPIO_PQ2_SSI3XDAT0);
    	GPIOPinConfigure(GPIO_PF0_SSI3XDAT1);
    
    	// Enable GPIO Ports pin types as SPI
    	GPIOPinTypeSSI(GPIO_PORTQ_BASE,(GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2));
    	GPIOPinTypeSSI(GPIO_PORTF_BASE,GPIO_PIN_0);
    
    	// Provide colck to the module.
    	SSIConfigSetExpClk(SSI3_BASE, ui32SysClk, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 1000000, 8);
    
    	SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE);
    	SSIAdvFrameHoldEnable(SSI3_BASE);
    	SSIEnable(SSI3_BASE);
    
    	while(SSIDataGetNonBlocking(SSI3_BASE, &ui32Trash)){}
    
    	// Check the Device ID
    	ID_check = ReadID(SSI3_BASE);
    
    	// Send erase command befor page program
    	Sector_Erase(SSI3_BASE,0x00,0x20);
    
    	// Prepare the data that you want to write to page
    	for(ui32Index=0;ui32Index<20;ui32Index++)
    	{
    		data_page[ui32Index] = 0xAA;
    	}
    
    	// Write something to Page
    	Page_program(SSI3_BASE,0x00,0x02);
    	for(ui32Index=0;ui32Index<19;ui32Index++)
    	{
    		SSIDataPut(SSI3_BASE,data_page[ui32Index]);
    	}
    	SSIAdvDataPutFrameEnd(SSI3_BASE,data_page[19]);
    
    	// Read the data that you just wrote
    	Read_Data(SSI3_BASE,0x0,0x03);
    	for(ui32Index=0;ui32Index<19;ui32Index++)
    	{
    		SSIDataPut(SSI3_BASE,0x00);
    		SSIDataGet(SSI3_BASE,&rx_data[ui32Index]);
    	}
    	SSIAdvDataPutFrameEnd(SSI3_BASE,0x00);
    	SSIDataGet(SSI3_BASE,&rx_data[19]);
    
    	while(1);
    
    }
    

    Thanks

  • Hello Spandan89

    In the Read Status Register function the sequence is incorrect. First you set the mode, then frame hold and then send the data.

        SSIAdvFrameHoldEnable(ui32Base);
        SSIDataPut(ui32Base,ui8FlashCommand);
        SSIAdvModeSet(ui32Base,SSI_ADV_MODE_READ_WRITE);

    Also the RDSR is a 3 bytecommand, whereas the function shows that only 2 bytes will be sent

    Regards

    Amit

  • Hi Amit,

    The same sequence is there in your code also. Just to check , I use the same code function from your code and still no luck.

    Can you please explain your last sentence? "Also the RDSR is a 3 bytecommand, whereas the function shows that only 2 bytes will be sent."

    Thanks

  • Hello Spandan89

    OK, my bad, I misread the timing diagram as to be having two Status register whereas on macronix device it is only one status register. So you are right that the RDSR command is correct.

    I need to check my sequence as to how come it is working.

    Regards

    Amit

  • Hi Amit,

    I have tried the following method for reading the status register value and it works fine. Finally I was able to write something into sector and read it back.

    uint8_t ReadStatusReg(uint32_t ui32Base, uint8_t ui8FlashCommand)
    {
        uint32_t ui32Status = 0;
        uint8_t ui8FlashStatus;
    
        SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE);
        SSIDataPut(SSI3_BASE,0x05);
    //    SSIAdvDataPutFrameEnd(SSI3_BASE,0x00);
    //    while(SSIBusy(SSI3_BASE));
    
        SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_READ_WRITE);
        SSIAdvDataPutFrameEnd(SSI3_BASE,0x00);
        SSIDataGet(SSI3_BASE,&ui32Status);
    
        return ui32Status;
    }

    But I'm still confused like how come your ReadStatus() function works? The sequence doesnt make any sense. 

    Thanks

  • Hello Spandan89,

    In the function I have as SSILibSendReadStatusRegister, every where it is called there is a SSI_ADV_MODE_WRITE before it. So in essence what it does is send the command in Write mode and then writes the dummy byte with frame end causing the correct status to be shifted in.

        SSIAdvFrameHoldEnable(ui32Base);
        SSIDataPut(ui32Base,ui8FlashCommand);
        SSIAdvModeSet(ui32Base,SSI_ADV_MODE_READ_WRITE);
        SSIAdvDataPutFrameEnd(ui32Base,DUMMY_BYTE);
        while(SSIBusy(ui32Base));
        SSIDataGet(ui32Base, &ui32Status);
        ui8FlashStatus = (uint8_t)ui32Status;
        SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE);

    But then it is a good point you have raised, and I need to change my example code to be more clean and readable. Appreciate the feedback.

    Regards

    Amit

  • Hi Amit,

    I have one more question. The address of the 0th sector is 0x0000000, which is of 7 hex digits. Now when we send the address to slave its only 3 bytes(6 hex digits). So Lets say if I wanna write into top most sector which is 0x3FFF000, how can I break into 3 bytes? or i have to use the 4 byte address mode?

    One more thing. I was trying to write into other higher sectors. But I couldnt write into 0x00000FF or 0x0000FFF.

    I dont know why.

    In the flash datasheet, it says the first sector address range is 0x0000000 to 0x0000FFF. So is the whole address range sums upto 4KByte ? with 3 bytes address mode I should be able to write upto 0x0FFFFFF. The next address after that will be 0x1000000 for which I need to enter into 4 byte address mode. Did I understand it correctly?

    Thanks

  • Hello Spandan89

    Yes. The 4 Byte addressing mode is required when it is required to access flash memory greater than 128Mb. This is mentioned in the data sheet as well

    Regards

    Amit

  • Hi Amit,

    One more thing. I was trying to write into other higher sectors. But I couldnt write into 0x00000FF or 0x0000FFF.

    I dont know why. these addresses doesnt require to enter into 4 byte mode.

    In the flash datasheet, it says the first sector address range is 0x0000000 to 0x0000FFF. So is the whole address range sums upto 4KByte ? with 3 bytes address mode I should be able to write upto 0x0FFFFFF. The next address after that will be 0x1000000 for which I need to enter into 4 byte address mode. Did I understand it correctly?

    Thanks

  • Hello Spandan89,

    The Macronix Flash accepts 256 bytes in every program operation. So locations from 0x0 to 0xFF should be written. To write to the next location you would need to change the address to 0x0000100 and then program.

    Regards

    Amit

  • Hi Amit,

    My sector ease is working fine. I can write into any sector and read it back. However, When i tried to implement the chip erase function, its not working. I followed implemented chip erase in simillar way to sector erase. But it gets stuck in SSIBusy() loop in ReadStatusReg(). I have tried few things and its not working. 

    I read the datasheet and I have followed the same procedure as mentioned in datasheet. I would really appreciate it if you can point out mistake.

    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_memmap.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/ssi.h"
    #include "driverlib/sysctl.h"
    #include "inc/hw_ssi.h"
    #include "inc/hw_types.h"
    #include "inc/hw_gpio.h"
    
    
    #define FLASH_BUSY_BIT				0x01
    #define FLASH_WRITE_EN_LATCH_BIT	0x02
    #define SECTOR_ADDRESS				0X0000000
    #define DATA 						0x33
    
    uint32_t ReadID(uint32_t ui32Base)
    {
        uint32_t ui32MfgID,ui32DevID,Device_ID;
    
    	// First set the master in write mode only. any data sent by slave will be discarded by master.
    	// since dlave may send upto 3 bytes in return, write 3 dummy bytes and slave's sent data will be discarded by master.
    	// untill the next command is issued, slave will keep sending the 3 bytes in sequence
    	// After 3 dummy write start the real communication by setting the master in READ_WRITE_MODE
    	// Now provide one dummy write and slave will send the first of 3 bytes.
    	// provide second dummy write and slave will send the second byte and so on...
    
    
    	SSIDataPut(ui32Base, 0x9F); // Instead of issuing 4 instruction, use only one.
    	SSIDataPut(ui32Base, 0x00);
    	SSIDataPut(ui32Base, 0x00);
    	SSIDataPut(ui32Base, 0x00);
    
    // ---------  Untill this point discard the data sent by slave. So set the master in Write_mode only. --------------
    
    	SSIAdvModeSet(ui32Base,SSI_ADV_MODE_READ_WRITE);
    	SSIDataPut(ui32Base, 0x00);
    	SSIDataGet(ui32Base, &ui32MfgID);	// Read Manufacture ID
    
    	SSIAdvDataPutFrameEnd(ui32Base,0x00); // Puts data into Tx FIFO with end of frame bits
    
    	SSIDataGet(ui32Base, &ui32DevID);
    
    	Device_ID = (ui32MfgID<<8) | ui32DevID;
    	SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE);
    
    	return Device_ID;
    }
    
    uint8_t ReadStatusReg(uint32_t ui32Base, uint8_t ui8FlashCommand)
    {
        uint32_t ui32Status = 0;
        uint8_t ui8FlashStatus;
    
    //    SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE);
        SSIAdvFrameHoldEnable(ui32Base);
        SSIDataPut(SSI3_BASE,0x05);
    
        SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_READ_WRITE);
        SSIAdvDataPutFrameEnd(SSI3_BASE,0x00);
        while(SSIBusy(ui32Base));
        SSIDataGet(SSI3_BASE,&ui32Status);
        ui8FlashStatus = (uint8_t)ui32Status;
        SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE);
    
        return ui8FlashStatus;
    }
    
    void DeviceBusyCheck(uint32_t ui32Base)
    {
    	uint8_t ui8TempData;
    
    	ui8TempData = ReadStatusReg(ui32Base,0x05);
    
    	while((ui8TempData & FLASH_BUSY_BIT) == FLASH_BUSY_BIT)
     	{
    		ui8TempData = ReadStatusReg(ui32Base,0x05);
     	}
    }
    
    void Sector_Erase(uint32_t ui32Base, uint32_t ui32Address, uint8_t ui8FlashCommand)
    {
    	uint32_t getstatus = 0x00;
    
        SSIAdvModeSet(ui32Base, SSI_ADV_MODE_WRITE);
        SSIAdvFrameHoldEnable(ui32Base);
        SSIAdvDataPutFrameEnd(ui32Base,0x06);
        while(SSIBusy(ui32Base));
    
    /*
        //check for the WIP bit.
        getstatus = ReadStatusReg(SSI3_BASE,0x05);
        while((getstatus & 0x02) != 0x02)
        {
        	getstatus = ReadStatusReg(SSI3_BASE,0x05);
        }
    */
        DeviceBusyCheck(SSI3_BASE);
    
        SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE);
    	SSIAdvFrameHoldEnable(ui32Base);
    
        SSIDataPut(ui32Base, 0x20);	// send the sector erase command.
    //    SSIDataPut(ui32Base, 0x60);		// send the chip erase command
    
        SSIDataPut(ui32Base, (ui32Address >> 16) & 0xff);
        SSIDataPut(ui32Base, (ui32Address >> 8) & 0xff);
        SSIAdvDataPutFrameEnd(ui32Base, ui32Address & 0xff);
    
        while(SSIBusy(SSI3_BASE));
        DeviceBusyCheck(SSI3_BASE);
    }
    
    void ChipErase(uint32_t ui32Base)
    {
    	uint32_t getstatus = 0x00;
    
    	SSIAdvModeSet(ui32Base, SSI_ADV_MODE_WRITE);
    	SSIAdvFrameHoldEnable(ui32Base);
    	SSIAdvDataPutFrameEnd(ui32Base,0x06);
    	while(SSIBusy(ui32Base));
    /*
    	getstatus = ReadStatusReg(SSI3_BASE,0x05);
    	while((getstatus & 0x02) != 0x02)
    	{
    		getstatus = ReadStatusReg(SSI3_BASE,0x05);
    	}*/
    
    	DeviceBusyCheck(SSI3_BASE);
    
    	SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE);
    	SSIAdvFrameHoldEnable(ui32Base);
    
    	SSIAdvDataPutFrameEnd(ui32Base, 0xC7);	// send the Chip erase command.
    //	SSIDataPut(ui32Base, 0x60);
    //	SSIAdvDataPutFrameEnd(ui32Base,0x00);
    	while(SSIBusy(SSI3_BASE));
    	DeviceBusyCheck(SSI3_BASE);
    
    }
    
    void Read_Data(uint32_t ui32Base, uint32_t ui32Address, uint8_t ui8FlashCommand)
    {
    	uint32_t ui32TempAddr,ui32Trash;
    
    	while(SSIDataGetNonBlocking(ui32Base, &ui32Trash) != 0);	// Get the useless data
    
    	SSIAdvModeSet(ui32Base,SSI_ADV_MODE_WRITE);
    	SSIAdvFrameHoldEnable(ui32Base);
    
    	SSIDataPut(ui32Base,ui8FlashCommand);
    	SSIDataPut(ui32Base, (ui32Address >> 16) & 0xff);
    	SSIDataPut(ui32Base, (ui32Address >> 8) & 0xff);
    	SSIDataPut(ui32Base, ui32Address & 0xff);
    
    	SSIAdvModeSet(ui32Base,SSI_ADV_MODE_READ_WRITE);
    }
    
    void Page_program(uint32_t ui32Base, uint32_t ui32Address, uint8_t ui8FlashCommand)
    {
    	uint32_t getstatus;
    
    	SSIAdvModeSet(ui32Base, SSI_ADV_MODE_WRITE);
    	SSIAdvFrameHoldEnable(ui32Base);
    	SSIAdvDataPutFrameEnd(ui32Base, 0x06);	// send the WREN command
    	while(SSIBusy(SSI3_BASE));
    
    	// Get the status register and check the WEL bit. It gets cleared when the Page Program cycle gets completed
    	getstatus = ReadStatusReg(SSI3_BASE,0x05);
    	while((getstatus & 0x02) != 0x02)
    	{
    		getstatus = ReadStatusReg(SSI3_BASE,0x05);
    	}
    
    	SSIAdvModeSet(ui32Base,SSI_ADV_MODE_WRITE);
    	SSIAdvFrameHoldEnable(SSI3_BASE);
    	SSIDataPut(ui32Base,0x02);	// send the Page Program Command
    	SSIDataPut(ui32Base, (ui32Address >> 16) & 0xff);
    	SSIDataPut(ui32Base, (ui32Address >> 8) & 0xff);
    	SSIDataPut(ui32Base, ui32Address & 0xff);
    }
    
    int main()
    {
    	uint32_t ui32SysClk, ui32Index;
    	uint32_t data_page[20], rx_data[20];
    
    	// define data that you want to receive
    	uint32_t ui32Trash, ID_check;
    
    	// set the system clock to be 25MHz
    	ui32SysClk = SysCtlClockFreqSet(SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_25MHZ, 25000000);
    
    	//Configure Master Module and system Parameters.
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI3);
    
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOQ);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    
    	HWREG(GPIO_PORTF_BASE+GPIO_O_LOCK) = GPIO_LOCK_KEY;
    	HWREG(GPIO_PORTF_BASE+GPIO_O_CR)   |= GPIO_PIN_0;
    
    	// Configure GPIO pins
    	GPIOPinConfigure(GPIO_PQ0_SSI3CLK);
    	GPIOPinConfigure(GPIO_PQ1_SSI3FSS);
    	GPIOPinConfigure(GPIO_PQ2_SSI3XDAT0);
    	GPIOPinConfigure(GPIO_PF0_SSI3XDAT1);
    
    	// Enable GPIO Ports pin types as SPI
    	GPIOPinTypeSSI(GPIO_PORTQ_BASE,(GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2));
    	GPIOPinTypeSSI(GPIO_PORTF_BASE,GPIO_PIN_0);
    
    	// Provide colck to the module.
    	SSIConfigSetExpClk(SSI3_BASE, ui32SysClk, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 1000000, 8);
    
    	SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE);
    	SSIAdvFrameHoldEnable(SSI3_BASE);
    	SSIEnable(SSI3_BASE);
    
    	while(SSIDataGetNonBlocking(SSI3_BASE, &ui32Trash)){}
    
    	// Prepare the data that you want to write to page
    	for(ui32Index=0;ui32Index<20;ui32Index++)
    	{
    		data_page[ui32Index] = DATA;
    		rx_data[ui32Index] = 0x00;
    	}
    
    	// Check the Device ID
    	ID_check = ReadID(SSI3_BASE);
    
    	// Send erase command befor page program
    //	Sector_Erase(SSI3_BASE,SECTOR_ADDRESS,0x20);
    
    	// Erase Entire Chip
    	ChipErase(SSI3_BASE);
    //	DeviceBusyCheck(SSI3_BASE);
    
    
    
    /*
    	// Write something to Page
    	Page_program(SSI3_BASE,SECTOR_ADDRESS,0x02);
    	for(ui32Index=0;ui32Index<19;ui32Index++)
    	{
    		SSIDataPut(SSI3_BASE,(data_page[ui32Index]& 0x00FF));
    	}
    	SSIAdvDataPutFrameEnd(SSI3_BASE,data_page[19]);
    	while(SSIBusy(SSI3_BASE)){}
    	DeviceBusyCheck(SSI3_BASE);
    */
    
    
    
    	// Read the data that you just wrote
    	Read_Data(SSI3_BASE,SECTOR_ADDRESS,0x03);
    	for(ui32Index=0;ui32Index<19;ui32Index++)
    	{
    		SSIDataPut(SSI3_BASE,0x00);
    		SSIDataGet(SSI3_BASE,&rx_data[ui32Index]);
    	}
    	SSIAdvDataPutFrameEnd(SSI3_BASE,0x00);
    	SSIDataGet(SSI3_BASE,&rx_data[19]);
    
    	while(1)
    	{
    	}
    
    }
    

    Thanks

  • Hello Spandan89,

    When doing the RDSR can you check what is the value of the RDSR register on the scope? Also is there any protected sector?

    Regards

    Amit

  • Hi Amit,

    My ChipErase() is still not working. but before that I tried to write the whole Page with some values and I can not write beyond 48 value. Untill now I was only writing 20 values. I believe SSIDataPut method is blocking method, so if the TX FIFO is full then it will wait untill there is space and then it will put more data into it. I guess, 256 byte of a page is organized as 16x16 byte array. I really dont know why it doesnt go beyond 48. 

    Just to check, I tried your program to write more data and Obviously it worked.  I compared my function with yours and looks fine to me. If I run my program trying to write beyond 48 values, then it goes into FaultISR(). Any suggestions?

    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_memmap.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/ssi.h"
    #include "driverlib/sysctl.h"
    #include "inc/hw_ssi.h"
    #include "inc/hw_types.h"
    #include "inc/hw_gpio.h"
    
    
    #define FLASH_BUSY_BIT				0x01
    #define FLASH_WRITE_EN_LATCH_BIT	0x02
    #define SECTOR_ADDRESS				0X0000000
    #define DATA 						0xDD
    #define TX_RX_BUFFER_SIZE			64
    #define NUM_DATA					(TX_RX_BUFFER_SIZE - 1)
    
    uint32_t ReadID(uint32_t ui32Base)
    {
        uint32_t ui32MfgID,ui32DevID,Device_ID;
    
    	// First set the master in write mode only. any data sent by slave will be discarded by master.
    	// since dlave may send upto 3 bytes in return, write 3 dummy bytes and slave's sent data will be discarded by master.
    	// untill the next command is issued, slave will keep sending the 3 bytes in sequence
    	// After 3 dummy write start the real communication by setting the master in READ_WRITE_MODE
    	// Now provide one dummy write and slave will send the first of 3 bytes.
    	// provide second dummy write and slave will send the second byte and so on...
    
    
    	SSIDataPut(ui32Base, 0x9F); // Instead of issuing 4 instruction, use only one.
    	SSIDataPut(ui32Base, 0x00);
    	SSIDataPut(ui32Base, 0x00);
    	SSIDataPut(ui32Base, 0x00);
    
    // ---------  Untill this point discard the data sent by slave. So set the master in Write_mode only. --------------
    
    	SSIAdvModeSet(ui32Base,SSI_ADV_MODE_READ_WRITE);
    	SSIDataPut(ui32Base, 0x00);
    	SSIDataGet(ui32Base, &ui32MfgID);	// Read Manufacture ID
    
    	SSIAdvDataPutFrameEnd(ui32Base,0x00); // Puts data into Tx FIFO with end of frame bits
    
    	SSIDataGet(ui32Base, &ui32DevID);
    
    	Device_ID = (ui32MfgID<<8) | ui32DevID;
    	SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE);
    
    	return Device_ID;
    }
    
    uint8_t ReadStatusReg(uint32_t ui32Base, uint8_t ui8FlashCommand)
    {
        uint32_t ui32Status = 0;
        uint8_t ui8FlashStatus;
    
    //    SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE);
        SSIAdvFrameHoldEnable(ui32Base);
        SSIDataPut(SSI3_BASE,0x05);
    
        SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_READ_WRITE);
        SSIAdvDataPutFrameEnd(SSI3_BASE,0x00);
        while(SSIBusy(ui32Base));
        SSIDataGet(SSI3_BASE,&ui32Status);
        ui8FlashStatus = (uint8_t)ui32Status;
        SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE);
    
        return ui8FlashStatus;
    }
    
    void DeviceBusyCheck(uint32_t ui32Base)
    {
    	uint8_t ui8TempData;
    
    	ui8TempData = ReadStatusReg(ui32Base,0x05);
    
    	while((ui8TempData & FLASH_BUSY_BIT) == FLASH_BUSY_BIT)
     	{
    		ui8TempData = ReadStatusReg(ui32Base,0x05);
     	}
    }
    
    void Sector_Erase(uint32_t ui32Base, uint32_t ui32Address, uint8_t ui8FlashCommand)
    {
    	uint32_t getstatus = 0x00;
    
        SSIAdvModeSet(ui32Base, SSI_ADV_MODE_WRITE);
        SSIAdvFrameHoldEnable(ui32Base);
        SSIAdvDataPutFrameEnd(ui32Base,0x06);
        while(SSIBusy(ui32Base));
    
    
        //check for the WIP bit.
        getstatus = ReadStatusReg(SSI3_BASE,0x05);
        while((getstatus & 0x02) != 0x02)
        {
        	getstatus = ReadStatusReg(SSI3_BASE,0x05);
        }
    
    //    DeviceBusyCheck(SSI3_BASE);
    
        SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE);
    	SSIAdvFrameHoldEnable(ui32Base);
    
        SSIDataPut(ui32Base, 0x20);	// send the sector erase command.
    //    SSIDataPut(ui32Base, 0x60);		// send the chip erase command
    
        SSIDataPut(ui32Base, (ui32Address >> 16) & 0xff);
        SSIDataPut(ui32Base, (ui32Address >> 8) & 0xff);
        SSIAdvDataPutFrameEnd(ui32Base, ui32Address & 0xff);
    
        while(SSIBusy(SSI3_BASE));
        DeviceBusyCheck(SSI3_BASE);
    }
    
    void ChipErase(uint32_t ui32Base)
    {
    	uint32_t getstatus = 0x00;
    
    	SSIAdvModeSet(ui32Base, SSI_ADV_MODE_WRITE);
    	SSIAdvFrameHoldEnable(ui32Base);
    	SSIAdvDataPutFrameEnd(ui32Base,0x06);
    	while(SSIBusy(ui32Base));
    
    	getstatus = ReadStatusReg(SSI3_BASE,0x05);
    	while((getstatus & 0x02) != 0x02)
    	{
    		getstatus = ReadStatusReg(SSI3_BASE,0x05);
    	}
    
    //	DeviceBusyCheck(SSI3_BASE);
    
    	SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE);
    	SSIAdvFrameHoldEnable(ui32Base);
    
    	SSIAdvDataPutFrameEnd(ui32Base, 0xC7);	// send the Chip erase command.
    //	SSIDataPut(ui32Base, 0x60);
    //	SSIAdvDataPutFrameEnd(ui32Base,0x00);
    	while(SSIBusy(SSI3_BASE));
    //	DeviceBusyCheck(SSI3_BASE);
    }
    
    void Read_Data(uint32_t ui32Base, uint32_t ui32Address, uint8_t ui8FlashCommand)
    {
    	uint32_t ui32TempAddr,ui32Trash;
    
    	while(SSIDataGetNonBlocking(ui32Base, &ui32Trash) != 0);	// Get the useless data
    
    	SSIAdvModeSet(ui32Base,SSI_ADV_MODE_WRITE);
    	SSIAdvFrameHoldEnable(ui32Base);
    
    	SSIDataPut(ui32Base,ui8FlashCommand);
    	SSIDataPut(ui32Base, (ui32Address >> 16) & 0xff);
    	SSIDataPut(ui32Base, (ui32Address >> 8) & 0xff);
    	SSIDataPut(ui32Base, ui32Address & 0xff);
    
    	SSIAdvModeSet(ui32Base,SSI_ADV_MODE_READ_WRITE);
    }
    
    void Page_program(uint32_t ui32Base, uint32_t ui32Address, uint8_t ui8FlashCommand)
    {
    	uint32_t getstatus;
    
    	SSIAdvModeSet(ui32Base, SSI_ADV_MODE_WRITE);
    	SSIAdvFrameHoldEnable(ui32Base);
    	SSIAdvDataPutFrameEnd(ui32Base, 0x06);	// send the WREN command
    	while(SSIBusy(SSI3_BASE));
    
    	// Get the status register and check the WEL bit. It gets cleared when the Page Program cycle gets completed
    	getstatus = ReadStatusReg(SSI3_BASE,0x05);
    	while((getstatus & 0x02) != 0x02)
    	{
    		getstatus = ReadStatusReg(SSI3_BASE,0x05);
    	}
    
    	SSIAdvModeSet(ui32Base,SSI_ADV_MODE_WRITE);
    	SSIAdvFrameHoldEnable(SSI3_BASE);
    	SSIDataPut(ui32Base,0x02);	// send the Page Program Command
    	SSIDataPut(ui32Base, (ui32Address >> 16) & 0xff);
    	SSIDataPut(ui32Base, (ui32Address >> 8) & 0xff);
    	SSIDataPut(ui32Base, ui32Address & 0xff);
    }
    
    int main()
    {
    	uint32_t ui32SysClk, ui32Index;
    	uint32_t data_page[TX_RX_BUFFER_SIZE], rx_data[TX_RX_BUFFER_SIZE];
    
    	// define data that you want to receive
    	uint32_t ui32Trash, ID_check;
    
    	// set the system clock to be 25MHz
    	ui32SysClk = SysCtlClockFreqSet(SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_25MHZ, 25000000);
    
    	//Configure Master Module and system Parameters.
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI3);
    
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOQ);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    
    	HWREG(GPIO_PORTF_BASE+GPIO_O_LOCK) = GPIO_LOCK_KEY;
    	HWREG(GPIO_PORTF_BASE+GPIO_O_CR)   |= GPIO_PIN_0;
    
    	// Configure GPIO pins
    	GPIOPinConfigure(GPIO_PQ0_SSI3CLK);
    	GPIOPinConfigure(GPIO_PQ1_SSI3FSS);
    	GPIOPinConfigure(GPIO_PQ2_SSI3XDAT0);
    	GPIOPinConfigure(GPIO_PF0_SSI3XDAT1);
    
    	// Enable GPIO Ports pin types as SPI
    	GPIOPinTypeSSI(GPIO_PORTQ_BASE,(GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2));
    	GPIOPinTypeSSI(GPIO_PORTF_BASE,GPIO_PIN_0);
    
    	// Provide colck to the module.
    	SSIConfigSetExpClk(SSI3_BASE, ui32SysClk, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 1000000, 8);
    
    	SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE);
    	SSIAdvFrameHoldEnable(SSI3_BASE);
    	SSIEnable(SSI3_BASE);
    
    	while(SSIDataGetNonBlocking(SSI3_BASE, &ui32Trash)){}
    
    	// Prepare the data that you want to write to page
    	for(ui32Index=0;ui32Index<TX_RX_BUFFER_SIZE;ui32Index++)
    	{
    		data_page[ui32Index] = DATA;
    		rx_data[ui32Index] = 0x00;
    	}
    
    	// Check the Device ID
    //	ID_check = ReadID(SSI3_BASE);
    
    	// Send erase command befor page program
    	Sector_Erase(SSI3_BASE,SECTOR_ADDRESS,0x20);
    
    	// Erase Entire Chip
    //	ChipErase(SSI3_BASE);
    //	DeviceBusyCheck(SSI3_BASE);
    
    	// Write something to Page
    	Page_program(SSI3_BASE,SECTOR_ADDRESS,0x02);
    	for(ui32Index=0;ui32Index<NUM_DATA;ui32Index++)
    	{
    		SSIDataPut(SSI3_BASE,(data_page[ui32Index]& 0x00FF));
    	}
    	SSIAdvDataPutFrameEnd(SSI3_BASE,data_page[NUM_DATA]);
    	while(SSIBusy(SSI3_BASE)){}
    	DeviceBusyCheck(SSI3_BASE);
    
    	// Read the data that you just wrote
    	Read_Data(SSI3_BASE,SECTOR_ADDRESS,0x03);
    	for(ui32Index=0;ui32Index<NUM_DATA;ui32Index++)
    	{
    		SSIDataPut(SSI3_BASE,0x00);
    		SSIDataGet(SSI3_BASE,&rx_data[ui32Index]);
    	}
    	SSIAdvDataPutFrameEnd(SSI3_BASE,0x00);
    	SSIDataGet(SSI3_BASE,&rx_data[NUM_DATA]);
    
    	while(1)
    	{
    	}
    
    }
    

    Thanks

  • Hello Spandam89,

    Make the following variable declaration as global. It works after doing so.

    uint32_t data_page[TX_RX_BUFFER_SIZE], rx_data[TX_RX_BUFFER_SIZE];

    Regards

    Amit

  • Hi Amit,

    Its now working. But I'm still stuck with ChipErase(). 

    I found that WIP bit in the status register is not getting cleared by the flash. So in the loop, it continuously checks for the WIP bit to set to 0 which indicates that the Chip has finished erasing. When WIP bit gets cleared, it also clears WEL bit.

    void DeviceBusyCheck(uint32_t ui32Base)
    {
    	uint8_t ui8TempData;
    
    	ui8TempData = ReadStatusReg(ui32Base,0x05);
    
    	while((ui8TempData & 0x02) != 0x00)	// Checking WEL bit instead of WIP bit
     	{
    		ui8TempData = ReadStatusReg(ui32Base,0x05);
     	}
    }

    I modified my DeviceBusyCheck() to check for WEL bit but same result. Any suggestions?

    Thanks

  • Hello Spandan89,

    How about my original code. Does it behave the same. Trying to isolate it to the SW or the Flash itslef

    Regards

    Amit

  • Hi Amit,

    I found that you just have to wait long enough for the flash to finish erasing. In the datasheet of the flash it says that it can take upto 2 to 5 mins to erase. I thought that the erasing would be fast as reading the data. 

    I go back to original code and waited like 2 mins or so and it worked. Silly enough.. !!

    Thanks

  • Hello Spandan89,

    So the WIP is not effective for Chip Erase it seems.

    Regards

    Amit

  • Hi Amit,

    WIP bit will be set to 0 once the flash finishes erasing. So one has to poll that bit and make sure that its 0. if its not then throw error or whatever...

    But again it seems that in the Sector erase function we dont have to check the WEL bit as you have done it. Becoz First we are sending WREN command which will set the WEL bit. After that you are checking the same bit if its 1 or not. So looks like that step is redundant.

    void Sector_Erase(uint32_t ui32Base, uint32_t ui32Address, uint8_t ui8FlashCommand)
    {
    	uint32_t getstatus = 0x00;
    
        SSIAdvModeSet(ui32Base, SSI_ADV_MODE_WRITE);
        SSIAdvFrameHoldEnable(ui32Base);
        SSIAdvDataPutFrameEnd(ui32Base,0x06);
        while(SSIBusy(ui32Base));
    
        //check for the WIP bit.
        getstatus = ReadStatusReg(SSI3_BASE,0x05);
        while((getstatus & 0x02) != 0x02)
        {
        	getstatus = ReadStatusReg(SSI3_BASE,0x05);
        }
    
        SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE);
    	SSIAdvFrameHoldEnable(ui32Base);
    
        SSIDataPut(ui32Base, 0x20);	// send the sector erase command.
    
        SSIDataPut(ui32Base, (ui32Address >> 16) & 0xff);
        SSIDataPut(ui32Base, (ui32Address >> 8) & 0xff);
        SSIAdvDataPutFrameEnd(ui32Base, ui32Address & 0xff);
    
        while(SSIBusy(SSI3_BASE));
        DeviceBusyCheck(SSI3_BASE);
    }

    Next, I'm gonna try writing multiple pages and erasing. Any advice, "take care", things from your side will be really helpful.

    Thanks

  • Hello Spandan89,

    You are way much advanced than me... So no more "take care".

    Regards

    Amit

  • Hi Amit,

    Ha ha ha ha.. Following code is specially for you..

    while(1)
    {
        char Spandan89, AmitSir;
        SetGuruji(AmitSir);
        Spandan89 = Always_Follow_Learn_from(AmitSir);
    }
        

    Thanks for all your inputs and help.

  • Hi Frnds

    we are planning to use this serial flash. But it is not having PAGE WRITE instruction. Can anybody suggest me any other Flash which is meaning is having PAGE WRITE option.

  • Hello Sanjay

    The command for the Serial Flash is called Page Program (PP) or 4xI/O Page Program (4PP), where you can write 256 bytes and then de-assert CS which will cause the 256 byte buffer in the Flash to be committed to the actual physical memory

    Regards
    Amit
  • Hello Amit

    Page Program Instruction will only convert bits from 1 to 0.

    for e.g. if address 0x10 is having 0x0f written on it and i have to write 0xf0 on it. then Page Program instruction will convert it to 0x00.

    Now one option is to first erase sector having address 0x10 and then program it to  value 0xf0. But in this way rest bytes of that sector will get erased.

    But if it is having PAGE WRITE Command then problem can be solved. so can you suggest me any flash having this Command.

  • Hello Sanjay

    Welcome to Flash. The Flash bits are programmed to 1 by erasing them. After that a write turns them to 0. So if you need something like this to be done then copy the Flash Sector to the device SRAM, erase the flash, update the internal SRAM and program the Flash again. Alternatively, you would need to create some sort of buffer management structure, so that you can program to other words of the sector and then erase it when the entire sector is completed.

    Regards
    Amit