mirror of
https://github.com/grblHAL/core.git
synced 2026-03-23 11:32:44 +08:00
Improved handling of current working directory (CWD).
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
## grblHAL ##
|
## grblHAL ##
|
||||||
|
|
||||||
Latest build date is 20260308, see the [changelog](changelog.md) for details.
|
Latest build date is 20260311, see the [changelog](changelog.md) for details.
|
||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
> A settings reset will be performed on an update of builds prior to 20241208. Backup and restore of settings is recommended.
|
> A settings reset will be performed on an update of builds prior to 20241208. Backup and restore of settings is recommended.
|
||||||
@@ -89,4 +89,4 @@ G/M-codes not supported by [legacy Grbl](https://github.com/gnea/grbl/wiki) are
|
|||||||
Some [plugins](https://github.com/grblHAL/plugins) implements additional M-codes.
|
Some [plugins](https://github.com/grblHAL/plugins) implements additional M-codes.
|
||||||
|
|
||||||
---
|
---
|
||||||
20260218
|
20260311
|
||||||
|
|||||||
21
changelog.md
21
changelog.md
@@ -1,5 +1,26 @@
|
|||||||
## grblHAL changelog
|
## grblHAL changelog
|
||||||
|
|
||||||
|
<a name="20260311">Build 20260311
|
||||||
|
|
||||||
|
Core:
|
||||||
|
|
||||||
|
* Improved handling of current working directory \(CWD\).
|
||||||
|
|
||||||
|
Drivers:
|
||||||
|
|
||||||
|
* STM32F4xx: added support for additional aux input ports. Changed IRQ priority for motor fault inputs.
|
||||||
|
|
||||||
|
Plugins:
|
||||||
|
|
||||||
|
* SD card: added `$PWD` command for outputting current working directory and `$CWD=<directory>` as an alternative to `$F=<directory>` to set current working directory.
|
||||||
|
`<directory>` can be `..` for up one level, `/` for the root directory, a single directory name or a path to a directory - either relative to CWD or absolute.
|
||||||
|
|
||||||
|
* Spindle: delayed on actions on soft reset till after reset is cleared.
|
||||||
|
|
||||||
|
* Networking, ftp: improved handling of current working directory. Note that this is not the same as maintained by the core.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
<a name="20260308">Build 20260308
|
<a name="20260308">Build 20260308
|
||||||
|
|
||||||
Core:
|
Core:
|
||||||
|
|||||||
2
grbl.h
2
grbl.h
@@ -42,7 +42,7 @@
|
|||||||
#else
|
#else
|
||||||
#define GRBL_VERSION "1.1f"
|
#define GRBL_VERSION "1.1f"
|
||||||
#endif
|
#endif
|
||||||
#define GRBL_BUILD 20260308
|
#define GRBL_BUILD 20260311
|
||||||
|
|
||||||
#define GRBL_URL "https://github.com/grblHAL"
|
#define GRBL_URL "https://github.com/grblHAL"
|
||||||
|
|
||||||
|
|||||||
170
grbllib.c
170
grbllib.c
@@ -90,13 +90,19 @@ DCRAM system_t sys; //!< System global variable structure.
|
|||||||
DCRAM grbl_t grbl;
|
DCRAM grbl_t grbl;
|
||||||
DCRAM grbl_hal_t hal;
|
DCRAM grbl_hal_t hal;
|
||||||
|
|
||||||
DCRAM static core_task_t task_pool[CORE_TASK_POOL_SIZE];
|
|
||||||
static driver_startup_t driver = { .ok = 0xFF };
|
static driver_startup_t driver = { .ok = 0xFF };
|
||||||
static core_task_t *next_task = NULL, *immediate_task = NULL, *on_booted = NULL, *systick_task = NULL, *last_freed = NULL;
|
|
||||||
static on_linestate_changed_ptr on_linestate_changed;
|
static on_linestate_changed_ptr on_linestate_changed;
|
||||||
static settings_changed_ptr hal_settings_changed;
|
static settings_changed_ptr hal_settings_changed;
|
||||||
static stepper_enable_ptr stepper_enable;
|
static stepper_enable_ptr stepper_enable;
|
||||||
|
DCRAM static struct {
|
||||||
|
volatile core_task_t *immediate; //!< Pointer to first entry of linked list of tasks to run immediately.
|
||||||
|
volatile core_task_t *delayed; //!< Pointer to first entry of linked list of delayed tasks to run, in execution order.
|
||||||
|
volatile core_task_t *systick; //!< Pointer to first entry of linked list of systick (1 ms) tasks to run.
|
||||||
|
volatile core_task_t *on_booted; //!< Pointer to first entry of linked list of tasks to run once on cold boot.
|
||||||
|
volatile core_task_t *on_reset; //!< Pointer to first entry of linked list of tasks to on soft reset.
|
||||||
|
volatile core_task_t *last_freed; //!< Pointer to last freed task.
|
||||||
|
core_task_t pool[CORE_TASK_POOL_SIZE];
|
||||||
|
} tasks;
|
||||||
#ifdef KINEMATICS_API
|
#ifdef KINEMATICS_API
|
||||||
kinematics_t kinematics;
|
kinematics_t kinematics;
|
||||||
#endif
|
#endif
|
||||||
@@ -110,8 +116,8 @@ __attribute__((always_inline)) static inline void task_free (core_task_t *task)
|
|||||||
{
|
{
|
||||||
task->fn = NULL;
|
task->fn = NULL;
|
||||||
task->next = NULL;
|
task->next = NULL;
|
||||||
if(last_freed == NULL)
|
if(tasks.last_freed == NULL)
|
||||||
last_freed = task;
|
tasks.last_freed = task;
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((always_inline)) static inline core_task_t *task_run (core_task_t *task)
|
__attribute__((always_inline)) static inline core_task_t *task_run (core_task_t *task)
|
||||||
@@ -220,14 +226,23 @@ FLASHMEM static void stepperEnable (axes_signals_t enable, bool hold)
|
|||||||
sys.steppers_enabled = /*!hold &&*/ enable.bits == AXES_BITMASK;
|
sys.steppers_enabled = /*!hold &&*/ enable.bits == AXES_BITMASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wdiscarded-qualifiers"
|
||||||
|
#endif
|
||||||
|
|
||||||
FLASHMEM static void print_pos_msg (void *data)
|
FLASHMEM static void print_pos_msg (void *data)
|
||||||
{
|
{
|
||||||
hal.stream.write("grblHAL: power on self-test (POS) failed!" ASCII_EOL);
|
hal.stream.write("grblHAL: power on self-test (POS) failed!" ASCII_EOL);
|
||||||
|
|
||||||
if(on_booted) do {
|
if(tasks.on_booted) do {
|
||||||
} while((on_booted = task_run(on_booted)));
|
} while((tasks.on_booted = task_run(tasks.on_booted)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
FLASHMEM static void onPosFailure (serial_linestate_t state)
|
FLASHMEM static void onPosFailure (serial_linestate_t state)
|
||||||
{
|
{
|
||||||
if(state.dtr) // delay a bit to let the USB stack come up
|
if(state.dtr) // delay a bit to let the USB stack come up
|
||||||
@@ -275,7 +290,7 @@ FLASHMEM int grbl_enter (void)
|
|||||||
bool looping = true;
|
bool looping = true;
|
||||||
|
|
||||||
memset(&sys, 0, sizeof(system_t));
|
memset(&sys, 0, sizeof(system_t));
|
||||||
memset(&task_pool, 0, sizeof(task_pool));
|
memset(&tasks, 0, sizeof(tasks));
|
||||||
|
|
||||||
// Clear all and set some core function pointers
|
// Clear all and set some core function pointers
|
||||||
memset(&grbl, 0, sizeof(grbl_t));
|
memset(&grbl, 0, sizeof(grbl_t));
|
||||||
@@ -354,9 +369,9 @@ FLASHMEM int grbl_enter (void)
|
|||||||
polar_init();
|
polar_init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if NVSDATA_BUFFER_ENABLE
|
#if NVSDATA_BUFFER_ENABLE
|
||||||
nvs_buffer_init();
|
nvs_buffer_init();
|
||||||
#endif
|
#endif
|
||||||
settings_init(); // Load settings from non-volatile storage
|
settings_init(); // Load settings from non-volatile storage
|
||||||
|
|
||||||
memset(sys.position, 0, sizeof(sys.position)); // Clear machine position.
|
memset(sys.position, 0, sizeof(sys.position)); // Clear machine position.
|
||||||
@@ -520,6 +535,9 @@ FLASHMEM int grbl_enter (void)
|
|||||||
if(hal.driver_cap.mpg_mode)
|
if(hal.driver_cap.mpg_mode)
|
||||||
protocol_enqueue_realtime_command(sys.mpg_mode ? CMD_STATUS_REPORT_ALL : CMD_STATUS_REPORT);
|
protocol_enqueue_realtime_command(sys.mpg_mode ? CMD_STATUS_REPORT_ALL : CMD_STATUS_REPORT);
|
||||||
|
|
||||||
|
if(tasks.on_reset)
|
||||||
|
system_set_exec_state_flag(EXEC_RT_COMMAND); // execute any on reset tasks
|
||||||
|
|
||||||
// Start main loop. Processes program inputs and executes them.
|
// Start main loop. Processes program inputs and executes them.
|
||||||
if(!(looping = protocol_main_loop()))
|
if(!(looping = protocol_main_loop()))
|
||||||
looping = hal.driver_release == NULL || hal.driver_release();
|
looping = hal.driver_release == NULL || hal.driver_release();
|
||||||
@@ -532,17 +550,22 @@ FLASHMEM int grbl_enter (void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wdiscarded-qualifiers"
|
||||||
|
#endif
|
||||||
|
|
||||||
__attribute__((always_inline)) static inline core_task_t *task_alloc (void)
|
__attribute__((always_inline)) static inline core_task_t *task_alloc (void)
|
||||||
{
|
{
|
||||||
core_task_t *task = NULL;
|
core_task_t *task = NULL;
|
||||||
uint_fast8_t idx = CORE_TASK_POOL_SIZE;
|
uint_fast8_t idx = CORE_TASK_POOL_SIZE;
|
||||||
|
|
||||||
if(last_freed) {
|
if(tasks.last_freed) {
|
||||||
task = last_freed;
|
task = tasks.last_freed;
|
||||||
last_freed = NULL;
|
tasks.last_freed = NULL;
|
||||||
} else do {
|
} else do {
|
||||||
if(task_pool[--idx].fn == NULL)
|
if(tasks.pool[--idx].fn == NULL)
|
||||||
task = &task_pool[idx];
|
task = &tasks.pool[idx];
|
||||||
} while(task == NULL && idx);
|
} while(task == NULL && idx);
|
||||||
|
|
||||||
return task;
|
return task;
|
||||||
@@ -560,11 +583,11 @@ static void task_execute (sys_state_t state)
|
|||||||
|
|
||||||
lock = true;
|
lock = true;
|
||||||
|
|
||||||
if(immediate_task && sys.driver_started) {
|
if(tasks.immediate && sys.driver_started) {
|
||||||
|
|
||||||
hal.irq_disable();
|
hal.irq_disable();
|
||||||
if((task = immediate_task))
|
if((task = tasks.immediate))
|
||||||
immediate_task = NULL;
|
tasks.immediate = NULL;
|
||||||
hal.irq_enable();
|
hal.irq_enable();
|
||||||
|
|
||||||
if(task) do {
|
if(task) do {
|
||||||
@@ -572,23 +595,23 @@ static void task_execute (sys_state_t state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t now = hal.get_elapsed_ticks();
|
uint32_t now = hal.get_elapsed_ticks();
|
||||||
if(!(now == last_ms || next_task == systick_task)) {
|
if(!(now == last_ms || tasks.delayed == tasks.systick)) {
|
||||||
|
|
||||||
last_ms = now;
|
last_ms = now;
|
||||||
|
|
||||||
if((task = systick_task)) do {
|
if((task = tasks.systick)) do {
|
||||||
task->fn(task->data);
|
task->fn(task->data);
|
||||||
} while((task = task->next));
|
} while((task = task->next));
|
||||||
|
|
||||||
while((task = next_task) && (int32_t)(task->time - now) <= 0) {
|
while((task = tasks.delayed) && (int32_t)(task->time - now) <= 0) {
|
||||||
|
|
||||||
hal.irq_disable();
|
hal.irq_disable();
|
||||||
|
|
||||||
if(task == next_task)
|
if(task == tasks.delayed)
|
||||||
next_task = task->next;
|
tasks.delayed = task->next;
|
||||||
else {
|
else {
|
||||||
core_task_t *t;
|
core_task_t *t;
|
||||||
if((t = next_task)) {
|
if((t = tasks.delayed)) {
|
||||||
while(t->next && t->next != task)
|
while(t->next && t->next != task)
|
||||||
t = t->next;
|
t = t->next;
|
||||||
if(t->next && t->next == task)
|
if(t->next && t->next == task)
|
||||||
@@ -622,13 +645,13 @@ ISR_CODE bool ISR_FUNC(task_add_delayed)(foreground_task_ptr fn, void *data, uin
|
|||||||
task->data = data;
|
task->data = data;
|
||||||
task->next = NULL;
|
task->next = NULL;
|
||||||
|
|
||||||
if(next_task == NULL)
|
if(tasks.delayed == NULL)
|
||||||
next_task = task;
|
tasks.delayed = task;
|
||||||
else if((int32_t)(task->time - next_task->time) <= 0) {
|
else if((int32_t)(task->time - tasks.delayed->time) <= 0) {
|
||||||
task->next = next_task;
|
task->next = tasks.delayed;
|
||||||
next_task = task;
|
tasks.delayed = task;
|
||||||
} else {
|
} else {
|
||||||
core_task_t *t = next_task;
|
core_task_t *t = tasks.delayed;
|
||||||
while(t) {
|
while(t) {
|
||||||
if(t->next == NULL || (int32_t)(task->time - t->next->time) < 0) {
|
if(t->next == NULL || (int32_t)(task->time - t->next->time) < 0) {
|
||||||
task->next = t->next;
|
task->next = t->next;
|
||||||
@@ -651,12 +674,12 @@ ISR_CODE void task_delete (foreground_task_ptr fn, void *data)
|
|||||||
|
|
||||||
hal.irq_disable();
|
hal.irq_disable();
|
||||||
|
|
||||||
if((task = next_task)) do {
|
if((task = tasks.delayed)) do {
|
||||||
if(fn == task->fn && (data == NULL || data == task->data)) {
|
if(fn == task->fn && (data == NULL || data == task->data)) {
|
||||||
if(prev)
|
if(prev)
|
||||||
prev->next = task->next;
|
prev->next = task->next;
|
||||||
else
|
else
|
||||||
next_task = task->next;
|
tasks.delayed = task->next;
|
||||||
task_free(task);
|
task_free(task);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -678,10 +701,10 @@ ISR_CODE bool ISR_FUNC(task_add_systick)(foreground_task_ptr fn, void *data)
|
|||||||
task->data = data;
|
task->data = data;
|
||||||
task->next = NULL;
|
task->next = NULL;
|
||||||
|
|
||||||
if(systick_task == NULL)
|
if(tasks.systick == NULL)
|
||||||
systick_task = task;
|
tasks.systick = task;
|
||||||
else {
|
else {
|
||||||
core_task_t *t = systick_task;
|
core_task_t *t = tasks.systick;
|
||||||
while(t->next)
|
while(t->next)
|
||||||
t = t->next;
|
t = t->next;
|
||||||
t->next = task;
|
t->next = task;
|
||||||
@@ -699,12 +722,12 @@ FLASHMEM void task_delete_systick (foreground_task_ptr fn, void *data)
|
|||||||
|
|
||||||
hal.irq_disable();
|
hal.irq_disable();
|
||||||
|
|
||||||
if((task = systick_task)) do {
|
if((task = tasks.systick)) do {
|
||||||
if(fn == task->fn && data == task->data) {
|
if(fn == task->fn && data == task->data) {
|
||||||
if(prev)
|
if(prev)
|
||||||
prev->next = task->next;
|
prev->next = task->next;
|
||||||
else
|
else
|
||||||
systick_task = task->next;
|
tasks.systick = task->next;
|
||||||
task_free(task);
|
task_free(task);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -731,10 +754,10 @@ ISR_CODE bool ISR_FUNC(task_add_immediate)(foreground_task_ptr fn, void *data)
|
|||||||
task->data = data;
|
task->data = data;
|
||||||
task->next = NULL;
|
task->next = NULL;
|
||||||
|
|
||||||
if(immediate_task == NULL)
|
if(tasks.immediate == NULL)
|
||||||
immediate_task = task;
|
tasks.immediate = task;
|
||||||
else {
|
else {
|
||||||
core_task_t *t = immediate_task;
|
core_task_t *t = tasks.immediate;
|
||||||
while(t->next)
|
while(t->next)
|
||||||
t = t->next;
|
t = t->next;
|
||||||
t->next = task;
|
t->next = task;
|
||||||
@@ -746,6 +769,42 @@ ISR_CODE bool ISR_FUNC(task_add_immediate)(foreground_task_ptr fn, void *data)
|
|||||||
return task != NULL;
|
return task != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief Enqueue a function to be called once by the foreground process after the reset sequence is completed.
|
||||||
|
\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.
|
||||||
|
*/
|
||||||
|
ISR_CODE bool ISR_FUNC(task_run_on_reset)(foreground_task_ptr fn, void *data)
|
||||||
|
{
|
||||||
|
core_task_t *task = NULL;
|
||||||
|
|
||||||
|
if(!sys.cold_start) {
|
||||||
|
|
||||||
|
hal.irq_disable();
|
||||||
|
|
||||||
|
if(fn && (task = task_alloc())) {
|
||||||
|
|
||||||
|
task->fn = fn;
|
||||||
|
task->data = data;
|
||||||
|
task->next = NULL;
|
||||||
|
|
||||||
|
if(tasks.on_reset == NULL)
|
||||||
|
tasks.on_reset = task;
|
||||||
|
else {
|
||||||
|
core_task_t *t = tasks.on_reset;
|
||||||
|
while(t->next)
|
||||||
|
t = t->next;
|
||||||
|
t->next = task;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hal.irq_enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
return task != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! \brief Enqueue a function to be called once by the foreground process after the boot sequence is completed.
|
/*! \brief Enqueue a function to be called once by the foreground process after the boot sequence is completed.
|
||||||
\param fn pointer to a \a foreground_task_ptr type of function.
|
\param fn pointer to a \a foreground_task_ptr type of function.
|
||||||
\param data pointer to data to be passed to the callee.
|
\param data pointer to data to be passed to the callee.
|
||||||
@@ -765,10 +824,10 @@ ISR_CODE bool ISR_FUNC(task_run_on_startup)(foreground_task_ptr fn, void *data)
|
|||||||
task->data = data;
|
task->data = data;
|
||||||
task->next = NULL;
|
task->next = NULL;
|
||||||
|
|
||||||
if(on_booted == NULL)
|
if(tasks.on_booted == NULL)
|
||||||
on_booted = task;
|
tasks.on_booted = task;
|
||||||
else {
|
else {
|
||||||
core_task_t *t = on_booted;
|
core_task_t *t = tasks.on_booted;
|
||||||
while(t->next)
|
while(t->next)
|
||||||
t = t->next;
|
t = t->next;
|
||||||
t->next = task;
|
t->next = task;
|
||||||
@@ -792,28 +851,31 @@ FLASHMEM void task_execute_on_startup (void)
|
|||||||
|
|
||||||
core_task_t *task, *prev = NULL;
|
core_task_t *task, *prev = NULL;
|
||||||
|
|
||||||
if((task = on_booted)) do {
|
if((task = tasks.on_booted)) do {
|
||||||
if(!(task->fn == report_warning)) {
|
if(!(task->fn == report_warning)) {
|
||||||
if(prev)
|
if(prev)
|
||||||
prev->next = task->next;
|
prev->next = task->next;
|
||||||
else {
|
else {
|
||||||
prev = NULL;
|
prev = NULL;
|
||||||
on_booted = task->next;
|
tasks.on_booted = task->next;
|
||||||
}
|
}
|
||||||
task_free(task);
|
task_free(task);
|
||||||
} else
|
} else
|
||||||
prev = task;
|
prev = task;
|
||||||
} while((task = prev ? prev->next : on_booted));
|
} while((task = prev ? prev->next : tasks.on_booted));
|
||||||
|
|
||||||
while(next_task)
|
while(tasks.delayed)
|
||||||
task_delete(next_task->fn, NULL);
|
task_delete(tasks.delayed->fn, NULL);
|
||||||
|
|
||||||
while(systick_task)
|
while(tasks.systick)
|
||||||
task_delete_systick(systick_task->fn, NULL);
|
task_delete_systick(tasks.systick->fn, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(on_booted && (sys.driver_started || !hal.stream.state.linestate_event)) do {
|
if(tasks.on_booted && (sys.driver_started || !hal.stream.state.linestate_event)) do {
|
||||||
} while((on_booted = task_run(on_booted)));
|
} while((tasks.on_booted = task_run(tasks.on_booted)));
|
||||||
|
|
||||||
|
if(tasks.on_reset) do {
|
||||||
|
} while((tasks.on_reset = task_run(tasks.on_reset)));
|
||||||
|
|
||||||
if(!sys.driver_started) {
|
if(!sys.driver_started) {
|
||||||
|
|
||||||
@@ -825,6 +887,10 @@ FLASHMEM void task_execute_on_startup (void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
FLASHMEM void task_raise_alarm (void *data)
|
FLASHMEM void task_raise_alarm (void *data)
|
||||||
{
|
{
|
||||||
system_raise_alarm((alarm_code_t)data);
|
system_raise_alarm((alarm_code_t)data);
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ static bool modbus_send_rtu (modbus_message_t *msg, const modbus_callbacks_t *ca
|
|||||||
|
|
||||||
while(spin_lock);
|
while(spin_lock);
|
||||||
|
|
||||||
if(block) {
|
if((block &= !sys.blocking_event)) {
|
||||||
|
|
||||||
if(is_blocking)
|
if(is_blocking)
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ typedef struct {
|
|||||||
float rpm_high_limit;
|
float rpm_high_limit;
|
||||||
float angular_position; //!< Number of revolutions since last reset
|
float angular_position; //!< Number of revolutions since last reset
|
||||||
float rpm_programmed;
|
float rpm_programmed;
|
||||||
|
bool ccw;
|
||||||
uint32_t index_count;
|
uint32_t index_count;
|
||||||
uint32_t pulse_count;
|
uint32_t pulse_count;
|
||||||
uint32_t error_count;
|
uint32_t error_count;
|
||||||
|
|||||||
1
task.h
1
task.h
@@ -26,6 +26,7 @@ typedef void (*foreground_task_ptr)(void *data);
|
|||||||
|
|
||||||
bool task_add_immediate (foreground_task_ptr fn, void *data);
|
bool task_add_immediate (foreground_task_ptr fn, void *data);
|
||||||
bool task_add_delayed (foreground_task_ptr fn, void *data, uint32_t delay_ms);
|
bool task_add_delayed (foreground_task_ptr fn, void *data, uint32_t delay_ms);
|
||||||
|
bool task_run_on_reset (foreground_task_ptr fn, void *data);
|
||||||
bool task_run_on_startup (foreground_task_ptr fn, void *data);
|
bool task_run_on_startup (foreground_task_ptr fn, void *data);
|
||||||
void task_delete (foreground_task_ptr fn, void *data);
|
void task_delete (foreground_task_ptr fn, void *data);
|
||||||
bool task_add_systick (foreground_task_ptr fn, void *data);
|
bool task_add_systick (foreground_task_ptr fn, void *data);
|
||||||
|
|||||||
137
vfs.c
137
vfs.c
@@ -226,6 +226,43 @@ char *vfs_fixpath (char *path)
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *parse_path (const char *path)
|
||||||
|
{
|
||||||
|
static char *abspath;
|
||||||
|
static size_t maxlen = 0;
|
||||||
|
|
||||||
|
if(strlen(cwd) + strlen(path) + 2 > maxlen) {
|
||||||
|
maxlen = max(VFS_CWD_LENGTH, strlen(cwd) + strlen(path) + 2);
|
||||||
|
abspath = realloc(abspath, maxlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(abspath) {
|
||||||
|
|
||||||
|
char newpath[VFS_CWD_LENGTH];
|
||||||
|
|
||||||
|
strcpy(newpath, path);
|
||||||
|
strcpy(abspath, *path == '/' ? "/" : cwd);
|
||||||
|
|
||||||
|
char *p, *el = strtok(newpath, "/");
|
||||||
|
|
||||||
|
while(el) {
|
||||||
|
if(!strcmp("..", el)) {
|
||||||
|
if((p = strrchr(abspath, '/')))
|
||||||
|
*(p + (p == abspath ? 1 : 0)) = '\0';
|
||||||
|
} else if(*el && strcmp(el, ".")) {
|
||||||
|
if(strlen(abspath) == 1)
|
||||||
|
strcat(abspath, el);
|
||||||
|
else
|
||||||
|
strcat(strcat(abspath, "/"), el);
|
||||||
|
}
|
||||||
|
el = strtok(NULL, "/");
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
maxlen = 0;
|
||||||
|
|
||||||
|
return abspath ? (const char *)abspath : path;
|
||||||
|
}
|
||||||
|
|
||||||
static vfs_mount_t *get_mount (const char *path)
|
static vfs_mount_t *get_mount (const char *path)
|
||||||
{
|
{
|
||||||
vfs_errno = 0;
|
vfs_errno = 0;
|
||||||
@@ -384,44 +421,26 @@ int vfs_rmdir (const char *path)
|
|||||||
|
|
||||||
int vfs_chdir (const char *path)
|
int vfs_chdir (const char *path)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret = -1;
|
||||||
char *p;
|
vfs_mount_t *mount;
|
||||||
|
|
||||||
vfs_errno = 0;
|
vfs_errno = 0;
|
||||||
|
path = parse_path(path);
|
||||||
|
|
||||||
if(!strcmp("..", path) && strcmp("/", (path = cwd)) && (p = strrchr(cwd, '/')))
|
if((mount = get_mount(path))) {
|
||||||
*(p + (p == cwd ? 1 : 0)) = '\0';
|
if(mount->vfs->fchdir)
|
||||||
|
ret = mount->vfs->fchdir(get_filename(mount, path));
|
||||||
if(*path != '/' && strcmp(cwd, "/")) {
|
else {
|
||||||
if(strcmp(path, "..")) {
|
vfs_stat_t st;
|
||||||
if(strlen(cwd) > 1)
|
if(!((ret = mount->vfs->fstat(get_filename(mount, path), &st)) == 0 && st.st_mode.directory))
|
||||||
strcat(cwd, "/");
|
ret = -1;
|
||||||
strcat(cwd, path);
|
|
||||||
} else {
|
|
||||||
char *s = strrchr(cwd, '/');
|
|
||||||
if(s)
|
|
||||||
*s = '\0';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if(*path == '/')
|
|
||||||
strcpy(cwd, path);
|
|
||||||
else
|
|
||||||
strcat(strcpy(cwd, "/"), path);
|
|
||||||
|
|
||||||
vfs_fixpath(cwd);
|
|
||||||
|
|
||||||
if((cwdmount = get_mount(cwd)) && strchr(cwd + 1, '/') == NULL && cwdmount != &root) {
|
|
||||||
|
|
||||||
strcpy(cwd, cwdmount->path);
|
|
||||||
vfs_fixpath(cwd);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if((ret = cwdmount ? cwdmount->vfs->fchdir(path) : -1) != 0) // + strlen(mount->path));))
|
if(ret == 0) {
|
||||||
vfs_fixpath(cwd);
|
strcpy(cwd, path);
|
||||||
|
cwdmount = mount;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -498,16 +517,21 @@ void vfs_closedir (vfs_dir_t *dir)
|
|||||||
char *vfs_getcwd (char *buf, size_t len)
|
char *vfs_getcwd (char *buf, size_t len)
|
||||||
{
|
{
|
||||||
char *cwds = cwdmount->vfs->fgetcwd ? cwdmount->vfs->fgetcwd(NULL, len) : cwd;
|
char *cwds = cwdmount->vfs->fgetcwd ? cwdmount->vfs->fgetcwd(NULL, len) : cwd;
|
||||||
|
size_t cwdlen = strlen(cwdmount->path) + strlen(cwds) + 2;
|
||||||
|
|
||||||
vfs_errno = 0;
|
vfs_errno = 0;
|
||||||
|
|
||||||
if(buf == NULL)
|
if(buf == NULL) {
|
||||||
buf = (char *)malloc(strlen(cwds) + 1);
|
len = cwdlen + 1;
|
||||||
|
buf = (char *)malloc(cwdlen + 1);
|
||||||
|
}
|
||||||
|
|
||||||
if(buf)
|
if(buf && cwdlen < len)
|
||||||
strcpy(buf, cwds);
|
strcat(strcpy(buf, cwdmount->path), cwds + 1);
|
||||||
|
|
||||||
return buf ? buf : cwds;
|
vfs_fixpath(buf);
|
||||||
|
|
||||||
|
return cwdlen < len ? buf : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vfs_chmod (const char *filename, vfs_st_mode_t attr, vfs_st_mode_t mask)
|
int vfs_chmod (const char *filename, vfs_st_mode_t attr, vfs_st_mode_t mask)
|
||||||
@@ -519,39 +543,11 @@ int vfs_chmod (const char *filename, vfs_st_mode_t attr, vfs_st_mode_t mask)
|
|||||||
|
|
||||||
int vfs_stat (const char *filename, vfs_stat_t *st)
|
int vfs_stat (const char *filename, vfs_stat_t *st)
|
||||||
{
|
{
|
||||||
char tmp[VFS_CWD_LENGTH], *p;
|
filename = parse_path(filename);
|
||||||
|
|
||||||
if(!strcmp("..", filename)) {
|
|
||||||
strcpy(tmp, cwd);
|
|
||||||
if((p = strrchr(tmp, '/')))
|
|
||||||
*(p + (p == tmp ? 1 : 0)) = '\0';
|
|
||||||
filename = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
vfs_mount_t *mount = get_mount(filename);
|
vfs_mount_t *mount = get_mount(filename);
|
||||||
|
|
||||||
int ret = mount ? mount->vfs->fstat(get_filename(mount, filename), st) : -1;
|
return mount ? mount->vfs->fstat(get_filename(mount, filename), st) : -1;
|
||||||
|
|
||||||
if(ret == -1 && (!strcmp("/", filename) || (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 = mount->st_mtim;
|
|
||||||
#else
|
|
||||||
st->st_mtime = mount->st_mtime;
|
|
||||||
#endif
|
|
||||||
ret = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int vfs_utime (const char *filename, struct tm *modified)
|
int vfs_utime (const char *filename, struct tm *modified)
|
||||||
@@ -634,11 +630,18 @@ bool vfs_unmount (const char *path)
|
|||||||
if(!strcmp(path, "/")) {
|
if(!strcmp(path, "/")) {
|
||||||
root.vfs = &fs_null;
|
root.vfs = &fs_null;
|
||||||
root.mode = (vfs_st_mode_t){ .directory = true, .read_only = true, .hidden = true };
|
root.mode = (vfs_st_mode_t){ .directory = true, .read_only = true, .hidden = true };
|
||||||
|
if(cwdmount == &root)
|
||||||
|
strcpy(cwd, "/");
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
vfs_mount_t *mount = get_mount(path);
|
vfs_mount_t *mount = get_mount(path);
|
||||||
if(mount) {
|
if(mount) {
|
||||||
|
|
||||||
|
if(mount == cwdmount) {
|
||||||
|
cwdmount = &root;
|
||||||
|
strcpy(cwd, "/");
|
||||||
|
}
|
||||||
|
|
||||||
vfs_mount_t *pmount = &root;
|
vfs_mount_t *pmount = &root;
|
||||||
|
|
||||||
while(pmount->next && pmount->next != mount)
|
while(pmount->next && pmount->next != mount)
|
||||||
|
|||||||
Reference in New Issue
Block a user