mirror of
https://github.com/bdring/Grbl_Esp32.git
synced 2025-08-29 17:19:50 +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,19 +42,27 @@
|
|||||||
*/
|
*/
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
# include <FreeRTOS.h>
|
// This block of #includes is necessary for Report.h
|
||||||
# include <driver/periph_ctrl.h>
|
#include "Error.h"
|
||||||
# include <rom/lldesc.h>
|
#include "WebUI/Authentication.h"
|
||||||
# include <soc/i2s_struct.h>
|
#include "WebUI/ESPResponse.h"
|
||||||
# include <freertos/queue.h>
|
#include "Probe.h"
|
||||||
|
#include "System.h"
|
||||||
|
#include "Report.h"
|
||||||
|
|
||||||
# include <stdatomic.h>
|
#include <FreeRTOS.h>
|
||||||
|
#include <driver/periph_ctrl.h>
|
||||||
|
#include <rom/lldesc.h>
|
||||||
|
#include <soc/i2s_struct.h>
|
||||||
|
#include <freertos/queue.h>
|
||||||
|
|
||||||
# include "Pins.h"
|
#include <stdatomic.h>
|
||||||
# include "I2SOut.h"
|
|
||||||
|
#include "Pins.h"
|
||||||
|
#include "I2SOut.h"
|
||||||
|
|
||||||
// Always enable I2S streaming logic
|
// Always enable I2S streaming logic
|
||||||
# define USE_I2S_OUT_STREAM_IMPL
|
#define USE_I2S_OUT_STREAM_IMPL
|
||||||
|
|
||||||
//
|
//
|
||||||
// Configrations for DMA connected I2S
|
// Configrations for DMA connected I2S
|
||||||
@@ -76,7 +84,7 @@ const int I2S_SAMPLE_SIZE = 4; /* 4 bytes,
|
|||||||
const int DMA_SAMPLE_COUNT = I2S_OUT_DMABUF_LEN / I2S_SAMPLE_SIZE; /* number of samples per buffer */
|
const int DMA_SAMPLE_COUNT = I2S_OUT_DMABUF_LEN / I2S_SAMPLE_SIZE; /* number of samples per buffer */
|
||||||
const int SAMPLE_SAFE_COUNT = (20 / I2S_OUT_USEC_PER_PULSE); /* prevent buffer overrun (GRBL's $0 should be less than or equal 20) */
|
const int SAMPLE_SAFE_COUNT = (20 / I2S_OUT_USEC_PER_PULSE); /* prevent buffer overrun (GRBL's $0 should be less than or equal 20) */
|
||||||
|
|
||||||
# ifdef USE_I2S_OUT_STREAM_IMPL
|
#ifdef USE_I2S_OUT_STREAM_IMPL
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t** buffers;
|
uint32_t** buffers;
|
||||||
uint32_t* current;
|
uint32_t* current;
|
||||||
@@ -87,39 +95,39 @@ typedef struct {
|
|||||||
|
|
||||||
static i2s_out_dma_t o_dma;
|
static i2s_out_dma_t o_dma;
|
||||||
static intr_handle_t i2s_out_isr_handle;
|
static intr_handle_t i2s_out_isr_handle;
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
// output value
|
// output value
|
||||||
static atomic_uint_least32_t i2s_out_port_data = ATOMIC_VAR_INIT(0);
|
static atomic_uint_least32_t i2s_out_port_data = ATOMIC_VAR_INIT(0);
|
||||||
|
|
||||||
// inner lock
|
// inner lock
|
||||||
static portMUX_TYPE i2s_out_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
static portMUX_TYPE i2s_out_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||||
# define I2S_OUT_ENTER_CRITICAL() \
|
#define I2S_OUT_ENTER_CRITICAL() \
|
||||||
do { \
|
do { \
|
||||||
if (xPortInIsrContext()) { \
|
if (xPortInIsrContext()) { \
|
||||||
portENTER_CRITICAL_ISR(&i2s_out_spinlock); \
|
portENTER_CRITICAL_ISR(&i2s_out_spinlock); \
|
||||||
} else { \
|
} else { \
|
||||||
portENTER_CRITICAL(&i2s_out_spinlock); \
|
portENTER_CRITICAL(&i2s_out_spinlock); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
# define I2S_OUT_EXIT_CRITICAL() \
|
#define I2S_OUT_EXIT_CRITICAL() \
|
||||||
do { \
|
do { \
|
||||||
if (xPortInIsrContext()) { \
|
if (xPortInIsrContext()) { \
|
||||||
portEXIT_CRITICAL_ISR(&i2s_out_spinlock); \
|
portEXIT_CRITICAL_ISR(&i2s_out_spinlock); \
|
||||||
} else { \
|
} else { \
|
||||||
portEXIT_CRITICAL(&i2s_out_spinlock); \
|
portEXIT_CRITICAL(&i2s_out_spinlock); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
# define I2S_OUT_ENTER_CRITICAL_ISR() portENTER_CRITICAL_ISR(&i2s_out_spinlock)
|
#define I2S_OUT_ENTER_CRITICAL_ISR() portENTER_CRITICAL_ISR(&i2s_out_spinlock)
|
||||||
# define I2S_OUT_EXIT_CRITICAL_ISR() portEXIT_CRITICAL_ISR(&i2s_out_spinlock)
|
#define I2S_OUT_EXIT_CRITICAL_ISR() portEXIT_CRITICAL_ISR(&i2s_out_spinlock)
|
||||||
|
|
||||||
static int i2s_out_initialized = 0;
|
static int i2s_out_initialized = 0;
|
||||||
|
|
||||||
# ifdef USE_I2S_OUT_STREAM_IMPL
|
#ifdef USE_I2S_OUT_STREAM_IMPL
|
||||||
static volatile uint32_t i2s_out_pulse_period;
|
static volatile uint32_t i2s_out_pulse_period;
|
||||||
static uint32_t i2s_out_remain_time_until_next_pulse; // Time remaining until the next pulse (μsec)
|
static uint32_t i2s_out_remain_time_until_next_pulse; // Time remaining until the next pulse (μsec)
|
||||||
static volatile i2s_out_pulse_func_t i2s_out_pulse_func;
|
static volatile i2s_out_pulse_func_t i2s_out_pulse_func;
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
static uint8_t i2s_out_ws_pin = 255;
|
static uint8_t i2s_out_ws_pin = 255;
|
||||||
static uint8_t i2s_out_bck_pin = 255;
|
static uint8_t i2s_out_bck_pin = 255;
|
||||||
@@ -129,24 +137,24 @@ static volatile i2s_out_pulser_status_t i2s_out_pulser_status = PASSTHROUGH;
|
|||||||
|
|
||||||
// outer lock
|
// outer lock
|
||||||
static portMUX_TYPE i2s_out_pulser_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
static portMUX_TYPE i2s_out_pulser_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||||
# define I2S_OUT_PULSER_ENTER_CRITICAL() \
|
#define I2S_OUT_PULSER_ENTER_CRITICAL() \
|
||||||
do { \
|
do { \
|
||||||
if (xPortInIsrContext()) { \
|
if (xPortInIsrContext()) { \
|
||||||
portENTER_CRITICAL_ISR(&i2s_out_pulser_spinlock); \
|
portENTER_CRITICAL_ISR(&i2s_out_pulser_spinlock); \
|
||||||
} else { \
|
} else { \
|
||||||
portENTER_CRITICAL(&i2s_out_pulser_spinlock); \
|
portENTER_CRITICAL(&i2s_out_pulser_spinlock); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
# define I2S_OUT_PULSER_EXIT_CRITICAL() \
|
#define I2S_OUT_PULSER_EXIT_CRITICAL() \
|
||||||
do { \
|
do { \
|
||||||
if (xPortInIsrContext()) { \
|
if (xPortInIsrContext()) { \
|
||||||
portEXIT_CRITICAL_ISR(&i2s_out_pulser_spinlock); \
|
portEXIT_CRITICAL_ISR(&i2s_out_pulser_spinlock); \
|
||||||
} else { \
|
} else { \
|
||||||
portEXIT_CRITICAL(&i2s_out_pulser_spinlock); \
|
portEXIT_CRITICAL(&i2s_out_pulser_spinlock); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
# define I2S_OUT_PULSER_ENTER_CRITICAL_ISR() portENTER_CRITICAL_ISR(&i2s_out_pulser_spinlock)
|
#define I2S_OUT_PULSER_ENTER_CRITICAL_ISR() portENTER_CRITICAL_ISR(&i2s_out_pulser_spinlock)
|
||||||
# define I2S_OUT_PULSER_EXIT_CRITICAL_ISR() portEXIT_CRITICAL_ISR(&i2s_out_pulser_spinlock)
|
#define I2S_OUT_PULSER_EXIT_CRITICAL_ISR() portEXIT_CRITICAL_ISR(&i2s_out_pulser_spinlock)
|
||||||
|
|
||||||
//
|
//
|
||||||
// Internal functions
|
// Internal functions
|
||||||
@@ -161,13 +169,13 @@ static inline void gpio_matrix_out_check(uint8_t gpio, uint32_t signal_idx, bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void i2s_out_single_data() {
|
static inline void i2s_out_single_data() {
|
||||||
# if I2S_OUT_NUM_BITS == 16
|
#if I2S_OUT_NUM_BITS == 16
|
||||||
uint32_t port_data = atomic_load(&i2s_out_port_data);
|
uint32_t port_data = atomic_load(&i2s_out_port_data);
|
||||||
port_data <<= 16; // Shift needed. This specification is not spelled out in the manual.
|
port_data <<= 16; // Shift needed. This specification is not spelled out in the manual.
|
||||||
I2S0.conf_single_data = port_data; // Apply port data in real-time (static I2S)
|
I2S0.conf_single_data = port_data; // Apply port data in real-time (static I2S)
|
||||||
# else
|
#else
|
||||||
I2S0.conf_single_data = atomic_load(&i2s_out_port_data); // Apply port data in real-time (static I2S)
|
I2S0.conf_single_data = atomic_load(&i2s_out_port_data); // Apply port data in real-time (static I2S)
|
||||||
# endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void i2s_out_reset_fifo_without_lock() {
|
static inline void i2s_out_reset_fifo_without_lock() {
|
||||||
@@ -183,7 +191,7 @@ static void IRAM_ATTR i2s_out_reset_fifo() {
|
|||||||
I2S_OUT_EXIT_CRITICAL();
|
I2S_OUT_EXIT_CRITICAL();
|
||||||
}
|
}
|
||||||
|
|
||||||
# ifdef USE_I2S_OUT_STREAM_IMPL
|
#ifdef USE_I2S_OUT_STREAM_IMPL
|
||||||
static int IRAM_ATTR i2s_clear_dma_buffer(lldesc_t* dma_desc, uint32_t port_data) {
|
static int IRAM_ATTR i2s_clear_dma_buffer(lldesc_t* dma_desc, uint32_t port_data) {
|
||||||
uint32_t* buf = (uint32_t*)dma_desc->buf;
|
uint32_t* buf = (uint32_t*)dma_desc->buf;
|
||||||
for (int i = 0; i < DMA_SAMPLE_COUNT; i++) {
|
for (int i = 0; i < DMA_SAMPLE_COUNT; i++) {
|
||||||
@@ -210,7 +218,7 @@ static int IRAM_ATTR i2s_clear_o_dma_buffers(uint32_t port_data) {
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
static int IRAM_ATTR i2s_out_gpio_attach(uint8_t ws, uint8_t bck, uint8_t data) {
|
static int IRAM_ATTR i2s_out_gpio_attach(uint8_t ws, uint8_t bck, uint8_t data) {
|
||||||
// Route the i2s pins to the appropriate GPIO
|
// Route the i2s pins to the appropriate GPIO
|
||||||
@@ -243,13 +251,13 @@ static int IRAM_ATTR i2s_out_gpio_shiftout(uint32_t port_data) {
|
|||||||
|
|
||||||
static int IRAM_ATTR i2s_out_stop() {
|
static int IRAM_ATTR i2s_out_stop() {
|
||||||
I2S_OUT_ENTER_CRITICAL();
|
I2S_OUT_ENTER_CRITICAL();
|
||||||
# ifdef USE_I2S_OUT_STREAM_IMPL
|
#ifdef USE_I2S_OUT_STREAM_IMPL
|
||||||
// Stop FIFO DMA
|
// Stop FIFO DMA
|
||||||
I2S0.out_link.stop = 1;
|
I2S0.out_link.stop = 1;
|
||||||
|
|
||||||
// Disconnect DMA from FIFO
|
// Disconnect DMA from FIFO
|
||||||
I2S0.fifo_conf.dscr_en = 0; //Unset this bit to disable I2S DMA mode. (R/W)
|
I2S0.fifo_conf.dscr_en = 0; //Unset this bit to disable I2S DMA mode. (R/W)
|
||||||
# endif
|
#endif
|
||||||
// stop TX module
|
// stop TX module
|
||||||
I2S0.conf.tx_start = 0;
|
I2S0.conf.tx_start = 0;
|
||||||
|
|
||||||
@@ -269,10 +277,10 @@ static int IRAM_ATTR i2s_out_stop() {
|
|||||||
uint32_t port_data = atomic_load(&i2s_out_port_data); // current expanded port value
|
uint32_t port_data = atomic_load(&i2s_out_port_data); // current expanded port value
|
||||||
i2s_out_gpio_shiftout(port_data);
|
i2s_out_gpio_shiftout(port_data);
|
||||||
|
|
||||||
# ifdef USE_I2S_OUT_STREAM_IMPL
|
#ifdef USE_I2S_OUT_STREAM_IMPL
|
||||||
//clear pending interrupt
|
//clear pending interrupt
|
||||||
I2S0.int_clr.val = I2S0.int_st.val;
|
I2S0.int_clr.val = I2S0.int_st.val;
|
||||||
# endif
|
#endif
|
||||||
I2S_OUT_EXIT_CRITICAL();
|
I2S_OUT_EXIT_CRITICAL();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -296,7 +304,7 @@ static int IRAM_ATTR i2s_out_start() {
|
|||||||
I2S0.conf.rx_reset = 1;
|
I2S0.conf.rx_reset = 1;
|
||||||
I2S0.conf.rx_reset = 0;
|
I2S0.conf.rx_reset = 0;
|
||||||
|
|
||||||
# ifdef USE_I2S_OUT_STREAM_IMPL
|
#ifdef USE_I2S_OUT_STREAM_IMPL
|
||||||
// reset DMA
|
// reset DMA
|
||||||
I2S0.lc_conf.in_rst = 1;
|
I2S0.lc_conf.in_rst = 1;
|
||||||
I2S0.lc_conf.in_rst = 0;
|
I2S0.lc_conf.in_rst = 0;
|
||||||
@@ -304,13 +312,13 @@ static int IRAM_ATTR i2s_out_start() {
|
|||||||
I2S0.lc_conf.out_rst = 0;
|
I2S0.lc_conf.out_rst = 0;
|
||||||
|
|
||||||
I2S0.out_link.addr = (uint32_t)o_dma.desc[0];
|
I2S0.out_link.addr = (uint32_t)o_dma.desc[0];
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
// reset FIFO
|
// reset FIFO
|
||||||
i2s_out_reset_fifo_without_lock();
|
i2s_out_reset_fifo_without_lock();
|
||||||
|
|
||||||
// start DMA link
|
// start DMA link
|
||||||
# ifdef USE_I2S_OUT_STREAM_IMPL
|
#ifdef USE_I2S_OUT_STREAM_IMPL
|
||||||
if (i2s_out_pulser_status == PASSTHROUGH) {
|
if (i2s_out_pulser_status == PASSTHROUGH) {
|
||||||
I2S0.conf_chan.tx_chan_mod = 3; // 3:right+constant 4:left+constant (when tx_msb_right = 1)
|
I2S0.conf_chan.tx_chan_mod = 3; // 3:right+constant 4:left+constant (when tx_msb_right = 1)
|
||||||
I2S0.conf_single_data = port_data;
|
I2S0.conf_single_data = port_data;
|
||||||
@@ -318,17 +326,17 @@ static int IRAM_ATTR i2s_out_start() {
|
|||||||
I2S0.conf_chan.tx_chan_mod = 4; // 3:right+constant 4:left+constant (when tx_msb_right = 1)
|
I2S0.conf_chan.tx_chan_mod = 4; // 3:right+constant 4:left+constant (when tx_msb_right = 1)
|
||||||
I2S0.conf_single_data = 0;
|
I2S0.conf_single_data = 0;
|
||||||
}
|
}
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
I2S0.conf1.tx_stop_en = 1; // BCK and WCK are suppressed while FIFO is empty
|
I2S0.conf1.tx_stop_en = 1; // BCK and WCK are suppressed while FIFO is empty
|
||||||
|
|
||||||
# ifdef USE_I2S_OUT_STREAM_IMPL
|
#ifdef USE_I2S_OUT_STREAM_IMPL
|
||||||
// Connect DMA to FIFO
|
// Connect DMA to FIFO
|
||||||
I2S0.fifo_conf.dscr_en = 1; // Set this bit to enable I2S DMA mode. (R/W)
|
I2S0.fifo_conf.dscr_en = 1; // Set this bit to enable I2S DMA mode. (R/W)
|
||||||
|
|
||||||
I2S0.int_clr.val = 0xFFFFFFFF;
|
I2S0.int_clr.val = 0xFFFFFFFF;
|
||||||
I2S0.out_link.start = 1;
|
I2S0.out_link.start = 1;
|
||||||
# endif
|
#endif
|
||||||
I2S0.conf.tx_start = 1;
|
I2S0.conf.tx_start = 1;
|
||||||
// Wait for the first FIFO data to prevent the unintentional generation of 0 data
|
// Wait for the first FIFO data to prevent the unintentional generation of 0 data
|
||||||
ets_delay_us(20);
|
ets_delay_us(20);
|
||||||
@@ -339,7 +347,7 @@ static int IRAM_ATTR i2s_out_start() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
# ifdef USE_I2S_OUT_STREAM_IMPL
|
#ifdef USE_I2S_OUT_STREAM_IMPL
|
||||||
// Fill out one DMA buffer
|
// Fill out one DMA buffer
|
||||||
// Call with the I2S_OUT_PULSER lock acquired.
|
// Call with the I2S_OUT_PULSER lock acquired.
|
||||||
// Note that the lock is temporarily released while calling the callback function.
|
// Note that the lock is temporarily released while calling the callback function.
|
||||||
@@ -516,15 +524,18 @@ 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
|
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
|
I2S_OUT_PULSER_EXIT_CRITICAL(); // Unlock pulser status
|
||||||
|
|
||||||
|
static UBaseType_t uxHighWaterMark = 0;
|
||||||
|
reportTaskStackSize(uxHighWaterMark);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
// External funtions
|
// External funtions
|
||||||
//
|
//
|
||||||
void IRAM_ATTR i2s_out_delay() {
|
void IRAM_ATTR i2s_out_delay() {
|
||||||
# ifdef USE_I2S_OUT_STREAM_IMPL
|
#ifdef USE_I2S_OUT_STREAM_IMPL
|
||||||
I2S_OUT_PULSER_ENTER_CRITICAL();
|
I2S_OUT_PULSER_ENTER_CRITICAL();
|
||||||
if (i2s_out_pulser_status == PASSTHROUGH) {
|
if (i2s_out_pulser_status == PASSTHROUGH) {
|
||||||
// Depending on the timing, it may not be reflected immediately,
|
// Depending on the timing, it may not be reflected immediately,
|
||||||
@@ -536,9 +547,9 @@ void IRAM_ATTR i2s_out_delay() {
|
|||||||
delay(I2S_OUT_DELAY_MS);
|
delay(I2S_OUT_DELAY_MS);
|
||||||
}
|
}
|
||||||
I2S_OUT_PULSER_EXIT_CRITICAL();
|
I2S_OUT_PULSER_EXIT_CRITICAL();
|
||||||
# else
|
#else
|
||||||
ets_delay_us(I2S_OUT_USEC_PER_PULSE * 2);
|
ets_delay_us(I2S_OUT_USEC_PER_PULSE * 2);
|
||||||
# endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR i2s_out_write(uint8_t pin, uint8_t val) {
|
void IRAM_ATTR i2s_out_write(uint8_t pin, uint8_t val) {
|
||||||
@@ -548,15 +559,15 @@ void IRAM_ATTR i2s_out_write(uint8_t pin, uint8_t val) {
|
|||||||
} else {
|
} else {
|
||||||
atomic_fetch_and(&i2s_out_port_data, ~bit);
|
atomic_fetch_and(&i2s_out_port_data, ~bit);
|
||||||
}
|
}
|
||||||
# ifdef USE_I2S_OUT_STREAM_IMPL
|
#ifdef USE_I2S_OUT_STREAM_IMPL
|
||||||
// It needs a lock for access, but I've given up because I need speed.
|
// It needs a lock for access, but I've given up because I need speed.
|
||||||
// This is not a problem as long as there is no overlap between the status change and digitalWrite().
|
// This is not a problem as long as there is no overlap between the status change and digitalWrite().
|
||||||
if (i2s_out_pulser_status == PASSTHROUGH) {
|
if (i2s_out_pulser_status == PASSTHROUGH) {
|
||||||
i2s_out_single_data();
|
i2s_out_single_data();
|
||||||
}
|
}
|
||||||
# else
|
#else
|
||||||
i2s_out_single_data();
|
i2s_out_single_data();
|
||||||
# endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t IRAM_ATTR i2s_out_read(uint8_t pin) {
|
uint8_t IRAM_ATTR i2s_out_read(uint8_t pin) {
|
||||||
@@ -565,9 +576,9 @@ uint8_t IRAM_ATTR i2s_out_read(uint8_t pin) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t IRAM_ATTR i2s_out_push_sample(uint32_t usec) {
|
uint32_t IRAM_ATTR i2s_out_push_sample(uint32_t usec) {
|
||||||
uint32_t num = usec/I2S_OUT_USEC_PER_PULSE;
|
uint32_t num = usec / I2S_OUT_USEC_PER_PULSE;
|
||||||
|
|
||||||
# ifdef USE_I2S_OUT_STREAM_IMPL
|
#ifdef USE_I2S_OUT_STREAM_IMPL
|
||||||
if (num > SAMPLE_SAFE_COUNT) {
|
if (num > SAMPLE_SAFE_COUNT) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -579,9 +590,9 @@ uint32_t IRAM_ATTR i2s_out_push_sample(uint32_t usec) {
|
|||||||
n++;
|
n++;
|
||||||
} while (n < num);
|
} while (n < num);
|
||||||
return n;
|
return n;
|
||||||
# else
|
#else
|
||||||
return 0;
|
return 0;
|
||||||
# endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
i2s_out_pulser_status_t IRAM_ATTR i2s_out_get_pulser_status() {
|
i2s_out_pulser_status_t IRAM_ATTR i2s_out_get_pulser_status() {
|
||||||
@@ -593,7 +604,7 @@ i2s_out_pulser_status_t IRAM_ATTR i2s_out_get_pulser_status() {
|
|||||||
|
|
||||||
int IRAM_ATTR i2s_out_set_passthrough() {
|
int IRAM_ATTR i2s_out_set_passthrough() {
|
||||||
I2S_OUT_PULSER_ENTER_CRITICAL();
|
I2S_OUT_PULSER_ENTER_CRITICAL();
|
||||||
# ifdef USE_I2S_OUT_STREAM_IMPL
|
#ifdef USE_I2S_OUT_STREAM_IMPL
|
||||||
// Triggers a change of mode if it is compiled to use I2S stream.
|
// Triggers a change of mode if it is compiled to use I2S stream.
|
||||||
// The mode is not changed directly by this function.
|
// The mode is not changed directly by this function.
|
||||||
// Pull the trigger
|
// Pull the trigger
|
||||||
@@ -604,17 +615,17 @@ int IRAM_ATTR i2s_out_set_passthrough() {
|
|||||||
// (i2sOutTask() -> stepper_pulse_func() -> st_go_idle() -> Stepper_Timer_Stop() -> this function)
|
// (i2sOutTask() -> stepper_pulse_func() -> st_go_idle() -> Stepper_Timer_Stop() -> this function)
|
||||||
// And only i2sOutTask() can change the state to PASSTHROUGH.
|
// And only i2sOutTask() can change the state to PASSTHROUGH.
|
||||||
// So, to change the state, you need to return to i2sOutTask() as soon as possible.
|
// So, to change the state, you need to return to i2sOutTask() as soon as possible.
|
||||||
# else
|
#else
|
||||||
// If it is compiled to not use I2S streams, change the mode directly.
|
// If it is compiled to not use I2S streams, change the mode directly.
|
||||||
i2s_out_pulser_status = PASSTHROUGH;
|
i2s_out_pulser_status = PASSTHROUGH;
|
||||||
# endif
|
#endif
|
||||||
I2S_OUT_PULSER_EXIT_CRITICAL();
|
I2S_OUT_PULSER_EXIT_CRITICAL();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int IRAM_ATTR i2s_out_set_stepping() {
|
int IRAM_ATTR i2s_out_set_stepping() {
|
||||||
I2S_OUT_PULSER_ENTER_CRITICAL();
|
I2S_OUT_PULSER_ENTER_CRITICAL();
|
||||||
# ifdef USE_I2S_OUT_STREAM_IMPL
|
#ifdef USE_I2S_OUT_STREAM_IMPL
|
||||||
if (i2s_out_pulser_status == STEPPING) {
|
if (i2s_out_pulser_status == STEPPING) {
|
||||||
// Re-entered (fail safe)
|
// Re-entered (fail safe)
|
||||||
I2S_OUT_PULSER_EXIT_CRITICAL();
|
I2S_OUT_PULSER_EXIT_CRITICAL();
|
||||||
@@ -650,31 +661,31 @@ int IRAM_ATTR i2s_out_set_stepping() {
|
|||||||
// because the process in i2s_out_start() is different depending on the status.
|
// because the process in i2s_out_start() is different depending on the status.
|
||||||
i2s_out_pulser_status = STEPPING;
|
i2s_out_pulser_status = STEPPING;
|
||||||
i2s_out_start();
|
i2s_out_start();
|
||||||
# else
|
#else
|
||||||
i2s_out_pulser_status = STEPPING;
|
i2s_out_pulser_status = STEPPING;
|
||||||
# endif
|
#endif
|
||||||
I2S_OUT_PULSER_EXIT_CRITICAL();
|
I2S_OUT_PULSER_EXIT_CRITICAL();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int IRAM_ATTR i2s_out_set_pulse_period(uint32_t period) {
|
int IRAM_ATTR i2s_out_set_pulse_period(uint32_t period) {
|
||||||
# ifdef USE_I2S_OUT_STREAM_IMPL
|
#ifdef USE_I2S_OUT_STREAM_IMPL
|
||||||
i2s_out_pulse_period = period;
|
i2s_out_pulse_period = period;
|
||||||
# endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int IRAM_ATTR i2s_out_set_pulse_callback(i2s_out_pulse_func_t func) {
|
int IRAM_ATTR i2s_out_set_pulse_callback(i2s_out_pulse_func_t func) {
|
||||||
# ifdef USE_I2S_OUT_STREAM_IMPL
|
#ifdef USE_I2S_OUT_STREAM_IMPL
|
||||||
i2s_out_pulse_func = func;
|
i2s_out_pulse_func = func;
|
||||||
# endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int IRAM_ATTR i2s_out_reset() {
|
int IRAM_ATTR i2s_out_reset() {
|
||||||
I2S_OUT_PULSER_ENTER_CRITICAL();
|
I2S_OUT_PULSER_ENTER_CRITICAL();
|
||||||
i2s_out_stop();
|
i2s_out_stop();
|
||||||
# ifdef USE_I2S_OUT_STREAM_IMPL
|
#ifdef USE_I2S_OUT_STREAM_IMPL
|
||||||
if (i2s_out_pulser_status == STEPPING) {
|
if (i2s_out_pulser_status == STEPPING) {
|
||||||
uint32_t port_data = atomic_load(&i2s_out_port_data);
|
uint32_t port_data = atomic_load(&i2s_out_port_data);
|
||||||
i2s_clear_o_dma_buffers(port_data);
|
i2s_clear_o_dma_buffers(port_data);
|
||||||
@@ -682,7 +693,7 @@ int IRAM_ATTR i2s_out_reset() {
|
|||||||
i2s_clear_o_dma_buffers(0);
|
i2s_clear_o_dma_buffers(0);
|
||||||
i2s_out_pulser_status = PASSTHROUGH;
|
i2s_out_pulser_status = PASSTHROUGH;
|
||||||
}
|
}
|
||||||
# endif
|
#endif
|
||||||
// You need to set the status before calling i2s_out_start()
|
// You need to set the status before calling i2s_out_start()
|
||||||
// because the process in i2s_out_start() is different depending on the status.
|
// because the process in i2s_out_start() is different depending on the status.
|
||||||
i2s_out_start();
|
i2s_out_start();
|
||||||
@@ -733,7 +744,7 @@ int IRAM_ATTR i2s_out_init(i2s_out_init_t& init_param) {
|
|||||||
* M = 2
|
* M = 2
|
||||||
*/
|
*/
|
||||||
|
|
||||||
# ifdef USE_I2S_OUT_STREAM_IMPL
|
#ifdef USE_I2S_OUT_STREAM_IMPL
|
||||||
// Allocate the array of pointers to the buffers
|
// Allocate the array of pointers to the buffers
|
||||||
o_dma.buffers = (uint32_t**)malloc(sizeof(uint32_t*) * I2S_OUT_DMABUF_COUNT);
|
o_dma.buffers = (uint32_t**)malloc(sizeof(uint32_t*) * I2S_OUT_DMABUF_COUNT);
|
||||||
if (o_dma.buffers == nullptr) {
|
if (o_dma.buffers == nullptr) {
|
||||||
@@ -770,7 +781,7 @@ int IRAM_ATTR i2s_out_init(i2s_out_init_t& init_param) {
|
|||||||
|
|
||||||
// Set the first DMA descriptor
|
// Set the first DMA descriptor
|
||||||
I2S0.out_link.addr = (uint32_t)o_dma.desc[0];
|
I2S0.out_link.addr = (uint32_t)o_dma.desc[0];
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
// stop i2s
|
// stop i2s
|
||||||
I2S0.out_link.stop = 1;
|
I2S0.out_link.stop = 1;
|
||||||
@@ -806,9 +817,9 @@ int IRAM_ATTR i2s_out_init(i2s_out_init_t& init_param) {
|
|||||||
I2S0.lc_conf.outdscr_burst_en = 0;
|
I2S0.lc_conf.outdscr_burst_en = 0;
|
||||||
I2S0.lc_conf.out_no_restart_clr = 0;
|
I2S0.lc_conf.out_no_restart_clr = 0;
|
||||||
I2S0.lc_conf.indscr_burst_en = 0;
|
I2S0.lc_conf.indscr_burst_en = 0;
|
||||||
# ifdef USE_I2S_OUT_STREAM_IMPL
|
#ifdef USE_I2S_OUT_STREAM_IMPL
|
||||||
I2S0.lc_conf.out_eof_mode = 1; // I2S_OUT_EOF_INT generated when DMA has popped all data from the FIFO;
|
I2S0.lc_conf.out_eof_mode = 1; // I2S_OUT_EOF_INT generated when DMA has popped all data from the FIFO;
|
||||||
# endif
|
#endif
|
||||||
I2S0.conf2.lcd_en = 0;
|
I2S0.conf2.lcd_en = 0;
|
||||||
I2S0.conf2.camera_en = 0;
|
I2S0.conf2.camera_en = 0;
|
||||||
I2S0.pdm_conf.pcm2pdm_conv_en = 0;
|
I2S0.pdm_conf.pcm2pdm_conv_en = 0;
|
||||||
@@ -816,7 +827,7 @@ int IRAM_ATTR i2s_out_init(i2s_out_init_t& init_param) {
|
|||||||
|
|
||||||
I2S0.fifo_conf.dscr_en = 0;
|
I2S0.fifo_conf.dscr_en = 0;
|
||||||
|
|
||||||
# ifdef USE_I2S_OUT_STREAM_IMPL
|
#ifdef USE_I2S_OUT_STREAM_IMPL
|
||||||
if (i2s_out_pulser_status == STEPPING) {
|
if (i2s_out_pulser_status == STEPPING) {
|
||||||
// Stream output mode
|
// Stream output mode
|
||||||
I2S0.conf_chan.tx_chan_mod = 4; // 3:right+constant 4:left+constant (when tx_msb_right = 1)
|
I2S0.conf_chan.tx_chan_mod = 4; // 3:right+constant 4:left+constant (when tx_msb_right = 1)
|
||||||
@@ -826,31 +837,31 @@ int IRAM_ATTR i2s_out_init(i2s_out_init_t& init_param) {
|
|||||||
I2S0.conf_chan.tx_chan_mod = 3; // 3:right+constant 4:left+constant (when tx_msb_right = 1)
|
I2S0.conf_chan.tx_chan_mod = 3; // 3:right+constant 4:left+constant (when tx_msb_right = 1)
|
||||||
I2S0.conf_single_data = init_param.init_val;
|
I2S0.conf_single_data = init_param.init_val;
|
||||||
}
|
}
|
||||||
# else
|
#else
|
||||||
// For the static output mode
|
// For the static output mode
|
||||||
I2S0.conf_chan.tx_chan_mod = 3; // 3:right+constant 4:left+constant (when tx_msb_right = 1)
|
I2S0.conf_chan.tx_chan_mod = 3; // 3:right+constant 4:left+constant (when tx_msb_right = 1)
|
||||||
I2S0.conf_single_data = init_param.init_val; // initial constant value
|
I2S0.conf_single_data = init_param.init_val; // initial constant value
|
||||||
# endif
|
#endif
|
||||||
# if I2S_OUT_NUM_BITS == 16
|
#if I2S_OUT_NUM_BITS == 16
|
||||||
I2S0.fifo_conf.tx_fifo_mod = 0; // 0: 16-bit dual channel data, 3: 32-bit single channel data
|
I2S0.fifo_conf.tx_fifo_mod = 0; // 0: 16-bit dual channel data, 3: 32-bit single channel data
|
||||||
I2S0.fifo_conf.rx_fifo_mod = 0; // 0: 16-bit dual channel data, 3: 32-bit single channel data
|
I2S0.fifo_conf.rx_fifo_mod = 0; // 0: 16-bit dual channel data, 3: 32-bit single channel data
|
||||||
I2S0.sample_rate_conf.tx_bits_mod = 16; // default is 16-bits
|
I2S0.sample_rate_conf.tx_bits_mod = 16; // default is 16-bits
|
||||||
I2S0.sample_rate_conf.rx_bits_mod = 16; // default is 16-bits
|
I2S0.sample_rate_conf.rx_bits_mod = 16; // default is 16-bits
|
||||||
# else
|
#else
|
||||||
I2S0.fifo_conf.tx_fifo_mod = 3; // 0: 16-bit dual channel data, 3: 32-bit single channel data
|
I2S0.fifo_conf.tx_fifo_mod = 3; // 0: 16-bit dual channel data, 3: 32-bit single channel data
|
||||||
I2S0.fifo_conf.rx_fifo_mod = 3; // 0: 16-bit dual channel data, 3: 32-bit single channel data
|
I2S0.fifo_conf.rx_fifo_mod = 3; // 0: 16-bit dual channel data, 3: 32-bit single channel data
|
||||||
// Data width is 32-bit. Forgetting this setting will result in a 16-bit transfer.
|
// Data width is 32-bit. Forgetting this setting will result in a 16-bit transfer.
|
||||||
I2S0.sample_rate_conf.tx_bits_mod = 32;
|
I2S0.sample_rate_conf.tx_bits_mod = 32;
|
||||||
I2S0.sample_rate_conf.rx_bits_mod = 32;
|
I2S0.sample_rate_conf.rx_bits_mod = 32;
|
||||||
# endif
|
#endif
|
||||||
I2S0.conf.tx_mono = 0; // Set this bit to enable transmitter’s mono mode in PCM standard mode.
|
I2S0.conf.tx_mono = 0; // Set this bit to enable transmitter’s mono mode in PCM standard mode.
|
||||||
|
|
||||||
I2S0.conf_chan.rx_chan_mod = 1; // 1: right+right
|
I2S0.conf_chan.rx_chan_mod = 1; // 1: right+right
|
||||||
I2S0.conf.rx_mono = 0;
|
I2S0.conf.rx_mono = 0;
|
||||||
|
|
||||||
# ifdef USE_I2S_OUT_STREAM_IMPL
|
#ifdef USE_I2S_OUT_STREAM_IMPL
|
||||||
I2S0.fifo_conf.dscr_en = 1; //connect DMA to fifo
|
I2S0.fifo_conf.dscr_en = 1; //connect DMA to fifo
|
||||||
# endif
|
#endif
|
||||||
I2S0.conf.tx_start = 0;
|
I2S0.conf.tx_start = 0;
|
||||||
I2S0.conf.rx_start = 0;
|
I2S0.conf.rx_start = 0;
|
||||||
|
|
||||||
@@ -858,9 +869,9 @@ int IRAM_ATTR i2s_out_init(i2s_out_init_t& init_param) {
|
|||||||
I2S0.conf.tx_right_first = 0; // Setting this bit allows the right-channel data to be sent first.
|
I2S0.conf.tx_right_first = 0; // Setting this bit allows the right-channel data to be sent first.
|
||||||
|
|
||||||
I2S0.conf.tx_slave_mod = 0; // Master
|
I2S0.conf.tx_slave_mod = 0; // Master
|
||||||
# ifdef USE_I2S_OUT_STREAM_IMPL
|
#ifdef USE_I2S_OUT_STREAM_IMPL
|
||||||
I2S0.fifo_conf.tx_fifo_mod_force_en = 1; //The bit should always be set to 1.
|
I2S0.fifo_conf.tx_fifo_mod_force_en = 1; //The bit should always be set to 1.
|
||||||
# endif
|
#endif
|
||||||
I2S0.pdm_conf.rx_pdm_en = 0; // Set this bit to enable receiver’s PDM mode.
|
I2S0.pdm_conf.rx_pdm_en = 0; // Set this bit to enable receiver’s PDM mode.
|
||||||
I2S0.pdm_conf.tx_pdm_en = 0; // Set this bit to enable transmitter’s PDM mode.
|
I2S0.pdm_conf.tx_pdm_en = 0; // Set this bit to enable transmitter’s PDM mode.
|
||||||
|
|
||||||
@@ -877,13 +888,13 @@ int IRAM_ATTR i2s_out_init(i2s_out_init_t& init_param) {
|
|||||||
// set clock (fi2s) 160MHz / 5
|
// set clock (fi2s) 160MHz / 5
|
||||||
I2S0.clkm_conf.clka_en = 0; // Use 160 MHz PLL_D2_CLK as reference
|
I2S0.clkm_conf.clka_en = 0; // Use 160 MHz PLL_D2_CLK as reference
|
||||||
// N + b/a = 0
|
// N + b/a = 0
|
||||||
# if I2S_OUT_NUM_BITS == 16
|
#if I2S_OUT_NUM_BITS == 16
|
||||||
// N = 10
|
// N = 10
|
||||||
I2S0.clkm_conf.clkm_div_num = 10; // minimum value of 2, reset value of 4, max 256 (I²S clock divider’s integral value)
|
I2S0.clkm_conf.clkm_div_num = 10; // minimum value of 2, reset value of 4, max 256 (I²S clock divider’s integral value)
|
||||||
# else
|
#else
|
||||||
// N = 5
|
// N = 5
|
||||||
I2S0.clkm_conf.clkm_div_num = 5; // minimum value of 2, reset value of 4, max 256 (I²S clock divider’s integral value)
|
I2S0.clkm_conf.clkm_div_num = 5; // minimum value of 2, reset value of 4, max 256 (I²S clock divider’s integral value)
|
||||||
# endif
|
#endif
|
||||||
// b/a = 0
|
// b/a = 0
|
||||||
I2S0.clkm_conf.clkm_div_b = 0; // 0 at reset
|
I2S0.clkm_conf.clkm_div_b = 0; // 0 at reset
|
||||||
I2S0.clkm_conf.clkm_div_a = 0; // 0 at reset, what about divide by 0? (not an issue)
|
I2S0.clkm_conf.clkm_div_a = 0; // 0 at reset, what about divide by 0? (not an issue)
|
||||||
@@ -893,7 +904,7 @@ int IRAM_ATTR i2s_out_init(i2s_out_init_t& init_param) {
|
|||||||
I2S0.sample_rate_conf.tx_bck_div_num = 2; // minimum value of 2 defaults to 6
|
I2S0.sample_rate_conf.tx_bck_div_num = 2; // minimum value of 2 defaults to 6
|
||||||
I2S0.sample_rate_conf.rx_bck_div_num = 2;
|
I2S0.sample_rate_conf.rx_bck_div_num = 2;
|
||||||
|
|
||||||
# ifdef USE_I2S_OUT_STREAM_IMPL
|
#ifdef USE_I2S_OUT_STREAM_IMPL
|
||||||
// Enable TX interrupts (DMA Interrupts)
|
// Enable TX interrupts (DMA Interrupts)
|
||||||
I2S0.int_ena.out_eof = 1; // Triggered when rxlink has finished sending a packet.
|
I2S0.int_ena.out_eof = 1; // Triggered when rxlink has finished sending a packet.
|
||||||
I2S0.int_ena.out_dscr_err = 0; // Triggered when invalid rxlink descriptors are encountered.
|
I2S0.int_ena.out_dscr_err = 0; // Triggered when invalid rxlink descriptors are encountered.
|
||||||
@@ -907,7 +918,7 @@ int IRAM_ATTR i2s_out_init(i2s_out_init_t& init_param) {
|
|||||||
// Create the task that will feed the buffer
|
// Create the task that will feed the buffer
|
||||||
xTaskCreatePinnedToCore(i2sOutTask,
|
xTaskCreatePinnedToCore(i2sOutTask,
|
||||||
"I2SOutTask",
|
"I2SOutTask",
|
||||||
1024 * 10,
|
4096,
|
||||||
NULL,
|
NULL,
|
||||||
1,
|
1,
|
||||||
nullptr,
|
nullptr,
|
||||||
@@ -917,7 +928,7 @@ int IRAM_ATTR i2s_out_init(i2s_out_init_t& init_param) {
|
|||||||
// Allocate and Enable the I2S interrupt
|
// Allocate and Enable the I2S interrupt
|
||||||
esp_intr_alloc(ETS_I2S0_INTR_SOURCE, 0, i2s_out_intr_handler, nullptr, &i2s_out_isr_handle);
|
esp_intr_alloc(ETS_I2S0_INTR_SOURCE, 0, i2s_out_intr_handler, nullptr, &i2s_out_isr_handle);
|
||||||
esp_intr_enable(i2s_out_isr_handle);
|
esp_intr_enable(i2s_out_isr_handle);
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
// Remember GPIO pin numbers
|
// Remember GPIO pin numbers
|
||||||
i2s_out_ws_pin = init_param.ws_pin;
|
i2s_out_ws_pin = init_param.ws_pin;
|
||||||
@@ -931,18 +942,18 @@ int IRAM_ATTR i2s_out_init(i2s_out_init_t& init_param) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
# ifndef I2S_OUT_WS
|
#ifndef I2S_OUT_WS
|
||||||
# define I2S_OUT_WS GPIO_NUM_17
|
# define I2S_OUT_WS GPIO_NUM_17
|
||||||
# endif
|
#endif
|
||||||
# ifndef I2S_OUT_BCK
|
#ifndef I2S_OUT_BCK
|
||||||
# define I2S_OUT_BCK GPIO_NUM_22
|
# define I2S_OUT_BCK GPIO_NUM_22
|
||||||
# endif
|
#endif
|
||||||
# ifndef I2S_OUT_DATA
|
#ifndef I2S_OUT_DATA
|
||||||
# define I2S_OUT_DATA GPIO_NUM_21
|
# define I2S_OUT_DATA GPIO_NUM_21
|
||||||
# endif
|
#endif
|
||||||
# ifndef I2S_OUT_INIT_VAL
|
#ifndef I2S_OUT_INIT_VAL
|
||||||
# define I2S_OUT_INIT_VAL 0
|
# define I2S_OUT_INIT_VAL 0
|
||||||
# endif
|
#endif
|
||||||
/*
|
/*
|
||||||
Initialize I2S out by default parameters.
|
Initialize I2S out by default parameters.
|
||||||
|
|
||||||
|
@@ -330,11 +330,8 @@ void limits_init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (limit_sw_queue == NULL) {
|
if (limit_sw_queue == NULL) {
|
||||||
grbl_msg_sendf(CLIENT_SERIAL,
|
grbl_msg_sendf(
|
||||||
MsgLevel::Info,
|
CLIENT_SERIAL, MsgLevel::Info, "%s limit switch on pin %s", reportAxisNameMsg(axis, gang_index), pinName(pin).c_str());
|
||||||
"%s limit switch on pin %s",
|
|
||||||
reportAxisNameMsg(axis, gang_index),
|
|
||||||
pinName(pin).c_str());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -427,17 +424,19 @@ void limitCheckTask(void* pvParameters) {
|
|||||||
mc_reset(); // Initiate system kill.
|
mc_reset(); // Initiate system kill.
|
||||||
sys_rt_exec_alarm = ExecAlarm::HardLimit; // Indicate hard limit critical event
|
sys_rt_exec_alarm = ExecAlarm::HardLimit; // Indicate hard limit critical event
|
||||||
}
|
}
|
||||||
|
static UBaseType_t uxHighWaterMark = 0;
|
||||||
|
reportTaskStackSize(uxHighWaterMark);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float limitsMaxPosition(uint8_t axis) {
|
float limitsMaxPosition(uint8_t axis) {
|
||||||
float mpos = axis_settings[axis]->home_mpos->get();
|
float mpos = axis_settings[axis]->home_mpos->get();
|
||||||
|
|
||||||
return bitnum_istrue(homing_dir_mask->get(), axis) ? mpos + axis_settings[axis]->max_travel->get() : mpos;
|
return bitnum_istrue(homing_dir_mask->get(), axis) ? mpos + axis_settings[axis]->max_travel->get() : mpos;
|
||||||
}
|
}
|
||||||
|
|
||||||
float limitsMinPosition(uint8_t axis) {
|
float limitsMinPosition(uint8_t axis) {
|
||||||
float mpos = axis_settings[axis]->home_mpos->get();
|
float mpos = axis_settings[axis]->home_mpos->get();
|
||||||
|
|
||||||
return bitnum_istrue(homing_dir_mask->get(), axis) ? mpos : mpos - axis_settings[axis]->max_travel->get();
|
return bitnum_istrue(homing_dir_mask->get(), axis) ? mpos : mpos - axis_settings[axis]->max_travel->get();
|
||||||
}
|
}
|
||||||
|
@@ -60,18 +60,14 @@ namespace Motors {
|
|||||||
xLastWakeTime = xTaskGetTickCount(); // Initialise the xLastWakeTime variable with the current time.
|
xLastWakeTime = xTaskGetTickCount(); // Initialise the xLastWakeTime variable with the current time.
|
||||||
vTaskDelay(2000); // initial delay
|
vTaskDelay(2000); // initial delay
|
||||||
while (true) { // don't ever return from this or the task dies
|
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) {
|
for (Servo* p = List; p; p = p->link) {
|
||||||
p->update();
|
p->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
vTaskDelayUntil(&xLastWakeTime, xUpdate);
|
vTaskDelayUntil(&xLastWakeTime, xUpdate);
|
||||||
|
|
||||||
|
static UBaseType_t uxHighWaterMark = 0;
|
||||||
|
reportTaskStackSize(uxHighWaterMark);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -360,13 +360,10 @@ namespace Motors {
|
|||||||
} // sys.state
|
} // sys.state
|
||||||
} // if mask
|
} // 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);
|
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));
|
sprintf(name, "%c Axis", report_get_axis_letter(axis));
|
||||||
return name;
|
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* reportAxisLimitsMsg(uint8_t axis);
|
||||||
char* reportAxisNameMsg(uint8_t axis);
|
char* reportAxisNameMsg(uint8_t axis);
|
||||||
char* reportAxisNameMsg(uint8_t axis, uint8_t dual_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_ready_next = false;
|
||||||
sd_current_line_number = 0;
|
sd_current_line_number = 0;
|
||||||
myFile.close();
|
myFile.close();
|
||||||
|
SD.end();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,7 +148,7 @@ uint8_t get_sd_state(bool refresh) {
|
|||||||
sd_state = SDCARD_NOT_PRESENT;
|
sd_state = SDCARD_NOT_PRESENT;
|
||||||
//using default value for speed ? should be parameter
|
//using default value for speed ? should be parameter
|
||||||
//refresh content if card was removed
|
//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) {
|
if (SD.cardSize() > 0) {
|
||||||
sd_state = SDCARD_IDLE;
|
sd_state = SDCARD_IDLE;
|
||||||
}
|
}
|
||||||
|
@@ -68,7 +68,27 @@ uint8_t serial_get_rx_buffer_available(uint8_t client) {
|
|||||||
return client_buffer[client].availableforwrite();
|
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() {
|
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.begin(BAUD_RATE);
|
||||||
Serial.setRxBufferSize(256);
|
Serial.setRxBufferSize(256);
|
||||||
// reset all buffers
|
// reset all buffers
|
||||||
@@ -76,9 +96,11 @@ void serial_init() {
|
|||||||
grbl_send(CLIENT_SERIAL, "\r\n"); // create some white space after ESP32 boot info
|
grbl_send(CLIENT_SERIAL, "\r\n"); // create some white space after ESP32 boot info
|
||||||
serialCheckTaskHandle = 0;
|
serialCheckTaskHandle = 0;
|
||||||
// create a task to check for incoming data
|
// create a task to check for incoming data
|
||||||
|
// For a 4096-word stack, uxTaskGetStackHighWaterMark reports 244 words available
|
||||||
|
// after WebUI attaches.
|
||||||
xTaskCreatePinnedToCore(serialCheckTask, // task
|
xTaskCreatePinnedToCore(serialCheckTask, // task
|
||||||
"serialCheckTask", // name for task
|
"serialCheckTask", // name for task
|
||||||
8192, // size of task stack
|
4096, // size of task stack
|
||||||
NULL, // parameters
|
NULL, // parameters
|
||||||
1, // priority
|
1, // priority
|
||||||
&serialCheckTaskHandle,
|
&serialCheckTaskHandle,
|
||||||
@@ -89,9 +111,10 @@ void serial_init() {
|
|||||||
// this task runs and checks for data on all interfaces
|
// this task runs and checks for data on all interfaces
|
||||||
// REaltime stuff is acted upon, then characters are added to the appropriate buffer
|
// REaltime stuff is acted upon, then characters are added to the appropriate buffer
|
||||||
void serialCheckTask(void* pvParameters) {
|
void serialCheckTask(void* pvParameters) {
|
||||||
uint8_t data = 0;
|
uint8_t data = 0;
|
||||||
uint8_t client = CLIENT_ALL; // who sent the data
|
uint8_t client = CLIENT_ALL; // who sent the data
|
||||||
while (true) { // run continuously
|
static UBaseType_t uxHighWaterMark = 0;
|
||||||
|
while (true) { // run continuously
|
||||||
while (any_client_has_data()) {
|
while (any_client_has_data()) {
|
||||||
if (Serial.available()) {
|
if (Serial.available()) {
|
||||||
client = CLIENT_SERIAL;
|
client = CLIENT_SERIAL;
|
||||||
@@ -149,7 +172,10 @@ void serialCheckTask(void* pvParameters) {
|
|||||||
WebUI::Serial2Socket.handle_flush();
|
WebUI::Serial2Socket.handle_flush();
|
||||||
#endif
|
#endif
|
||||||
vTaskDelay(1 / portTICK_RATE_MS); // Yield to other tasks
|
vTaskDelay(1 / portTICK_RATE_MS); // Yield to other tasks
|
||||||
} // while(true)
|
|
||||||
|
static UBaseType_t uxHighWaterMark = 0;
|
||||||
|
reportTaskStackSize(uxHighWaterMark);
|
||||||
|
} // while(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
void serial_reset_read_buffer(uint8_t client) {
|
void serial_reset_read_buffer(uint8_t client) {
|
||||||
|
@@ -185,6 +185,9 @@ namespace Spindles {
|
|||||||
// Wait a bit before we retry. Set the delay to poll-rate. Not sure
|
// Wait a bit before we retry. Set the delay to poll-rate. Not sure
|
||||||
// if we should use a different value...
|
// if we should use a different value...
|
||||||
vTaskDelay(VFD_RS485_POLL_RATE);
|
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);
|
system_exec_control_pin(pins);
|
||||||
}
|
}
|
||||||
debouncing = false;
|
debouncing = false;
|
||||||
|
|
||||||
|
static UBaseType_t uxHighWaterMark = 0;
|
||||||
|
reportTaskStackSize(uxHighWaterMark);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -20,8 +20,6 @@
|
|||||||
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
|
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Grbl.h"
|
|
||||||
|
|
||||||
// System states. The state variable primarily tracks the individual functions
|
// 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
|
// of Grbl to manage each without overlapping. It is also used as a messaging flag for
|
||||||
// critical events.
|
// critical events.
|
||||||
|
@@ -600,9 +600,9 @@ namespace WebUI {
|
|||||||
|
|
||||||
#ifdef ENABLE_WIFI
|
#ifdef ENABLE_WIFI
|
||||||
static Error listAPs(char* parameter, AuthenticationLevel auth_level) { // ESP410
|
static Error listAPs(char* parameter, AuthenticationLevel auth_level) { // ESP410
|
||||||
JSONencoder* j = new JSONencoder(espresponse->client() != CLIENT_WEBUI);
|
JSONencoder j(espresponse->client() != CLIENT_WEBUI);
|
||||||
j->begin();
|
j.begin();
|
||||||
j->begin_array("AP_LIST");
|
j.begin_array("AP_LIST");
|
||||||
// An initial async scanNetworks was issued at startup, so there
|
// An initial async scanNetworks was issued at startup, so there
|
||||||
// is a good chance that scan information is already available.
|
// is a good chance that scan information is already available.
|
||||||
int n = WiFi.scanComplete();
|
int n = WiFi.scanComplete();
|
||||||
@@ -614,12 +614,12 @@ namespace WebUI {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
for (int i = 0; i < n; ++i) {
|
for (int i = 0; i < n; ++i) {
|
||||||
j->begin_object();
|
j.begin_object();
|
||||||
j->member("SSID", WiFi.SSID(i));
|
j.member("SSID", WiFi.SSID(i));
|
||||||
j->member("SIGNAL", wifi_config.getSignal(WiFi.RSSI(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);
|
||||||
// j->member("IS_PROTECTED", WiFi.encryptionType(i) == WIFI_AUTH_OPEN ? "0" : "1");
|
// j->member("IS_PROTECTED", WiFi.encryptionType(i) == WIFI_AUTH_OPEN ? "0" : "1");
|
||||||
j->end_object();
|
j.end_object();
|
||||||
}
|
}
|
||||||
WiFi.scanDelete();
|
WiFi.scanDelete();
|
||||||
// Restart the scan in async mode so new data will be available
|
// Restart the scan in async mode so new data will be available
|
||||||
@@ -630,9 +630,8 @@ namespace WebUI {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
j->end_array();
|
j.end_array();
|
||||||
webPrint(j->end());
|
webPrint(j.end());
|
||||||
delete j;
|
|
||||||
if (espresponse->client() != CLIENT_WEBUI) {
|
if (espresponse->client() != CLIENT_WEBUI) {
|
||||||
espresponse->println("");
|
espresponse->println("");
|
||||||
}
|
}
|
||||||
@@ -657,17 +656,16 @@ namespace WebUI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Error listSettings(char* parameter, AuthenticationLevel auth_level) { // ESP400
|
static Error listSettings(char* parameter, AuthenticationLevel auth_level) { // ESP400
|
||||||
JSONencoder* j = new JSONencoder(espresponse->client() != CLIENT_WEBUI);
|
JSONencoder j(espresponse->client() != CLIENT_WEBUI);
|
||||||
j->begin();
|
j.begin();
|
||||||
j->begin_array("EEPROM");
|
j.begin_array("EEPROM");
|
||||||
for (Setting* js = Setting::List; js; js = js->next()) {
|
for (Setting* js = Setting::List; js; js = js->next()) {
|
||||||
if (js->getType() == WEBSET) {
|
if (js->getType() == WEBSET) {
|
||||||
js->addWebui(j);
|
js->addWebui(&j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
j->end_array();
|
j.end_array();
|
||||||
webPrint(j->end());
|
webPrint(j.end());
|
||||||
delete j;
|
|
||||||
return Error::Ok;
|
return Error::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -833,15 +831,15 @@ namespace WebUI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Error listLocalFilesJSON(char* parameter, AuthenticationLevel auth_level) { // No ESP command
|
static Error listLocalFilesJSON(char* parameter, AuthenticationLevel auth_level) { // No ESP command
|
||||||
JSONencoder* j = new JSONencoder(espresponse->client() != CLIENT_WEBUI);
|
JSONencoder j(espresponse->client() != CLIENT_WEBUI);
|
||||||
j->begin();
|
j.begin();
|
||||||
j->begin_array("files");
|
j.begin_array("files");
|
||||||
listDirJSON(SPIFFS, "/", 4, j);
|
listDirJSON(SPIFFS, "/", 4, &j);
|
||||||
j->end_array();
|
j.end_array();
|
||||||
j->member("total", SPIFFS.totalBytes());
|
j.member("total", SPIFFS.totalBytes());
|
||||||
j->member("used", SPIFFS.usedBytes());
|
j.member("used", SPIFFS.usedBytes());
|
||||||
j->member("occupation", String(100 * SPIFFS.usedBytes() / SPIFFS.totalBytes()));
|
j.member("occupation", String(100 * SPIFFS.usedBytes() / SPIFFS.totalBytes()));
|
||||||
webPrint(j->end());
|
webPrint(j.end());
|
||||||
if (espresponse->client() != CLIENT_WEBUI) {
|
if (espresponse->client() != CLIENT_WEBUI) {
|
||||||
webPrintln("");
|
webPrintln("");
|
||||||
}
|
}
|
||||||
|
@@ -28,6 +28,8 @@ build_flags =
|
|||||||
-DCORE_DEBUG_LEVEL=0
|
-DCORE_DEBUG_LEVEL=0
|
||||||
-Wno-unused-variable
|
-Wno-unused-variable
|
||||||
-Wno-unused-function
|
-Wno-unused-function
|
||||||
|
;-DDEBUG_REPORT_HEAP_SIZE
|
||||||
|
;-DDEBUG_REPORT_STACK_FREE
|
||||||
|
|
||||||
[env]
|
[env]
|
||||||
lib_deps =
|
lib_deps =
|
||||||
|
Reference in New Issue
Block a user