Pulled interrupts into an optional module.
This commit is contained in:
25
Makefile
25
Makefile
@ -167,7 +167,7 @@ clean-esp32:
|
||||
|
||||
vet:
|
||||
$(MAKE) clean
|
||||
$(MAKE) all
|
||||
$(MAKE)
|
||||
$(MAKE) esp32-build
|
||||
$(MAKE) esp32s2-build
|
||||
$(MAKE) esp32c3-build
|
||||
@ -175,7 +175,7 @@ vet:
|
||||
$(MAKE) add-optional
|
||||
$(MAKE) esp32-build
|
||||
$(MAKE) clean
|
||||
$(MAKE) all
|
||||
$(MAKE)
|
||||
|
||||
clean:
|
||||
rm -rf $(OUT)
|
||||
@ -292,7 +292,7 @@ ESP32_BOOT = $(COMMON_PHASE1) \
|
||||
$(COMMON_PHASE2) $(COMMON_FILETOOLS) \
|
||||
esp32/platform.fs \
|
||||
posix/httpd.fs posix/web_interface.fs esp32/web_interface.fs \
|
||||
esp32/registers.fs esp32/timers.fs \
|
||||
esp32/registers.fs \
|
||||
posix/telnetd.fs \
|
||||
esp32/optionals.fs \
|
||||
esp32/autoboot.fs common/fini.fs
|
||||
@ -325,6 +325,14 @@ $(GEN)/esp32_camera.h: \
|
||||
esp32/optional/camera/camera.fs \
|
||||
esp32/optional/camera/camera_server.fs >$@
|
||||
|
||||
$(GEN)/esp32_interrupts.h: \
|
||||
tools/source_to_string.js \
|
||||
esp32/optional/interrupts/interrupts.fs \
|
||||
esp32/optional/interrupts/timers.fs | $(GEN)
|
||||
$< interrupts_source $(VERSION) $(REVISION) \
|
||||
esp32/optional/interrupts/interrupts.fs \
|
||||
esp32/optional/interrupts/timers.fs >$@
|
||||
|
||||
$(GEN)/esp32_oled.h: \
|
||||
tools/source_to_string.js esp32/optional/oled/oled.fs | $(GEN)
|
||||
$< oled_source $(VERSION) $(REVISION) \
|
||||
@ -347,6 +355,7 @@ OPTIONAL_MODULES = \
|
||||
$(ESP32)/ESP32forth/assemblers.h \
|
||||
$(ESP32)/ESP32forth/camera.h \
|
||||
$(ESP32)/ESP32forth/oled.h \
|
||||
$(ESP32)/ESP32forth/interrupts.h \
|
||||
$(ESP32)/ESP32forth/rmt.h \
|
||||
$(ESP32)/ESP32forth/serial-bluetooth.h \
|
||||
$(ESP32)/ESP32forth/spi-flash.h
|
||||
@ -650,6 +659,15 @@ $(ESP32)/ESP32forth/optional/camera.h: \
|
||||
camera=@$(GEN)/esp32_camera.h \
|
||||
>$@
|
||||
|
||||
$(ESP32)/ESP32forth/optional/interrupts.h: \
|
||||
esp32/optional/interrupts/interrupts.h \
|
||||
$(GEN)/esp32_interrupts.h | $(ESP32)/ESP32forth/optional
|
||||
cat esp32/optional/interrupts/interrupts.h | tools/replace.js \
|
||||
VERSION=$(VERSION) \
|
||||
REVISION=$(REVISION) \
|
||||
interrupts=@$(GEN)/esp32_interrupts.h \
|
||||
>$@
|
||||
|
||||
$(ESP32)/ESP32forth/optional/oled.h: \
|
||||
esp32/optional/oled/oled.h \
|
||||
$(GEN)/esp32_oled.h | $(ESP32)/ESP32forth/optional
|
||||
@ -784,6 +802,7 @@ $(ESP32)/ESP32forth.zip: \
|
||||
$(ESP32)/ESP32forth/optional/assemblers.h \
|
||||
$(ESP32)/ESP32forth/optional/camera.h \
|
||||
$(ESP32)/ESP32forth/optional/oled.h \
|
||||
$(ESP32)/ESP32forth/optional/interrupts.h \
|
||||
$(ESP32)/ESP32forth/optional/rmt.h \
|
||||
$(ESP32)/ESP32forth/optional/serial-bluetooth.h \
|
||||
$(ESP32)/ESP32forth/optional/spi-flash.h
|
||||
|
||||
@ -37,3 +37,6 @@ typedef struct {
|
||||
void *DOCREATE_OP;
|
||||
const BUILTIN_WORD *builtins;
|
||||
} G_SYS;
|
||||
|
||||
static G_SYS *g_sys = 0;
|
||||
static cell_t *forth_run(cell_t *init_rp);
|
||||
|
||||
@ -43,8 +43,6 @@ enum {
|
||||
#undef V
|
||||
};
|
||||
|
||||
static G_SYS *g_sys = 0;
|
||||
|
||||
static cell_t convert(const char *pos, cell_t n, cell_t base, cell_t *ret) {
|
||||
*ret = 0;
|
||||
cell_t negate = 0;
|
||||
|
||||
@ -623,7 +623,6 @@ e: test-esp32-forth-voclist
|
||||
out: streams
|
||||
out: tasks
|
||||
out: rtos
|
||||
out: interrupts
|
||||
out: sockets
|
||||
out: Serial
|
||||
out: ledc
|
||||
@ -682,7 +681,6 @@ e: check-esp32-builtins
|
||||
|
||||
e: check-esp32-bindings
|
||||
out: rtos
|
||||
out: interrupts
|
||||
out: sockets
|
||||
out: Serial
|
||||
out: ledc
|
||||
@ -699,7 +697,6 @@ e: test-esp32-forth-namespace
|
||||
' forth list-from
|
||||
out: FORTH
|
||||
out: telnetd
|
||||
out: timers
|
||||
out: registers
|
||||
out: webui
|
||||
out: login
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
{{tier2_opcodes}}
|
||||
{{floats}}
|
||||
{{calls}}
|
||||
{{bits}}
|
||||
{{builtins.h}}
|
||||
{{builtins.cpp}}
|
||||
{{main.cpp}}
|
||||
|
||||
@ -79,30 +79,6 @@ transfer sockets-builtins
|
||||
: ip. ( n -- ) ip# ip# ip# 255 and n. ;
|
||||
forth definitions
|
||||
|
||||
vocabulary interrupts interrupts definitions
|
||||
transfer interrupts-builtins
|
||||
DEFINED? gpio_config [IF]
|
||||
0 constant ESP_INTR_FLAG_DEFAULT
|
||||
: ESP_INTR_FLAG_LEVELn ( n=1-6 -- n ) 1 swap lshift ;
|
||||
1 7 lshift constant ESP_INTR_FLAG_NMI
|
||||
1 8 lshift constant ESP_INTR_FLAG_SHARED
|
||||
1 9 lshift constant ESP_INTR_FLAG_EDGE
|
||||
1 10 lshift constant ESP_INTR_FLAG_IRAM
|
||||
1 11 lshift constant ESP_INTR_FLAG_INTRDISABLED
|
||||
( Prefix these with # because GPIO_INTR_DISABLE conflicts with a function. )
|
||||
0 constant #GPIO_INTR_DISABLE
|
||||
1 constant #GPIO_INTR_POSEDGE
|
||||
2 constant #GPIO_INTR_NEGEDGE
|
||||
3 constant #GPIO_INTR_ANYEDGE
|
||||
4 constant #GPIO_INTR_LOW_LEVEL
|
||||
5 constant #GPIO_INTR_HIGH_LEVEL
|
||||
( Easy word to trigger on any change to a pin )
|
||||
ESP_INTR_FLAG_DEFAULT gpio_install_isr_service drop
|
||||
: pinchange ( xt pin ) dup #GPIO_INTR_ANYEDGE gpio_set_intr_type throw
|
||||
swap 0 gpio_isr_handler_add throw ;
|
||||
[THEN]
|
||||
forth definitions
|
||||
|
||||
vocabulary rtos rtos definitions
|
||||
transfer rtos-builtins
|
||||
forth definitions
|
||||
|
||||
@ -15,7 +15,6 @@
|
||||
static char filename[PATH_MAX];
|
||||
static char filename2[PATH_MAX];
|
||||
|
||||
{{bits}}
|
||||
{{core}}
|
||||
{{faults}}
|
||||
{{calling}}
|
||||
@ -52,63 +51,3 @@ static cell_t ResizeFile(cell_t fd, cell_t size) {
|
||||
if (t < 0) { return errno; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_INTERRUPTS_SUPPORT
|
||||
struct handle_interrupt_args {
|
||||
cell_t xt;
|
||||
cell_t arg;
|
||||
};
|
||||
|
||||
static void IRAM_ATTR HandleInterrupt(void *arg) {
|
||||
struct handle_interrupt_args *args = (struct handle_interrupt_args *) arg;
|
||||
cell_t code[2];
|
||||
code[0] = args->xt;
|
||||
code[1] = g_sys->YIELD_XT;
|
||||
cell_t fstack[INTERRUPT_STACK_CELLS];
|
||||
cell_t rstack[INTERRUPT_STACK_CELLS];
|
||||
cell_t stack[INTERRUPT_STACK_CELLS];
|
||||
stack[0] = args->arg;
|
||||
cell_t *rp = rstack;
|
||||
*++rp = (cell_t) code;
|
||||
*++rp = (cell_t) (fstack + 1);
|
||||
*++rp = (cell_t) (stack + 1);
|
||||
forth_run(rp);
|
||||
}
|
||||
|
||||
static bool IRAM_ATTR HandleInterruptAndRet(void *arg) {
|
||||
HandleInterrupt(arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
static cell_t EspIntrAlloc(cell_t source, cell_t flags, cell_t xt, cell_t arg, void *ret) {
|
||||
// NOTE: Leaks memory.
|
||||
struct handle_interrupt_args *args = (struct handle_interrupt_args *) malloc(sizeof(struct handle_interrupt_args));
|
||||
args->xt = xt;
|
||||
args->arg = arg;
|
||||
return esp_intr_alloc(source, flags, HandleInterrupt, args, (intr_handle_t *) ret);
|
||||
}
|
||||
|
||||
static cell_t GpioIsrHandlerAdd(cell_t pin, cell_t xt, cell_t arg) {
|
||||
// NOTE: Leaks memory.
|
||||
struct handle_interrupt_args *args = (struct handle_interrupt_args *) malloc(sizeof(struct handle_interrupt_args));
|
||||
args->xt = xt;
|
||||
args->arg = arg;
|
||||
return gpio_isr_handler_add((gpio_num_t) pin, HandleInterrupt, args);
|
||||
}
|
||||
|
||||
static void TimerInitNull(cell_t group, cell_t timer) {
|
||||
// Seems to be required starting in the 2.0 IDE.
|
||||
timer_config_t config;
|
||||
memset(&config, 0, sizeof(config));
|
||||
config.divider = 2;
|
||||
timer_init((timer_group_t) group, (timer_idx_t) timer, &config);
|
||||
}
|
||||
|
||||
static cell_t TimerIsrCallbackAdd(cell_t group, cell_t timer, cell_t xt, cell_t arg, cell_t flags) {
|
||||
// NOTE: Leaks memory.
|
||||
struct handle_interrupt_args *args = (struct handle_interrupt_args *) malloc(sizeof(struct handle_interrupt_args));
|
||||
args->xt = xt;
|
||||
args->arg = arg;
|
||||
return timer_isr_callback_add((timer_group_t) group, (timer_idx_t) timer, HandleInterruptAndRet, args, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -36,6 +36,14 @@
|
||||
# define OPTIONAL_ASSEMBLERS_SUPPORT
|
||||
# endif
|
||||
|
||||
// Hook to pull in optional interrupts and timers support.
|
||||
# if __has_include("interrupts.h")
|
||||
# include "interrupts.h"
|
||||
# else
|
||||
# define OPTIONAL_INTERRUPTS_VOCABULARIES
|
||||
# define OPTIONAL_INTERRUPTS_SUPPORT
|
||||
# endif
|
||||
|
||||
// Hook to pull in optional Oled support.
|
||||
# if __has_include("oled.h")
|
||||
# include "oled.h"
|
||||
@ -101,13 +109,13 @@ static cell_t ResizeFile(cell_t fd, cell_t size);
|
||||
OPTIONAL_I2C_SUPPORT \
|
||||
OPTIONAL_SOCKETS_SUPPORT \
|
||||
OPTIONAL_FREERTOS_SUPPORT \
|
||||
OPTIONAL_INTERRUPTS_SUPPORT \
|
||||
CALLING_OPCODE_LIST \
|
||||
FLOATING_POINT_LIST
|
||||
|
||||
#define EXTERNAL_OPTIONAL_MODULE_SUPPORT \
|
||||
OPTIONAL_ASSEMBLERS_SUPPORT \
|
||||
OPTIONAL_CAMERA_SUPPORT \
|
||||
OPTIONAL_INTERRUPTS_SUPPORT \
|
||||
OPTIONAL_OLED_SUPPORT \
|
||||
OPTIONAL_RMT_SUPPORT \
|
||||
OPTIONAL_SERIAL_BLUETOOTH_SUPPORT \
|
||||
@ -278,85 +286,6 @@ static cell_t ResizeFile(cell_t fd, cell_t size);
|
||||
YV(rtos, xPortGetCoreID, PUSH xPortGetCoreID())
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_INTERRUPTS_SUPPORT
|
||||
# define OPTIONAL_INTERRUPTS_SUPPORT
|
||||
#else
|
||||
# ifndef SIM_PRINT_ONLY
|
||||
# include "esp_intr_alloc.h"
|
||||
# include "driver/timer.h"
|
||||
# include "driver/gpio.h"
|
||||
static cell_t EspIntrAlloc(cell_t source, cell_t flags, cell_t xt, cell_t arg, void *ret);
|
||||
static cell_t GpioIsrHandlerAdd(cell_t pin, cell_t xt, cell_t arg);
|
||||
static cell_t TimerIsrCallbackAdd(cell_t group, cell_t timer, cell_t xt, cell_t arg, cell_t flags);
|
||||
static void TimerInitNull(cell_t group, cell_t timer);
|
||||
# endif
|
||||
# define OPTIONAL_INTERRUPTS_SUPPORT \
|
||||
YV(interrupts, gpio_config, n0 = gpio_config((const gpio_config_t *) a0)) \
|
||||
YV(interrupts, gpio_reset_pin, n0 = gpio_reset_pin((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_set_intr_type, n0 = gpio_set_intr_type((gpio_num_t) n1, (gpio_int_type_t) n0); NIP) \
|
||||
YV(interrupts, gpio_intr_enable, n0 = gpio_intr_enable((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_intr_disable, n0 = gpio_intr_disable((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_set_level, n0 = gpio_set_level((gpio_num_t) n1, n0); NIP) \
|
||||
YV(interrupts, gpio_get_level, n0 = gpio_get_level((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_set_direction, n0 = gpio_set_direction((gpio_num_t) n1, (gpio_mode_t) n0); NIP) \
|
||||
YV(interrupts, gpio_set_pull_mode, n0 = gpio_set_pull_mode((gpio_num_t) n1, (gpio_pull_mode_t) n0); NIP) \
|
||||
YV(interrupts, gpio_wakeup_enable, n0 = gpio_wakeup_enable((gpio_num_t) n1, (gpio_int_type_t) n0); NIP) \
|
||||
YV(interrupts, gpio_wakeup_disable, n0 = gpio_wakeup_disable((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_pullup_en, n0 = gpio_pullup_en((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_pullup_dis, n0 = gpio_pullup_dis((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_pulldown_en, n0 = gpio_pulldown_en((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_pulldown_dis, n0 = gpio_pulldown_dis((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_hold_en, n0 = gpio_hold_en((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_hold_dis, n0 = gpio_hold_dis((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_deep_sleep_hold_en, gpio_deep_sleep_hold_en()) \
|
||||
YV(interrupts, gpio_deep_sleep_hold_dis, gpio_deep_sleep_hold_dis()) \
|
||||
YV(interrupts, gpio_install_isr_service, n0 = gpio_install_isr_service(n0)) \
|
||||
YV(interrupts, gpio_uninstall_isr_service, gpio_uninstall_isr_service()) \
|
||||
YV(interrupts, gpio_isr_handler_add, n0 = GpioIsrHandlerAdd(n2, n1, n0); NIPn(2)) \
|
||||
YV(interrupts, gpio_isr_handler_remove, n0 = gpio_isr_handler_remove((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_set_drive_capability, n0 = gpio_set_drive_capability((gpio_num_t) n1, (gpio_drive_cap_t) n0); NIP) \
|
||||
YV(interrupts, gpio_get_drive_capability, n0 = gpio_get_drive_capability((gpio_num_t) n1, (gpio_drive_cap_t *) a0); NIP) \
|
||||
YV(interrupts, esp_intr_alloc, n0 = EspIntrAlloc(n4, n3, n2, n1, a0); NIPn(4)) \
|
||||
YV(interrupts, esp_intr_free, n0 = esp_intr_free((intr_handle_t) n0)) \
|
||||
YV(timers, timer_isr_callback_add, n0 = TimerIsrCallbackAdd(n4, n3, n2, n1, n0); NIPn(4)) \
|
||||
YV(timers, timer_init_null, TimerInitNull(n1, n0); DROPn(2)) \
|
||||
YV(timers, timer_get_counter_value, \
|
||||
n0 = timer_get_counter_value((timer_group_t) n2, (timer_idx_t) n1, \
|
||||
(uint64_t *) a0); NIPn(2)) \
|
||||
YV(timers, timer_set_counter_value, \
|
||||
uint64_t val = *(uint64_t *) a0; \
|
||||
n0 = timer_set_counter_value((timer_group_t) n2, (timer_idx_t) n1, val); NIPn(2)) \
|
||||
YV(timers, timer_start, \
|
||||
n0 = timer_start((timer_group_t) n1, (timer_idx_t) n0); NIP) \
|
||||
YV(timers, timer_pause, \
|
||||
n0 = timer_pause((timer_group_t) n1, (timer_idx_t) n0); NIP) \
|
||||
YV(timers, timer_set_counter_mode, \
|
||||
n0 = timer_set_counter_mode((timer_group_t) n2, (timer_idx_t) n1, \
|
||||
(timer_count_dir_t) n0); NIPn(2)) \
|
||||
YV(timers, timer_set_auto_reload, \
|
||||
n0 = timer_set_auto_reload((timer_group_t) n2, (timer_idx_t) n1, \
|
||||
(timer_autoreload_t) n0); NIPn(2)) \
|
||||
YV(timers, timer_set_divider, \
|
||||
n0 = timer_set_divider((timer_group_t) n2, (timer_idx_t) n1, n0); NIPn(2)) \
|
||||
YV(timers, timer_set_alarm_value, uint64_t val = *(uint64_t *) a0; \
|
||||
n0 = timer_set_alarm_value((timer_group_t) n2, (timer_idx_t) n1, val); NIPn(2)) \
|
||||
YV(timers, timer_get_alarm_value, \
|
||||
n0 = timer_get_alarm_value((timer_group_t) n2, (timer_idx_t) n1, \
|
||||
(uint64_t *) a0); NIPn(2)) \
|
||||
YV(timers, timer_set_alarm, \
|
||||
n0 = timer_set_alarm((timer_group_t) n2, (timer_idx_t) n1, \
|
||||
(timer_alarm_t) n0); NIPn(2)) \
|
||||
YV(timers, timer_group_intr_enable, \
|
||||
n0 = timer_group_intr_enable((timer_group_t) n1, (timer_intr_t) n0); NIP) \
|
||||
YV(timers, timer_group_intr_disable, \
|
||||
n0 = timer_group_intr_disable((timer_group_t) n1, (timer_intr_t) n0); NIP) \
|
||||
YV(timers, timer_enable_intr, \
|
||||
n0 = timer_enable_intr((timer_group_t) n1, (timer_idx_t) n0); NIP) \
|
||||
YV(timers, timer_disable_intr, \
|
||||
n0 = timer_disable_intr((timer_group_t) n1, (timer_idx_t) n0); NIP)
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_SOCKETS_SUPPORT
|
||||
# define OPTIONAL_SOCKETS_SUPPORT
|
||||
#else
|
||||
|
||||
37
esp32/optional/interrupts/interrupts.fs
Normal file
37
esp32/optional/interrupts/interrupts.fs
Normal file
@ -0,0 +1,37 @@
|
||||
\ Copyright 2023 Bradley D. Nelson
|
||||
\
|
||||
\ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
\ you may not use this file except in compliance with the License.
|
||||
\ You may obtain a copy of the License at
|
||||
\
|
||||
\ http://www.apache.org/licenses/LICENSE-2.0
|
||||
\
|
||||
\ Unless required by applicable law or agreed to in writing, software
|
||||
\ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
\ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
\ See the License for the specific language governing permissions and
|
||||
\ limitations under the License.
|
||||
|
||||
vocabulary interrupts interrupts definitions
|
||||
transfer interrupts-builtins
|
||||
DEFINED? gpio_config [IF]
|
||||
0 constant ESP_INTR_FLAG_DEFAULT
|
||||
: ESP_INTR_FLAG_LEVELn ( n=1-6 -- n ) 1 swap lshift ;
|
||||
1 7 lshift constant ESP_INTR_FLAG_NMI
|
||||
1 8 lshift constant ESP_INTR_FLAG_SHARED
|
||||
1 9 lshift constant ESP_INTR_FLAG_EDGE
|
||||
1 10 lshift constant ESP_INTR_FLAG_IRAM
|
||||
1 11 lshift constant ESP_INTR_FLAG_INTRDISABLED
|
||||
( Prefix these with # because GPIO_INTR_DISABLE conflicts with a function. )
|
||||
0 constant #GPIO_INTR_DISABLE
|
||||
1 constant #GPIO_INTR_POSEDGE
|
||||
2 constant #GPIO_INTR_NEGEDGE
|
||||
3 constant #GPIO_INTR_ANYEDGE
|
||||
4 constant #GPIO_INTR_LOW_LEVEL
|
||||
5 constant #GPIO_INTR_HIGH_LEVEL
|
||||
( Easy word to trigger on any change to a pin )
|
||||
ESP_INTR_FLAG_DEFAULT gpio_install_isr_service drop
|
||||
: pinchange ( xt pin ) dup #GPIO_INTR_ANYEDGE gpio_set_intr_type throw
|
||||
swap 0 gpio_isr_handler_add throw ;
|
||||
[THEN]
|
||||
forth definitions
|
||||
152
esp32/optional/interrupts/interrupts.h
Normal file
152
esp32/optional/interrupts/interrupts.h
Normal file
@ -0,0 +1,152 @@
|
||||
// Copyright 2023 Bradley D. Nelson
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#define INTERRUPT_STACK_CELLS 64
|
||||
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "driver/timer.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
static cell_t EspIntrAlloc(cell_t source, cell_t flags, cell_t xt, cell_t arg, void *ret);
|
||||
static cell_t GpioIsrHandlerAdd(cell_t pin, cell_t xt, cell_t arg);
|
||||
static cell_t TimerIsrCallbackAdd(cell_t group, cell_t timer, cell_t xt, cell_t arg, cell_t flags);
|
||||
static void TimerInitNull(cell_t group, cell_t timer);
|
||||
|
||||
#define OPTIONAL_INTERRUPTS_VOCABULARIES V(interrupts) V(timers)
|
||||
#define OPTIONAL_INTERRUPTS_SUPPORT \
|
||||
XV(internals, "interrupts-source", INTERRUPTS_SOURCE, \
|
||||
PUSH interrupts_source; PUSH sizeof(interrupts_source) - 1) \
|
||||
YV(interrupts, gpio_config, n0 = gpio_config((const gpio_config_t *) a0)) \
|
||||
YV(interrupts, gpio_reset_pin, n0 = gpio_reset_pin((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_set_intr_type, n0 = gpio_set_intr_type((gpio_num_t) n1, (gpio_int_type_t) n0); NIP) \
|
||||
YV(interrupts, gpio_intr_enable, n0 = gpio_intr_enable((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_intr_disable, n0 = gpio_intr_disable((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_set_level, n0 = gpio_set_level((gpio_num_t) n1, n0); NIP) \
|
||||
YV(interrupts, gpio_get_level, n0 = gpio_get_level((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_set_direction, n0 = gpio_set_direction((gpio_num_t) n1, (gpio_mode_t) n0); NIP) \
|
||||
YV(interrupts, gpio_set_pull_mode, n0 = gpio_set_pull_mode((gpio_num_t) n1, (gpio_pull_mode_t) n0); NIP) \
|
||||
YV(interrupts, gpio_wakeup_enable, n0 = gpio_wakeup_enable((gpio_num_t) n1, (gpio_int_type_t) n0); NIP) \
|
||||
YV(interrupts, gpio_wakeup_disable, n0 = gpio_wakeup_disable((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_pullup_en, n0 = gpio_pullup_en((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_pullup_dis, n0 = gpio_pullup_dis((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_pulldown_en, n0 = gpio_pulldown_en((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_pulldown_dis, n0 = gpio_pulldown_dis((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_hold_en, n0 = gpio_hold_en((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_hold_dis, n0 = gpio_hold_dis((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_deep_sleep_hold_en, gpio_deep_sleep_hold_en()) \
|
||||
YV(interrupts, gpio_deep_sleep_hold_dis, gpio_deep_sleep_hold_dis()) \
|
||||
YV(interrupts, gpio_install_isr_service, n0 = gpio_install_isr_service(n0)) \
|
||||
YV(interrupts, gpio_uninstall_isr_service, gpio_uninstall_isr_service()) \
|
||||
YV(interrupts, gpio_isr_handler_add, n0 = GpioIsrHandlerAdd(n2, n1, n0); NIPn(2)) \
|
||||
YV(interrupts, gpio_isr_handler_remove, n0 = gpio_isr_handler_remove((gpio_num_t) n0)) \
|
||||
YV(interrupts, gpio_set_drive_capability, n0 = gpio_set_drive_capability((gpio_num_t) n1, (gpio_drive_cap_t) n0); NIP) \
|
||||
YV(interrupts, gpio_get_drive_capability, n0 = gpio_get_drive_capability((gpio_num_t) n1, (gpio_drive_cap_t *) a0); NIP) \
|
||||
YV(interrupts, esp_intr_alloc, n0 = EspIntrAlloc(n4, n3, n2, n1, a0); NIPn(4)) \
|
||||
YV(interrupts, esp_intr_free, n0 = esp_intr_free((intr_handle_t) n0)) \
|
||||
YV(timers, timer_isr_callback_add, n0 = TimerIsrCallbackAdd(n4, n3, n2, n1, n0); NIPn(4)) \
|
||||
YV(timers, timer_init_null, TimerInitNull(n1, n0); DROPn(2)) \
|
||||
YV(timers, timer_get_counter_value, \
|
||||
n0 = timer_get_counter_value((timer_group_t) n2, (timer_idx_t) n1, \
|
||||
(uint64_t *) a0); NIPn(2)) \
|
||||
YV(timers, timer_set_counter_value, \
|
||||
uint64_t val = *(uint64_t *) a0; \
|
||||
n0 = timer_set_counter_value((timer_group_t) n2, (timer_idx_t) n1, val); NIPn(2)) \
|
||||
YV(timers, timer_start, \
|
||||
n0 = timer_start((timer_group_t) n1, (timer_idx_t) n0); NIP) \
|
||||
YV(timers, timer_pause, \
|
||||
n0 = timer_pause((timer_group_t) n1, (timer_idx_t) n0); NIP) \
|
||||
YV(timers, timer_set_counter_mode, \
|
||||
n0 = timer_set_counter_mode((timer_group_t) n2, (timer_idx_t) n1, \
|
||||
(timer_count_dir_t) n0); NIPn(2)) \
|
||||
YV(timers, timer_set_auto_reload, \
|
||||
n0 = timer_set_auto_reload((timer_group_t) n2, (timer_idx_t) n1, \
|
||||
(timer_autoreload_t) n0); NIPn(2)) \
|
||||
YV(timers, timer_set_divider, \
|
||||
n0 = timer_set_divider((timer_group_t) n2, (timer_idx_t) n1, n0); NIPn(2)) \
|
||||
YV(timers, timer_set_alarm_value, uint64_t val = *(uint64_t *) a0; \
|
||||
n0 = timer_set_alarm_value((timer_group_t) n2, (timer_idx_t) n1, val); NIPn(2)) \
|
||||
YV(timers, timer_get_alarm_value, \
|
||||
n0 = timer_get_alarm_value((timer_group_t) n2, (timer_idx_t) n1, \
|
||||
(uint64_t *) a0); NIPn(2)) \
|
||||
YV(timers, timer_set_alarm, \
|
||||
n0 = timer_set_alarm((timer_group_t) n2, (timer_idx_t) n1, \
|
||||
(timer_alarm_t) n0); NIPn(2)) \
|
||||
YV(timers, timer_group_intr_enable, \
|
||||
n0 = timer_group_intr_enable((timer_group_t) n1, (timer_intr_t) n0); NIP) \
|
||||
YV(timers, timer_group_intr_disable, \
|
||||
n0 = timer_group_intr_disable((timer_group_t) n1, (timer_intr_t) n0); NIP) \
|
||||
YV(timers, timer_enable_intr, \
|
||||
n0 = timer_enable_intr((timer_group_t) n1, (timer_idx_t) n0); NIP) \
|
||||
YV(timers, timer_disable_intr, \
|
||||
n0 = timer_disable_intr((timer_group_t) n1, (timer_idx_t) n0); NIP)
|
||||
|
||||
struct handle_interrupt_args {
|
||||
cell_t xt;
|
||||
cell_t arg;
|
||||
};
|
||||
|
||||
static void IRAM_ATTR HandleInterrupt(void *arg) {
|
||||
struct handle_interrupt_args *args = (struct handle_interrupt_args *) arg;
|
||||
cell_t code[2];
|
||||
code[0] = args->xt;
|
||||
code[1] = g_sys->YIELD_XT;
|
||||
cell_t fstack[INTERRUPT_STACK_CELLS];
|
||||
cell_t rstack[INTERRUPT_STACK_CELLS];
|
||||
cell_t stack[INTERRUPT_STACK_CELLS];
|
||||
stack[0] = args->arg;
|
||||
cell_t *rp = rstack;
|
||||
*++rp = (cell_t) code;
|
||||
*++rp = (cell_t) (fstack + 1);
|
||||
*++rp = (cell_t) (stack + 1);
|
||||
forth_run(rp);
|
||||
}
|
||||
|
||||
static bool IRAM_ATTR HandleInterruptAndRet(void *arg) {
|
||||
HandleInterrupt(arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
static cell_t EspIntrAlloc(cell_t source, cell_t flags, cell_t xt, cell_t arg, void *ret) {
|
||||
// NOTE: Leaks memory.
|
||||
struct handle_interrupt_args *args = (struct handle_interrupt_args *) malloc(sizeof(struct handle_interrupt_args));
|
||||
args->xt = xt;
|
||||
args->arg = arg;
|
||||
return esp_intr_alloc(source, flags, HandleInterrupt, args, (intr_handle_t *) ret);
|
||||
}
|
||||
|
||||
static cell_t GpioIsrHandlerAdd(cell_t pin, cell_t xt, cell_t arg) {
|
||||
// NOTE: Leaks memory.
|
||||
struct handle_interrupt_args *args = (struct handle_interrupt_args *) malloc(sizeof(struct handle_interrupt_args));
|
||||
args->xt = xt;
|
||||
args->arg = arg;
|
||||
return gpio_isr_handler_add((gpio_num_t) pin, HandleInterrupt, args);
|
||||
}
|
||||
|
||||
static void TimerInitNull(cell_t group, cell_t timer) {
|
||||
// Seems to be required starting in the 2.0 IDE.
|
||||
timer_config_t config;
|
||||
memset(&config, 0, sizeof(config));
|
||||
config.divider = 2;
|
||||
timer_init((timer_group_t) group, (timer_idx_t) timer, &config);
|
||||
}
|
||||
|
||||
static cell_t TimerIsrCallbackAdd(cell_t group, cell_t timer, cell_t xt, cell_t arg, cell_t flags) {
|
||||
// NOTE: Leaks memory.
|
||||
struct handle_interrupt_args *args = (struct handle_interrupt_args *) malloc(sizeof(struct handle_interrupt_args));
|
||||
args->xt = xt;
|
||||
args->arg = arg;
|
||||
return timer_isr_callback_add((timer_group_t) group, (timer_idx_t) timer, HandleInterruptAndRet, args, flags);
|
||||
}
|
||||
|
||||
{{interrupts}}
|
||||
@ -26,6 +26,10 @@ internals DEFINED? camera-source [IF]
|
||||
camera-source evaluate
|
||||
[THEN] forth
|
||||
|
||||
internals DEFINED? interrupts-source [IF]
|
||||
interrupts-source evaluate
|
||||
[THEN] forth
|
||||
|
||||
internals DEFINED? oled-source [IF]
|
||||
oled-source evaluate
|
||||
[THEN] forth
|
||||
|
||||
@ -13,7 +13,6 @@
|
||||
// limitations under the License.
|
||||
|
||||
#define STACK_CELLS 512
|
||||
#define INTERRUPT_STACK_CELLS 64
|
||||
#define MINIMUM_FREE_SYSTEM_HEAP (64 * 1024)
|
||||
|
||||
// Default on several options.
|
||||
@ -23,7 +22,6 @@
|
||||
#define ENABLE_I2C_SUPPORT
|
||||
#define ENABLE_SOCKETS_SUPPORT
|
||||
#define ENABLE_FREERTOS_SUPPORT
|
||||
#define ENABLE_INTERRUPTS_SUPPORT
|
||||
#define ENABLE_LEDC_SUPPORT
|
||||
#define ENABLE_SD_SUPPORT
|
||||
#define ENABLE_ESP32_FORTH_FAULT_HANDLING
|
||||
@ -91,9 +89,9 @@
|
||||
V(forth) V(internals) \
|
||||
V(rtos) V(SPIFFS) V(serial) V(SD) V(SD_MMC) V(ESP) \
|
||||
V(ledc) V(Wire) V(WiFi) V(sockets) \
|
||||
V(interrupts) V(timers) \
|
||||
OPTIONAL_CAMERA_VOCABULARY \
|
||||
OPTIONAL_BLUETOOTH_VOCABULARY \
|
||||
OPTIONAL_INTERRUPTS_VOCABULARIES \
|
||||
OPTIONAL_OLED_VOCABULARY \
|
||||
OPTIONAL_RMT_VOCABULARY \
|
||||
OPTIONAL_SPI_FLASH_VOCABULARY \
|
||||
|
||||
@ -25,15 +25,17 @@
|
||||
#define USER_WORDS
|
||||
|
||||
#define OPTIONAL_ASSEMBLERS_SUPPORT
|
||||
#define OPTIONAL_OLED_SUPPORT
|
||||
#define OPTIONAL_CAMERA_SUPPORT
|
||||
#define OPTIONAL_INTERRUPTS_SUPPORT
|
||||
#define OPTIONAL_OLED_SUPPORT
|
||||
#define OPTIONAL_RMT_SUPPORT
|
||||
#define OPTIONAL_SERIAL_BLUETOOTH_SUPPORT
|
||||
#define OPTIONAL_SPI_FLASH_SUPPORT
|
||||
|
||||
#define OPTIONAL_OLED_VOCABULARY
|
||||
#define OPTIONAL_CAMERA_VOCABULARY
|
||||
#define OPTIONAL_BLUETOOTH_VOCABULARY
|
||||
#define OPTIONAL_CAMERA_VOCABULARY
|
||||
#define OPTIONAL_INTERRUPTS_VOCABULARIES
|
||||
#define OPTIONAL_OLED_VOCABULARY
|
||||
#define OPTIONAL_RMT_VOCABULARY
|
||||
#define OPTIONAL_SPI_FLASH_VOCABULARY
|
||||
|
||||
|
||||
@ -22,9 +22,10 @@
|
||||
|
||||
#define SIM_HEAP_SIZE (100 * 1024 + 1024 * 1024)
|
||||
|
||||
#define OPTIONAL_OLED_VOCABULARY
|
||||
#define OPTIONAL_CAMERA_VOCABULARY
|
||||
#define OPTIONAL_BLUETOOTH_VOCABULARY
|
||||
#define OPTIONAL_CAMERA_VOCABULARY
|
||||
#define OPTIONAL_INTERRUPTS_VOCABULARIES
|
||||
#define OPTIONAL_OLED_VOCABULARY
|
||||
#define OPTIONAL_RMT_VOCABULARY
|
||||
#define OPTIONAL_SPI_FLASH_VOCABULARY
|
||||
|
||||
@ -104,9 +105,6 @@ static cell_t *simulated(cell_t *sp, const char *op) {
|
||||
} else if (op == STR_digitalWrite) {
|
||||
sp -= 2;
|
||||
return sp;
|
||||
} else if (op == STR_gpio_install_isr_service) {
|
||||
*sp = 0;
|
||||
return sp;
|
||||
} else if (op == STR_SERIAL_AVAILABLE) {
|
||||
*++sp = 1;
|
||||
return sp;
|
||||
|
||||
@ -474,45 +474,6 @@ WiFi.softAPgetStationNum ( -- num )
|
||||
MDNS.begin ( name-z -- ) Start multicast dns
|
||||
</pre>
|
||||
|
||||
<h5>SPI Flash</h5>
|
||||
These words are inside the <code>spi_flash</code> vocabulary.
|
||||
<p><b>
|
||||
NOTE: Starting in v7.0.7.13 the optional module spi-flash.h must be
|
||||
placed next to ESP32forth.ino to include this capability.
|
||||
</b></p>
|
||||
<pre>
|
||||
spi_flash_init ( -- ) Init driver access.
|
||||
spi_flash_get_chip_size ( -- n ) Get flash size.
|
||||
spi_flash_erase_sector ( sector -- err ) Erase a sector.
|
||||
spi_flash_erase_range ( addr size -- err ) Erase a range.
|
||||
spi_flash_write ( destaddr src size -- err ) Write to flash.
|
||||
spi_flash_write_encrypted ( destaddr src size -- err ) Write encrypted.
|
||||
spi_flash_read ( srcaddr dst size -- err ) Read from flash.
|
||||
spi_flash_read_encrypted ( srcaddr dst size -- err ) Read encrypted.
|
||||
spi_flash_mmap ( srcaddr size memtype out outhandle -- err ) Map region.
|
||||
spi_flash_mmap_pages ( pages pages# memtype out outhandle -- err ) Map pages.
|
||||
spi_flash_munmap ( handle -- ) Unmap region.
|
||||
spi_flash_mmap_dump ( -- ) Dump memory map.
|
||||
spi_flash_mmap_get_free_pages ( memtype -- n ) Get free pages.
|
||||
spi_flash_cache2phys ( a -- addr ) Get flash addr.
|
||||
spi_flash_phys2cache ( addr memtype -- a ) Get mapped flash addr.
|
||||
spi_flash_cache_enabled ( -- f ) Is flash enabled.
|
||||
|
||||
esp_partition_t_size ( -- n ) sizeof(esp_parition_t).
|
||||
esp_partition_find ( type subtype szlabel -- it ) Get partition iterator.
|
||||
esp_partition_find_first ( type subtype szlabel -- part ) Get first partition.
|
||||
esp_partition_get ( it -- part ) Get current partition.
|
||||
esp_partition_next ( it -- it' ) Get next partition.
|
||||
esp_partition_iterator_release ( it -- ) Free iterator.
|
||||
esp_partition_verify ( part -- part' ) Verify partition.
|
||||
esp_partition_read ( part srcoff dst size -- err ) Read from partition.
|
||||
esp_partition_write ( part dstoff src size -- err ) Write to partition.
|
||||
esp_partition_erase_range ( part start size -- err ) Erase range.
|
||||
esp_partition_mmap ( part off size memtype out outhandle -- err ) Map memory.
|
||||
esp_partition_get_sha256 ( part a -- err ) Get sha256 digest.
|
||||
esp_partition_check_identity ( part part -- f ) Check partitions for equality.
|
||||
</pre>
|
||||
|
||||
<h5>SPIFFS</h5>
|
||||
These words are inside the <code>SPIFFS</code> vocabulary.
|
||||
<pre>
|
||||
@ -614,6 +575,169 @@ Wire.writeTransmission ( addr a n sendstop -- err )
|
||||
Wire.readTransmission ( addr a n sendstop acount -- err )
|
||||
</pre>
|
||||
|
||||
<h5>SD</h5>
|
||||
These words are inside the <code>SD</code> vocabulary.
|
||||
They allow use of an SDcard over SPI.
|
||||
<pre>
|
||||
SD.begin ( -- ok ) uses all the defaults "/sd" etc.
|
||||
SD.beginDefaults ( -- sspin SPIClass frequency mountpointsz maxfiles format_if_empty )
|
||||
( SS SPI 4000000 "/sd" 5 false )
|
||||
SD.beginFull ( sspin SPIClass frequency mountpoint maxfiles format_if_empty -- ok )
|
||||
SD.end ( -- )
|
||||
SD.cardType ( -- n )
|
||||
SD.totalBytes ( -- n )
|
||||
SD.usedBytes ( -- n )
|
||||
</pre>
|
||||
|
||||
<h5>SD_MMC</h5>
|
||||
These words are inside the <code>SD_MMC</code> vocabulary.
|
||||
They allow use of an SDcard over MMC internal interface.
|
||||
<br/>
|
||||
Note, SD_MMC is unavailable on ESP32-S2 and ESP32-C3.
|
||||
<pre>
|
||||
SD_MMC.begin ( -- ok ) uses all the defaults "/sdcard" etc.
|
||||
SD_MMC.beginDefaults ( -- mountsz mode1bit format_if_fail )
|
||||
( "/sdcard" false false )
|
||||
( sdmmc_freq not supported for generality )
|
||||
SD_MMC.beginFull ( mountsz mode1bit format_if_fail -- ok )
|
||||
SD_MMC.end ( -- )
|
||||
SD_MMC.cardType ( -- n )
|
||||
SD_MMC.totalBytes ( -- n )
|
||||
SD_MMC.usedBytes ( -- n )
|
||||
</pre>
|
||||
|
||||
<h5 id="tasks">Tasks</h5>
|
||||
These words are inside the <code>TASKS</code> vocabulary.
|
||||
|
||||
<pre>
|
||||
PAUSE ( -- ) Yield to other tasks.
|
||||
MS ( n -- ) Pause for some number of milliseconds (yields to other tasks).
|
||||
TASK ( xt dsz rsz "name" -- ) Create a new task with dsz size data stack
|
||||
and rsz size return stack running xt.
|
||||
START-TASK ( task -- ) Activate a task.
|
||||
.TASKS ( -- ) List running tasks.
|
||||
|
||||
Example:
|
||||
tasks
|
||||
: hi begin ." Time is: " ms-ticks . cr 1000 ms again ;
|
||||
' hi 100 100 task my-counter
|
||||
my-counter start-task
|
||||
</pre>
|
||||
|
||||
<h5>RTOS</h5>
|
||||
These words are inside the <code>RTOS</code> vocabulary.
|
||||
<pre>
|
||||
xPortGetCoreID ( -- n )
|
||||
xTaskCreatePinnedToCore ( fn name stack-depth params priority taskout coreid -- )
|
||||
vTaskDelete ( task ) -- )
|
||||
</pre>
|
||||
|
||||
<h3 id="webui">ESP32 WebUI</h3>
|
||||
|
||||
<p>
|
||||
A terminal over the web can be activated.
|
||||
Contact at port printed or via mDNS <a href="http://forth/">http://forth/</a>.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
webui ( network-z password-z -- ) login and start webui
|
||||
login ( network-z password-z -- ) login to wifi only
|
||||
</pre>
|
||||
|
||||
<p>Usage:</p>
|
||||
|
||||
<pre>
|
||||
z" NETWORK-NAME" z" PASSWORD" webui
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
See <a href="https://github.com/flagxor/ueforth/blob/main/esp32/web_interface.fs">web_interface.fs</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="autoexec">Autoexec.fs</h3>
|
||||
|
||||
<p>
|
||||
NOTE: This section describes one mechanism for running code at startup.
|
||||
See <a href="#dictimages">this</a> for an alternate option.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The system will automatically attempt to mount SPIFFS filesystem at <code>/spiffs</code>.
|
||||
It will then at start attempt to load <code>/spiffs/autoexec.fs</code>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
One way this feature can be used to configure the Web UI to start by default.
|
||||
When doing this, be sure to test your Web UI settings work well first.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
r| z" NETWORK-NAME" z" PASSWORD" webui | s" /spiffs/autoexec.fs" dump-file
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
To remove a previously configured <code>autoexec.fs</code> you will need
|
||||
to be able to reboot in a mode with Forth. One way to do this is to search
|
||||
for the line in the .ino file that refers to <code>autoexec.fs</code>
|
||||
and replace it with a different name. Then run the following:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
s" /spiffs/autoexec.fs" delete-file
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
See <a href="https://github.com/flagxor/ueforth/blob/main/esp32/autoboot.fs">autoboot.fs</a>.
|
||||
</p>
|
||||
|
||||
|
||||
<h3>ESP32forth Optional Modules</h3>
|
||||
|
||||
<p>
|
||||
Several optional modules are now available in the <code>optional/</code>
|
||||
directory next to ESP32forth.ino. To use these modules,
|
||||
move them up a directory to be adjacent to ESP32forth.ino.
|
||||
</p>
|
||||
|
||||
<h5>SPI Flash</h5>
|
||||
These words are inside the <code>spi_flash</code> vocabulary.
|
||||
<p><b>
|
||||
NOTE: Starting in v7.0.7.13 the optional module spi-flash.h must be
|
||||
placed next to ESP32forth.ino to include this capability.
|
||||
</b></p>
|
||||
<pre>
|
||||
spi_flash_init ( -- ) Init driver access.
|
||||
spi_flash_get_chip_size ( -- n ) Get flash size.
|
||||
spi_flash_erase_sector ( sector -- err ) Erase a sector.
|
||||
spi_flash_erase_range ( addr size -- err ) Erase a range.
|
||||
spi_flash_write ( destaddr src size -- err ) Write to flash.
|
||||
spi_flash_write_encrypted ( destaddr src size -- err ) Write encrypted.
|
||||
spi_flash_read ( srcaddr dst size -- err ) Read from flash.
|
||||
spi_flash_read_encrypted ( srcaddr dst size -- err ) Read encrypted.
|
||||
spi_flash_mmap ( srcaddr size memtype out outhandle -- err ) Map region.
|
||||
spi_flash_mmap_pages ( pages pages# memtype out outhandle -- err ) Map pages.
|
||||
spi_flash_munmap ( handle -- ) Unmap region.
|
||||
spi_flash_mmap_dump ( -- ) Dump memory map.
|
||||
spi_flash_mmap_get_free_pages ( memtype -- n ) Get free pages.
|
||||
spi_flash_cache2phys ( a -- addr ) Get flash addr.
|
||||
spi_flash_phys2cache ( addr memtype -- a ) Get mapped flash addr.
|
||||
spi_flash_cache_enabled ( -- f ) Is flash enabled.
|
||||
|
||||
esp_partition_t_size ( -- n ) sizeof(esp_parition_t).
|
||||
esp_partition_find ( type subtype szlabel -- it ) Get partition iterator.
|
||||
esp_partition_find_first ( type subtype szlabel -- part ) Get first partition.
|
||||
esp_partition_get ( it -- part ) Get current partition.
|
||||
esp_partition_next ( it -- it' ) Get next partition.
|
||||
esp_partition_iterator_release ( it -- ) Free iterator.
|
||||
esp_partition_verify ( part -- part' ) Verify partition.
|
||||
esp_partition_read ( part srcoff dst size -- err ) Read from partition.
|
||||
esp_partition_write ( part dstoff src size -- err ) Write to partition.
|
||||
esp_partition_erase_range ( part start size -- err ) Erase range.
|
||||
esp_partition_mmap ( part off size memtype out outhandle -- err ) Map memory.
|
||||
esp_partition_get_sha256 ( part a -- err ) Get sha256 digest.
|
||||
esp_partition_check_identity ( part part -- f ) Check partitions for equality.
|
||||
</pre>
|
||||
|
||||
<h5>Camera</h5>
|
||||
These words are inside the <code>camera</code> vocabulary.
|
||||
<p><b>
|
||||
@ -718,39 +842,12 @@ server ( port -- ) Start an image server at port,
|
||||
e.g. http://IP/image will produce an image
|
||||
</pre>
|
||||
|
||||
<h5>SD</h5>
|
||||
These words are inside the <code>SD</code> vocabulary.
|
||||
They allow use of an SDcard over SPI.
|
||||
<pre>
|
||||
SD.begin ( -- ok ) uses all the defaults "/sd" etc.
|
||||
SD.beginDefaults ( -- sspin SPIClass frequency mountpointsz maxfiles format_if_empty )
|
||||
( SS SPI 4000000 "/sd" 5 false )
|
||||
SD.beginFull ( sspin SPIClass frequency mountpoint maxfiles format_if_empty -- ok )
|
||||
SD.end ( -- )
|
||||
SD.cardType ( -- n )
|
||||
SD.totalBytes ( -- n )
|
||||
SD.usedBytes ( -- n )
|
||||
</pre>
|
||||
|
||||
<h5>SD_MMC</h5>
|
||||
These words are inside the <code>SD_MMC</code> vocabulary.
|
||||
They allow use of an SDcard over MMC internal interface.
|
||||
<br/>
|
||||
Note, SD_MMC is unavailable on ESP32-S2 and ESP32-C3.
|
||||
<pre>
|
||||
SD_MMC.begin ( -- ok ) uses all the defaults "/sdcard" etc.
|
||||
SD_MMC.beginDefaults ( -- mountsz mode1bit format_if_fail )
|
||||
( "/sdcard" false false )
|
||||
( sdmmc_freq not supported for generality )
|
||||
SD_MMC.beginFull ( mountsz mode1bit format_if_fail -- ok )
|
||||
SD_MMC.end ( -- )
|
||||
SD_MMC.cardType ( -- n )
|
||||
SD_MMC.totalBytes ( -- n )
|
||||
SD_MMC.usedBytes ( -- n )
|
||||
</pre>
|
||||
|
||||
<h5 id="interrupts">Interrupts</h5>
|
||||
These words are inside the <code>INTERRUPTS</code> vocabulary.
|
||||
<p><b>
|
||||
NOTE: Starting in v7.0.7.15 the optional module interrupts.h must be
|
||||
placed next to ESP32forth.ino to include this capability.
|
||||
</b></p>
|
||||
|
||||
<p>High Level words:</p>
|
||||
<pre>
|
||||
@ -758,15 +855,13 @@ pinchange ( xt pin -- ) Call xt when pin changes.
|
||||
</pre>
|
||||
|
||||
<p>Example:</p>
|
||||
|
||||
<pre>
|
||||
17 input pinMode
|
||||
: test ." pinvalue: " 17 digitalRead . cr ;
|
||||
' test 17 pinchange
|
||||
</pre>
|
||||
|
||||
<h5 id="interrupts">Interrupts</h5>
|
||||
These words are inside the <code>interrupts</code> vocabulary.
|
||||
<p>Low Level words:</p>
|
||||
<pre>
|
||||
ESP_INTR_FLAG_DEFAULT -- Default handler allows per pin routing
|
||||
|
||||
@ -887,26 +982,12 @@ rmt_clr_intr_enable_mask --- DEPRECATED interrupt handled by driver
|
||||
rmt_set_pin --- DEPRECATED use rmt_set_gpio instead
|
||||
</pre>
|
||||
|
||||
<h5 id="tasks">Tasks</h5>
|
||||
These words are inside the <code>TASKS</code> vocabulary.
|
||||
|
||||
<pre>
|
||||
PAUSE ( -- ) Yield to other tasks.
|
||||
MS ( n -- ) Pause for some number of milliseconds (yields to other tasks).
|
||||
TASK ( xt dsz rsz "name" -- ) Create a new task with dsz size data stack
|
||||
and rsz size return stack running xt.
|
||||
START-TASK ( task -- ) Activate a task.
|
||||
.TASKS ( -- ) List running tasks.
|
||||
|
||||
Example:
|
||||
tasks
|
||||
: hi begin ." Time is: " ms-ticks . cr 1000 ms again ;
|
||||
' hi 100 100 task my-counter
|
||||
my-counter start-task
|
||||
</pre>
|
||||
|
||||
<h5 id="timers">Timers</h5>
|
||||
These words are inside the <code>TIMERS</code> vocabulary.
|
||||
<p><b>
|
||||
NOTE: Starting in v7.0.7.15 the optional module interrupts.h must be
|
||||
placed next to ESP32forth.ino to include this capability.
|
||||
</b></p>
|
||||
|
||||
<br/><b>NOTE: These are low level ESP32 timers. For a periodic background
|
||||
operation, you'll probably want to use <a href="#tasks">TASKS</a>.</b>
|
||||
@ -974,72 +1055,6 @@ TIMGn_Tx_INT_ST_REG ( n -- a )
|
||||
TIMGn_Tx_INT_CLR_REG ( n -- a )
|
||||
</pre>
|
||||
|
||||
<h5>RTOS</h5>
|
||||
These words are inside the <code>RTOS</code> vocabulary.
|
||||
<pre>
|
||||
xPortGetCoreID ( -- n )
|
||||
xTaskCreatePinnedToCore ( fn name stack-depth params priority taskout coreid -- )
|
||||
vTaskDelete ( task ) -- )
|
||||
</pre>
|
||||
|
||||
<h3 id="webui">ESP32 WebUI</h3>
|
||||
|
||||
<p>
|
||||
A terminal over the web can be activated.
|
||||
Contact at port printed or via mDNS <a href="http://forth/">http://forth/</a>.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
webui ( network-z password-z -- ) login and start webui
|
||||
login ( network-z password-z -- ) login to wifi only
|
||||
</pre>
|
||||
|
||||
<p>Usage:</p>
|
||||
|
||||
<pre>
|
||||
z" NETWORK-NAME" z" PASSWORD" webui
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
See <a href="https://github.com/flagxor/ueforth/blob/main/esp32/web_interface.fs">web_interface.fs</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="autoexec">Autoexec.fs</h3>
|
||||
|
||||
<p>
|
||||
NOTE: This section describes one mechanism for running code at startup.
|
||||
See <a href="#dictimages">this</a> for an alternate option.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The system will automatically attempt to mount SPIFFS filesystem at <code>/spiffs</code>.
|
||||
It will then at start attempt to load <code>/spiffs/autoexec.fs</code>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
One way this feature can be used to configure the Web UI to start by default.
|
||||
When doing this, be sure to test your Web UI settings work well first.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
r| z" NETWORK-NAME" z" PASSWORD" webui | s" /spiffs/autoexec.fs" dump-file
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
To remove a previously configured <code>autoexec.fs</code> you will need
|
||||
to be able to reboot in a mode with Forth. One way to do this is to search
|
||||
for the line in the .ino file that refers to <code>autoexec.fs</code>
|
||||
and replace it with a different name. Then run the following:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
s" /spiffs/autoexec.fs" delete-file
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
See <a href="https://github.com/flagxor/ueforth/blob/main/esp32/autoboot.fs">autoboot.fs</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="adding_words">Adding Words</h3>
|
||||
|
||||
<p>
|
||||
|
||||
@ -51,6 +51,9 @@ enum {
|
||||
#undef V
|
||||
};
|
||||
|
||||
static cell_t *forth_run(cell_t *init_rp) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc == 2 && strcmp(argv[1], "cases") == 0) {
|
||||
@ -75,6 +78,8 @@ int main(int argc, char *argv[]) {
|
||||
TIER0_OPCODE_LIST
|
||||
#undef Z
|
||||
} else if (argc == 2 && strcmp(argv[1], "sys") == 0) {
|
||||
(void) g_sys;
|
||||
(void) forth_run;
|
||||
G_SYS *g_sys = 0;
|
||||
#define G_SYS 256
|
||||
printf(" const g_sys = %d;\n", G_SYS);
|
||||
|
||||
Reference in New Issue
Block a user