diff --git a/lib/libesp32/Berry/default/be_flash_lib.c b/lib/libesp32/Berry/default/be_flash_lib.c new file mode 100644 index 000000000..b05b23637 --- /dev/null +++ b/lib/libesp32/Berry/default/be_flash_lib.c @@ -0,0 +1,32 @@ +/******************************************************************** + * Berry module `webserver` + * + * To use: `import webserver` + * + * Allows to respond to HTTP request + *******************************************************************/ +#include "be_constobj.h" + +extern int p_flash_read(bvm *vm); +extern int p_flash_write(bvm *vm); +extern int p_flash_erase(bvm *vm); + +#if !BE_USE_PRECOMPILED_OBJECT +be_native_module_attr_table(flash) { + be_native_module_function("read", p_flash_read), + be_native_module_function("write", p_flash_write), + be_native_module_function("erase", p_flash_erase), + +}; + +be_define_native_module(flash, NULL); +#else +/* @const_object_info_begin +module flash (scope: global) { + read, func(p_flash_read) + write, func(p_flash_write) + erase, func(p_flash_erase) +} +@const_object_info_end */ +#include "../generate/be_fixed_flash.h" +#endif diff --git a/lib/libesp32/Berry/default/be_modtab.c b/lib/libesp32/Berry/default/be_modtab.c index e79d3c9cb..4a9c4d7ba 100644 --- a/lib/libesp32/Berry/default/be_modtab.c +++ b/lib/libesp32/Berry/default/be_modtab.c @@ -26,6 +26,7 @@ be_extern_native_module(light); be_extern_native_module(gpio); be_extern_native_module(energy); be_extern_native_module(webserver); +be_extern_native_module(flash); #ifdef USE_LVGL be_extern_native_module(lvgl); #endif // USE_LVGL @@ -83,6 +84,7 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = { #ifdef USE_WEBSERVER &be_native_module(webserver), #endif // USE_WEBSERVER + &be_native_module(flash), /* user-defined modules register end */ diff --git a/lib/libesp32/Berry/generate/be_const_strtab.h b/lib/libesp32/Berry/generate/be_const_strtab.h index a7b4cb905..17904c043 100644 --- a/lib/libesp32/Berry/generate/be_const_strtab.h +++ b/lib/libesp32/Berry/generate/be_const_strtab.h @@ -223,6 +223,7 @@ extern const bcstring be_const_str_SYMBOL_NEXT; extern const bcstring be_const_str_lv_label; extern const bcstring be_const_str_str; extern const bcstring be_const_str_ZIGBEE_TX; +extern const bcstring be_const_str_erase; extern const bcstring be_const_str_ILI9341_CS; extern const bcstring be_const_str_VL53L0X_XSHUT1; extern const bcstring be_const_str_time_reached; diff --git a/lib/libesp32/Berry/generate/be_const_strtab_def.h b/lib/libesp32/Berry/generate/be_const_strtab_def.h index 31c2c5338..f20cfe652 100644 --- a/lib/libesp32/Berry/generate/be_const_strtab_def.h +++ b/lib/libesp32/Berry/generate/be_const_strtab_def.h @@ -222,7 +222,8 @@ be_define_const_str(FALLING, "FALLING", 2851701064u, 0, 7, &be_const_str_SYMBOL_ be_define_const_str(SYMBOL_NEXT, "SYMBOL_NEXT", 1102844455u, 0, 11, &be_const_str_lv_label); be_define_const_str(lv_label, "lv_label", 4199664246u, 0, 8, NULL); be_define_const_str(str, "str", 3259748752u, 0, 3, NULL); -be_define_const_str(ZIGBEE_TX, "ZIGBEE_TX", 25119256u, 0, 9, NULL); +be_define_const_str(ZIGBEE_TX, "ZIGBEE_TX", 25119256u, 0, 9, &be_const_str_erase); +be_define_const_str(erase, "erase", 1010949589u, 0, 5, NULL); be_define_const_str(ILI9341_CS, "ILI9341_CS", 3519318851u, 0, 10, &be_const_str_VL53L0X_XSHUT1); be_define_const_str(VL53L0X_XSHUT1, "VL53L0X_XSHUT1", 2341134183u, 0, 14, &be_const_str_time_reached); be_define_const_str(time_reached, "time_reached", 2075136773u, 0, 12, NULL); @@ -868,6 +869,6 @@ static const bstring* const m_string_table[] = { static const struct bconststrtab m_const_string_table = { .size = 281, - .count = 562, + .count = 563, .table = m_string_table }; diff --git a/lib/libesp32/Berry/generate/be_fixed_flash.h b/lib/libesp32/Berry/generate/be_fixed_flash.h new file mode 100644 index 000000000..fc9305aac --- /dev/null +++ b/lib/libesp32/Berry/generate/be_fixed_flash.h @@ -0,0 +1,19 @@ +#include "be_constobj.h" + +static be_define_const_map_slots(m_libflash_map) { + { be_const_key(read, -1), be_const_func(p_flash_read) }, + { be_const_key(erase, -1), be_const_func(p_flash_erase) }, + { be_const_key(write, -1), be_const_func(p_flash_write) }, +}; + +static be_define_const_map( + m_libflash_map, + 3 +); + +static be_define_const_module( + m_libflash, + "flash" +); + +BE_EXPORT_VARIABLE be_define_const_native_module(flash, NULL); diff --git a/tasmota/xdrv_52_3_berry_flash.ino b/tasmota/xdrv_52_3_berry_flash.ino new file mode 100644 index 000000000..5670365e4 --- /dev/null +++ b/tasmota/xdrv_52_3_berry_flash.ino @@ -0,0 +1,107 @@ +/* + xdrv_52_3_berry_webserver.ino - Berry scripting language, webserver module + + Copyright (C) 2021 Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + +#ifdef USE_BERRY + +#include +#include "esp_spi_flash.h" + +/*********************************************************************************************\ + * Native functions mapped to Berry functions + * + * import flash + * +\*********************************************************************************************/ +extern "C" { + // Berry: `flash.read(address:int[, length:int]) -> bytes()` + // + // If length is not specified, it is full block 4KB + int32_t p_flash_read(struct bvm *vm); + int32_t p_flash_read(struct bvm *vm) { + int32_t argc = be_top(vm); // Get the number of arguments + if (argc >= 1 && be_isint(vm, 1) && + (argc < 2 || be_isint(vm, 2)) ) { // optional second argument must be int + uint32_t address = be_toint(vm, 1); + uint32_t length = 0x1000; + if (argc >= 2) { + length = be_toint(vm, 2); + if (length <= 0) { length = 0x1000; } + } + // allocate a buffer in the heap that will be automatically freed when going out of scope + auto buf = std::unique_ptr(new uint8_t[length]); + esp_err_t ret = spi_flash_read(address, buf.get(), length); + if (ret) { + be_raise(vm, "internal_error", "Error calling spi_flash_read()"); + } + be_pushbytes(vm, buf.get(), length); + be_return(vm); + } + be_raise(vm, kTypeError, nullptr); + } + + // Berry: `flash.write(address:int, content:bytes()) -> nil` + // + // If length is not specified, it is full block 4KB + int32_t p_flash_write(struct bvm *vm); + int32_t p_flash_write(struct bvm *vm) { + int32_t argc = be_top(vm); // Get the number of arguments + if (argc >= 2 && be_isint(vm, 1) && be_isinstance(vm, 2)) { + be_getglobal(vm, "bytes"); /* get the bytes class */ /* TODO eventually replace with be_getbuiltin */ + if (be_isderived(vm, 2)) { + uint32_t address = be_toint(vm, 1); + size_t length = 0; + const void * bytes = be_tobytes(vm, 2, &length); + if (bytes && length > 0) { + esp_err_t ret = spi_flash_write(address, bytes, length); + if (ret) { + be_raise(vm, "internal_error", "Error calling spi_flash_read()"); + } + be_return_nil(vm); + // success + } + } + } + be_raise(vm, kTypeError, nullptr); + } + + // Berry: `flash.erase(address:int, length:int) -> nil` + // + // Address and length must be 4KB aligned + int32_t p_flash_erase(struct bvm *vm); + int32_t p_flash_erase(struct bvm *vm) { + int32_t argc = be_top(vm); // Get the number of arguments + if (argc >= 2 && be_isint(vm, 1) && be_isint(vm, 2)) { + int32_t address = be_toint(vm, 1); + int32_t length = be_toint(vm, 2); + if ((address % 0x1000) != 0 || address < 0) { + be_raise(vm, "value_error", "Address must be a multiple of 0x1000"); + } + if ((length % 0x1000) != 0 || length < 0) { + be_raise(vm, "value_error", "Length must be a multiple of 0x1000"); + } + esp_err_t ret = spi_flash_erase_range(address, length); + be_return_nil(vm); + } + be_raise(vm, kTypeError, nullptr); + } + +} + +#endif // USE_BERRY