I have an existing project where I am using a CH32V003 microcontroller to emulate an I2C EEPROM. The contents of the emulated EEPROM are stored in the MCU's flash. At the moment it is read-only, but I want to add the ability to write to the emulated EEPROM from the system connected as I2C master. This will of course mean that I need to write the received data to the MCU's flash, but I'm not 100% certain on the strategy I should employ, so I'm seeking some advice.
To start with, I have ascertained that the I2C master only ever writes the entire contents of the EEPROM (4 kB) at once, but it does so a single byte at a time. This has been verified with a logic analyser capture of the I2C bus. That is, it will perform 4,096 transactions of [slave addr + write flag, 16-bit ROM addr, data byte] in sequential manner for every byte of the EEPROM.
However, my microcontroller's flash memory can only be written with a minimum granularity of half-words, 16-bits. The only other mode of writing/erasing is by 64-byte page.
First, I have a question about the need for erasure of the flash before writing new data. There is no explicit half-word erasure feature (as there is for pages), so I presume in order to write new single-byte values to the flash, I will need to perform a kind of 'manual' erasure by writing 0xFF to the relevant location, right? Or is it not possible to erase flash memory by simply writing all 1's to it?
The procedure I'm thinking of implementing to handle the single-byte writes is as follows:
1. Receive the single data byte and the virtual EEPROM address where it is to be written (0x0000 to 0xFFFF).
2. Map the virtual address to the actual location in flash memory.
3. Adjust that location to the nearest half-word, and determine whether it is the upper or lower byte to be modified.
4. Read in the existing half-word of data; if that modified with the new byte value results in unchanged data, do nothing.
5. Modify the relevant upper/lower byte in the half-word to be 0xFF and write it back to flash, erasing the byte to be modified.
6. Modify the relevant upper/lower byte with the new value, and write the resulting half-word to flash.
I will also make sure to set __attribute__((aligned(64))) on the static const uint8_t array holding the virtual EEPROM contents. This will ensure that it is not only aligned to the flash page size, but also has half-word alignment, given the flash page size (64) is a multiple of 2. I think this is important because the MCU documentation says that a bus error will be generated if any non-half-word data is written once the PG flag is set to initiate a half-word write.
Am I on the right track? Any gotchas I've failed to see? My fear is that it's not actually possible to do half-word writing without first erasing the containing page, which I of course have no opportunity to do in a feasible manner ahead of time.