diff --git a/Makefile b/Makefile index d7d9bf6..a48699c 100644 --- a/Makefile +++ b/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 diff --git a/common/bits.h b/common/bits.h index b05d430..97ceca2 100644 --- a/common/bits.h +++ b/common/bits.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); diff --git a/common/core.h b/common/core.h index a4544ee..c073043 100644 --- a/common/core.h +++ b/common/core.h @@ -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; diff --git a/common/forth_namespace_tests.fs b/common/forth_namespace_tests.fs index 537ed4f..c4ea266 100644 --- a/common/forth_namespace_tests.fs +++ b/common/forth_namespace_tests.fs @@ -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 diff --git a/esp32/ESP32forth.ino b/esp32/ESP32forth.ino index b556050..ca698f7 100644 --- a/esp32/ESP32forth.ino +++ b/esp32/ESP32forth.ino @@ -26,6 +26,7 @@ {{tier2_opcodes}} {{floats}} {{calls}} +{{bits}} {{builtins.h}} {{builtins.cpp}} {{main.cpp}} diff --git a/esp32/bindings.fs b/esp32/bindings.fs index 01ac1d0..dbd69d8 100644 --- a/esp32/bindings.fs +++ b/esp32/bindings.fs @@ -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 diff --git a/esp32/builtins.cpp b/esp32/builtins.cpp index f798302..80c27ed 100644 --- a/esp32/builtins.cpp +++ b/esp32/builtins.cpp @@ -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 diff --git a/esp32/builtins.h b/esp32/builtins.h index cd0170f..74b37a6 100644 --- a/esp32/builtins.h +++ b/esp32/builtins.h @@ -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 diff --git a/esp32/optional/interrupts/interrupts.fs b/esp32/optional/interrupts/interrupts.fs new file mode 100644 index 0000000..96a28e2 --- /dev/null +++ b/esp32/optional/interrupts/interrupts.fs @@ -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 diff --git a/esp32/optional/interrupts/interrupts.h b/esp32/optional/interrupts/interrupts.h new file mode 100644 index 0000000..b5c2197 --- /dev/null +++ b/esp32/optional/interrupts/interrupts.h @@ -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}} diff --git a/esp32/timers.fs b/esp32/optional/interrupts/timers.fs similarity index 100% rename from esp32/timers.fs rename to esp32/optional/interrupts/timers.fs diff --git a/esp32/optionals.fs b/esp32/optionals.fs index c383c22..9f5d7df 100644 --- a/esp32/optionals.fs +++ b/esp32/optionals.fs @@ -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 diff --git a/esp32/options.h b/esp32/options.h index a85da02..6250c6e 100644 --- a/esp32/options.h +++ b/esp32/options.h @@ -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 \ diff --git a/esp32/print-builtins.cpp b/esp32/print-builtins.cpp index b32b5a2..c5e1037 100644 --- a/esp32/print-builtins.cpp +++ b/esp32/print-builtins.cpp @@ -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 diff --git a/esp32/sim_main.cpp b/esp32/sim_main.cpp index a6d3516..7ca335e 100644 --- a/esp32/sim_main.cpp +++ b/esp32/sim_main.cpp @@ -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; diff --git a/site/ESP32forth.html b/site/ESP32forth.html index 61de242..b973183 100644 --- a/site/ESP32forth.html +++ b/site/ESP32forth.html @@ -474,45 +474,6 @@ WiFi.softAPgetStationNum ( -- num ) MDNS.begin ( name-z -- ) Start multicast dns -
SPI Flash
-These words are inside the spi_flash vocabulary. -

- NOTE: Starting in v7.0.7.13 the optional module spi-flash.h must be - placed next to ESP32forth.ino to include this capability. -

-
-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.
-
-
SPIFFS
These words are inside the SPIFFS vocabulary.
@@ -614,6 +575,169 @@ Wire.writeTransmission ( addr a n sendstop -- err )
 Wire.readTransmission ( addr a n sendstop acount -- err )
 
+
SD
+These words are inside the SD vocabulary. +They allow use of an SDcard over SPI. +
+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 )
+
+ +
SD_MMC
+These words are inside the SD_MMC vocabulary. +They allow use of an SDcard over MMC internal interface. +
+Note, SD_MMC is unavailable on ESP32-S2 and ESP32-C3. +
+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 )
+
+ +
Tasks
+These words are inside the TASKS vocabulary. + +
+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
+
+ +
RTOS
+These words are inside the RTOS vocabulary. +
+xPortGetCoreID ( -- n )
+xTaskCreatePinnedToCore ( fn name stack-depth params priority taskout coreid -- )
+vTaskDelete ( task ) -- )
+
+ +

ESP32 WebUI

+ +

+A terminal over the web can be activated. +Contact at port printed or via mDNS http://forth/. +

+ +
+webui ( network-z password-z -- ) login and start webui
+login ( network-z password-z -- ) login to wifi only
+
+ +

Usage:

+ +
+z" NETWORK-NAME" z" PASSWORD" webui
+
+ +

+See web_interface.fs. +

+ +

Autoexec.fs

+ +

+NOTE: This section describes one mechanism for running code at startup. +See this for an alternate option. +

+ +

+The system will automatically attempt to mount SPIFFS filesystem at /spiffs. +It will then at start attempt to load /spiffs/autoexec.fs +

+ +

+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. +

+ +
+r| z" NETWORK-NAME" z" PASSWORD" webui | s" /spiffs/autoexec.fs" dump-file
+
+ +

+To remove a previously configured autoexec.fs 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 autoexec.fs +and replace it with a different name. Then run the following: +

+ +
+s" /spiffs/autoexec.fs" delete-file
+
+ +

+See autoboot.fs. +

+ + +

ESP32forth Optional Modules

+ +

+Several optional modules are now available in the optional/ +directory next to ESP32forth.ino. To use these modules, +move them up a directory to be adjacent to ESP32forth.ino. +

+ +
SPI Flash
+These words are inside the spi_flash vocabulary. +

+ NOTE: Starting in v7.0.7.13 the optional module spi-flash.h must be + placed next to ESP32forth.ino to include this capability. +

+
+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.
+
+
Camera
These words are inside the camera vocabulary.

@@ -718,39 +842,12 @@ server ( port -- ) Start an image server at port, e.g. http://IP/image will produce an image -

SD
-These words are inside the SD vocabulary. -They allow use of an SDcard over SPI. -
-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 )
-
- -
SD_MMC
-These words are inside the SD_MMC vocabulary. -They allow use of an SDcard over MMC internal interface. -
-Note, SD_MMC is unavailable on ESP32-S2 and ESP32-C3. -
-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 )
-
-
Interrupts
These words are inside the INTERRUPTS vocabulary. +

+ NOTE: Starting in v7.0.7.15 the optional module interrupts.h must be + placed next to ESP32forth.ino to include this capability. +

High Level words:

@@ -758,15 +855,13 @@ pinchange ( xt pin -- ) Call xt when pin changes.
 

Example:

-
 17 input pinMode
 : test ." pinvalue: " 17 digitalRead . cr ;
 ' test 17 pinchange
 
-
Interrupts
-These words are inside the interrupts vocabulary. +

Low Level words:

 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
 
-
Tasks
-These words are inside the TASKS vocabulary. - -
-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
-
-
Timers
These words are inside the TIMERS vocabulary. +

+ NOTE: Starting in v7.0.7.15 the optional module interrupts.h must be + placed next to ESP32forth.ino to include this capability. +


NOTE: These are low level ESP32 timers. For a periodic background operation, you'll probably want to use TASKS. @@ -974,72 +1055,6 @@ TIMGn_Tx_INT_ST_REG ( n -- a ) TIMGn_Tx_INT_CLR_REG ( n -- a ) -
RTOS
-These words are inside the RTOS vocabulary. -
-xPortGetCoreID ( -- n )
-xTaskCreatePinnedToCore ( fn name stack-depth params priority taskout coreid -- )
-vTaskDelete ( task ) -- )
-
- -

ESP32 WebUI

- -

-A terminal over the web can be activated. -Contact at port printed or via mDNS http://forth/. -

- -
-webui ( network-z password-z -- ) login and start webui
-login ( network-z password-z -- ) login to wifi only
-
- -

Usage:

- -
-z" NETWORK-NAME" z" PASSWORD" webui
-
- -

-See web_interface.fs. -

- -

Autoexec.fs

- -

-NOTE: This section describes one mechanism for running code at startup. -See this for an alternate option. -

- -

-The system will automatically attempt to mount SPIFFS filesystem at /spiffs. -It will then at start attempt to load /spiffs/autoexec.fs -

- -

-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. -

- -
-r| z" NETWORK-NAME" z" PASSWORD" webui | s" /spiffs/autoexec.fs" dump-file
-
- -

-To remove a previously configured autoexec.fs 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 autoexec.fs -and replace it with a different name. Then run the following: -

- -
-s" /spiffs/autoexec.fs" delete-file
-
- -

-See autoboot.fs. -

-

Adding Words

diff --git a/web/dump_web_opcodes.c b/web/dump_web_opcodes.c index 4972810..05a3baa 100644 --- a/web/dump_web_opcodes.c +++ b/web/dump_web_opcodes.c @@ -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);