mirror of
https://github.com/grblHAL/core.git
synced 2026-02-06 00:52:35 +08:00
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:
21
changelog.md
21
changelog.md
@@ -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:
|
||||
|
||||
@@ -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"
|
||||
|
||||
2
gcode.c
2
gcode.c
@@ -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
2
grbl.h
@@ -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"
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
3
report.c
3
report.c
@@ -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];
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
2
stream.h
2
stream.h
@@ -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);
|
||||
|
||||
15
system.h
15
system.h
@@ -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
90
vfs.c
@@ -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
18
vfs.h
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user