mirror of
https://github.com/bdring/Grbl_Esp32.git
synced 2025-08-30 17:49:56 +02:00
Use less memory (#644)
a) closeFile() now does SD.end() to release memory after running a file from SD. b) Several task stacks are smaller c) All tasks now check their free space if DEBUG_REPORT_STACK_FREE is defined. platformio.ini has a commented-out line that can be uncommented to turn that on. d) Similarly, platformio.ini can turn on DEBUG_REPORT_HEAP_SIZE e) Fixed a small leak that occurred when listing local files. With these changes, the heap size tends to hover around 53K, dropping to about 37K when running a file from SD.
This commit is contained in:
@@ -42,6 +42,14 @@
|
||||
*/
|
||||
#include "Config.h"
|
||||
|
||||
// This block of #includes is necessary for Report.h
|
||||
#include "Error.h"
|
||||
#include "WebUI/Authentication.h"
|
||||
#include "WebUI/ESPResponse.h"
|
||||
#include "Probe.h"
|
||||
#include "System.h"
|
||||
#include "Report.h"
|
||||
|
||||
#include <FreeRTOS.h>
|
||||
#include <driver/periph_ctrl.h>
|
||||
#include <rom/lldesc.h>
|
||||
@@ -516,6 +524,9 @@ static void IRAM_ATTR i2sOutTask(void* parameter) {
|
||||
o_dma.rw_pos = 0; // If someone calls i2s_out_push_sample, make sure there is no buffer overflow
|
||||
}
|
||||
I2S_OUT_PULSER_EXIT_CRITICAL(); // Unlock pulser status
|
||||
|
||||
static UBaseType_t uxHighWaterMark = 0;
|
||||
reportTaskStackSize(uxHighWaterMark);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -907,7 +918,7 @@ int IRAM_ATTR i2s_out_init(i2s_out_init_t& init_param) {
|
||||
// Create the task that will feed the buffer
|
||||
xTaskCreatePinnedToCore(i2sOutTask,
|
||||
"I2SOutTask",
|
||||
1024 * 10,
|
||||
4096,
|
||||
NULL,
|
||||
1,
|
||||
nullptr,
|
||||
|
@@ -330,11 +330,8 @@ void limits_init() {
|
||||
}
|
||||
|
||||
if (limit_sw_queue == NULL) {
|
||||
grbl_msg_sendf(CLIENT_SERIAL,
|
||||
MsgLevel::Info,
|
||||
"%s limit switch on pin %s",
|
||||
reportAxisNameMsg(axis, gang_index),
|
||||
pinName(pin).c_str());
|
||||
grbl_msg_sendf(
|
||||
CLIENT_SERIAL, MsgLevel::Info, "%s limit switch on pin %s", reportAxisNameMsg(axis, gang_index), pinName(pin).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -427,6 +424,8 @@ void limitCheckTask(void* pvParameters) {
|
||||
mc_reset(); // Initiate system kill.
|
||||
sys_rt_exec_alarm = ExecAlarm::HardLimit; // Indicate hard limit critical event
|
||||
}
|
||||
static UBaseType_t uxHighWaterMark = 0;
|
||||
reportTaskStackSize(uxHighWaterMark);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -60,18 +60,14 @@ namespace Motors {
|
||||
xLastWakeTime = xTaskGetTickCount(); // Initialise the xLastWakeTime variable with the current time.
|
||||
vTaskDelay(2000); // initial delay
|
||||
while (true) { // don't ever return from this or the task dies
|
||||
|
||||
// static UBaseType_t uxHighWaterMark = 0;
|
||||
// if (uxHighWaterMark != uxTaskGetStackHighWaterMark(NULL)) {
|
||||
// uxHighWaterMark = uxTaskGetStackHighWaterMark(NULL);
|
||||
// grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Servo Task Min Stack Space: %d", uxHighWaterMark);
|
||||
// }
|
||||
|
||||
for (Servo* p = List; p; p = p->link) {
|
||||
p->update();
|
||||
}
|
||||
|
||||
vTaskDelayUntil(&xLastWakeTime, xUpdate);
|
||||
|
||||
static UBaseType_t uxHighWaterMark = 0;
|
||||
reportTaskStackSize(uxHighWaterMark);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -360,13 +360,10 @@ namespace Motors {
|
||||
} // sys.state
|
||||
} // if mask
|
||||
|
||||
// static UBaseType_t uxHighWaterMark = 0;
|
||||
// if (uxHighWaterMark != uxTaskGetStackHighWaterMark(NULL)) {
|
||||
// uxHighWaterMark = uxTaskGetStackHighWaterMark(NULL);
|
||||
// grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "SG Task Stack Space: %d", uxHighWaterMark);
|
||||
// }
|
||||
|
||||
vTaskDelayUntil(&xLastWakeTime, xreadSg);
|
||||
|
||||
static UBaseType_t uxHighWaterMark = 0;
|
||||
reportTaskStackSize(uxHighWaterMark);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -938,3 +938,13 @@ char* reportAxisNameMsg(uint8_t axis) {
|
||||
sprintf(name, "%c Axis", report_get_axis_letter(axis));
|
||||
return name;
|
||||
}
|
||||
|
||||
void reportTaskStackSize(UBaseType_t& saved) {
|
||||
#ifdef DEBUG_REPORT_STACK_FREE
|
||||
UBaseType_t newHighWater = uxTaskGetStackHighWaterMark(NULL);
|
||||
if (newHighWater != saved) {
|
||||
saved = newHighWater;
|
||||
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "%s Min Stack Space: %d", pcTaskGetTaskName(NULL), saved);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@@ -127,3 +127,5 @@ char report_get_axis_letter(uint8_t axis);
|
||||
char* reportAxisLimitsMsg(uint8_t axis);
|
||||
char* reportAxisNameMsg(uint8_t axis);
|
||||
char* reportAxisNameMsg(uint8_t axis, uint8_t dual_axis);
|
||||
|
||||
void reportTaskStackSize(UBaseType_t& saved);
|
||||
|
@@ -81,6 +81,7 @@ boolean closeFile() {
|
||||
SD_ready_next = false;
|
||||
sd_current_line_number = 0;
|
||||
myFile.close();
|
||||
SD.end();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -147,7 +148,7 @@ uint8_t get_sd_state(bool refresh) {
|
||||
sd_state = SDCARD_NOT_PRESENT;
|
||||
//using default value for speed ? should be parameter
|
||||
//refresh content if card was removed
|
||||
if (SD.begin((GRBL_SPI_SS == -1) ? SS : GRBL_SPI_SS, SPI, GRBL_SPI_FREQ)) {
|
||||
if (SD.begin((GRBL_SPI_SS == -1) ? SS : GRBL_SPI_SS, SPI, GRBL_SPI_FREQ, "/sd", 2)) {
|
||||
if (SD.cardSize() > 0) {
|
||||
sd_state = SDCARD_IDLE;
|
||||
}
|
||||
|
@@ -68,7 +68,27 @@ uint8_t serial_get_rx_buffer_available(uint8_t client) {
|
||||
return client_buffer[client].availableforwrite();
|
||||
}
|
||||
|
||||
void heapCheckTask(void* pvParameters) {
|
||||
static uint32_t heapSize = 0;
|
||||
while (true) {
|
||||
uint32_t newHeapSize = xPortGetFreeHeapSize();
|
||||
if (newHeapSize != heapSize) {
|
||||
heapSize = newHeapSize;
|
||||
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "heap %d", heapSize);
|
||||
}
|
||||
vTaskDelay(3000 / portTICK_RATE_MS); // Yield to other tasks
|
||||
|
||||
static UBaseType_t uxHighWaterMark = 0;
|
||||
reportTaskStackSize(uxHighWaterMark);
|
||||
}
|
||||
}
|
||||
|
||||
void serial_init() {
|
||||
#ifdef DEBUG_REPORT_HEAP_SIZE
|
||||
// For a 2000-word stack, uxTaskGetStackHighWaterMark reports 288 words available
|
||||
xTaskCreatePinnedToCore(heapCheckTask, "heapTask", 2000, NULL, 1, NULL, 1);
|
||||
#endif
|
||||
|
||||
Serial.begin(BAUD_RATE);
|
||||
Serial.setRxBufferSize(256);
|
||||
// reset all buffers
|
||||
@@ -76,9 +96,11 @@ void serial_init() {
|
||||
grbl_send(CLIENT_SERIAL, "\r\n"); // create some white space after ESP32 boot info
|
||||
serialCheckTaskHandle = 0;
|
||||
// create a task to check for incoming data
|
||||
// For a 4096-word stack, uxTaskGetStackHighWaterMark reports 244 words available
|
||||
// after WebUI attaches.
|
||||
xTaskCreatePinnedToCore(serialCheckTask, // task
|
||||
"serialCheckTask", // name for task
|
||||
8192, // size of task stack
|
||||
4096, // size of task stack
|
||||
NULL, // parameters
|
||||
1, // priority
|
||||
&serialCheckTaskHandle,
|
||||
@@ -91,6 +113,7 @@ void serial_init() {
|
||||
void serialCheckTask(void* pvParameters) {
|
||||
uint8_t data = 0;
|
||||
uint8_t client = CLIENT_ALL; // who sent the data
|
||||
static UBaseType_t uxHighWaterMark = 0;
|
||||
while (true) { // run continuously
|
||||
while (any_client_has_data()) {
|
||||
if (Serial.available()) {
|
||||
@@ -149,6 +172,9 @@ void serialCheckTask(void* pvParameters) {
|
||||
WebUI::Serial2Socket.handle_flush();
|
||||
#endif
|
||||
vTaskDelay(1 / portTICK_RATE_MS); // Yield to other tasks
|
||||
|
||||
static UBaseType_t uxHighWaterMark = 0;
|
||||
reportTaskStackSize(uxHighWaterMark);
|
||||
} // while(true)
|
||||
}
|
||||
|
||||
|
@@ -185,6 +185,9 @@ namespace Spindles {
|
||||
// Wait a bit before we retry. Set the delay to poll-rate. Not sure
|
||||
// if we should use a different value...
|
||||
vTaskDelay(VFD_RS485_POLL_RATE);
|
||||
|
||||
static UBaseType_t uxHighWaterMark = 0;
|
||||
reportTaskStackSize(uxHighWaterMark);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -123,6 +123,9 @@ void controlCheckTask(void* pvParameters) {
|
||||
system_exec_control_pin(pins);
|
||||
}
|
||||
debouncing = false;
|
||||
|
||||
static UBaseType_t uxHighWaterMark = 0;
|
||||
reportTaskStackSize(uxHighWaterMark);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@@ -20,8 +20,6 @@
|
||||
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Grbl.h"
|
||||
|
||||
// System states. The state variable primarily tracks the individual functions
|
||||
// of Grbl to manage each without overlapping. It is also used as a messaging flag for
|
||||
// critical events.
|
||||
|
@@ -600,9 +600,9 @@ namespace WebUI {
|
||||
|
||||
#ifdef ENABLE_WIFI
|
||||
static Error listAPs(char* parameter, AuthenticationLevel auth_level) { // ESP410
|
||||
JSONencoder* j = new JSONencoder(espresponse->client() != CLIENT_WEBUI);
|
||||
j->begin();
|
||||
j->begin_array("AP_LIST");
|
||||
JSONencoder j(espresponse->client() != CLIENT_WEBUI);
|
||||
j.begin();
|
||||
j.begin_array("AP_LIST");
|
||||
// An initial async scanNetworks was issued at startup, so there
|
||||
// is a good chance that scan information is already available.
|
||||
int n = WiFi.scanComplete();
|
||||
@@ -614,12 +614,12 @@ namespace WebUI {
|
||||
break;
|
||||
default:
|
||||
for (int i = 0; i < n; ++i) {
|
||||
j->begin_object();
|
||||
j->member("SSID", WiFi.SSID(i));
|
||||
j->member("SIGNAL", wifi_config.getSignal(WiFi.RSSI(i)));
|
||||
j->member("IS_PROTECTED", WiFi.encryptionType(i) != WIFI_AUTH_OPEN);
|
||||
j.begin_object();
|
||||
j.member("SSID", WiFi.SSID(i));
|
||||
j.member("SIGNAL", wifi_config.getSignal(WiFi.RSSI(i)));
|
||||
j.member("IS_PROTECTED", WiFi.encryptionType(i) != WIFI_AUTH_OPEN);
|
||||
// j->member("IS_PROTECTED", WiFi.encryptionType(i) == WIFI_AUTH_OPEN ? "0" : "1");
|
||||
j->end_object();
|
||||
j.end_object();
|
||||
}
|
||||
WiFi.scanDelete();
|
||||
// Restart the scan in async mode so new data will be available
|
||||
@@ -630,9 +630,8 @@ namespace WebUI {
|
||||
}
|
||||
break;
|
||||
}
|
||||
j->end_array();
|
||||
webPrint(j->end());
|
||||
delete j;
|
||||
j.end_array();
|
||||
webPrint(j.end());
|
||||
if (espresponse->client() != CLIENT_WEBUI) {
|
||||
espresponse->println("");
|
||||
}
|
||||
@@ -657,17 +656,16 @@ namespace WebUI {
|
||||
}
|
||||
|
||||
static Error listSettings(char* parameter, AuthenticationLevel auth_level) { // ESP400
|
||||
JSONencoder* j = new JSONencoder(espresponse->client() != CLIENT_WEBUI);
|
||||
j->begin();
|
||||
j->begin_array("EEPROM");
|
||||
JSONencoder j(espresponse->client() != CLIENT_WEBUI);
|
||||
j.begin();
|
||||
j.begin_array("EEPROM");
|
||||
for (Setting* js = Setting::List; js; js = js->next()) {
|
||||
if (js->getType() == WEBSET) {
|
||||
js->addWebui(j);
|
||||
js->addWebui(&j);
|
||||
}
|
||||
}
|
||||
j->end_array();
|
||||
webPrint(j->end());
|
||||
delete j;
|
||||
j.end_array();
|
||||
webPrint(j.end());
|
||||
return Error::Ok;
|
||||
}
|
||||
|
||||
@@ -833,15 +831,15 @@ namespace WebUI {
|
||||
}
|
||||
|
||||
static Error listLocalFilesJSON(char* parameter, AuthenticationLevel auth_level) { // No ESP command
|
||||
JSONencoder* j = new JSONencoder(espresponse->client() != CLIENT_WEBUI);
|
||||
j->begin();
|
||||
j->begin_array("files");
|
||||
listDirJSON(SPIFFS, "/", 4, j);
|
||||
j->end_array();
|
||||
j->member("total", SPIFFS.totalBytes());
|
||||
j->member("used", SPIFFS.usedBytes());
|
||||
j->member("occupation", String(100 * SPIFFS.usedBytes() / SPIFFS.totalBytes()));
|
||||
webPrint(j->end());
|
||||
JSONencoder j(espresponse->client() != CLIENT_WEBUI);
|
||||
j.begin();
|
||||
j.begin_array("files");
|
||||
listDirJSON(SPIFFS, "/", 4, &j);
|
||||
j.end_array();
|
||||
j.member("total", SPIFFS.totalBytes());
|
||||
j.member("used", SPIFFS.usedBytes());
|
||||
j.member("occupation", String(100 * SPIFFS.usedBytes() / SPIFFS.totalBytes()));
|
||||
webPrint(j.end());
|
||||
if (espresponse->client() != CLIENT_WEBUI) {
|
||||
webPrintln("");
|
||||
}
|
||||
|
@@ -28,6 +28,8 @@ build_flags =
|
||||
-DCORE_DEBUG_LEVEL=0
|
||||
-Wno-unused-variable
|
||||
-Wno-unused-function
|
||||
;-DDEBUG_REPORT_HEAP_SIZE
|
||||
;-DDEBUG_REPORT_STACK_FREE
|
||||
|
||||
[env]
|
||||
lib_deps =
|
||||
|
Reference in New Issue
Block a user