Writing Issue to External Flash Memory [SOLVED]

I've been trying read and write from the flash memory as @zach had mentioned in the post, I'm getting a peculiar issue. When I'm writing two bytes at a time like "11", what's actually getting written is "!!". It seems to be subtracting 16 from the bytes before writing.

I'm doing the following:

 uint8_t global_buffer[8];  // Global Buffer to store what is read from the Flash

    int SparkFlash_read(int address, uint8_t buffer_length){
        if (address & 1)
            return -1; // error, can only access half words      
        sFLASH_ReadBuffer(global_buffer, 0x80064 + address, buffer_length);      
        return 2;
    }
    
    int SparkFlash_write(int address, uint8_t* value_buffer, uint8_t buffer_length){
        if (address & 1)
            return -1; // error, can only access half words      
        sFLASH_WriteBuffer(value_buffer, 0x80064 + address, buffer_length);      
        return 2; // or anything else signifying it worked
    }

void loop(){
    uint8_t temp_WriteBuffer[3] = "11";  // or uint8_t temp_WriteBuffer[3] = {49, 49};    
    
    SparkFlash_write(100, temp_WriteBuffer, 2);
    delay(100);
    SparkFlash_read(100, 2);

    char temp_ReadBuffer[3];  // Char Array Buffer to print what is being read
    memcpy(temp_ReadBuffer, global_buffer, 2);  // Copying uint8_t array into char array
    Serial.println(temp_ReadBuffer);  // Printing what is read

    delay(5000); // Lets not stress the Flash
}

Input (Write) : "11" or {49,49}
Output (Read) : "!!" or {33,33} // What is actually being written I think

Is there something I'm missing out on that is causing this issue. It doesn't always start off this way, but once it does, it always happens.

You do know that flash memory may have to be erased before you can write again, right? The technology lets you change 1’s to 0’s without erasing but you need to erase to go the other way. Normally erasing sets the memory to all 1’s. The devices only have a large-but-finite number erase cycles available, so you should think about how often you want to do this since writing a particular sector over and over again in a high-speed loop can “wear” it out.

The external flash is on a bus shared with the TI CC3000 WiFi module and sometimes there are problems with sharing the bus. Another user here proposed and I have good luck with surrounding the calls to write the external flash with small delays to give the WiFi driver time to its work. A longer term solution is being created but this work-around worked for me.

    //Write a 256-byte buffer to flash
    delay(20);
    sFLASH_EraseSector(FLASHADDR);
    delay(20);
    sFLASH_WriteBuffer(byteBuffer, FLASHADDR, 256);   
    delay(20);

    //Reading a 256-byte buffer
    memset(byteBuffer,0,256);
    delay(20);
    sFLASH_ReadBuffer(byteBuffer, FLASHADDR, 256);
    delay(20);

One other quick reminder: you are memcpy’ing a uint8_t array into a char array but char is a signed type. That should be OK for the things you are doing above, but you need to be careful with any data that has the MSB set.

3 Likes

@bko You have saved my life yet again! I promise you I'm not very ignorant, information on this matter is a little hard to come by.

I have a few questions though:

  1. I assume I can only erase a sector 256 bytes at a time, with a starting address of FLASHADDR? Can I erase a smaller sector?
  2. I foresee a problem for myself because of your warning about conversion from uint8_t array to char array
  • I have to read data from the Flash Memory which I get as "uint8_t"
  • I then send this data over TCPClient again as "unsigned char or uint8_t" (no problems)
  • I also have to send this data over UDPClient which seems to accept only "char" data. I've been using memcpy from time to time to convert "uint8_t arrays" to "char arrays" so that I can send the data over UDPClient. I haven't had any problems yet, but is there an alternative.

@bko I can't thank you and the other user enough for the above :smile:

The external flash chip on the :spark: Core has an "erase sector" size of 4KB. That means you can only erase in 4KB chunks. This number can be found on the flash chip's datasheet in the core hardware repo.

Also, though it's not well documented yet, @satishgn recently created an an EEPROM emulation layer that uses the microcontroller's internal flash memory. There are 100 bytes available there, that you can use easily without worrying about the erase semantics.

// address 0-99
uint8_t EEPROM.read(int address);

// address 0-99, value 0-255
void EEPROM.write(int address, uint8_t value); 
2 Likes

4KB!? That’s very depressing since I was looking to store a decent amount of data quite frequently. I think I’ll at least move my critical data to the EEPROM for now. Thanks :smile:

Edit: Tested out the EEPROM Library just now, works brilliantly!

1 Like

The requirement to erase sectors is one of the reasons that many people are looking at FRAM devices. These devices are non-volatile and can be read and written at the speed of whatever bus they are using. Also, for most intents and purposes the have a life similar to static or dram, but have a storage life which is similar to eprom and flash.

The issue is that FRAM devices tend to be smaller than flash, and also more expensive. But depending on how much data you want to store and also how often it changes, this may be a good option. Until I realised that there was a RTC battery input on the chip used by the Spark core, I was thinking of actually storing the current time to FRAM once a second so that I could have a rough time synchronization if my module lost power until internet access was re-established. Saving data to flash like this will quickly kill the flash

Of course you need to add another part to your project. Just do a search for FRAM.

1 Like

@vk2tds That is very valuable information! I was amazed at some Fram chips claiming to have 10^10 read/write cycle endurance! I think I have a need of about 128Kbits (16KB), $2 - $3 for a chip and dedicating the SPI Pins seems reasonable for new functionality and features. Thanks :smile:

1 Like

@nitred FYI @kennetlimcp is finalizing work on his FRAM/SD shield.

1 Like