/** * @brief Write data to EEPROM. * @details Only one EEPROM page can be written at once. So fucntion * splits large data chunks in small EEPROM transactions if needed. * @note To achieve the maximum effectivity use write operations * aligned to EEPROM page boundaries. */ static size_t write(void *ip, const uint8_t *bp, size_t n) { size_t len = 0; /* bytes to be written at one trasaction */ uint32_t written; /* total bytes successfully written */ uint16_t pagesize; uint32_t firstpage; uint32_t lastpage; chDbgCheck((ip != NULL) && (((EepromFileStream *)ip)->vmt != NULL), "write"); if (n == 0) return 0; n = __clamp_size(ip, n); if (n == 0) return 0; pagesize = ((EepromFileStream *)ip)->cfg->pagesize; firstpage = (((EepromFileStream *)ip)->cfg->barrier_low + eepfs_getposition(ip)) / pagesize; lastpage = (((EepromFileStream *)ip)->cfg->barrier_low + eepfs_getposition(ip) + n - 1) / pagesize; written = 0; /* data fitted in single page */ if (firstpage == lastpage) { len = n; __fitted_write(ip, bp, len, &written); bp += len; return written; } else { /* write first piece of data to first page boundary */ len = ((firstpage + 1) * pagesize) - eepfs_getposition(ip); len -= ((EepromFileStream *)ip)->cfg->barrier_low; __fitted_write(ip, bp, len, &written); bp += len; /* now writes blocks at a size of pages (may be no one) */ while ((n - written) > pagesize) { len = pagesize; __fitted_write(ip, bp, len, &written); bp += len; } /* wrtie tail */ len = n - written; if (len == 0) return written; else { __fitted_write(ip, bp, len, &written); } } return written; }
/** * Read some bytes from current position in file. After successful * read operation the position pointer will be increased by the number * of read bytes. */ static size_t read(void *ip, uint8_t *bp, size_t n) { msg_t status = RDY_OK; chDbgCheck((ip != NULL) && (((EepromFileStream *)ip)->vmt != NULL), "read"); if (n == 0) return 0; n = __clamp_size(ip, n); if (n == 0) return 0; /* Stupid I2C cell in STM32F1x does not allow to read single byte. So we must read 2 bytes and return needed one. */ #if defined(STM32F1XX_I2C) if (n == 1) { uint8_t __buf[2]; /* if NOT last byte of file requested */ if ((eepfs_getposition(ip) + 1) < eepfs_getsize(ip)) { if (read(ip, __buf, 2) == 2) { eepfs_lseek(ip, (eepfs_getposition(ip) + 1)); bp[0] = __buf[0]; return 1; } else return 0; } else { eepfs_lseek(ip, (eepfs_getposition(ip) - 1)); if (read(ip, __buf, 2) == 2) { eepfs_lseek(ip, (eepfs_getposition(ip) + 2)); bp[0] = __buf[1]; return 1; } else return 0; } } #endif /* defined(STM32F1XX_I2C) */ /* call low level function */ status = eeprom_read(((I2CEepromFileStream *)ip)->cfg, eepfs_getposition(ip), bp, n); if (status != RDY_OK) return 0; else { eepfs_lseek(ip, (eepfs_getposition(ip) + n)); return n; } }
/** * Read some bytes from current position in file. After successful * read operation the position pointer will be increased by the number * of read bytes. */ static size_t read(void *ip, uint8_t *bp, size_t n) { msg_t status = RDY_OK; chDbgCheck((ip != NULL) && (((EepromFileStream*)ip)->vmt != NULL), ""); if (n == 0) return 0; n = __clamp_size(ip, n); if (n == 0) return 0; /* Stupid STM32 I2C cell does not allow to read less than 2 bytes. So we must read 2 bytes and return needed one. */ #if (defined(STM32F4XX) || defined(STM32F2XX) || defined(STM32F1XX) || \ defined(STM32L1XX)) if (n == 1) { uint8_t __buf[2]; /* if NOT last byte of file requested */ if ((getposition(ip) + 1) < getsize(ip)) { if (read(ip, __buf, 2) == 2) { lseek(ip, (getposition(ip) + 1)); bp[0] = __buf[0]; return 1; } else return 0; } else { lseek(ip, (getposition(ip) - 1)); if (read(ip, __buf, 2) == 2) { lseek(ip, (getposition(ip) + 2)); bp[0] = __buf[1]; return 1; } else return 0; } } #endif /* call low level function */ status = eeprom_read(getposition(ip), bp, n); if (status != RDY_OK) return 0; else { lseek(ip, (getposition(ip) + n)); return n; } }
/** * @brief Write data to EEPROM. * @details Only one EEPROM page can be written at once. So fucntion * splits large data chunks in small EEPROM transactions if needed. * @note To achieve the maximum effectivity use write operations * aligned to EEPROM page boundaries. */ static size_t write(void *ip, const uint8_t *bp, size_t n) { msg_t status = RDY_OK; size_t len = 0; /* bytes to be written at one trasaction */ uint32_t written = 0; /* total bytes successfully written */ uint32_t firstpage = getposition(ip) / EEPROM_PAGE_SIZE; uint32_t lastpage = (getposition(ip) + n - 1) / EEPROM_PAGE_SIZE; chDbgCheck((ip != NULL) && (((EepromFileStream*)ip)->vmt != NULL), ""); if (n == 0) return 0; n = __clamp_size(ip, n); if (n == 0) return 0; /* data fitted in single page */ if (firstpage == lastpage) { len = n; __fitted_write(); return written; } else { /* write first piece of data to first page boundary */ len = ((firstpage + 1) * EEPROM_PAGE_SIZE) - getposition(ip); __fitted_write(); /* now writes blocks at a size of pages (may be no one) */ while ((n - written) > EEPROM_PAGE_SIZE) { len = EEPROM_PAGE_SIZE; __fitted_write(); } /* wrtie tail */ len = n - written; if (len == 0) return written; else { __fitted_write(); } } return written; }