Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix 2.0.x #3

Merged
merged 8 commits into from
Dec 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions Marlin/src/HAL/HAL_ESP32/WebSocketSerial.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,16 @@

#include <Stream.h>

#ifndef RX_BUFFER_SIZE
#define RX_BUFFER_SIZE 128
#endif
#ifndef TX_BUFFER_SIZE
#define TX_BUFFER_SIZE 32
#endif
#if TX_BUFFER_SIZE <= 0
#error "TX_BUFFER_SIZE is required for the WebSocket."
#if ENABLED(WIFISUPPORT)
#ifndef RX_BUFFER_SIZE
#define RX_BUFFER_SIZE 128
#endif
#if TX_BUFFER_SIZE <= 0
#error "TX_BUFFER_SIZE is required for the WebSocket."
#endif
#endif

typedef uint16_t ring_buffer_pos_t;
Expand Down
265 changes: 265 additions & 0 deletions Marlin/src/HAL/HAL_STM32/persistent_store_flash.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
/**
* Marlin 3D Printer Firmware
*
* Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* Copyright (c) 2016 Bob Cousins [email protected]
* Copyright (c) 2015-2016 Nico Tonnhofer [email protected]
* Copyright (c) 2016 Victor Perez [email protected]
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC)

#include "../../inc/MarlinConfig.h"

#if BOTH(EEPROM_SETTINGS, FLASH_EEPROM_EMULATION)

#include "../shared/persistent_store_api.h"


// Only STM32F4 can support wear leveling at this time
#ifndef STM32F4xx
#undef FLASH_EEPROM_LEVELING
#endif

/**
* The STM32 HAL supports chips that deal with "pages" and some with "sectors" and some that
* even have multiple "banks" of flash.
*
* This code is a bit of a mashup of
* framework-arduinoststm32/cores/arduino/stm32/stm32_eeprom.c
* hal/hal_lpc1768/persistent_store_flash.cpp
*
* This has only be written against those that use a single "sector" design.
*
* Those that deal with "pages" could be made to work. Looking at the STM32F07 for example, there are
* 128 "pages", each 2kB in size. If we continued with our EEPROM being 4Kb, we'd always need to operate
* on 2 of these pages. Each write, we'd use 2 different pages from a pool of pages until we are done.
*/

#if ENABLED(FLASH_EEPROM_LEVELING)

#include "stm32_def.h"

#define DEBUG_OUT ENABLED(EEPROM_CHITCHAT)
#include "src/core/debug_out.h"

#ifndef EEPROM_SIZE
#define EEPROM_SIZE 0x1000 // 4kB
#endif

#ifndef FLASH_SECTOR
#define FLASH_SECTOR (FLASH_SECTOR_TOTAL - 1)
#endif
#ifndef FLASH_UNIT_SIZE
#define FLASH_UNIT_SIZE 0x20000 // 128kB
#endif

#define FLASH_ADDRESS_START (FLASH_END - ((FLASH_SECTOR_TOTAL - FLASH_SECTOR) * FLASH_UNIT_SIZE) + 1)
#define FLASH_ADDRESS_END (FLASH_ADDRESS_START + FLASH_UNIT_SIZE - 1)

#define EEPROM_SLOTS (FLASH_UNIT_SIZE/EEPROM_SIZE)
#define SLOT_ADDRESS(slot) (FLASH_ADDRESS_START + (slot * EEPROM_SIZE))

#define UNLOCK_FLASH() if (!flash_unlocked) { \
HAL_FLASH_Unlock(); \
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | \
FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); \
flash_unlocked = true; \
}
#define LOCK_FLASH() if (flash_unlocked) { HAL_FLASH_Lock(); flash_unlocked = false; }

#define EMPTY_UINT32 ((uint32_t)-1)
#define EMPTY_UINT8 ((uint8_t)-1)

static uint8_t ram_eeprom[EEPROM_SIZE] __attribute__((aligned(4))) = {0};
static int current_slot = -1;

static_assert(0 == EEPROM_SIZE % 4, "EEPROM_SIZE must be a multiple of 4"); // Ensure copying as uint32_t is safe
static_assert(0 == FLASH_UNIT_SIZE % EEPROM_SIZE, "EEPROM_SIZE must divide evenly into your FLASH_UNIT_SIZE");
static_assert(FLASH_UNIT_SIZE >= EEPROM_SIZE, "FLASH_UNIT_SIZE must be greater than or equal to your EEPROM_SIZE");
static_assert(IS_FLASH_SECTOR(FLASH_SECTOR), "FLASH_SECTOR is invalid");
static_assert(IS_POWER_OF_2(FLASH_UNIT_SIZE), "FLASH_UNIT_SIZE should be a power of 2, please check your chip's spec sheet");

#endif

static bool eeprom_data_written = false;

bool PersistentStore::access_start() {

#if ENABLED(FLASH_EEPROM_LEVELING)

if (current_slot == -1 || eeprom_data_written) {
// This must be the first time since power on that we have accessed the storage, or someone
// loaded and called write_data and never called access_finish.
// Lets go looking for the slot that holds our configuration.
if (eeprom_data_written) DEBUG_ECHOLN("Dangling EEPROM write_data");
uint32_t address = FLASH_ADDRESS_START;
while (address <= FLASH_ADDRESS_END) {
uint32_t address_value = (*(__IO uint32_t*)address);
if (address_value != EMPTY_UINT32) {
current_slot = (address - FLASH_ADDRESS_START) / EEPROM_SIZE;
break;
}
address += sizeof(uint32_t);
}
if (current_slot == -1) {
// We didn't find anything, so we'll just intialize to empty
for (int i = 0; i < EEPROM_SIZE; i++) ram_eeprom[i] = EMPTY_UINT8;
current_slot = EEPROM_SLOTS;
}
else {
// load current settings
uint8_t *eeprom_data = (uint8_t *)SLOT_ADDRESS(current_slot);
for (int i = 0; i < EEPROM_SIZE; i++) ram_eeprom[i] = eeprom_data[i];
DEBUG_ECHOLNPAIR("EEPROM loaded from slot ", current_slot, ".");
}
eeprom_data_written = false;
}

#else
eeprom_buffer_fill();
#endif

return true;
}

bool PersistentStore::access_finish() {

if (eeprom_data_written) {

#if ENABLED(FLASH_EEPROM_LEVELING)

HAL_StatusTypeDef status = HAL_ERROR;
bool flash_unlocked = false;

if (--current_slot < 0) {
// all slots have been used, erase everything and start again

FLASH_EraseInitTypeDef EraseInitStruct;
uint32_t SectorError = 0;

EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
EraseInitStruct.Sector = FLASH_SECTOR;
EraseInitStruct.NbSectors = 1;

current_slot = EEPROM_SLOTS - 1;
UNLOCK_FLASH();

status = HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError);
if (status != HAL_OK) {
DEBUG_ECHOLNPAIR("HAL_FLASHEx_Erase=", status);
DEBUG_ECHOLNPAIR("GetError=", HAL_FLASH_GetError());
DEBUG_ECHOLNPAIR("SectorError=", SectorError);
LOCK_FLASH();
return false;
}
}

UNLOCK_FLASH();

uint32_t offset = 0;
uint32_t address = SLOT_ADDRESS(current_slot);
uint32_t address_end = address + EEPROM_SIZE;
uint32_t data = 0;

bool success = true;

while (address < address_end) {
memcpy(&data, ram_eeprom + offset, sizeof(uint32_t));
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, data);
if (status == HAL_OK) {
address += sizeof(uint32_t);
offset += sizeof(uint32_t);
}
else {
DEBUG_ECHOLNPAIR("HAL_FLASH_Program=", status);
DEBUG_ECHOLNPAIR("GetError=", HAL_FLASH_GetError());
DEBUG_ECHOLNPAIR("address=", address);
success = false;
break;
}
}

LOCK_FLASH();

if (success) {
eeprom_data_written = false;
DEBUG_ECHOLNPAIR("EEPROM saved to slot ", current_slot, ".");
}

return success;

#else
eeprom_buffer_flush();
eeprom_data_written = false;
#endif
}

return true;
}

bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
while (size--) {
uint8_t v = *value;
#if ENABLED(FLASH_EEPROM_LEVELING)
if (v != ram_eeprom[pos]) {
ram_eeprom[pos] = v;
eeprom_data_written = true;
}
#else
if (v != eeprom_buffered_read_byte(pos)) {
eeprom_buffered_write_byte(pos, v);
eeprom_data_written = true;
}
#endif
crc16(crc, &v, 1);
pos++;
value++;
}
return false;
}

bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
do {
const uint8_t c = (
#if ENABLED(FLASH_EEPROM_LEVELING)
ram_eeprom[pos]
#else
eeprom_buffered_read_byte(pos)
#endif
);
if (writing) *value = c;
crc16(crc, &c, 1);
pos++;
value++;
} while (--size);
return false;
}

size_t PersistentStore::capacity() {
return (
#if ENABLED(FLASH_EEPROM_LEVELING)
EEPROM_SIZE
#else
E2END + 1
#endif
);
}

#endif // EEPROM_SETTINGS && FLASH_EEPROM_EMULATION
#endif // ARDUINO_ARCH_STM32 && !STM32GENERIC
25 changes: 2 additions & 23 deletions Marlin/src/HAL/HAL_STM32/persistent_store_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,29 +24,15 @@

#include "../../inc/MarlinConfig.h"

#if ENABLED(EEPROM_SETTINGS) && ANY(FLASH_EEPROM_EMULATION, SRAM_EEPROM_EMULATION, SPI_EEPROM, I2C_EEPROM)
#if ENABLED(EEPROM_SETTINGS) && ANY(SRAM_EEPROM_EMULATION, SPI_EEPROM, I2C_EEPROM)

#include "../shared/persistent_store_api.h"

#if ENABLED(FLASH_EEPROM_EMULATION)
#include <EEPROM.h>
static bool eeprom_data_written = false;
#endif

bool PersistentStore::access_start() {
#if ENABLED(FLASH_EEPROM_EMULATION)
eeprom_buffer_fill();
#endif
return true;
}

bool PersistentStore::access_finish() {
#if ENABLED(FLASH_EEPROM_EMULATION)
if (eeprom_data_written) {
eeprom_buffer_flush();
eeprom_data_written = false;
}
#endif
return true;
}

Expand All @@ -66,8 +52,6 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
return true;
}
}
#elif ENABLED(FLASH_EEPROM_EMULATION)
eeprom_buffered_write_byte(pos, v);
#else
*(__IO uint8_t *)(BKPSRAM_BASE + (uint8_t * const)pos) = v;
#endif
Expand All @@ -76,9 +60,6 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
pos++;
value++;
};
#if ENABLED(FLASH_EEPROM_EMULATION)
eeprom_data_written = true;
#endif

return false;
}
Expand All @@ -89,8 +70,6 @@ bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t
const uint8_t c = (
#if EITHER(SPI_EEPROM, I2C_EEPROM)
eeprom_read_byte((uint8_t*)pos)
#elif ENABLED(FLASH_EEPROM_EMULATION)
eeprom_buffered_read_byte(pos)
#else
(*(__IO uint8_t *)(BKPSRAM_BASE + ((uint8_t*)pos)))
#endif
Expand All @@ -114,5 +93,5 @@ size_t PersistentStore::capacity() {
);
}

#endif // EEPROM_SETTINGS && (FLASH_EEPROM_EMULATION || SRAM_EEPROM_EMULATION || SPI_EEPROM || I2C_EEPROM)
#endif // EEPROM_SETTINGS && (SRAM_EEPROM_EMULATION || SPI_EEPROM || I2C_EEPROM)
#endif // ARDUINO_ARCH_STM32 && !STM32GENERIC
3 changes: 3 additions & 0 deletions Marlin/src/core/boards.h
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@
#define BOARD_LERDGE_X 4210 // Lerdge X (STM32F407VE)
#define BOARD_VAKE403D 4211 // VAkE 403D (STM32F446VET6)
#define BOARD_FYSETC_S6 4212 // FYSETC S6 board
#define BOARD_FLYF407ZG 4213 // FLYF407ZG board (STM32F407ZG)

//
// ARM Cortex M7
Expand All @@ -322,6 +323,8 @@
// Espressif ESP32 WiFi
//
#define BOARD_ESPRESSIF_ESP32 6000
#define BOARD_MRR_ESPA 6001
#define BOARD_MRR_ESPE 6002

//
// Simulations
Expand Down
2 changes: 1 addition & 1 deletion Marlin/src/core/serial.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ extern uint8_t marlin_debug_flags;
#define SERIAL_PRINTF(V...) SERIAL_OUT(printf, V)
#define SERIAL_FLUSH() SERIAL_OUT(flush)

#ifdef __STM32F1__
#ifdef ARDUINO_ARCH_STM32
#define SERIAL_FLUSHTX() SERIAL_OUT(flush)
#elif TX_BUFFER_SIZE > 0
#define SERIAL_FLUSHTX() SERIAL_OUT(flushTX)
Expand Down
4 changes: 4 additions & 0 deletions Marlin/src/feature/pause.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,10 @@ void resume_print(const float &slow_load_length/*=0*/, const float &fast_load_le
thermalManager.set_fans_paused(false);
#endif

#if HAS_FILAMENT_SENSOR
runout.reset();
#endif

// Resume the print job timer if it was running
if (print_job_timer.isPaused()) print_job_timer.start();

Expand Down
2 changes: 1 addition & 1 deletion Marlin/src/lcd/dogm/u8g_dev_st7920_128x64_HAL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ u8g_dev_t u8g_dev_st7920_128x64_HAL_4x_sw_spi = { u8g_dev_st7920_128x64_HAL_4x_f
U8G_PB_DEV(u8g_dev_st7920_128x64_HAL_hw_spi, LCD_PIXEL_WIDTH, LCD_PIXEL_HEIGHT, PAGE_HEIGHT, u8g_dev_st7920_128x64_HAL_fn, U8G_COM_ST7920_HAL_HW_SPI);
u8g_dev_t u8g_dev_st7920_128x64_HAL_4x_hw_spi = { u8g_dev_st7920_128x64_HAL_4x_fn, &u8g_dev_st7920_128x64_HAL_4x_pb, U8G_COM_ST7920_HAL_HW_SPI };

#if NONE(__AVR__, ARDUINO_ARCH_STM32) || defined(U8G_HAL_LINKS)
#if NONE(__AVR__, ARDUINO_ARCH_STM32, ARDUINO_ARCH_ESP32) || defined(U8G_HAL_LINKS)
// Also use this device for HAL version of rrd class. This results in the same device being used
// for the ST7920 for HAL systems no matter what is selected in ultralcd_impl_DOGM.h.
u8g_dev_t u8g_dev_st7920_128x64_rrd_sw_spi = { u8g_dev_st7920_128x64_HAL_4x_fn, &u8g_dev_st7920_128x64_HAL_4x_pb, U8G_COM_ST7920_HAL_SW_SPI };
Expand Down
Loading