ajuckler opened a new pull request, #17376:
URL: https://github.com/apache/nuttx/pull/17376
## Preamble
This PR is marked as Draft because I would like some opinion on
* How to handle the fact that the dedicated SPI commands for 25xx512 and
25xx1024 are untested. As they aren't supported on the mtd/at25ee driver
either, I assume that none of the maintainers have theses chips at hand. Should
these commands be marked as EXPERIMENTAL and enabled through Kconfig?
* Whether it is necessary to make the value being written on "erase" as
configurable?
* I'd appreciate some help in testing this on a xx24xx I2C chip. If this is
too much of a burden I'll remove support on these chips.
## Summary
Add `EEPIOC_PAGEERASE`, `EEPIOC_SECTORERASE` and `EEPIOC_CHIPERASE` ioctl to
write a page, sector or the entire EEPROM with 0xFF.
On supported devices (Microchip 25xx512 and 25xx1024), dedicated commands
are used instead of explicitly writing 0xFF.
## Impact
No impact as long as the new ioctl aren't called.
## Testing
Tested on a custom target (STM32F7-based) with a Rhom BR25G256FVT EEPROM
(equivalent to a Microchip 25xx256).
* The dedicated SPI commands for sector erase, page erase and chip erase are
**UNTESTED**
* The I2C driver is **UNTESTED**
Test sequence:
1. Write the entire chip to anything but 0x00 and 0xFF
2. Read the entire chip and check that everything has been written correctly
3. Erase one page
4. Check that the page contents have been set to 0xFF and that the rest of
the memory is unaltered
5. Erase one sector
6. Check that the sector contents have been set to 0xFF and that the rest of
the memory is unaltered
7. Erase the chip
8. Check that the entire chip memory is now 0xFF
<details>
<summary>Sample code</summary>
```c
static bool checkmem(uint8_t *buff, size_t nbytes, uint8_t val)
{
for(size_t i = 0; i < nbytes; ++i) {
if(buff[i] != val) {
printf("ERROR byte @%zd is %d\n", i, buff[i]);
return false;
}
}
return true;
}
bool test_erase_xx25xx(struct spi_dev_s *spi_eep_p)
{
if(ee25xx_initialize(spi_eep_p, 0, "/dev/ee25xx", EEPROM_25XX256, 0) !=
0) {
return false;
}
int fd = open("/dev/ee25xx", O_RDWR);
bool success = (fd >= 0);
struct eeprom_geometry_s geo = {0};
if(success) {
success = (ioctl(fd, EEPIOC_GEOMETRY, (unsigned long)&geo) == 0);
}
if(success) {
printf("Geometry: %lld pages, %zd sec size, %zd page size\n",
geo.npages, geo.sectsize, geo.pagesize);
success = (ioctl(fd, EEPIOC_SETSPEED, 10000000) == 0);
}
if(success) {
printf("Populating EEPROM...\n");
// Write the whole EEPROM to 0xA5
uint8_t *buff = (uint8_t *)calloc(geo.pagesize, sizeof(uint8_t));
memset(buff, 0xA5, geo.pagesize);
lseek(fd, 0, SEEK_SET);
for(size_t i = 0U; i < geo.npages; ++i) {
if(write(fd, buff, geo.pagesize) != geo.pagesize) {
printf("ERROR writing @%zd\n", (geo.pagesize * i));
success = false;
break;
}
}
free(buff);
}
if(success) {
printf("Checking successful population...\n");
// Read the whole EEPROM and find any non 0xA5 byte
uint8_t *buff = (uint8_t *)calloc(geo.pagesize, sizeof(uint8_t));
off_t offset = 0;
for(size_t i = 0; i < geo.npages; ++i) {
success = (lseek(fd, offset, SEEK_SET) >= 0);
if(!success) {
printf("Failed to seek to %lld\n", offset);
}
if(success) {
success = read(fd, buff, geo.pagesize) == geo.pagesize;
if(!success) {
printf("Failed to read @%lld\n", offset);
}
}
if(success) {
success = checkmem(buff, geo.pagesize, 0xA5);
if(!success) {
printf("Failure offset: %lld\n", offset);
}
}
if(success) {
offset += geo.pagesize;
}
else {
break;
}
}
free(buff);
}
if(success) {
printf("Page erase\n");
// Erase a page
success = ioctl(fd, EEPIOC_PAGEERASE, 5) == OK;
}
if(success) {
printf("Checking successful erase...\n");
// Read the whole EEPROM and check that everything is still 0xA5
except on page #5
uint8_t *buff = (uint8_t *)calloc(geo.pagesize, sizeof(uint8_t));
off_t offset = 0;
for(size_t i = 0; i < geo.npages; ++i) {
success = (lseek(fd, offset, SEEK_SET) >= 0);
if(success) {
success = read(fd, buff, geo.pagesize) == geo.pagesize;
if(!success) {
printf("Failed to read @%lld\n", offset);
}
}
if(success) {
success = checkmem(buff, geo.pagesize, (i == 5) ? 0xFF :
0xA5);
if(!success) {
printf("Failure offset: %lld\n", offset);
}
}
if(success) {
offset += geo.pagesize;
}
else {
break;
}
}
free(buff);
}
if(success) {
printf("Sector erase\n");
success = ioctl(fd, EEPIOC_SECTORERASE, geo.npages - 1) == OK;
}
if(success) {
printf("Checking successful erase...\n");
// Read the whole EEPROM and check that everything is still 0xA5
except on page #5 and the last one
uint8_t *buff = (uint8_t *)calloc(geo.sectsize, sizeof(uint8_t));
off_t offset = 0;
for(size_t i = 0; i < geo.npages; ++i) {
success = (lseek(fd, offset, SEEK_SET) >= 0);
if(success) {
success = read(fd, buff, geo.sectsize) == geo.sectsize;
if(!success) {
printf("Failed to read @%lld\n", offset);
}
}
if(success) {
const bool erased = (i == 5) || (i == geo.npages - 1);
success = checkmem(buff, geo.sectsize, erased ?
0xFF : 0xA5);
if(!success) {
printf("Failure offset: %lld\n", offset);
}
}
if(success) {
offset += geo.sectsize;
}
else {
break;
}
}
free(buff);
}
if(success) {
printf("Chip erase\n");
success = ioctl(fd, EEPIOC_CHIPERASE, 0) == OK;
}
if(success) {
printf("Checking successful erase...\n");
// Read the whole EEPROM and find any non 0xA5 byte
uint8_t *buff = (uint8_t *)calloc(geo.pagesize, sizeof(uint8_t));
off_t offset = 0;
for(size_t i = 0; i < geo.npages; ++i) {
success = (lseek(fd, offset, SEEK_SET) >= 0);
if(success) {
success = read(fd, buff, geo.pagesize) == geo.pagesize;
if(!success) {
printf("Failed to read @%lld\n", offset);
}
}
if(success) {
success = checkmem(buff, geo.pagesize, 0xFF);
if(!success) {
printf("Failure offset: %lld\n", offset);
}
}
if(success) {
offset += geo.pagesize;
}
else {
break;
}
}
free(buff);
}
close(fd);
return success;
}
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]