mirror of https://github.com/arendst/Tasmota.git
Berry flash write unaligned and download to flash
This commit is contained in:
parent
bc64dd6b9d
commit
f28dc39b82
|
@ -1016,6 +1016,7 @@ extern const bcstring be_const_str_write8;
|
|||
extern const bcstring be_const_str_write_bit;
|
||||
extern const bcstring be_const_str_write_bytes;
|
||||
extern const bcstring be_const_str_write_file;
|
||||
extern const bcstring be_const_str_write_flash;
|
||||
extern const bcstring be_const_str_write_gpio;
|
||||
extern const bcstring be_const_str_x;
|
||||
extern const bcstring be_const_str_x1;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,27 +1,28 @@
|
|||
#include "be_constobj.h"
|
||||
|
||||
static be_define_const_map_slots(be_class_webclient_map) {
|
||||
{ be_const_key(close, -1), be_const_func(wc_close) },
|
||||
{ be_const_key(get_string, 5), be_const_func(wc_getstring) },
|
||||
{ be_const_key(_X2Ew, 11), be_const_var(0) },
|
||||
{ be_const_key(_X2Ep, 13), be_const_var(1) },
|
||||
{ be_const_key(add_header, 10), be_const_func(wc_addheader) },
|
||||
{ be_const_key(url_encode, -1), be_const_func(wc_urlencode) },
|
||||
{ be_const_key(POST, -1), be_const_func(wc_POST) },
|
||||
{ be_const_key(GET, 6), be_const_func(wc_GET) },
|
||||
{ be_const_key(deinit, -1), be_const_func(wc_deinit) },
|
||||
{ be_const_key(get_size, -1), be_const_func(wc_getsize) },
|
||||
{ be_const_key(set_timeouts, -1), be_const_func(wc_set_timeouts) },
|
||||
{ be_const_key(set_auth, -1), be_const_func(wc_set_auth) },
|
||||
{ be_const_key(set_useragent, -1), be_const_func(wc_set_useragent) },
|
||||
{ be_const_key(init, 0), be_const_func(wc_init) },
|
||||
{ be_const_key(write_file, 3), be_const_func(wc_writefile) },
|
||||
{ be_const_key(begin, -1), be_const_func(wc_begin) },
|
||||
{ be_const_key(write_file, -1), be_const_func(wc_writefile) },
|
||||
{ be_const_key(_X2Ep, 16), be_const_var(0) },
|
||||
{ be_const_key(set_useragent, -1), be_const_func(wc_set_useragent) },
|
||||
{ be_const_key(get_size, -1), be_const_func(wc_getsize) },
|
||||
{ be_const_key(set_auth, -1), be_const_func(wc_set_auth) },
|
||||
{ be_const_key(write_flash, -1), be_const_func(wc_writeflash) },
|
||||
{ be_const_key(get_string, -1), be_const_func(wc_getstring) },
|
||||
{ be_const_key(init, -1), be_const_func(wc_init) },
|
||||
{ be_const_key(GET, 0), be_const_func(wc_GET) },
|
||||
{ be_const_key(_X2Ew, -1), be_const_var(1) },
|
||||
{ be_const_key(deinit, -1), be_const_func(wc_deinit) },
|
||||
{ be_const_key(set_timeouts, 1), be_const_func(wc_set_timeouts) },
|
||||
{ be_const_key(close, 2), be_const_func(wc_close) },
|
||||
{ be_const_key(add_header, -1), be_const_func(wc_addheader) },
|
||||
{ be_const_key(url_encode, 8), be_const_func(wc_urlencode) },
|
||||
{ be_const_key(POST, -1), be_const_func(wc_POST) },
|
||||
};
|
||||
|
||||
static be_define_const_map(
|
||||
be_class_webclient_map,
|
||||
16
|
||||
17
|
||||
);
|
||||
|
||||
BE_EXPORT_VARIABLE be_define_const_class(
|
||||
|
|
|
@ -22,6 +22,7 @@ extern int wc_GET(bvm *vm);
|
|||
extern int wc_POST(bvm *vm);
|
||||
extern int wc_getstring(bvm *vm);
|
||||
extern int wc_writefile(bvm *vm);
|
||||
extern int wc_writeflash(bvm *vm);
|
||||
extern int wc_getsize(bvm *vm);
|
||||
|
||||
#include "be_fixed_be_class_webclient.h"
|
||||
|
@ -50,6 +51,7 @@ class be_class_webclient (scope: global, name: webclient) {
|
|||
POST, func(wc_POST)
|
||||
get_string, func(wc_getstring)
|
||||
write_file, func(wc_writefile)
|
||||
write_flash, func(wc_writeflash)
|
||||
get_size, func(wc_getsize)
|
||||
}
|
||||
@const_object_info_end */
|
||||
|
|
|
@ -23,6 +23,44 @@
|
|||
#include <berry.h>
|
||||
#include "esp_spi_flash.h"
|
||||
|
||||
size_t FlashWriteSubSector(uint32_t address_start, const uint8_t *data, size_t size) {
|
||||
uint32_t addr = address_start;
|
||||
size_t size_left = size;
|
||||
size_t current_offset = 0;
|
||||
esp_err_t ret;
|
||||
// Memory is unaligned, so we need to copy it to an aligned buffer
|
||||
uint8_t buffer[SPI_FLASH_SEC_SIZE] __attribute__((aligned(4)));
|
||||
|
||||
while (size_left) {
|
||||
uint32_t page_addr = addr & ~(SPI_FLASH_SEC_SIZE - 1);
|
||||
uint32_t addr_in_page = addr & (SPI_FLASH_SEC_SIZE - 1);
|
||||
uint32_t size_in_page = size_left;
|
||||
if (addr_in_page + size_in_page > SPI_FLASH_SEC_SIZE) {
|
||||
size_in_page = SPI_FLASH_SEC_SIZE - addr_in_page;
|
||||
}
|
||||
|
||||
AddLog(LOG_LEVEL_DEBUG, ">>>: flash_write addr=%p size=%i -- page_addr=%p addr_in_page=%p size_in_page=%i size_left=%i", address_start, size, page_addr, addr_in_page, size_in_page, size_left);
|
||||
// check if whole page?
|
||||
if (addr_in_page == 0 && size_in_page == SPI_FLASH_SEC_SIZE) {
|
||||
memcpy(buffer, data + current_offset, SPI_FLASH_SEC_SIZE);
|
||||
} else {
|
||||
ret = spi_flash_read(page_addr, buffer, SPI_FLASH_SEC_SIZE);
|
||||
if (ret) { AddLog(LOG_LEVEL_INFO, "BRY: could not read flash %p (0x%X)", page_addr, SPI_FLASH_SEC_SIZE); return 0; }
|
||||
memcpy(buffer + addr_in_page, data + current_offset, size_in_page);
|
||||
}
|
||||
ret = spi_flash_erase_sector(page_addr / SPI_FLASH_SEC_SIZE);
|
||||
if (ret) { AddLog(LOG_LEVEL_INFO, "BRY: could not erase flash sector 0x%X", page_addr / SPI_FLASH_SEC_SIZE); return 0; }
|
||||
spi_flash_write(page_addr, buffer, SPI_FLASH_SEC_SIZE);
|
||||
if (ret) { AddLog(LOG_LEVEL_INFO, "BRY: could not write flash %p (0x%X)", page_addr, SPI_FLASH_SEC_SIZE); return 0; }
|
||||
|
||||
addr += size_in_page;
|
||||
current_offset += size_in_page;
|
||||
size_left -= size_in_page;
|
||||
}
|
||||
|
||||
return current_offset;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Native functions mapped to Berry functions
|
||||
*
|
||||
|
@ -69,9 +107,9 @@ extern "C" {
|
|||
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()");
|
||||
size_t ret = FlashWriteSubSector(address, (const uint8_t*)bytes, length);
|
||||
if (ret == 0) {
|
||||
be_raise(vm, "internal_error", "Error calling spi_flash_write()");
|
||||
}
|
||||
be_return_nil(vm);
|
||||
// success
|
||||
|
|
|
@ -454,7 +454,58 @@ extern "C" {
|
|||
be_pushint(vm, cl->getSize());
|
||||
be_return(vm); /* return code */
|
||||
}
|
||||
}
|
||||
|
||||
extern size_t FlashWriteSubSector(uint32_t address_start, const uint8_t *data, size_t size);
|
||||
|
||||
class StreamFlash: public Stream
|
||||
{
|
||||
public:
|
||||
StreamFlash(uint32_t addr) : addr_start(addr), offset(0) {};
|
||||
|
||||
size_t write(const uint8_t *buffer, size_t size) override {
|
||||
AddLog(LOG_LEVEL_INFO, "FLASH: addr=%p hex=%*_H size=%i", addr_start + offset, 32, buffer, size);
|
||||
if (size > 0) {
|
||||
size_t ret = FlashWriteSubSector(addr_start + offset, buffer, size);
|
||||
if (ret == 0) { return 0; } // error
|
||||
offset += size;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
size_t write(uint8_t data) override {
|
||||
write(&data, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int available() override { return 0; }
|
||||
int read() override { return -1; }
|
||||
int peek() override { return -1; }
|
||||
void flush() override { }
|
||||
|
||||
protected:
|
||||
uint32_t addr_start; // start address
|
||||
uint32_t offset; // how many bytes have already been written
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
int32_t wc_writeflash(struct bvm *vm);
|
||||
int32_t wc_writeflash(struct bvm *vm) {
|
||||
int32_t argc = be_top(vm);
|
||||
if (argc >= 2 && be_isint(vm, 2)) {
|
||||
HTTPClientLight * cl = wc_getclient(vm);
|
||||
uint32_t addr = be_toint(vm, 2);
|
||||
if (addr < 0x10000 || addr >= 0x400000) {
|
||||
be_raise(vm, "value_error", "invalid flash address");
|
||||
}
|
||||
|
||||
StreamFlash flash_writer(addr);
|
||||
cl->writeToStream(&flash_writer);
|
||||
|
||||
be_pushbool(vm, btrue);
|
||||
be_return(vm); /* return code */
|
||||
}
|
||||
be_raise(vm, kTypeError, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_WEBCLIENT
|
||||
|
|
Loading…
Reference in New Issue