Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 23:51:36 +00:00
|
|
|
|
|
|
|
/* EEPROM emulation over flash with reduced wear
|
|
|
|
*
|
|
|
|
* We will use 2 contiguous groups of pages as main and alternate.
|
|
|
|
* We want an structure that allows to read as fast as possible,
|
|
|
|
* without the need of scanning the whole FLASH memory.
|
|
|
|
*
|
|
|
|
* FLASH bits default erased state is 1, and can be set to 0
|
|
|
|
* on a per bit basis. To reset them to 1, a full page erase
|
|
|
|
* is needed.
|
|
|
|
*
|
|
|
|
* Values are stored as differences that should be applied to a
|
|
|
|
* completely erased EEPROM (filled with 0xFFs). We just encode
|
|
|
|
* the starting address of the values to change, the length of
|
|
|
|
* the block of new values, and the values themselves. All diffs
|
|
|
|
* are accumulated into a RAM buffer, compacted into the least
|
|
|
|
* amount of non overlapping diffs possible and sorted by starting
|
|
|
|
* address before being saved into the next available page of FLASH
|
|
|
|
* of the current group.
|
|
|
|
* Once the current group is completely full, we compact it and save
|
|
|
|
* it into the other group, then erase the current group and switch
|
|
|
|
* to that new group and set it as current.
|
|
|
|
*
|
|
|
|
* The FLASH endurance is about 1/10 ... 1/100 of an EEPROM
|
|
|
|
* endurance, but EEPROM endurance is specified per byte, not
|
|
|
|
* per page. We can't emulate EE endurance with FLASH for all
|
|
|
|
* bytes, but we can emulate endurance for a given percent of
|
|
|
|
* bytes.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef ARDUINO_ARCH_SAM
|
|
|
|
|
|
|
|
#include "../persistent_store_api.h"
|
|
|
|
#include "../../inc/MarlinConfig.h"
|
|
|
|
|
|
|
|
#if ENABLED(EEPROM_SETTINGS) && DISABLED(I2C_EEPROM) && DISABLED(SPI_EEPROM)
|
|
|
|
|
|
|
|
#include <Arduino.h>
|
|
|
|
|
|
|
|
#define EEPROMSize 4096
|
|
|
|
#define PagesPerGroup 128
|
|
|
|
#define GroupCount 2
|
|
|
|
#define PageSize 256
|
|
|
|
|
|
|
|
/* Flash storage */
|
|
|
|
typedef struct FLASH_SECTOR {
|
|
|
|
uint8_t page[PageSize];
|
|
|
|
} FLASH_SECTOR_T;
|
|
|
|
|
|
|
|
#define PAGE_FILL \
|
|
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
|
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
|
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
|
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
|
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
|
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
|
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
|
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
|
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
|
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
|
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
|
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
|
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
|
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
|
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
|
|
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
|
|
|
|
|
|
|
|
#define FLASH_INIT_FILL \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
|
|
|
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL
|
|
|
|
|
|
|
|
/* This is the FLASH area used to emulate a 2Kbyte EEPROM -- We need this buffer aligned
|
|
|
|
to a 256 byte boundary. */
|
|
|
|
static const uint8_t flashStorage[PagesPerGroup * GroupCount * PageSize] __attribute__ ((aligned (PageSize))) = { FLASH_INIT_FILL };
|
|
|
|
|
|
|
|
/* Get the address of an specific page */
|
|
|
|
static const FLASH_SECTOR_T* getFlashStorage(int page) {
|
|
|
|
return (const FLASH_SECTOR_T*)&flashStorage[page*PageSize];
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint8_t buffer[256] = {0}; // The RAM buffer to accumulate writes
|
|
|
|
static uint8_t curPage = 0; // Current FLASH page inside the group
|
|
|
|
static uint8_t curGroup = 0xFF; // Current FLASH group
|
|
|
|
|
|
|
|
//#define EE_EMU_DEBUG
|
|
|
|
#ifdef EE_EMU_DEBUG
|
|
|
|
static void ee_Dump(int page,const void* data) {
|
|
|
|
|
|
|
|
const uint8_t* c = (const uint8_t*) data;
|
|
|
|
char buffer[80];
|
|
|
|
|
|
|
|
sprintf(buffer, "Page: %d (0x%04x)\n", page, page);
|
2017-11-05 14:49:38 +00:00
|
|
|
SERIAL_PROTOCOL(buffer);
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 23:51:36 +00:00
|
|
|
|
|
|
|
char* p = &buffer[0];
|
|
|
|
for (int i = 0; i< PageSize; ++i) {
|
|
|
|
if ((i & 15) == 0) {
|
|
|
|
p += sprintf(p,"%04x] ",i);
|
|
|
|
}
|
|
|
|
|
|
|
|
p += sprintf(p," %02x",c[i]);
|
|
|
|
if ((i & 15) == 15) {
|
|
|
|
*p++ = '\n';
|
|
|
|
*p = 0;
|
2017-11-05 14:49:38 +00:00
|
|
|
SERIAL_PROTOCOL(buffer);
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 23:51:36 +00:00
|
|
|
p = &buffer[0];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Flash Writing Protection Key */
|
|
|
|
#define FWP_KEY 0x5Au
|
|
|
|
|
|
|
|
#if SAM4S_SERIES
|
|
|
|
#define EEFC_FCR_FCMD(value) \
|
|
|
|
((EEFC_FCR_FCMD_Msk & ((value) << EEFC_FCR_FCMD_Pos)))
|
|
|
|
#define EEFC_ERROR_FLAGS (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE | EEFC_FSR_FLERR)
|
|
|
|
#else
|
|
|
|
#define EEFC_ERROR_FLAGS (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Writes the contents of the specified page (no previous erase)
|
|
|
|
* @param page (page #)
|
|
|
|
* @param data (pointer to the data buffer)
|
|
|
|
*/
|
|
|
|
__attribute__ ((long_call, section (".ramfunc")))
|
|
|
|
static bool ee_PageWrite(uint16_t page,const void* data) {
|
|
|
|
|
|
|
|
int i;
|
|
|
|
uint32_t addrflash = ((uint32_t)getFlashStorage(page));
|
|
|
|
|
|
|
|
// Read the flash contents
|
|
|
|
uint32_t pageContents[PageSize>>2];
|
|
|
|
memcpy(pageContents, (void*)addrflash, PageSize);
|
|
|
|
|
|
|
|
// We ONLY want to toggle bits that have changed, and that have changed to 0.
|
|
|
|
// SAM3X8E tends to destroy contiguous bits if reprogrammed without erasing, so
|
|
|
|
// we try by all means to avoid this. That is why it says: "The Partial
|
|
|
|
// Programming mode works only with 128-bit (or higher) boundaries. It cannot
|
|
|
|
// be used with boundaries lower than 128 bits (8, 16 or 32-bit for example)."
|
|
|
|
// All bits that did not change, set them to 1.
|
|
|
|
for (i = 0; i <PageSize >> 2; i++) {
|
|
|
|
pageContents[i] = (((uint32_t*)data)[i]) | (~(pageContents[i] ^ ((uint32_t*)data)[i]));
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef EE_EMU_DEBUG
|
|
|
|
SERIAL_ECHO_START();
|
|
|
|
SERIAL_ECHOLNPAIR("EEPROM PageWrite ",page);
|
|
|
|
SERIAL_ECHOLNPAIR(" in FLASH address ",(uint32_t)addrflash);
|
|
|
|
SERIAL_ECHOLNPAIR(" base address ",(uint32_t)getFlashStorage(0));
|
2017-11-05 14:49:38 +00:00
|
|
|
SERIAL_FLUSH();
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 23:51:36 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// Get the page relative to the start of the EFC controller, and the EFC controller to use
|
|
|
|
Efc *efc;
|
|
|
|
uint16_t fpage;
|
|
|
|
if (addrflash >= IFLASH1_ADDR) {
|
|
|
|
efc = EFC1;
|
|
|
|
fpage = (addrflash - IFLASH1_ADDR) / IFLASH1_PAGE_SIZE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
efc = EFC0;
|
|
|
|
fpage = (addrflash - IFLASH0_ADDR) / IFLASH0_PAGE_SIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the page that must be unlocked, then locked
|
|
|
|
uint16_t lpage = fpage & (~((IFLASH0_LOCK_REGION_SIZE / IFLASH0_PAGE_SIZE) - 1));
|
|
|
|
|
|
|
|
// Disable all interrupts
|
|
|
|
__disable_irq();
|
|
|
|
|
|
|
|
// Get the FLASH wait states
|
|
|
|
uint32_t orgWS = (efc->EEFC_FMR & EEFC_FMR_FWS_Msk) >> EEFC_FMR_FWS_Pos;
|
|
|
|
|
|
|
|
// Set wait states to 6 (SAM errata)
|
|
|
|
efc->EEFC_FMR = efc->EEFC_FMR & (~EEFC_FMR_FWS_Msk) | EEFC_FMR_FWS(6);
|
|
|
|
|
|
|
|
// Unlock the flash page
|
|
|
|
uint32_t status;
|
|
|
|
efc->EEFC_FCR = EEFC_FCR_FKEY(FWP_KEY) | EEFC_FCR_FARG(lpage) | EEFC_FCR_FCMD(EFC_FCMD_CLB);
|
|
|
|
while (((status = efc->EEFC_FSR) & EEFC_FSR_FRDY) != EEFC_FSR_FRDY) {
|
|
|
|
// force compiler to not optimize this -- NOPs don't work!
|
|
|
|
__asm__ __volatile__("");
|
|
|
|
};
|
|
|
|
|
|
|
|
if ((status & EEFC_ERROR_FLAGS) != 0) {
|
|
|
|
|
|
|
|
// Restore original wait states
|
|
|
|
efc->EEFC_FMR = efc->EEFC_FMR & (~EEFC_FMR_FWS_Msk) | EEFC_FMR_FWS(orgWS);
|
|
|
|
|
|
|
|
// Reenable interrupts
|
|
|
|
__enable_irq();
|
|
|
|
|
|
|
|
#ifdef EE_EMU_DEBUG
|
|
|
|
SERIAL_ECHO_START();
|
|
|
|
SERIAL_ECHOLNPAIR("EEPROM Unlock failure for page ",page);
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write page and lock: Writing 8-bit and 16-bit data is not allowed and may lead to unpredictable data corruption.
|
|
|
|
const uint32_t * aligned_src = (const uint32_t *) &pageContents[0]; /*data;*/
|
|
|
|
uint32_t * p_aligned_dest = (uint32_t *) addrflash;
|
|
|
|
for (i = 0; i < (IFLASH0_PAGE_SIZE / sizeof(uint32_t)); ++i) {
|
|
|
|
*p_aligned_dest++ = *aligned_src++;
|
|
|
|
}
|
|
|
|
efc->EEFC_FCR = EEFC_FCR_FKEY(FWP_KEY) | EEFC_FCR_FARG(fpage) | EEFC_FCR_FCMD(EFC_FCMD_WPL);
|
|
|
|
while (((status = efc->EEFC_FSR) & EEFC_FSR_FRDY) != EEFC_FSR_FRDY) {
|
|
|
|
// force compiler to not optimize this -- NOPs don't work!
|
|
|
|
__asm__ __volatile__("");
|
|
|
|
};
|
|
|
|
|
|
|
|
if ((status & EEFC_ERROR_FLAGS) != 0) {
|
|
|
|
|
|
|
|
// Restore original wait states
|
|
|
|
efc->EEFC_FMR = efc->EEFC_FMR & (~EEFC_FMR_FWS_Msk) | EEFC_FMR_FWS(orgWS);
|
|
|
|
|
|
|
|
// Reenable interrupts
|
|
|
|
__enable_irq();
|
|
|
|
|
|
|
|
#ifdef EE_EMU_DEBUG
|
|
|
|
SERIAL_ECHO_START();
|
|
|
|
SERIAL_ECHOLNPAIR("EEPROM Write failure for page ",page);
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Restore original wait states
|
|
|
|
efc->EEFC_FMR = efc->EEFC_FMR & (~EEFC_FMR_FWS_Msk) | EEFC_FMR_FWS(orgWS);
|
|
|
|
|
|
|
|
// Reenable interrupts
|
|
|
|
__enable_irq();
|
|
|
|
|
|
|
|
// Compare contents
|
|
|
|
if (memcmp(getFlashStorage(page),data,PageSize)) {
|
|
|
|
|
|
|
|
#ifdef EE_EMU_DEBUG
|
|
|
|
SERIAL_ECHO_START();
|
|
|
|
SERIAL_ECHOLNPAIR("EEPROM Verify Write failure for page ",page);
|
|
|
|
|
|
|
|
ee_Dump( page,(uint32_t *) addrflash);
|
|
|
|
ee_Dump(-page,data);
|
|
|
|
|
|
|
|
// Calculate count of changed bits
|
|
|
|
uint32_t* p1 = (uint32_t*)addrflash;
|
|
|
|
uint32_t* p2 = (uint32_t*)data;
|
|
|
|
int count = 0;
|
|
|
|
for (i =0; i<PageSize >> 2; i++) {
|
|
|
|
if (p1[i] != p2[i]) {
|
|
|
|
uint32_t delta = p1[i] ^ p2[i];
|
|
|
|
while (delta) {
|
|
|
|
if ((delta&1) != 0)
|
|
|
|
count++;
|
|
|
|
delta >>= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SERIAL_ECHOLNPAIR("--> Differing bits: ",count);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Erases the contents of the specified page
|
|
|
|
* @param page (page #)
|
|
|
|
*/
|
|
|
|
__attribute__ ((long_call, section (".ramfunc")))
|
|
|
|
static bool ee_PageErase(uint16_t page) {
|
|
|
|
|
|
|
|
int i;
|
|
|
|
uint32_t addrflash = ((uint32_t)getFlashStorage(page));
|
|
|
|
|
|
|
|
#ifdef EE_EMU_DEBUG
|
|
|
|
SERIAL_ECHO_START();
|
|
|
|
SERIAL_ECHOLNPAIR("EEPROM PageErase ",page);
|
|
|
|
SERIAL_ECHOLNPAIR(" in FLASH address ",(uint32_t)addrflash);
|
|
|
|
SERIAL_ECHOLNPAIR(" base address ",(uint32_t)getFlashStorage(0));
|
2017-11-05 14:49:38 +00:00
|
|
|
SERIAL_FLUSH();
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 23:51:36 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// Get the page relative to the start of the EFC controller, and the EFC controller to use
|
|
|
|
Efc *efc;
|
|
|
|
uint16_t fpage;
|
|
|
|
if (addrflash >= IFLASH1_ADDR) {
|
|
|
|
efc = EFC1;
|
|
|
|
fpage = (addrflash - IFLASH1_ADDR) / IFLASH1_PAGE_SIZE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
efc = EFC0;
|
|
|
|
fpage = (addrflash - IFLASH0_ADDR) / IFLASH0_PAGE_SIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the page that must be unlocked, then locked
|
|
|
|
uint16_t lpage = fpage & (~((IFLASH0_LOCK_REGION_SIZE / IFLASH0_PAGE_SIZE) - 1));
|
|
|
|
|
|
|
|
// Disable all interrupts
|
|
|
|
__disable_irq();
|
|
|
|
|
|
|
|
// Get the FLASH wait states
|
|
|
|
uint32_t orgWS = (efc->EEFC_FMR & EEFC_FMR_FWS_Msk) >> EEFC_FMR_FWS_Pos;
|
|
|
|
|
|
|
|
// Set wait states to 6 (SAM errata)
|
|
|
|
efc->EEFC_FMR = efc->EEFC_FMR & (~EEFC_FMR_FWS_Msk) | EEFC_FMR_FWS(6);
|
|
|
|
|
|
|
|
// Unlock the flash page
|
|
|
|
uint32_t status;
|
|
|
|
efc->EEFC_FCR = EEFC_FCR_FKEY(FWP_KEY) | EEFC_FCR_FARG(lpage) | EEFC_FCR_FCMD(EFC_FCMD_CLB);
|
|
|
|
while (((status = efc->EEFC_FSR) & EEFC_FSR_FRDY) != EEFC_FSR_FRDY) {
|
|
|
|
// force compiler to not optimize this -- NOPs don't work!
|
|
|
|
__asm__ __volatile__("");
|
|
|
|
};
|
|
|
|
if ((status & EEFC_ERROR_FLAGS) != 0) {
|
|
|
|
|
|
|
|
// Restore original wait states
|
|
|
|
efc->EEFC_FMR = efc->EEFC_FMR & (~EEFC_FMR_FWS_Msk) | EEFC_FMR_FWS(orgWS);
|
|
|
|
|
|
|
|
// Reenable interrupts
|
|
|
|
__enable_irq();
|
|
|
|
|
|
|
|
#ifdef EE_EMU_DEBUG
|
|
|
|
SERIAL_ECHO_START();
|
|
|
|
SERIAL_ECHOLNPAIR("EEPROM Unlock failure for page ",page);
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Erase Write page and lock: Writing 8-bit and 16-bit data is not allowed and may lead to unpredictable data corruption.
|
|
|
|
uint32_t * p_aligned_dest = (uint32_t *) addrflash;
|
|
|
|
for (i = 0; i < (IFLASH0_PAGE_SIZE / sizeof(uint32_t)); ++i) {
|
|
|
|
*p_aligned_dest++ = 0xFFFFFFFF;
|
|
|
|
}
|
|
|
|
efc->EEFC_FCR = EEFC_FCR_FKEY(FWP_KEY) | EEFC_FCR_FARG(fpage) | EEFC_FCR_FCMD(EFC_FCMD_EWPL);
|
|
|
|
while (((status = efc->EEFC_FSR) & EEFC_FSR_FRDY) != EEFC_FSR_FRDY) {
|
|
|
|
// force compiler to not optimize this -- NOPs don't work!
|
|
|
|
__asm__ __volatile__("");
|
|
|
|
};
|
|
|
|
if ((status & EEFC_ERROR_FLAGS) != 0) {
|
|
|
|
|
|
|
|
// Restore original wait states
|
|
|
|
efc->EEFC_FMR = efc->EEFC_FMR & (~EEFC_FMR_FWS_Msk) | EEFC_FMR_FWS(orgWS);
|
|
|
|
|
|
|
|
// Reenable interrupts
|
|
|
|
__enable_irq();
|
|
|
|
|
|
|
|
#ifdef EE_EMU_DEBUG
|
|
|
|
SERIAL_ECHO_START();
|
|
|
|
SERIAL_ECHOLNPAIR("EEPROM Erase failure for page ",page);
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Restore original wait states
|
|
|
|
efc->EEFC_FMR = efc->EEFC_FMR & (~EEFC_FMR_FWS_Msk) | EEFC_FMR_FWS(orgWS);
|
|
|
|
|
|
|
|
// Reenable interrupts
|
|
|
|
__enable_irq();
|
|
|
|
|
|
|
|
// Check erase
|
|
|
|
uint32_t * aligned_src = (uint32_t *) addrflash;
|
|
|
|
for (i = 0; i < PageSize >> 2; i++) {
|
|
|
|
if (*aligned_src++ != 0xFFFFFFFF) {
|
|
|
|
|
|
|
|
#ifdef EE_EMU_DEBUG
|
|
|
|
SERIAL_ECHO_START();
|
|
|
|
SERIAL_ECHOLNPAIR("EEPROM Verify Erase failure for page ",page);
|
|
|
|
|
|
|
|
ee_Dump( page,(uint32_t *) addrflash);
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
static uint8_t ee_Read(uint32_t address, bool excludeRAMBuffer = false) {
|
|
|
|
|
|
|
|
uint32_t baddr;
|
|
|
|
uint32_t blen;
|
|
|
|
|
|
|
|
// If we were requested an address outside of the emulated range, fail now
|
|
|
|
if (address >= EEPROMSize)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Check that the value is not contained in the RAM buffer
|
|
|
|
if (!excludeRAMBuffer) {
|
|
|
|
int i = 0;
|
|
|
|
while (i <= (PageSize - 4)) { /* (PageSize - 4) because otherwise, there is not enough room for data and headers */
|
|
|
|
|
|
|
|
// Get the address of the block
|
|
|
|
baddr = buffer[i] | (buffer[i + 1] << 8);
|
|
|
|
|
|
|
|
// Get the length of the block
|
|
|
|
blen = buffer[i + 2];
|
|
|
|
|
|
|
|
// If we reach the end of the list, break loop
|
|
|
|
if (blen == 0xFF)
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Check if data is contained in this block
|
|
|
|
if (address >= baddr &&
|
|
|
|
address < (baddr + blen)) {
|
|
|
|
|
|
|
|
// Yes, it is contained. Return it!
|
|
|
|
return buffer[i + 3 + address - baddr];
|
|
|
|
}
|
|
|
|
|
|
|
|
// As blocks are always sorted, if the starting address of this block is higher
|
|
|
|
// than the address we are looking for, break loop now - We wont find the value
|
|
|
|
// associated to the address
|
|
|
|
if (baddr > address)
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Jump to the next block
|
|
|
|
i += 3 + blen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// It is NOT on the RAM buffer. It could be stored in FLASH. We are
|
|
|
|
// ensured on a given FLASH page, address contents are never repeated
|
|
|
|
// but on different pages, there is no such warranty, so we must go
|
|
|
|
// backwards from the last written FLASH page to the first one.
|
|
|
|
for (int page = curPage - 1; page >= 0; --page) {
|
|
|
|
|
|
|
|
// Get a pointer to the flash page
|
|
|
|
uint8_t* pflash = (uint8_t*)getFlashStorage(page + curGroup * PagesPerGroup);
|
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
while (i <= (PageSize - 4)) { /* (PageSize - 4) because otherwise, there is not enough room for data and headers */
|
|
|
|
|
|
|
|
// Get the address of the block
|
|
|
|
baddr = pflash[i] | (pflash[i + 1] << 8);
|
|
|
|
|
|
|
|
// Get the length of the block
|
|
|
|
blen = pflash[i + 2];
|
|
|
|
|
|
|
|
// If we reach the end of the list, break loop
|
|
|
|
if (blen == 0xFF)
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Check if data is contained in this block
|
|
|
|
if (address >= baddr &&
|
|
|
|
address < (baddr + blen)) {
|
|
|
|
|
|
|
|
// Yes, it is contained. Return it!
|
|
|
|
return pflash[i + 3 + address - baddr];
|
|
|
|
}
|
|
|
|
|
|
|
|
// As blocks are always sorted, if the starting address of this block is higher
|
|
|
|
// than the address we are looking for, break loop now - We wont find the value
|
|
|
|
// associated to the address
|
|
|
|
if (baddr > address)
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Jump to the next block
|
|
|
|
i += 3 + blen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If reached here, value is not stored, so return its default value
|
|
|
|
return 0xFF;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint32_t ee_GetAddrRange(uint32_t address, bool excludeRAMBuffer = false) {
|
|
|
|
uint32_t baddr;
|
|
|
|
uint32_t blen;
|
|
|
|
uint32_t nextAddr = 0xFFFF;
|
|
|
|
uint32_t nextRange = 0;
|
|
|
|
|
|
|
|
// Check that the value is not contained in the RAM buffer
|
|
|
|
if (!excludeRAMBuffer) {
|
|
|
|
int i = 0;
|
|
|
|
while (i <= (PageSize - 4)) { /* (PageSize - 4) because otherwise, there is not enough room for data and headers */
|
|
|
|
|
|
|
|
// Get the address of the block
|
|
|
|
baddr = buffer[i] | (buffer[i + 1] << 8);
|
|
|
|
|
|
|
|
// Get the length of the block
|
|
|
|
blen = buffer[i + 2];
|
|
|
|
|
|
|
|
// If we reach the end of the list, break loop
|
|
|
|
if (blen == 0xFF)
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Check if address and address + 1 is contained in this block
|
|
|
|
if (address >= baddr &&
|
|
|
|
address < (baddr + blen)) {
|
|
|
|
|
|
|
|
// Yes, it is contained. Return it!
|
|
|
|
return address | ((blen - address + baddr) << 16);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, check if we can use it as a limit
|
|
|
|
if (baddr > address && baddr < nextAddr) {
|
|
|
|
nextAddr = baddr;
|
|
|
|
nextRange = blen;
|
|
|
|
}
|
|
|
|
|
|
|
|
// As blocks are always sorted, if the starting address of this block is higher
|
|
|
|
// than the address we are looking for, break loop now - We wont find the value
|
|
|
|
// associated to the address
|
|
|
|
if (baddr > address)
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Jump to the next block
|
|
|
|
i += 3 + blen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// It is NOT on the RAM buffer. It could be stored in FLASH. We are
|
|
|
|
// ensured on a given FLASH page, address contents are never repeated
|
|
|
|
// but on different pages, there is no such warranty, so we must go
|
|
|
|
// backwards from the last written FLASH page to the first one.
|
|
|
|
for (int page = curPage - 1; page >= 0; --page) {
|
|
|
|
|
|
|
|
// Get a pointer to the flash page
|
|
|
|
uint8_t* pflash = (uint8_t*)getFlashStorage(page + curGroup * PagesPerGroup);
|
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
while (i <= (PageSize - 4)) { /* (PageSize - 4) because otherwise, there is not enough room for data and headers */
|
|
|
|
|
|
|
|
// Get the address of the block
|
|
|
|
baddr = pflash[i] | (pflash[i + 1] << 8);
|
|
|
|
|
|
|
|
// Get the length of the block
|
|
|
|
blen = pflash[i + 2];
|
|
|
|
|
|
|
|
// If we reach the end of the list, break loop
|
|
|
|
if (blen == 0xFF)
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Check if data is contained in this block
|
|
|
|
if (address >= baddr &&
|
|
|
|
address < (baddr + blen)) {
|
|
|
|
|
|
|
|
// Yes, it is contained. Return it!
|
|
|
|
return address | ((blen - address + baddr) << 16);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, check if we can use it as a limit
|
|
|
|
if (baddr > address && baddr < nextAddr) {
|
|
|
|
nextAddr = baddr;
|
|
|
|
nextRange = blen;
|
|
|
|
}
|
|
|
|
|
|
|
|
// As blocks are always sorted, if the starting address of this block is higher
|
|
|
|
// than the address we are looking for, break loop now - We wont find the value
|
|
|
|
// associated to the address
|
|
|
|
if (baddr > address)
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Jump to the next block
|
|
|
|
i += 3 + blen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If reached here, we will return the next valid address
|
|
|
|
return nextAddr | (nextRange << 16);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool ee_IsPageClean(int page) {
|
|
|
|
|
|
|
|
uint32_t* pflash = (uint32_t*) getFlashStorage(page);
|
|
|
|
for (int i = 0; i < (PageSize >> 2); ++i) {
|
|
|
|
if (*pflash++ != 0xFFFFFFFF)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool ee_Flush(uint32_t overrideAddress = 0xFFFFFFFF, uint8_t overrideData = 0xFF) {
|
|
|
|
|
|
|
|
// Check if RAM buffer has something to be written
|
|
|
|
bool isEmpty = true;
|
|
|
|
uint32_t* p = (uint32_t*) &buffer[0];
|
|
|
|
for (int j = 0; j < (PageSize >> 2); j++) {
|
|
|
|
if (*p++ != 0xFFFFFFFF) {
|
|
|
|
isEmpty = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If something has to be written, do so!
|
|
|
|
if (!isEmpty) {
|
|
|
|
|
|
|
|
// Write the current ram buffer into FLASH
|
|
|
|
ee_PageWrite(curPage + curGroup * PagesPerGroup, buffer);
|
|
|
|
|
|
|
|
// Clear the RAM buffer
|
|
|
|
memset(buffer, 0xFF, sizeof(buffer));
|
|
|
|
|
|
|
|
// Increment the page to use the next time
|
|
|
|
++curPage;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Did we reach the maximum count of available pages per group for storage ?
|
|
|
|
if (curPage < PagesPerGroup) {
|
|
|
|
|
|
|
|
// Do we have an override address ?
|
|
|
|
if (overrideAddress < EEPROMSize) {
|
|
|
|
|
|
|
|
// Yes, just store the value into the RAM buffer
|
|
|
|
buffer[0] = overrideAddress & 0xFF;
|
|
|
|
buffer[0 + 1] = (overrideAddress >> 8) & 0xFF;
|
|
|
|
buffer[0 + 2] = 1;
|
|
|
|
buffer[0 + 3] = overrideData;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Done!
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We have no space left on the current group - We must compact the values
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
// Compute the next group to use
|
|
|
|
int curwPage = 0;
|
|
|
|
int curwGroup = curGroup + 1;
|
|
|
|
if (curwGroup >= GroupCount)
|
|
|
|
curwGroup = 0;
|
|
|
|
|
|
|
|
uint32_t rdAddr = 0;
|
|
|
|
do {
|
|
|
|
|
|
|
|
// Get the next valid range
|
|
|
|
uint32_t addrRange = ee_GetAddrRange(rdAddr, true);
|
|
|
|
|
|
|
|
// Make sure not to skip the override address, if specified
|
|
|
|
int rdRange;
|
|
|
|
if (overrideAddress < EEPROMSize &&
|
|
|
|
rdAddr <= overrideAddress &&
|
|
|
|
(addrRange & 0xFFFF) > overrideAddress) {
|
|
|
|
|
|
|
|
rdAddr = overrideAddress;
|
|
|
|
rdRange = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
rdAddr = addrRange & 0xFFFF;
|
|
|
|
rdRange = addrRange >> 16;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If no range, break loop
|
|
|
|
if (rdRange == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
|
|
|
// Get the value
|
|
|
|
uint8_t rdValue = overrideAddress == rdAddr ? overrideData : ee_Read(rdAddr, true);
|
|
|
|
|
|
|
|
// Do not bother storing default values
|
|
|
|
if (rdValue != 0xFF) {
|
|
|
|
|
|
|
|
// If we have room, add it to the buffer
|
|
|
|
if (buffer[i + 2] == 0xFF) {
|
|
|
|
|
|
|
|
// Uninitialized buffer, just add it!
|
|
|
|
buffer[i] = rdAddr & 0xFF;
|
|
|
|
buffer[i + 1] = (rdAddr >> 8) & 0xFF;
|
|
|
|
buffer[i + 2] = 1;
|
|
|
|
buffer[i + 3] = rdValue;
|
|
|
|
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Buffer already has contents. Check if we can extend it
|
|
|
|
|
|
|
|
// Get the address of the block
|
|
|
|
uint32_t baddr = buffer[i] | (buffer[i + 1] << 8);
|
|
|
|
|
|
|
|
// Get the length of the block
|
|
|
|
uint32_t blen = buffer[i + 2];
|
|
|
|
|
|
|
|
// Can we expand it ?
|
|
|
|
if (rdAddr == (baddr + blen) &&
|
|
|
|
i < (PageSize - 4) && /* This block has a chance to contain data AND */
|
|
|
|
buffer[i + 2] < (PageSize - i - 3)) {/* There is room for this block to be expanded */
|
|
|
|
|
|
|
|
// Yes, do it
|
|
|
|
++buffer[i + 2];
|
|
|
|
|
|
|
|
// And store the value
|
|
|
|
buffer[i + 3 + rdAddr - baddr] = rdValue;
|
|
|
|
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
|
|
|
|
// No, we can't expand it - Skip the existing block
|
|
|
|
i += 3 + blen;
|
|
|
|
|
|
|
|
// Can we create a new slot ?
|
|
|
|
if (i > (PageSize - 4)) {
|
|
|
|
|
|
|
|
// Not enough space - Write the current buffer to FLASH
|
|
|
|
ee_PageWrite(curwPage + curwGroup * PagesPerGroup, buffer);
|
|
|
|
|
|
|
|
// Advance write page (as we are compacting, should never overflow!)
|
|
|
|
++curwPage;
|
|
|
|
|
|
|
|
// Clear RAM buffer
|
|
|
|
memset(buffer, 0xFF, sizeof(buffer));
|
|
|
|
|
|
|
|
// Start fresh */
|
|
|
|
i = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Enough space, add the new block
|
|
|
|
buffer[i] = rdAddr & 0xFF;
|
|
|
|
buffer[i + 1] = (rdAddr >> 8) & 0xFF;
|
|
|
|
buffer[i + 2] = 1;
|
|
|
|
buffer[i + 3] = rdValue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Go to the next address
|
|
|
|
++rdAddr;
|
|
|
|
|
|
|
|
// Repeat for bytes of this range
|
|
|
|
} while (--rdRange);
|
|
|
|
|
|
|
|
// Repeat until we run out of ranges
|
|
|
|
} while (rdAddr < EEPROMSize);
|
|
|
|
|
|
|
|
// We must erase the previous group, in preparation for the next swap
|
|
|
|
for (int page = 0; page < curPage; page++) {
|
|
|
|
ee_PageErase(page + curGroup * PagesPerGroup);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Finally, Now the active group is the created new group
|
|
|
|
curGroup = curwGroup;
|
|
|
|
curPage = curwPage;
|
|
|
|
|
|
|
|
// Done!
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool ee_Write(uint32_t address, uint8_t data) {
|
|
|
|
|
|
|
|
// If we were requested an address outside of the emulated range, fail now
|
|
|
|
if (address >= EEPROMSize)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Lets check if we have a block with that data previously defined. Block
|
|
|
|
// start addresses are always sorted in ascending order
|
|
|
|
int i = 0;
|
|
|
|
while (i <= (PageSize - 4)) { /* (PageSize - 4) because otherwise, there is not enough room for data and headers */
|
|
|
|
|
|
|
|
// Get the address of the block
|
|
|
|
uint32_t baddr = buffer[i] | (buffer[i + 1] << 8);
|
|
|
|
|
|
|
|
// Get the length of the block
|
|
|
|
uint32_t blen = buffer[i + 2];
|
|
|
|
|
|
|
|
// If we reach the end of the list, break loop
|
|
|
|
if (blen == 0xFF)
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Check if data is contained in this block
|
|
|
|
if (address >= baddr &&
|
|
|
|
address < (baddr + blen)) {
|
|
|
|
|
|
|
|
// Yes, it is contained. Just modify it
|
|
|
|
buffer[i + 3 + address - baddr] = data;
|
|
|
|
|
|
|
|
// Done!
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Maybe we could add it to the front or to the back
|
|
|
|
// of this block ?
|
|
|
|
if ((address + 1) == baddr ||
|
|
|
|
address == (baddr + blen)) {
|
|
|
|
|
|
|
|
// Potentially, it could be done. But we must ensure there is room
|
|
|
|
// so we can expand the block. Lets find how much free space remains
|
|
|
|
uint32_t iend = i;
|
|
|
|
do {
|
|
|
|
uint32_t ln = buffer[iend + 2];
|
|
|
|
if (ln == 0xFF) break;
|
|
|
|
iend += 3 + ln;
|
|
|
|
} while (iend <= (PageSize - 4)); /* (PageSize - 4) because otherwise, there is not enough room for data and headers */
|
|
|
|
|
|
|
|
// Here, inxt points to the first free address in the buffer. Do we have room ?
|
|
|
|
if (iend < PageSize) {
|
|
|
|
// Yes, at least a byte is free - We can expand the block
|
|
|
|
|
|
|
|
// Do we have to insert at the beginning ?
|
|
|
|
if ((address + 1) == baddr) {
|
|
|
|
|
|
|
|
// Insert at the beginning
|
|
|
|
|
|
|
|
// Make room at the beginning for our byte
|
|
|
|
memmove(&buffer[i + 3 + 1], &buffer[i + 3], iend - i - 3);
|
|
|
|
|
|
|
|
// Adjust the header and store the data
|
|
|
|
buffer[i] = address & 0xFF;
|
|
|
|
buffer[i + 1] = (address >> 8) & 0xFF;
|
|
|
|
buffer[i + 2]++;
|
|
|
|
buffer[i + 3] = data;
|
|
|
|
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
|
|
|
|
// Insert at the end - There is a very interesting thing that could happen here:
|
|
|
|
// Maybe we could coalesce the next block with this block. Let's try to do it!
|
|
|
|
int inext = i + 3 + blen;
|
|
|
|
if (inext <= (PageSize - 4) &&
|
|
|
|
(buffer[inext] | (buffer[inext + 1] << 8)) == (baddr + blen + 1)) {
|
|
|
|
// YES! ... we can coalesce blocks! . Do it!
|
|
|
|
|
|
|
|
// Adjust this block header to include the next one
|
|
|
|
buffer[i + 2] += buffer[inext + 2] + 1;
|
|
|
|
|
|
|
|
// Store data at the right place
|
|
|
|
buffer[i + 3 + blen] = data;
|
|
|
|
|
|
|
|
// Remove the next block header and append its data
|
|
|
|
memmove(&buffer[inext + 1], &buffer[inext + 3], iend - inext - 3);
|
|
|
|
|
|
|
|
// Finally, as we have saved 2 bytes at the end, make sure to clean them
|
|
|
|
buffer[iend - 2] = 0xFF;
|
|
|
|
buffer[iend - 1] = 0xFF;
|
|
|
|
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// NO ... No coalescing possible yet
|
|
|
|
|
|
|
|
// Make room at the end for our byte
|
|
|
|
memmove(&buffer[i + 3 + blen + 1], &buffer[i + 3 + blen], iend - i - 3 - blen);
|
|
|
|
|
|
|
|
// And add the data to the block
|
|
|
|
buffer[i + 2]++;
|
|
|
|
buffer[i + 3 + blen] = data;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Done!
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// As blocks are always sorted, if the starting address of this block is higher
|
|
|
|
// than the address we are looking for, break loop now - We wont find the value
|
|
|
|
// associated to the address
|
|
|
|
if (baddr > address)
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Jump to the next block
|
|
|
|
i += 3 + blen;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Value is not stored AND we can't expand previous block to contain it. We must create a new block
|
|
|
|
|
|
|
|
// First, lets find how much free space remains
|
|
|
|
uint32_t iend = i;
|
|
|
|
while (iend <= (PageSize - 4)) { /* (PageSize - 4) because otherwise, there is not enough room for data and headers */
|
|
|
|
uint32_t ln = buffer[iend + 2];
|
|
|
|
if (ln == 0xFF) break;
|
|
|
|
iend += 3 + ln;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If there is room for a new block, insert it at the proper place
|
|
|
|
if (iend <= (PageSize - 4)) {
|
|
|
|
|
|
|
|
// We have room to create a new block. Do so --- But add
|
|
|
|
// the block at the proper position, sorted by starting
|
|
|
|
// address, so it will be possible to compact it with other blocks.
|
|
|
|
|
|
|
|
// Make space
|
|
|
|
memmove(&buffer[i + 4], &buffer[i], iend - i);
|
|
|
|
|
|
|
|
// And add the block
|
|
|
|
buffer[i] = address & 0xFF;
|
|
|
|
buffer[i + 1] = (address >> 8) & 0xFF;
|
|
|
|
buffer[i + 2] = 1;
|
|
|
|
buffer[i + 3] = data;
|
|
|
|
|
|
|
|
// Done!
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Not enough room to store this information on this FLASH page - Perform a
|
|
|
|
// flush and override the address with the specified contents
|
|
|
|
return ee_Flush(address, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ee_Init() {
|
|
|
|
|
|
|
|
// Just init once!
|
|
|
|
if (curGroup != 0xFF)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Clean up the SRAM buffer
|
|
|
|
memset(buffer, 0xFF, sizeof(buffer));
|
|
|
|
|
|
|
|
// Now, we must find out the group where settings are stored
|
|
|
|
for (curGroup = 0; curGroup < GroupCount; curGroup++) {
|
|
|
|
if (!ee_IsPageClean(curGroup * PagesPerGroup))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If all groups seem to be used, default to first group
|
|
|
|
if (curGroup >= GroupCount)
|
|
|
|
curGroup = 0;
|
|
|
|
|
|
|
|
#ifdef EE_EMU_DEBUG
|
|
|
|
SERIAL_ECHO_START();
|
|
|
|
SERIAL_ECHOLNPAIR("EEPROM Current Group: ",curGroup);
|
2017-11-05 14:49:38 +00:00
|
|
|
SERIAL_FLUSH();
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 23:51:36 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// Now, validate that all the other group pages are empty
|
|
|
|
for (int grp = 0; grp < GroupCount; grp++) {
|
|
|
|
if (grp == curGroup)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for (int page = 0; page < PagesPerGroup; page++) {
|
|
|
|
if (!ee_IsPageClean(grp * PagesPerGroup + page)) {
|
|
|
|
#ifdef EE_EMU_DEBUG
|
|
|
|
SERIAL_ECHO_START();
|
|
|
|
SERIAL_ECHOPAIR("EEPROM Page ",page);
|
|
|
|
SERIAL_ECHOLNPAIR(" not clean on group ",grp);
|
2017-11-05 14:49:38 +00:00
|
|
|
SERIAL_FLUSH();
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 23:51:36 +00:00
|
|
|
#endif
|
|
|
|
ee_PageErase(grp * PagesPerGroup + page);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Finally, for the active group, determine the first unused page
|
|
|
|
// and also validate that all the other ones are clean
|
|
|
|
for (curPage = 0; curPage < PagesPerGroup; curPage++) {
|
|
|
|
if (ee_IsPageClean(curGroup * PagesPerGroup + curPage)) {
|
|
|
|
#ifdef EE_EMU_DEBUG
|
|
|
|
ee_Dump(curGroup * PagesPerGroup + curPage, getFlashStorage(curGroup * PagesPerGroup + curPage));
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef EE_EMU_DEBUG
|
|
|
|
SERIAL_ECHO_START();
|
|
|
|
SERIAL_ECHOLNPAIR("EEPROM Active page: ",curPage);
|
2017-11-05 14:49:38 +00:00
|
|
|
SERIAL_FLUSH();
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 23:51:36 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// Make sure the pages following the first clean one are also clean
|
|
|
|
for (int page = curPage + 1; page < PagesPerGroup; page++) {
|
|
|
|
if (!ee_IsPageClean(curGroup * PagesPerGroup + page)) {
|
|
|
|
#ifdef EE_EMU_DEBUG
|
|
|
|
SERIAL_ECHO_START();
|
|
|
|
SERIAL_ECHOPAIR("EEPROM Page ",page);
|
|
|
|
SERIAL_ECHOLNPAIR(" not clean on active group ",curGroup);
|
2017-11-05 14:49:38 +00:00
|
|
|
SERIAL_FLUSH();
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 23:51:36 +00:00
|
|
|
ee_Dump(curGroup * PagesPerGroup + page, getFlashStorage(curGroup * PagesPerGroup + page));
|
|
|
|
#endif
|
|
|
|
ee_PageErase(curGroup * PagesPerGroup + page);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t eeprom_read_byte(uint8_t* addr) {
|
|
|
|
ee_Init();
|
|
|
|
return ee_Read((uint32_t)addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void eeprom_write_byte(uint8_t* addr, uint8_t value) {
|
|
|
|
ee_Init();
|
|
|
|
ee_Write((uint32_t)addr, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void eeprom_update_block(const void* __src, void* __dst, size_t __n) {
|
|
|
|
uint8_t* dst = (uint8_t*)__dst;
|
|
|
|
const uint8_t* src = (const uint8_t*)__src;
|
|
|
|
while (__n--) {
|
|
|
|
eeprom_write_byte(dst, *src);
|
|
|
|
++dst;
|
|
|
|
++src;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void eeprom_read_block(void* __dst, const void* __src, size_t __n) {
|
|
|
|
uint8_t* dst = (uint8_t*)__dst;
|
|
|
|
uint8_t* src = (uint8_t*)__src;
|
|
|
|
while (__n--) {
|
|
|
|
*dst = eeprom_read_byte(src);
|
|
|
|
++dst;
|
|
|
|
++src;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void eeprom_flush(void) {
|
|
|
|
ee_Flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // ENABLED(EEPROM_SETTINGS) && DISABLED(I2C_EEPROM) && DISABLED(SPI_EEPROM)
|
|
|
|
#endif // ARDUINO_ARCH_AVR
|