Workaround for POS (Power on self-test) failure messages(s) not output on "native" USB connect.

Fixed handling of NVS buffer allocation, size was not increased as expected when physical NVS is capable of holding more than 2 Kbytes.
This could lead to POS failure or plugins not initializing when a large tool table is configured.
This commit is contained in:
Terje Io
2025-10-23 10:40:01 +02:00
parent ba222d16aa
commit 720f6bd552
7 changed files with 157 additions and 77 deletions

View File

@@ -37,11 +37,14 @@
#include "crc.h"
#include "nvs.h"
static uint8_t *nvsbuffer = NULL;
settings_dirty_t settings_dirty;
static nvs_io_t physical_nvs;
static bool dirty;
uint32_t nvs_size_max = NVS_SIZE;
settings_dirty_t settings_dirty;
static struct {
uint8_t *addr;
uint32_t size;
} nvsbuffer = { .size = NVS_SIZE };
typedef struct {
uint16_t addr;
@@ -123,17 +126,17 @@ static const emap_t target[] = {
{0, 0, 0} // list termination - do not remove
};
inline static uint8_t ram_get_byte (uint32_t addr)
inline static uint8_t ram_get_byte (uint32_t offset)
{
return nvsbuffer[addr];
return nvsbuffer.addr[offset];
}
inline static void ram_put_byte (uint32_t addr, uint8_t new_value)
inline static void ram_put_byte (uint32_t offset, uint8_t new_value)
{
if(addr == 0)
if(offset == 0)
settings_dirty.version = true;
dirty = dirty || nvsbuffer[addr] != new_value || addr == 0;
nvsbuffer[addr] = new_value;
dirty = dirty || nvsbuffer.addr[offset] != new_value || offset == 0;
nvsbuffer.addr[offset] = new_value;
}
static nvs_transfer_result_t memcpy_to_ram (uint32_t destination, uint8_t *source, uint32_t size, bool with_checksum)
@@ -208,7 +211,7 @@ static nvs_transfer_result_t memcpy_from_ram (uint8_t *destination, uint32_t sou
if(hal.nvs.driver_area.address && source > hal.nvs.driver_area.address + hal.nvs.driver_area.size)
return physical_nvs.memcpy_from_nvs(destination, source, size, with_checksum);
uint16_t checksum = with_checksum ? calc_checksum(&nvsbuffer[source], size) : 0;
uint16_t checksum = with_checksum ? calc_checksum(&nvsbuffer.addr[source], size) : 0;
for(; size > 0; size--)
*(destination++) = ram_get_byte(source++);
@@ -223,29 +226,23 @@ static nvs_transfer_result_t memcpy_from_ram (uint8_t *destination, uint32_t sou
// Try to allocate RAM from heap for buffer/emulation.
bool nvs_buffer_alloc (void)
{
static uint32_t nvs_size = NVS_SIZE;
if(nvsbuffer.addr == NULL) {
if(hal.nvs.size_max > nvs_size) {
nvs_size_max = min(4096, hal.nvs.size_max); // Limit to 4K for now
if(nvsbuffer)
free(nvsbuffer);
if(hal.nvs.size_max > NVS_SIZE)
nvsbuffer.size = min(NVS_SIZE_MAX, hal.nvs.size_max);
if(nvsbuffer.size >= GRBL_NVS_SIZE && (nvsbuffer.addr = malloc(nvsbuffer.size)))
memset(nvsbuffer.addr, 0xFF, nvsbuffer.size);
}
assert(nvs_size_max >= GRBL_NVS_SIZE);
if((nvsbuffer = malloc(nvs_size_max))) {
nvs_size = nvs_size_max;
memset(nvsbuffer, 0xFF, nvs_size_max);
}
return nvsbuffer != NULL;
return nvsbuffer.addr != NULL;
}
void nvs_buffer_free (void)
{
if(nvsbuffer) {
if(nvsbuffer.addr) {
nvs_buffer_sync_physical();
free(nvsbuffer);
free(nvsbuffer.addr);
}
}
//
@@ -255,15 +252,15 @@ bool nvs_buffer_init (void)
{
hal.nvs.size = ((hal.nvs.size - 1) | 0x03) + 1; // Ensure NVS area ends on a word boundary
if(nvsbuffer) {
if(nvsbuffer.addr) {
memcpy(&physical_nvs, &hal.nvs, sizeof(nvs_io_t)); // save pointers to physical storage handler functions
// Copy physical storage content to RAM when available
if(physical_nvs.type == NVS_Flash)
physical_nvs.memcpy_from_flash(nvsbuffer);
physical_nvs.memcpy_from_flash(nvsbuffer.addr);
else if(physical_nvs.type != NVS_None)
physical_nvs.memcpy_from_nvs(nvsbuffer, 0, GRBL_NVS_SIZE + hal.nvs.driver_area.size, false);
physical_nvs.memcpy_from_nvs(nvsbuffer.addr, 0, GRBL_NVS_SIZE + hal.nvs.driver_area.size, false);
// Switch hal to use RAM version of non-volatile storage data
hal.nvs.type = NVS_Emulated;
@@ -279,9 +276,9 @@ bool nvs_buffer_init (void)
if(physical_nvs.type == NVS_None || ram_get_byte(0) != SETTINGS_VERSION) {
settings_restore(settings_all);
if(physical_nvs.type == NVS_Flash)
physical_nvs.memcpy_to_flash(nvsbuffer);
physical_nvs.memcpy_to_flash(nvsbuffer.addr);
else if(physical_nvs.memcpy_to_nvs)
physical_nvs.memcpy_to_nvs(0, nvsbuffer, GRBL_NVS_SIZE + hal.nvs.driver_area.size, false);
physical_nvs.memcpy_to_nvs(0, nvsbuffer.addr, GRBL_NVS_SIZE + hal.nvs.driver_area.size, false);
if(physical_nvs.type != NVS_None)
grbl.report.status_message(Status_SettingReadFail);
}
@@ -291,7 +288,7 @@ bool nvs_buffer_init (void)
// Clear settings dirty flags
memset(&settings_dirty, 0, sizeof(settings_dirty_t));
return nvsbuffer != NULL;
return nvsbuffer.addr != NULL;
}
// Allocate NVS block for driver settings.
@@ -300,22 +297,23 @@ nvs_address_t nvs_alloc (size_t size)
{
static uint8_t *mem_address;
uint8_t *start_address;
nvs_address_t addr = 0;
// Check if already switched to emulation or buffer allocation failed, return NULL if so.
if(hal.nvs.type == NVS_Emulated || nvsbuffer == NULL)
if(hal.nvs.type == NVS_Emulated || (nvsbuffer.addr == NULL && !nvs_buffer_alloc()))
return 0;
if(hal.nvs.driver_area.address == 0) {
hal.nvs.driver_area.address = GRBL_NVS_SIZE;
hal.nvs.driver_area.mem_address = mem_address = nvsbuffer + GRBL_NVS_SIZE;
hal.nvs.driver_area.mem_address = mem_address = nvsbuffer.addr + hal.nvs.driver_area.address;
}
size += NVS_CRC_BYTES; // add room for checksum.
if(hal.nvs.driver_area.size + size < (nvs_size_max - GRBL_NVS_SIZE)) {
mem_address = (uint8_t *)((uintptr_t)(mem_address - 1) | 0x03) + 1; // Align to word boundary
addr = mem_address - nvsbuffer;
mem_address += size;
start_address = (uint8_t *)((uintptr_t)(mem_address - 1) | 0x03) + 1; // Align to word boundary
if(start_address + size < nvsbuffer.addr + nvsbuffer.size) {
addr = start_address - nvsbuffer.addr;
mem_address = start_address + size;
hal.nvs.driver_area.size = mem_address - hal.nvs.driver_area.mem_address;
hal.nvs.size = GRBL_NVS_SIZE + hal.nvs.driver_area.size + 1;
}
@@ -332,13 +330,13 @@ void nvs_buffer_sync_physical (void)
if(physical_nvs.memcpy_to_nvs) {
if(settings_dirty.version)
settings_dirty.version = physical_nvs.memcpy_to_nvs(0, nvsbuffer, 1, false) != NVS_TransferResult_OK;
settings_dirty.version = physical_nvs.memcpy_to_nvs(0, nvsbuffer.addr, 1, false) != NVS_TransferResult_OK;
if(settings_dirty.global_settings)
settings_dirty.global_settings = physical_nvs.memcpy_to_nvs(NVS_ADDR_GLOBAL, (uint8_t *)(nvsbuffer + NVS_ADDR_GLOBAL), sizeof(settings_t) + NVS_CRC_BYTES, false) != NVS_TransferResult_OK;
settings_dirty.global_settings = physical_nvs.memcpy_to_nvs(NVS_ADDR_GLOBAL, (uint8_t *)(nvsbuffer.addr + NVS_ADDR_GLOBAL), sizeof(settings_t) + NVS_CRC_BYTES, false) != NVS_TransferResult_OK;
if(settings_dirty.build_info)
settings_dirty.build_info = physical_nvs.memcpy_to_nvs(NVS_ADDR_BUILD_INFO, (uint8_t *)(nvsbuffer + NVS_ADDR_BUILD_INFO), sizeof(stored_line_t) + NVS_CRC_BYTES, false) != NVS_TransferResult_OK;
settings_dirty.build_info = physical_nvs.memcpy_to_nvs(NVS_ADDR_BUILD_INFO, (uint8_t *)(nvsbuffer.addr + NVS_ADDR_BUILD_INFO), sizeof(stored_line_t) + NVS_CRC_BYTES, false) != NVS_TransferResult_OK;
uint_fast8_t idx = N_STARTUP_LINE, offset;
if(settings_dirty.startup_lines) do {
@@ -346,7 +344,7 @@ void nvs_buffer_sync_physical (void)
if(bit_istrue(settings_dirty.startup_lines, bit(idx))) {
bit_false(settings_dirty.startup_lines, bit(idx));
offset = NVS_ADDR_STARTUP_BLOCK + idx * (sizeof(stored_line_t) + NVS_CRC_BYTES);
if(physical_nvs.memcpy_to_nvs(offset, (uint8_t *)(nvsbuffer + offset), sizeof(stored_line_t) + NVS_CRC_BYTES, false) == NVS_TransferResult_OK)
if(physical_nvs.memcpy_to_nvs(offset, (uint8_t *)(nvsbuffer.addr + offset), sizeof(stored_line_t) + NVS_CRC_BYTES, false) == NVS_TransferResult_OK)
bit_false(settings_dirty.startup_lines, bit(idx));
}
} while(idx);
@@ -355,14 +353,14 @@ void nvs_buffer_sync_physical (void)
if(settings_dirty.coord_data) do {
if(bit_istrue(settings_dirty.coord_data, bit(idx))) {
offset = NVS_ADDR_PARAMETERS + idx * (sizeof(coord_data_t) + NVS_CRC_BYTES);
if(physical_nvs.memcpy_to_nvs(offset, (uint8_t *)(nvsbuffer + offset), sizeof(coord_data_t) + NVS_CRC_BYTES, false) == NVS_TransferResult_OK)
if(physical_nvs.memcpy_to_nvs(offset, (uint8_t *)(nvsbuffer.addr + offset), sizeof(coord_data_t) + NVS_CRC_BYTES, false) == NVS_TransferResult_OK)
bit_false(settings_dirty.coord_data, bit(idx));
}
} while(idx--);
if(settings_dirty.driver_settings) {
if(hal.nvs.driver_area.size > 0)
settings_dirty.driver_settings = physical_nvs.memcpy_to_nvs(hal.nvs.driver_area.address, (uint8_t *)(nvsbuffer + hal.nvs.driver_area.address), hal.nvs.driver_area.size, false) != NVS_TransferResult_OK;
settings_dirty.driver_settings = physical_nvs.memcpy_to_nvs(hal.nvs.driver_area.address, (uint8_t *)(nvsbuffer.addr + hal.nvs.driver_area.address), hal.nvs.driver_area.size, false) != NVS_TransferResult_OK;
else
settings_dirty.driver_settings = false;
}
@@ -373,7 +371,7 @@ void nvs_buffer_sync_physical (void)
idx--;
if(bit_istrue(settings_dirty.tool_data, bit(idx))) {
offset = NVS_ADDR_TOOL_TABLE + idx * (sizeof(tool_data_t) + NVS_CRC_BYTES);
if(physical_nvs.memcpy_to_nvs(offset, (uint8_t *)(nvsbuffer + offset), sizeof(tool_data_t) + NVS_CRC_BYTES, false) == NVS_TransferResult_OK)
if(physical_nvs.memcpy_to_nvs(offset, (uint8_t *)(nvsbuffer.addr + offset), sizeof(tool_data_t) + NVS_CRC_BYTES, false) == NVS_TransferResult_OK)
bit_false(settings_dirty.tool_data, bit(idx));
}
} while(idx);
@@ -390,7 +388,7 @@ void nvs_buffer_sync_physical (void)
} else if(physical_nvs.memcpy_to_flash) {
uint_fast8_t retries = 4;
do {
if(physical_nvs.memcpy_to_flash(nvsbuffer))
if(physical_nvs.memcpy_to_flash(nvsbuffer.addr))
retries = 0;
else if(--retries == 0)
report_message("Settings write failed!", Message_Warning);
@@ -425,7 +423,7 @@ void nvs_memmap (void)
strcpy(buf, "Parameters: ");
strcat(buf, uitoa(NVS_ADDR_PARAMETERS));
strcat(buf, " ");
strcat(buf, uitoa(N_CoordinateSystems * (sizeof(coord_data_t) + NVS_CRC_BYTES)));
strcat(buf, uitoa(NVS_SIZE_PARAMETERS));
strcat(buf, " ");
strcat(buf, uitoa(NVS_ADDR_PARAMETERS + N_CoordinateSystems * (sizeof(coord_data_t) + NVS_CRC_BYTES)));
report_message(buf, Message_Plain);
@@ -433,7 +431,7 @@ void nvs_memmap (void)
strcpy(buf, "Startup block: ");
strcat(buf, uitoa(NVS_ADDR_STARTUP_BLOCK));
strcat(buf, " ");
strcat(buf, uitoa(N_STARTUP_LINE * (sizeof(stored_line_t) + NVS_CRC_BYTES)));
strcat(buf, uitoa(NVS_SIZE_STARTUP_BLOCK));
strcat(buf, " ");
strcat(buf, uitoa(NVS_ADDR_STARTUP_BLOCK + N_STARTUP_LINE * (sizeof(stored_line_t) + NVS_CRC_BYTES)));
report_message(buf, Message_Plain);
@@ -441,7 +439,7 @@ void nvs_memmap (void)
strcpy(buf, "Build info: ");
strcat(buf, uitoa(NVS_ADDR_BUILD_INFO));
strcat(buf, " ");
strcat(buf, uitoa(sizeof(stored_line_t) + NVS_CRC_BYTES));
strcat(buf, uitoa(NVS_SIZE_BUILD_INFO));
strcat(buf, " ");
strcat(buf, uitoa(NVS_ADDR_BUILD_INFO + sizeof(stored_line_t) + NVS_CRC_BYTES));
report_message(buf, Message_Plain);