Added support for traversing directory structure across file system mounts. Allows access to littlefs mount via ftp.

Fixed inconsistent (random) real-time reporting of cycle start signal by adding a latch to ensure it is reported at least once.
This commit is contained in:
Terje Io
2023-07-16 13:03:22 +02:00
parent 8f5fa900be
commit 0c6f3f6dd7
11 changed files with 146 additions and 39 deletions

View File

@@ -1,5 +1,26 @@
## grblHAL changelog
<a name="20230714"/>20230714
Core:
* Added support for traversing directory structure across file system mounts. Allows access to littlefs mount via ftp.
* Fixed inconsistent \(random\) real-time reporting of cycle start signal by adding a latch to ensure it is reported at least once.
Drivers:
* ESP32: added WiFi settings for country, AP channel and BSSID. Changed default AP password to make it legal, was too short.
* STM32F7xx: added EStop signal handling. Driver now defaults to this for the reset input.
Plugins:
* Networking: improved telnet transmit handling.
* WebUI: added file seek function for embedded files, may be used later by gcode macros.
---
<a name="20230711"/>20230711
Core:

View File

@@ -430,7 +430,7 @@
#define NETWORK_AP_SSID "grblHAL_AP"
#endif
#ifndef NETWORK_AP_PASSWORD
#define NETWORK_AP_PASSWORD "grblHAL"
#define NETWORK_AP_PASSWORD "grblHALpwd"
#endif
#ifndef NETWORK_AP_HOSTNAME
#define NETWORK_AP_HOSTNAME "grblHAL_AP"

View File

@@ -1716,7 +1716,7 @@ status_code_t gc_execute_block (char *block)
gc_block.values.t = (uint32_t)gc_block.values.q;
gc_block.words.q = Off;
#if NGC_EXPRESSIONS_ENABLE
if(sys.macro_file) {
if(hal.stream.file) {
gc_state.tool_pending = 0; // force set tool
#if N_TOOLS
if(gc_state.g43_pending) {

2
grbl.h
View File

@@ -42,7 +42,7 @@
#else
#define GRBL_VERSION "1.1f"
#endif
#define GRBL_BUILD 20230711
#define GRBL_BUILD 20230714
#define GRBL_URL "https://github.com/grblHAL"

View File

@@ -170,7 +170,7 @@ static status_code_t stack_push (uint32_t o_label, ngc_cmd_t operation)
{
if(stack_idx < (NGC_STACK_DEPTH - 1)) {
stack[++stack_idx].o_label = o_label;
stack[stack_idx].file = sys.macro_file;
stack[stack_idx].file = hal.stream.file;
stack[stack_idx].operation = operation;
return Status_OK;
}
@@ -259,9 +259,9 @@ status_code_t ngc_flowctrl (uint32_t o_label, char *line, uint_fast8_t *pos, boo
break;
case NGCFlowCtrl_Do:
if(sys.macro_file) {
if(hal.stream.file) {
if(!skipping && (status = stack_push(o_label, operation)) == Status_OK) {
stack[stack_idx].file_pos = vfs_tell(sys.macro_file);
stack[stack_idx].file_pos = vfs_tell(hal.stream.file);
stack[stack_idx].skip = false;
}
} else
@@ -269,7 +269,7 @@ status_code_t ngc_flowctrl (uint32_t o_label, char *line, uint_fast8_t *pos, boo
break;
case NGCFlowCtrl_While:
if(sys.macro_file) {
if(hal.stream.file) {
char *expr = line + *pos;
if(stack[stack_idx].brk) {
if(last_op == NGCFlowCtrl_Do && o_label == stack[stack_idx].o_label)
@@ -286,8 +286,8 @@ status_code_t ngc_flowctrl (uint32_t o_label, char *line, uint_fast8_t *pos, boo
if(!(stack[stack_idx].skip = value == 0.0f)) {
if((stack[stack_idx].expr = malloc(strlen(expr) + 1))) {
strcpy(stack[stack_idx].expr, expr);
stack[stack_idx].file = sys.macro_file;
stack[stack_idx].file_pos = vfs_tell(sys.macro_file);
stack[stack_idx].file = hal.stream.file;
stack[stack_idx].file_pos = vfs_tell(hal.stream.file);
} else
status = Status_FlowControlOutOfMemory;
}
@@ -298,7 +298,7 @@ status_code_t ngc_flowctrl (uint32_t o_label, char *line, uint_fast8_t *pos, boo
break;
case NGCFlowCtrl_EndWhile:
if(sys.macro_file) {
if(hal.stream.file) {
if(last_op == NGCFlowCtrl_While) {
if(o_label == stack[stack_idx].o_label) {
uint_fast8_t pos = 0;
@@ -316,12 +316,12 @@ status_code_t ngc_flowctrl (uint32_t o_label, char *line, uint_fast8_t *pos, boo
break;
case NGCFlowCtrl_Repeat:
if(sys.macro_file) {
if(hal.stream.file) {
if(!skipping && (status = ngc_eval_expression(line, pos, &value)) == Status_OK) {
if((status = stack_push(o_label, operation)) == Status_OK) {
if(!(stack[stack_idx].skip = value == 0.0f)) {
stack[stack_idx].file = sys.macro_file;
stack[stack_idx].file_pos = vfs_tell(sys.macro_file);
stack[stack_idx].file = hal.stream.file;
stack[stack_idx].file_pos = vfs_tell(hal.stream.file);
stack[stack_idx].repeats = (uint32_t)value;
}
}
@@ -331,7 +331,7 @@ status_code_t ngc_flowctrl (uint32_t o_label, char *line, uint_fast8_t *pos, boo
break;
case NGCFlowCtrl_EndRepeat:
if(sys.macro_file) {
if(hal.stream.file) {
if(last_op == NGCFlowCtrl_Repeat) {
if(o_label == stack[stack_idx].o_label) {
if(stack[stack_idx].repeats && --stack[stack_idx].repeats)
@@ -346,7 +346,7 @@ status_code_t ngc_flowctrl (uint32_t o_label, char *line, uint_fast8_t *pos, boo
break;
case NGCFlowCtrl_Break:
if(sys.macro_file) {
if(hal.stream.file) {
if(!skipping) {
while(o_label != stack[stack_idx].o_label && stack_pull());
last_op = stack_idx >= 0 ? stack[stack_idx].operation : NGCFlowCtrl_NoOp;
@@ -363,7 +363,7 @@ status_code_t ngc_flowctrl (uint32_t o_label, char *line, uint_fast8_t *pos, boo
break;
case NGCFlowCtrl_Continue:
if(sys.macro_file) {
if(hal.stream.file) {
if(!skipping) {
while(o_label != stack[stack_idx].o_label && stack_pull());
if(stack_idx >= 0 && o_label == stack[stack_idx].o_label) switch(stack[stack_idx].operation) {

View File

@@ -1205,6 +1205,9 @@ void report_realtime_status (void)
axes_signals_t lim_pin_state = limit_signals_merge(hal.limits.get_state());
control_signals_t ctrl_pin_state = hal.control.get_state();
if(sys.report.cycle_start)
ctrl_pin_state.cycle_start = On;
if (lim_pin_state.value | ctrl_pin_state.value | probe_state.triggered | !probe_state.connected | sys.flags.block_delete_enabled) {
char *append = &buf[4];

View File

@@ -191,8 +191,10 @@ bool state_door_reopened (void)
void state_update (rt_exec_t rt_exec)
{
if ((rt_exec & EXEC_SAFETY_DOOR) && sys_state != STATE_SAFETY_DOOR)
if((rt_exec & EXEC_SAFETY_DOOR) && sys_state != STATE_SAFETY_DOOR)
state_set(STATE_SAFETY_DOOR);
else if(rt_exec & EXEC_CYCLE_START)
sys.report.cycle_start = settings.status_report.pin_state;
stateHandler(rt_exec);
}

View File

@@ -247,7 +247,7 @@ typedef struct {
get_stream_buffer_count_ptr get_tx_buffer_count; //!< Optional handler for getting number of characters in the output buffer(s). Count shall include any unsent characters in any transmit FIFO and/or transmit register. Required for Modbus support.
flush_stream_buffer_ptr reset_write_buffer; //!< Optional handler for flushing the output buffer. Any transmit FIFO shall be flushed as well. Required for Modbus support.
set_baud_rate_ptr set_baud_rate; //!< Optional handler for setting the stream baud rate. Required for Modbus support, recommended for Bluetooth support.
// vfs_file_t *file; //!< File handle, non-null if streaming from a file.
vfs_file_t *file; //!< File handle, non-null if streaming from a file.
} io_stream_t;
typedef const io_stream_t *(*stream_claim_ptr)(uint32_t baud_rate);

View File

@@ -186,6 +186,7 @@ typedef enum {
Report_Encoder = (1 << 14),
Report_TLOReference = (1 << 15),
Report_Fan = (1 << 16),
Report_CycleStart = (1 << 30),
Report_All = 0x8001FFFF
} report_tracking_t;
@@ -207,17 +208,18 @@ typedef union {
pwm :1, //!< Add PWM information (optional: to be added by driver).
motor :1, //!< Add motor information (optional: to be added by driver).
encoder :1, //!< Add encoder information (optional: to be added by driver).
tlo_reference :1, //!< Tool length offset reference changed
fan :1, //!< Fan on/off changed
unassigned :14, //
all :1; //!< Set when CMD_STATUS_REPORT_ALL is requested, may be used by user code
tlo_reference :1, //!< Tool length offset reference changed.
fan :1, //!< Fan on/off changed.
unassigned :13, //
cycle_start :1, //!< Cycle start signal triggered. __NOTE:__ do __NOT__ add to Report_All enum above!
all :1; //!< Set when CMD_STATUS_REPORT_ALL is requested, may be used by user code.
};
} report_tracking_flags_t;
typedef struct {
override_t feed_rate; //!< Feed rate override value in percent
override_t rapid_rate; //!< Rapids override value in percent
override_t spindle_rpm; //!< __NOTE:_ Not used by the core, it maintain per spindle override in \ref spindle_param_t
override_t spindle_rpm; //!< __NOTE:__ Not used by the core, it maintain per spindle override in \ref spindle_param_t
spindle_stop_t spindle_stop; //!< Tracks spindle stop override states
gc_override_flags_t control; //!< Tracks override control states.
} overrides_t;
@@ -286,9 +288,6 @@ typedef struct system {
volatile rt_exec_t rt_exec_state; //!< Realtime executor bitflag variable for state management. See EXEC bitmasks.
volatile uint_fast16_t rt_exec_alarm; //!< Realtime executor bitflag variable for setting various alarms.
int32_t var5399; //!< Last result from M66 - wait on input.
#if NGC_EXPRESSIONS_ENABLE
vfs_file_t *macro_file; //!< File handle of current G65 macro executing.
#endif
#ifdef PID_LOG
pid_data_t pid_log;
#endif

90
vfs.c
View File

@@ -191,7 +191,7 @@ static const char *get_filename (vfs_mount_t *mount, const char *filename)
{
if(*filename == '/') {
size_t len = strlen(mount->path);
return filename + (len == 1 ? 0 : len);
return filename + (len == 1 ? 0 : len - 1);
} else
return filename;
}
@@ -306,8 +306,18 @@ int vfs_chdir (const char *path)
*s = '\0';
}
} else {
strcpy(cwd, path);
cwdmount = get_mount(cwd);
if((cwdmount = get_mount(path)) && strchr(path + 1, '/') == NULL && cwdmount != &root) {
strcpy(cwd, cwdmount->path);
char *s;
if((s = strrchr(cwd, '/')))
*s = '\0';
return 0;
}
}
if((ret = cwdmount ? cwdmount->vfs->fchdir(path) : -1) != 0) { // + strlen(mount->path));))
@@ -322,10 +332,30 @@ int vfs_chdir (const char *path)
vfs_dir_t *vfs_opendir (const char *path)
{
vfs_dir_t *dir = NULL;
vfs_mount_t *mount = get_mount(path);
vfs_mount_t *mount = get_mount(path), *add_mount;
vfs_mount_ll_entry_t *ml = NULL, *mln;
if(mount && (dir = mount->vfs->fopendir(get_filename(mount, path)))) {
if(mount && (dir = mount->vfs->fopendir(get_filename(mount, path))))
dir->fs = mount->vfs;
dir->mounts = NULL;
add_mount = root.next;
do {
if(add_mount != mount && !strncmp(add_mount->path, path, strlen(path))) {
if(!add_mount->vfs->mode.hidden && (mln = malloc(sizeof(vfs_mount_ll_entry_t)))) {
mln->mount = add_mount;
mln->next = NULL;
if(dir->mounts == NULL)
dir->mounts = ml = mln;
else {
ml->next = mln;
ml = mln;
}
}
}
} while((add_mount = add_mount->next));
}
return dir;
}
@@ -338,6 +368,21 @@ vfs_dirent_t *vfs_readdir (vfs_dir_t *dir)
((vfs_t *)dir->fs)->readdir(dir, &dirent);
if(*dirent.name == '\0' && dir->mounts) {
char *s;
vfs_mount_ll_entry_t *ml = dir->mounts;
strcpy(dirent.name, ml->mount->path + 1);
if((s = strrchr(dirent.name, '/')))
*s = '\0';
dirent.st_mode = ml->mount->vfs->mode;
dirent.st_mode.directory = true;
dir->mounts = dir->mounts->next;
free(ml);
}
return *dirent.name == '\0' ? NULL : &dirent;
}
@@ -345,29 +390,56 @@ void vfs_closedir (vfs_dir_t *dir)
{
vfs_errno = 0;
while(dir->mounts) {
vfs_mount_ll_entry_t *ml = dir->mounts;
dir->mounts = dir->mounts->next;
free(ml);
}
((vfs_t *)dir->fs)->fclosedir(dir);
}
char *vfs_getcwd (char *buf, size_t len)
{
char *cwd = root.vfs->fgetcwd(NULL, len);
char *cwds = cwdmount->vfs->fgetcwd ? cwdmount->vfs->fgetcwd(NULL, len) : cwd;
vfs_errno = 0;
if(buf == NULL)
buf = (char *)malloc(strlen(cwd) + 1);
buf = (char *)malloc(strlen(cwds) + 1);
if(buf)
strcpy(buf, cwd);
strcpy(buf, cwds);
return buf ? buf : cwd;
return buf ? buf : cwds;
}
int vfs_stat (const char *filename, vfs_stat_t *st)
{
vfs_mount_t *mount = get_mount(filename);
return mount ? mount->vfs->fstat(get_filename(mount, filename), st) : -1;
int ret = mount ? mount->vfs->fstat(get_filename(mount, filename), st) : -1;
if(ret == -1 && strchr(filename, '/') == NULL && !strcmp("/", cwd)) {
strcat(cwd, filename);
mount = get_mount(cwd);
cwd[1] = '\0';
if(mount) {
st->st_size = 0;
st->st_mode.mode = 0;
st->st_mode.directory = true;
#if defined(ESP_PLATFORM)
st->st_mtim = (time_t)0;
#else
st->st_mtime = (time_t)0;
#endif
ret = 0;
}
}
return ret;
}
int vfs_utime (const char *filename, struct tm *modified)

18
vfs.h
View File

@@ -80,10 +80,8 @@ typedef struct {
uint8_t handle; // first byte of file handle structure
} vfs_file_t;
typedef struct {
const void *fs;
uint8_t handle;
} vfs_dir_t;
struct vfs_dir;
typedef struct vfs_dir vfs_dir_t;
typedef struct {
char name[255];
@@ -159,6 +157,12 @@ typedef struct vfs_mount
struct vfs_mount *next;
} vfs_mount_t;
typedef struct vfs_mount_ll_entry
{
vfs_mount_t *mount;
struct vfs_mount_ll_entry *next;
} vfs_mount_ll_entry_t;
typedef struct {
vfs_mount_t *mount;
} vfs_drives_t;
@@ -171,6 +175,12 @@ typedef struct {
const void *fs;
} vfs_drive_t;
struct vfs_dir {
const void *fs;
vfs_mount_ll_entry_t *mounts;
uint8_t handle; // must be last!
};
extern int vfs_errno;
char *vfs_fixpath (char *path);