From 609ce123025914026288cbdebb1bf5027afac9e1 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Fri, 13 Dec 2024 03:06:32 +0000 Subject: [PATCH] Fix crash by implementing a custom malloc Ref https://surma.dev/things/c-to-webassembly/ --- README.md | 7 ++- src/wasm/compile-wasm.sh | 4 +- src/wasm/include/wrapper.cpp | 102 +++++++++++++++++++---------------- 3 files changed, 65 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index b00515a..103f994 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ # osfs-wasm -Compiling the Over-Simplified FileSystem to WASM for fun and profit \ No newline at end of file +> Compiling the Over-Simplified FileSystem to WASM for fun and profit + + + + +EEPROM sizes, ref (which suggests kilo**bit**s?!) and (which suggests KiB) \ No newline at end of file diff --git a/src/wasm/compile-wasm.sh b/src/wasm/compile-wasm.sh index ac7b4f3..70a45b0 100755 --- a/src/wasm/compile-wasm.sh +++ b/src/wasm/compile-wasm.sh @@ -31,15 +31,15 @@ task_begin "Compile"; echo -e ">>> Working directory is ${HC}${PWD}${RS}" >&2; -execute clang -v -v -v --target=wasm32 -nostdlib -Wl,--export-all -Wl,--no-entry \ +execute clang --target=wasm32 -nostdlib -Wl,--export-all -Wl,--no-entry \ -I"${dirpath_include}" \ -I "${dirpath_walloc}" \ -I "${dirpath_osfs}" \ -o "${dirpath_output}/osfs.wasm" \ - "${dirpath_walloc}/walloc.c" \ "${dirpath_osfs}/OSFS.cpp" \ "${dirpath_include}/wrapper.cpp" \ ; + # "${dirpath_walloc}/walloc.c" \ task_end "${?}"; \ No newline at end of file diff --git a/src/wasm/include/wrapper.cpp b/src/wasm/include/wrapper.cpp index cefc7f0..4f36776 100644 --- a/src/wasm/include/wrapper.cpp +++ b/src/wasm/include/wrapper.cpp @@ -1,6 +1,27 @@ #include "Arduino.h" #include "OSFS.h" -#include + +// ------------------------------------------------------------------------- + +// Custom malloc implementation +// Initial design ref https://surma.dev/things/c-to-webassembly/ → Building an +// allocator + +// This started as a simple bump allocator, but we've turned it into a singleton +// allocator that always allocates the same area of memory, since we only want to allocate a single area of memory +extern unsigned char __heap_base; + +unsigned int bump_pointer = (unsigned int)&__heap_base; +void *malloc(int n) { + unsigned int r = bump_pointer; // This works because the heap grows *upwards* in WASM, not downwards + // bump_pointer += n; + + return (void *)r; +} + +void free(void *p) { + // lol +} // ------------------------------------------------------------------------- @@ -9,7 +30,7 @@ // strncmp, memset, strncpy ref https://github.com/bezlant/s21_strings int strncmp(const char *str1, const char *str2, size_t n) { int res = 0; - + if (str1 && str2 && n > 0) { for (size_t i = 0; i < n; i++) { if (str1[i] == '\0' || str1[i] != str2[i]) { @@ -18,25 +39,25 @@ int strncmp(const char *str1, const char *str2, size_t n) { } } } - + return res; } void *memset(void *str, int c, size_t n) { char *s = (char *)str; - + for (size_t i = 0; i < n; i++) { s[i] = c; } - + return str; } char *strncpy(char *dest, const char *src, size_t n) { memset(dest, '\0', n); - + for (size_t i = 0; i < n && src[i]; i++) { dest[i] = src[i]; } - + return dest; } @@ -51,29 +72,27 @@ OSFS::result result; uint16_t OSFS::startOfEEPROM = 1; uint16_t OSFS::endOfEEPROM = 64; // change w/set_eeprom_size +byte *memory = (byte*)malloc((size_t)(64 * 1024)); // virtual EEPROM, default 64KiB -byte* memory = (byte*)malloc((size_t)(64*1024)); // virtual EEPROM, default 64KiB - -void __create_memory(uint32_t size) { - free((void*)memory); - void* memory_raw = malloc((size_t)(size * 1024)); - memory = (byte*)memory_raw; +void __clear_memory(uint32_t size) { + memset(memory, 0, (size_t)(size * 1024)); } - - +void __create_memory(uint32_t size) { + free((void *)memory); + void *memory_raw = malloc((size_t)(size * 1024)); + memory = (byte *)memory_raw; +} // ------------------------------------------------------------------------- // Error handling -#define ERROR_OUT_OF_BOUNDS 1 +#define ERROR_OUT_OF_BOUNDS 1 int last_error = 0; -int get_last_error() { - return last_error; -} +int get_last_error() { return last_error; } // ------------------------------------------------------------------------- @@ -81,7 +100,7 @@ int get_last_error() { /** * Helper function to set the size of the EEPROM unit to operate on. - * + * * @param {uint16_t} size The size of the EEPROM unit, in KiB * @return void */ @@ -90,38 +109,31 @@ void set_eeprom_size(uint16_t new_size) { __create_memory(new_size); } -uint16_t get_eeprom_size() { - return OSFS::endOfEEPROM; -} -uint32_t get_eeprom_size_bytes() { - return OSFS::endOfEEPROM * 1024; -} +uint16_t get_eeprom_size() { return OSFS::endOfEEPROM; } +uint32_t get_eeprom_size_bytes() { return OSFS::endOfEEPROM * 1024; } - - -void OSFS::readNBytes(uint16_t address, unsigned int num, byte* output) { +void OSFS::readNBytes(uint16_t address, unsigned int num, byte *output) { // eeprom.read(address, output, num); last_error = 0; - - if(address < OSFS::startOfEEPROM || address + num > OSFS::endOfEEPROM * 1024) { - last_error = ERROR_OUT_OF_BOUNDS; - return; - } - - for (unsigned int i = 0; i < num; i++) { - output[i] = memory[address + i]; - } - -} -void OSFS::writeNBytes(uint16_t address, unsigned int num, const byte* input) { - // eeprom.write(address, input, num); - last_error = 0; - + if (address < OSFS::startOfEEPROM || address + num > OSFS::endOfEEPROM * 1024) { last_error = ERROR_OUT_OF_BOUNDS; return; } - + + for (unsigned int i = 0; i < num; i++) { + output[i] = memory[address + i]; + } +} +void OSFS::writeNBytes(uint16_t address, unsigned int num, const byte *input) { + // eeprom.write(address, input, num); + last_error = 0; + + if (address < OSFS::startOfEEPROM || address + num > OSFS::endOfEEPROM * 1024) { + last_error = ERROR_OUT_OF_BOUNDS; + return; + } + for (unsigned int i = 0; i < num; i++) { memory[address + i] = input[i]; }