Internal changes that may affect developers, see the changelog for details.

This commit is contained in:
Terje Io
2024-01-26 11:14:39 +01:00
parent f0ef77435e
commit b200199612
19 changed files with 269 additions and 146 deletions

View File

@@ -1,3 +1,25 @@
## grblHAL changelog
<a name="20240125"/>Build 20240125
Core, for developers:
* Simplified [regstration](http://svn.io-engineering.com/grblHAL/html/system_8c.html#a480cedc4c3840cfebb4d5fdce898dd3b) of additional system commands, deprecated original method.
* Added [improved call](http://svn.io-engineering.com/grblHAL/html/protocol_8c.html#a869dff1f8d0b3965578eb3e6a94729c1) for registering single run tasks to be executed in the foreground, deprecated [original call](http://svn.io-engineering.com/grblHAL/html/protocol_8c.html#a78fa9a198df36192acec52d28d760a6c).
* Moved VFS events from `grbl.*` to [vfs.*](http://svn.io-engineering.com/grblHAL/html/vfs_8h.html#ab87cc94daec156bea722f9f05d7eeb0c).
Drivers:
* Most: updated to use new method for registering single run tasks. Updated ioports code for improved core compliance.
* LPC176x: fix for [issue #44](https://github.com/grblHAL/LPC176x/issues/44), non-existing probe pin.
Plugins:
* Many: updated to use new method for registering single run tasks. Some bug fixes.
---
<a name="20240123"/>Build 20240123
Core:
@@ -39,8 +61,6 @@ These are based on original work by @wakass and might be published by him if a P
---
## grblHAL changelog
<a name="20240118"/>Build 20240118
Core:

View File

@@ -3,7 +3,7 @@
Part of grblHAL
Copyright (c) 2020-2023 Terje Io
Copyright (c) 2020-2024 Terje Io
Grbl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -116,8 +116,6 @@ typedef bool (*on_spindle_select_ptr)(spindle_ptrs_t *spindle);
typedef void (*on_spindle_selected_ptr)(spindle_ptrs_t *spindle);
typedef void (*on_gcode_message_ptr)(char *msg);
typedef void (*on_rt_reports_added_ptr)(report_tracking_flags_t report);
typedef void (*on_vfs_mount_ptr)(const char *path, const vfs_t *fs);
typedef void (*on_vfs_unmount_ptr)(const char *path);
typedef const char *(*on_set_axis_setting_unit_ptr)(setting_id_t setting_id, uint_fast8_t axis_idx);
typedef status_code_t (*on_file_open_ptr)(const char *fname, vfs_file_t *handle, bool stream);
typedef status_code_t (*on_unknown_sys_command_ptr)(sys_state_t state, char *line); // return Status_Unhandled.
@@ -155,7 +153,7 @@ typedef struct {
on_execute_realtime_ptr on_execute_delay;
on_unknown_accessory_override_ptr on_unknown_accessory_override;
on_report_options_ptr on_report_options;
on_report_command_help_ptr on_report_command_help;
on_report_command_help_ptr on_report_command_help; //!< Deprecated, use system_register_commands() to register new commands.
on_rt_reports_added_ptr on_rt_reports_added;
on_global_settings_restore_ptr on_global_settings_restore;
on_setting_get_description_ptr on_setting_get_description;
@@ -166,7 +164,7 @@ typedef struct {
on_unknown_feedback_message_ptr on_unknown_feedback_message;
on_unknown_realtime_cmd_ptr on_unknown_realtime_cmd;
on_unknown_sys_command_ptr on_unknown_sys_command; //!< return Status_Unhandled if not handled.
on_get_commands_ptr on_get_commands;
on_get_commands_ptr on_get_commands; //!< Deprecated, use system_register_commands() to register new commands.
on_user_command_ptr on_user_command;
on_stream_changed_ptr on_stream_changed;
on_homing_rate_set_ptr on_homing_rate_set;
@@ -185,8 +183,6 @@ typedef struct {
on_spindle_select_ptr on_spindle_select; //!< Called before spindle is selected, hook in HAL overrides here
on_spindle_selected_ptr on_spindle_selected; //!< Called when spindle is selected, do not change HAL pointers here!
on_reset_ptr on_reset; //!< Called from interrupt context.
on_vfs_mount_ptr on_vfs_mount; //!< Called when a file system is mounted.
on_vfs_unmount_ptr on_vfs_unmount; //!< Called when a file system is unmounted.
on_file_open_ptr on_file_open; //!< Called when a file is opened for streaming.
// core entry points - set up by core before driver_init() is called.
home_machine_ptr home_machine;

25
gcode.c
View File

@@ -3,7 +3,7 @@
Part of grblHAL
Copyright (c) 2017-2023 Terje Io
Copyright (c) 2017-2024 Terje Io
Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
Copyright (c) 2009-2011 Simen Svale Skogsrud
@@ -420,15 +420,18 @@ static status_code_t init_sync_motion (plan_line_data_t *pl_data, float pitch)
}
// Output and free previously allocated message
static void output_message (char *message)
void gc_output_message (char *message)
{
if(grbl.on_gcode_message)
grbl.on_gcode_message(message);
if(message) {
if(*message)
report_message(message, Message_Plain);
if(grbl.on_gcode_message)
grbl.on_gcode_message(message);
free(message);
if(*message)
report_message(message, Message_Plain);
free(message);
}
}
#if NGC_EXPRESSIONS_ENABLE
@@ -747,7 +750,7 @@ status_code_t gc_execute_block (char *block)
if(block[0] == '\0') {
if(message)
output_message(message);
gc_output_message(message);
return Status_OK;
}
@@ -760,7 +763,7 @@ status_code_t gc_execute_block (char *block)
if (block[0] == CMD_PROGRAM_DEMARCATION && block[1] == '\0') {
gc_state.file_run = !gc_state.file_run;
if(message)
output_message(message);
gc_output_message(message);
return Status_OK;
}
@@ -3109,7 +3112,7 @@ status_code_t gc_execute_block (char *block)
protocol_buffer_synchronize();
if(plan_data.message) {
output_message(plan_data.message);
gc_output_message(plan_data.message);
plan_data.message = NULL;
}
@@ -3535,7 +3538,7 @@ status_code_t gc_execute_block (char *block)
}
if(plan_data.message)
output_message(plan_data.message);
gc_output_message(plan_data.message);
// [21. Program flow ]:
// M0,M1,M2,M30,M60: Perform non-running program flow actions. During a program pause, the buffer may

2
grbl.h
View File

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

View File

@@ -97,7 +97,7 @@ static bool dummy_irq_claim (irq_type_t irq, uint_fast8_t id, irq_callback_ptr c
return false;
}
static void report_driver_error (sys_state_t state)
static void report_driver_error (void *data)
{
char msg[40];
@@ -266,7 +266,7 @@ int grbl_enter (void)
if(driver.ok != 0xFF) {
sys.alarm = Alarm_SelftestFailed;
protocol_enqueue_rt_command(report_driver_error);
protocol_enqueue_foreground_task(report_driver_error, NULL);
}
hal.stepper.enable(settings.steppers.deenergize);

View File

@@ -514,7 +514,7 @@ static void delta_limits_set_machine_positions (axes_signals_t cycle)
*/
}
static void delta_go_home (sys_state_t state)
static void delta_go_home (void *data)
{
plan_line_data_t plan_data;
@@ -542,7 +542,7 @@ static void delta_homing_complete (bool success)
: machine.home_z - settings.homing.pulloff;
if(machine.cfg.flags.home_to_cuboid_top)
protocol_enqueue_rt_command(delta_go_home);
protocol_enqueue_foreground_task(delta_go_home);
}
if(on_homing_completed)

View File

@@ -3,7 +3,7 @@
Part of grblHAL
Copyright (c) 2017-2023 Terje Io
Copyright (c) 2017-2024 Terje Io
Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC
Copyright (c) 2009-2011 Simen Svale Skogsrud
@@ -212,11 +212,6 @@ static nvs_transfer_result_t memcpy_from_ram (uint8_t *destination, uint32_t sou
return with_checksum ? (checksum == ram_get_byte(source) ? NVS_TransferResult_OK : NVS_TransferResult_Failed) : NVS_TransferResult_OK;
}
static void nvs_warning (sys_state_t state)
{
report_message("Not enough heap for NVS buffer!", Message_Warning);
}
// Try to allocate RAM from heap for buffer/emulation.
bool nvs_buffer_alloc (void)
{
@@ -273,7 +268,7 @@ bool nvs_buffer_init (void)
grbl.report.status_message(Status_SettingReadFail);
}
} else
protocol_enqueue_rt_command(nvs_warning);
protocol_enqueue_foreground_task(report_warning, "Not enough heap for NVS buffer!");
// Clear settings dirty flags
memset(&settings_dirty, 0, sizeof(settings_dirty_t));

View File

@@ -3,7 +3,7 @@
Part of grblHAL
Copyright (c) 2017-2023 Terje Io
Copyright (c) 2017-2024 Terje Io
Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
Copyright (c) 2009-2011 Simen Svale Skogsrud
Copyright (c) 2011 Jens Geisler
@@ -217,11 +217,6 @@ inline static void plan_reset_buffer (void)
block_buffer_planned = block_buffer_tail; // = block_buffer_tail
}
static void planner_warning (sys_state_t state)
{
report_message("Planner buffer size was reduced!", Message_Plain);
}
uint_fast16_t plan_get_buffer_size (void)
{
return block_buffer_size;
@@ -242,7 +237,7 @@ bool plan_reset (void)
}
if(block_buffer_size != settings.planner_buffer_blocks)
protocol_enqueue_rt_command(planner_warning);
protocol_enqueue_foreground_task(report_plain, "Planner buffer size was reduced!");
if(block_buffer == NULL)
return false;
@@ -402,7 +397,6 @@ bool plan_buffer_line (float *target, plan_line_data_t *pl_data)
block->line_number = pl_data->line_number;
block->output_commands = pl_data->output_commands;
block->message = pl_data->message;
pl_data->message = NULL;
// Copy position data based on type of motion being planned.
memcpy(position_steps, block->condition.system_motion ? sys.position : pl.position, sizeof(position_steps));
@@ -455,13 +449,15 @@ bool plan_buffer_line (float *target, plan_line_data_t *pl_data)
block->spindle.css->delta_rpm = block->spindle.css->target_rpm - block->spindle.rpm;
}
// Bail if this is a zero-length block. Highly unlikely to occur.
if (block->step_event_count == 0)
return false;
pl_data->message = NULL; // Indicate message is already queued for display on execution
pl_data->output_commands = NULL; // Indicate commands are already queued for execution
// Bail if this is a zero-length block. Highly unlikely to occur.
if(block->step_event_count == 0) {
plan_cleanup(block); // TODO: output message and execute output_commands?
return false;
}
#if N_AXIS > 3 && ROTARY_FIX
// NIST RS274 (2.1.2.5 A & 2.1.2.6) states that G94 linear motion with simultaneous angular motion

View File

@@ -3,7 +3,7 @@
Part of grblHAL
Copyright (c) 2017-2023 Terje Io
Copyright (c) 2017-2024 Terje Io
Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
Copyright (c) 2009-2011 Simen Svale Skogsrud
@@ -49,10 +49,18 @@ typedef union {
};
} line_flags_t;
typedef struct {
void *data;
union {
foreground_task_ptr fn;
on_execute_realtime_ptr fn_deprecated;
};
} delayed_task_t;
typedef struct {
volatile uint_fast8_t head;
volatile uint_fast8_t tail;
on_execute_realtime_ptr fn[RT_QUEUE_SIZE];
delayed_task_t task[RT_QUEUE_SIZE];
} realtime_queue_t;
static uint_fast16_t char_counter = 0;
@@ -190,7 +198,7 @@ bool protocol_main_loop (void)
if(realtime_queue.head != realtime_queue.tail)
system_set_exec_state_flag(EXEC_RT_COMMAND); // execute any boot up commands
sys.cold_start = false;
} else
} else // TODO: if flushing entries from the queue that has allocated data associated then these will be orphaned/leaked.
memset(&realtime_queue, 0, sizeof(realtime_queue_t));
// ---------------------------------------------------------------------------------
@@ -1010,31 +1018,54 @@ ISR_CODE bool ISR_FUNC(protocol_enqueue_realtime_command)(char c)
return drop;
}
// Enqueue a function to be called once by the
// foreground process, typically enqueued from an interrupt handler.
ISR_CODE bool ISR_FUNC(protocol_enqueue_rt_command)(on_execute_realtime_ptr fn)
static const uint32_t dummy_data = 0;
/*! \brief Enqueue a function to be called once by the foreground process.
\param fn pointer to a \a foreground_task_ptr type of function.
\param data pointer to data to be passed to the callee.
\returns true if successful, false otherwise.
*/
bool protocol_enqueue_foreground_task (foreground_task_ptr fn, void *data)
{
bool ok;
uint_fast8_t bptr = (realtime_queue.head + 1) & (RT_QUEUE_SIZE - 1); // Get next head pointer
if((ok = bptr != realtime_queue.tail)) { // If not buffer full
realtime_queue.fn[realtime_queue.head] = fn; // add function pointer to buffer,
realtime_queue.head = bptr; // update pointer and
system_set_exec_state_flag(EXEC_RT_COMMAND); // flag it for execute
if((ok = bptr != realtime_queue.tail)) { // If not buffer full
realtime_queue.task[realtime_queue.head].data = data;
realtime_queue.task[realtime_queue.head].fn = fn; // add function pointer to buffer,
realtime_queue.head = bptr; // update pointer and
system_set_exec_state_flag(EXEC_RT_COMMAND); // flag it for execute
}
return ok;
}
/*! \brief Enqueue a function to be called once by the foreground process.
\param fn pointer to a \a on_execute_realtime_ptr type of function.
\returns true if successful, false otherwise.
__NOTE:__ Deprecated, use protocol_enqueue_foreground_task instead.
*/
ISR_CODE bool ISR_FUNC(protocol_enqueue_rt_command)(on_execute_realtime_ptr fn)
{
return protocol_enqueue_foreground_task((foreground_task_ptr)fn, (void *)&dummy_data);
}
// Execute enqueued functions.
static void protocol_execute_rt_commands (void)
{
while(realtime_queue.tail != realtime_queue.head) {
uint_fast8_t bptr = realtime_queue.tail;
on_execute_realtime_ptr call;
if((call = realtime_queue.fn[bptr])) {
realtime_queue.fn[bptr] = NULL;
call(state_get());
if(realtime_queue.task[bptr].fn) {
if(realtime_queue.task[bptr].data == (void *)&dummy_data) {
on_execute_realtime_ptr call = realtime_queue.task[bptr].fn_deprecated;
realtime_queue.task[bptr].fn = NULL;
call(state_get());
} else {
foreground_task_ptr call = realtime_queue.task[bptr].fn;
realtime_queue.task[bptr].fn = NULL;
call(realtime_queue.task[bptr].data);
}
}
realtime_queue.tail = (bptr + 1) & (RT_QUEUE_SIZE - 1);
}

View File

@@ -33,6 +33,8 @@
#define LINE_BUFFER_SIZE 257 // 256 characters plus terminator
#endif
typedef void (*foreground_task_ptr)(void *data);
// Starts Grbl main loop. It handles all incoming characters from the input stream and executes
// them as they complete. It is also responsible for finishing the initialization procedures.
bool protocol_main_loop (void);
@@ -42,6 +44,7 @@ bool protocol_execute_realtime (void);
bool protocol_exec_rt_system (void);
void protocol_execute_noop (uint_fast16_t state);
bool protocol_enqueue_rt_command (on_execute_realtime_ptr fn);
bool protocol_enqueue_foreground_task (foreground_task_ptr fn, void *data);
// Executes the auto cycle feature, if enabled.
void protocol_auto_cycle_start (void);

View File

@@ -272,6 +272,24 @@ void report_message (const char *msg, message_type_t type)
hal.stream.write("]" ASCII_EOL);
}
// Message helper to be run as foreground task
void report_plain (void *message)
{
report_message((char *)message, Message_Plain);
}
// Message helper to be run as foreground task
void report_info (void *message)
{
report_message((char *)message, Message_Info);
}
// Message helper to be run as foreground task
void report_warning (void *message)
{
report_message((char *)message, Message_Warning);
}
// Prints feedback messages. This serves as a centralized method to provide additional
// user feedback for things that are not of the status/alarm message protocol. These are
// messages such as setup warnings, switch toggling, and how to exit alarms.

View File

@@ -3,7 +3,7 @@
Part of grblHAL
Copyright (c) 2018-2023 Terje Io
Copyright (c) 2018-2024 Terje Io
Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC
Grbl is free software: you can redistribute it and/or modify
@@ -40,6 +40,15 @@ void report_init_fns (void);
// Prints feedback message, typically from gcode.
void report_message (const char *msg, message_type_t type);
// Message helper to be run as foreground task.
void report_plain (void *message);
// Message helper to be run as foreground task.
void report_info (void *message);
// Message helper to be run as foreground task.
void report_warning (void *message);
// Prints Grbl help.
status_code_t report_help (char *args);

View File

@@ -3,7 +3,7 @@
Part of grblHAL
Copyright (c) 2016-2023 Terje Io
Copyright (c) 2016-2024 Terje Io
Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
Copyright (c) 2009-2011 Simen Svale Skogsrud
@@ -84,9 +84,6 @@ typedef struct {
static amass_t amass;
#endif
// Message to be output by foreground process
static char *message = NULL; // TODO: do we need a queue for this?
// Used for blocking new segments being added to the seqment buffer until deceleration starts
// after probe signal has been asserted.
static volatile bool probe_asserted = false;
@@ -140,6 +137,7 @@ typedef struct {
static st_prep_t prep;
extern void gc_output_message (char *message);
/* BLOCK VELOCITY PROFILE DEFINITION
__________________________
@@ -181,22 +179,6 @@ static st_prep_t prep;
//
// Output message in sync with motion, called by foreground process.
static void output_message (sys_state_t state)
{
if(message) {
if(grbl.on_gcode_message)
grbl.on_gcode_message(message);
if(*message)
report_message(message, Message_Plain);
free(message);
message = NULL;
}
}
// Callback from delay to deenergize steppers after movement, might been cancelled
void st_deenergize (void)
{
@@ -351,11 +333,8 @@ ISR_CODE void ISR_FUNC(stepper_driver_interrupt_handler)(void)
// Enqueue any message to be printed (by foreground process)
if(st.exec_block->message) {
if(message == NULL) {
message = st.exec_block->message;
protocol_enqueue_rt_command(output_message);
} else
free(st.exec_block->message); //
if(!protocol_enqueue_foreground_task((foreground_task_ptr)gc_output_message, st.exec_block->message))
free(st.exec_block->message);
st.exec_block->message = NULL;
}
@@ -559,11 +538,6 @@ void st_reset (void)
if(hal.probe.configure)
hal.probe.configure(false, false);
if(message) {
free(message);
message = NULL;
}
// Initialize stepper driver idle state, clear step and direction port pins.
st_go_idle();
// hal.stepper.go_idle(true);

View File

@@ -605,11 +605,6 @@ const io_stream_t *stream_null_init (uint32_t baud_rate)
static stream_write_ptr dbg_write = NULL;
static void debug_stream_warning (uint_fast16_t state)
{
report_message("Failed to initialize debug stream!", Message_Warning);
}
void debug_write (const char *s)
{
if(dbg_write) {
@@ -654,7 +649,7 @@ bool debug_stream_init (void)
if(stream_enumerate_streams(debug_claim_stream))
hal.debug.write(ASCII_EOL "UART debug active:" ASCII_EOL);
else
protocol_enqueue_rt_command(debug_stream_warning);
protocol_enqueue_foreground_task(report_warning, "Failed to initialize debug stream!");
return hal.debug.write == debug_write;
}

View File

@@ -923,36 +923,65 @@ PROGMEM static const sys_command_t sys_commands[] = {
#endif
};
void system_output_help (const sys_command_t *commands, uint32_t num_commands)
static sys_commands_t core_commands = {
.n_commands = sizeof(sys_commands) / sizeof(sys_command_t),
.commands = sys_commands,
};
static sys_commands_t *commands_root = &core_commands;
void system_register_commands (sys_commands_t *commands)
{
commands->next = commands_root;
commands_root = commands;
}
void _system_output_help (sys_commands_t *commands, bool traverse)
{
const char *help;
uint_fast8_t idx;
for(idx = 0; idx < num_commands; idx++) {
while(commands) {
for(idx = 0; idx < commands->n_commands; idx++) {
if(commands[idx].help.str) {
if(commands->commands[idx].help.str) {
if(commands[idx].flags.help_fn)
help = commands[idx].help.fn(commands[idx].command);
else
help = commands[idx].help.str;
if(commands->commands[idx].flags.help_fn)
help = commands->commands[idx].help.fn(commands->commands[idx].command);
else
help = commands->commands[idx].help.str;
if(help) {
if(*help != '$') {
hal.stream.write_char('$');
hal.stream.write(commands[idx].command);
hal.stream.write(" - ");
if(help) {
if(*help != '$') {
hal.stream.write_char('$');
hal.stream.write(commands->commands[idx].command);
hal.stream.write(" - ");
}
hal.stream.write(help);
hal.stream.write("." ASCII_EOL);
}
hal.stream.write(help);
hal.stream.write("." ASCII_EOL);
}
}
commands = traverse && commands->next != &core_commands ? commands->next : NULL;
}
}
// Deprecated, to be removed.
void system_output_help (const sys_command_t *commands, uint32_t num_commands)
{
sys_commands_t cmd = {
.commands = commands,
.n_commands = num_commands
};
_system_output_help(&cmd, false);
}
void system_command_help (void)
{
system_output_help(sys_commands, sizeof(sys_commands) / sizeof(sys_command_t));
_system_output_help(&core_commands, false);
if(commands_root != &core_commands)
_system_output_help(commands_root, true);
}
/*! \brief Directs and executes one line of input from protocol_process.
@@ -981,12 +1010,6 @@ status_code_t system_execute_line (char *line)
return Status_OK;
}
sys_commands_t base = {
.n_commands = sizeof(sys_commands) / sizeof(sys_command_t),
.commands = sys_commands,
.on_get_commands = grbl.on_get_commands
};
status_code_t retval = Status_Unhandled;
char c, *s1, *s2;
@@ -1014,7 +1037,7 @@ status_code_t system_execute_line (char *line)
*args++ = '\0';
uint_fast8_t idx;
sys_commands_t *cmd = &base;
sys_commands_t *cmd = commands_root;
do {
for(idx = 0; idx < cmd->n_commands; idx++) {
if(!strcmp(line, cmd->commands[idx].command)) {
@@ -1027,9 +1050,29 @@ status_code_t system_execute_line (char *line)
}
}
}
cmd = retval == Status_Unhandled && cmd->on_get_commands ? cmd->on_get_commands() : NULL;
cmd = retval == Status_Unhandled ? cmd->next : NULL;
} while(cmd);
// deprecated, to be removed
if(retval == Status_Unhandled && (cmd = grbl.on_get_commands ? grbl.on_get_commands() : NULL)) {
do {
for(idx = 0; idx < cmd->n_commands; idx++) {
if(!strcmp(line, cmd->commands[idx].command)) {
if(sys.blocking_event && !cmd->commands[idx].flags.allow_blocking) {
retval = Status_NotAllowedCriticalEvent;
break;
} else if(!cmd->commands[idx].flags.noargs || args == NULL) {
if((retval = cmd->commands[idx].execute(state_get(), args)) != Status_Unhandled)
break;
}
}
}
cmd = retval == Status_Unhandled && cmd->on_get_commands ? cmd->on_get_commands() : NULL;
} while(cmd);
}
// end of to be removed
// Let user code have a peek at system commands before check for global setting
if(retval == Status_Unhandled && grbl.on_unknown_sys_command) {
if(args)

View File

@@ -338,7 +338,8 @@ typedef struct
typedef struct sys_commands_str {
const uint8_t n_commands;
const sys_command_t *commands;
struct sys_commands_str *(*on_get_commands)(void);
struct sys_commands_str *next;
struct sys_commands_str *(*on_get_commands)(void); //!< deprecated, to be removed
} sys_commands_t;
extern system_t sys;
@@ -352,6 +353,7 @@ void system_raise_alarm (alarm_code_t alarm);
void system_init_switches (void);
void system_command_help (void);
void system_output_help (const sys_command_t *commands, uint32_t num_commands);
void system_register_commands (sys_commands_t *commands);
void system_add_rt_report (report_tracking_t report);
report_tracking_flags_t system_get_rt_report_flags (void);

View File

@@ -5,7 +5,7 @@
Part of grblHAL
Copyright (c) 2020-2023 Terje Io
Copyright (c) 2020-2024 Terje Io
Grbl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -147,14 +147,14 @@ static bool restore (void)
// Issue warning on cycle start event if touch off by $TPW is pending.
// Used in Manual and Manual_G59_3 modes ($341=1 or $341=2). Called from the foreground process.
static void execute_warning (sys_state_t state)
static void execute_warning (void *data)
{
grbl.report.feedback_message(Message_ExecuteTPW);
}
// Execute restore position after touch off (on cycle start event).
// Used in Manual and Manual_G59_3 modes ($341=1 or $341=2). Called from the foreground process.
static void execute_restore (sys_state_t state)
static void execute_restore (void *data)
{
// Get current position.
system_convert_array_steps_to_mpos(target.values, sys.position);
@@ -171,7 +171,7 @@ static void execute_restore (sys_state_t state)
// Execute touch off on cycle start event from @ G59.3 position.
// Used in SemiAutomatic mode ($341=3) only. Called from the foreground process.
static void execute_probe (sys_state_t state)
static void execute_probe (void *data)
{
#if COMPATIBILITY_LEVEL <= 1
bool ok;
@@ -245,9 +245,9 @@ ISR_CODE static void ISR_FUNC(trap_control_cycle_start)(control_signals_t signal
if(signals.cycle_start) {
if(!execute_posted) {
if(!block_cycle_start)
execute_posted = protocol_enqueue_rt_command(settings.tool_change.mode == ToolChange_SemiAutomatic ? execute_probe : execute_restore);
execute_posted = protocol_enqueue_foreground_task(settings.tool_change.mode == ToolChange_SemiAutomatic ? execute_probe : execute_restore, NULL);
else
protocol_enqueue_rt_command(execute_warning);
protocol_enqueue_foreground_task(execute_warning, NULL);
}
signals.cycle_start = Off;
} else
@@ -265,9 +265,9 @@ ISR_CODE static bool ISR_FUNC(trap_stream_cycle_start)(char c)
if((drop = (c == CMD_CYCLE_START || c == CMD_CYCLE_START_LEGACY))) {
if(!execute_posted) {
if(!block_cycle_start)
execute_posted = protocol_enqueue_rt_command(settings.tool_change.mode == ToolChange_SemiAutomatic ? execute_probe : execute_restore);
execute_posted = protocol_enqueue_foreground_task(settings.tool_change.mode == ToolChange_SemiAutomatic ? execute_probe : execute_restore, NULL);
else
protocol_enqueue_rt_command(execute_warning);
protocol_enqueue_foreground_task(execute_warning, NULL);
}
} else
drop = enqueue_realtime_command(c);

63
vfs.c
View File

@@ -5,7 +5,7 @@
Part of grblHAL
Copyright (c) 2022-2023 Terje Io
Copyright (c) 2022-2024 Terje Io
Grbl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -130,6 +130,7 @@ static vfs_mount_t *cwdmount = &root;
static char cwd[100] = "/";
int vfs_errno = 0;
vfs_events_t vfs = {0};
// Strip trailing directory separator, FatFS dont't like it (WinSCP adds it)
char *vfs_fixpath (char *path)
@@ -210,6 +211,8 @@ void vfs_close (vfs_file_t *file)
vfs_errno = 0;
((vfs_t *)(file->fs))->fclose(file);
// TODO: somehow raise vfs.on_fs_changed event when a file openened for writing is closed
}
size_t vfs_read (void *buffer, size_t size, size_t count, vfs_file_t *file)
@@ -261,30 +264,54 @@ bool vfs_eof (vfs_file_t *file)
int vfs_rename (const char *from, const char *to)
{
int ret;
vfs_mount_t *mount_from = get_mount(from), *mount_to = get_mount(to);
return mount_from == mount_to ? mount_from->vfs->frename(get_filename(mount_from, from), get_filename(mount_to, to)) : -1;
if((ret = mount_from == mount_to ? mount_from->vfs->frename(get_filename(mount_from, from), get_filename(mount_to, to)) : -1) != -1 &&
vfs.on_fs_changed && !mount_from->mode.hidden) {
vfs.on_fs_changed(mount_from->vfs);
if(mount_from != mount_to && !mount_to->mode.hidden)
vfs.on_fs_changed(mount_to->vfs);
}
return ret;
}
int vfs_unlink (const char *filename)
{
int ret;
vfs_mount_t *mount = get_mount(filename); // TODO: test for dir?
return mount ? mount->vfs->funlink(get_filename(mount, filename)) : -1;
if((ret = mount ? mount->vfs->funlink(get_filename(mount, filename)) : -1) != -1 && vfs.on_fs_changed && !mount->mode.hidden)
vfs.on_fs_changed(mount->vfs);
return ret;
}
int vfs_mkdir (const char *path)
{
int ret;
vfs_mount_t *mount = get_mount(path);
return mount ? mount->vfs->fmkdir(get_filename(mount, path)) : -1;
if((ret = mount ? mount->vfs->fmkdir(get_filename(mount, path)) : -1) != -1 && vfs.on_fs_changed && !mount->mode.hidden)
vfs.on_fs_changed(mount->vfs);
return ret;
}
int vfs_rmdir (const char *path)
{
int ret;
vfs_mount_t *mount = get_mount(path);
return mount ? mount->vfs->frmdir(get_filename(mount, path)) : -1;
if((ret = mount ? mount->vfs->frmdir(get_filename(mount, path)) : -1) != -1 && vfs.on_fs_changed && !mount->mode.hidden)
vfs.on_fs_changed(mount->vfs);
return ret;
}
int vfs_chdir (const char *path)
@@ -460,31 +487,31 @@ vfs_free_t *vfs_fgetfree (const char *path)
bool vfs_mount (const char *path, const vfs_t *fs, vfs_st_mode_t mode)
{
vfs_mount_t *vfs;
vfs_mount_t *mount;
if(!strcmp(path, "/")) {
root.vfs = fs;
root.mode = mode;
} else if((vfs = (vfs_mount_t *)malloc(sizeof(vfs_mount_t)))) {
} else if((mount = (vfs_mount_t *)malloc(sizeof(vfs_mount_t)))) {
strcpy(vfs->path, path);
if(vfs->path[strlen(path) - 1] != '/')
strcat(vfs->path, "/");
strcpy(mount->path, path);
if(mount->path[strlen(path) - 1] != '/')
strcat(mount->path, "/");
vfs->vfs = fs;
vfs->mode = mode;
vfs->next = NULL;
mount->vfs = fs;
mount->mode = mode;
mount->next = NULL;
vfs_mount_t *mount = &root;
while(mount->next)
mount = mount->next;
mount->next = vfs;
mount->next = mount;
}
if(fs && grbl.on_vfs_mount)
grbl.on_vfs_mount(path, fs);
if(fs && vfs.on_mount)
vfs.on_mount(path, fs);
return fs != NULL;
}
@@ -513,8 +540,8 @@ bool vfs_unmount (const char *path)
}
}
if(grbl.on_vfs_unmount)
grbl.on_vfs_unmount(path);
if(vfs.on_unmount)
vfs.on_unmount(path);
return true;
}

13
vfs.h
View File

@@ -5,7 +5,7 @@
Part of grblHAL
Copyright (c) 2022-2023 Terje Io
Copyright (c) 2022-2024 Terje Io
Grbl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -152,6 +152,16 @@ typedef struct
vfs_format_ptr format;
} vfs_t;
typedef void (*on_vfs_changed_ptr)(const vfs_t *fs);
typedef void (*on_vfs_mount_ptr)(const char *path, const vfs_t *fs);
typedef void (*on_vfs_unmount_ptr)(const char *path);
typedef struct {
on_vfs_mount_ptr on_mount; //!< Called when a file system is mounted.
on_vfs_unmount_ptr on_unmount; //!< Called when a file system is unmounted.
on_vfs_changed_ptr on_fs_changed; //!< Called when file system content is changed.
} vfs_events_t;
typedef struct vfs_mount
{
char path[64];
@@ -185,6 +195,7 @@ struct vfs_dir {
};
extern int vfs_errno;
extern vfs_events_t vfs;
char *vfs_fixpath (char *path);