Description
The Arduino String
class uses malloc, free and realloc to dynamically allocate memory for the strings. However, the core doesn't define the sbrk()
function as the base function needed for malloc to allocate more memory.
So a sketch like
#include <Arduino.h>
void setup() {
Serial.begin(115200);
}
static int i=0;
void loop() {
Serial.println("Hello " + String(i++));
}
fails with
Linking .pio\build\ch32v003f4p6_evt_r0\firmware.elf
c:/users/max/.platformio/packages/toolchain-riscv/bin/../lib/gcc/riscv-none-embed/8.2.0/../../../../riscv-none-embed/bin/ld.exe: .pio\build\ch32v003f4p6_evt_r0\FrameworkArduino\api\String.cpp.o: in function `arduino::String::~String()':
String.cpp:(.text._ZN7arduino6StringD2Ev+0x4): undefined reference to `free'
c:/users/max/.platformio/packages/toolchain-riscv/bin/../lib/gcc/riscv-none-embed/8.2.0/../../../../riscv-none-embed/bin/ld.exe: .pio\build\ch32v003f4p6_evt_r0\FrameworkArduino\api\String.cpp.o: in function `arduino::String::invalidate()':
String.cpp:(.text._ZN7arduino6String10invalidateEv+0xc): undefined reference to `free'
c:/users/max/.platformio/packages/toolchain-riscv/bin/../lib/gcc/riscv-none-embed/8.2.0/../../../../riscv-none-embed/bin/ld.exe: .pio\build\ch32v003f4p6_evt_r0\FrameworkArduino\api\String.cpp.o: in function `arduino::String::changeBuffer(unsigned int)':
String.cpp:(.text._ZN7arduino6String12changeBufferEj+0x10): undefined reference to `realloc'
c:/users/max/.platformio/packages/toolchain-riscv/bin/../lib/gcc/riscv-none-embed/8.2.0/../../../../riscv-none-embed/bin/ld.exe: .pio\build\ch32v003f4p6_evt_r0\FrameworkArduino\api\String.cpp.o: in function `arduino::String::String(int, unsigned char)':
String.cpp:(.text._ZN7arduino6StringC2Eih+0x18): undefined reference to `itoa'
So it also uses -nostdlib
which causes itoa
to not be found and stuff.
If I do make the required fixes per Community-PIO-CH32V@d098d4d, I get a successfull compile
Linking .pio\build\ch32v003f4p6_evt_r0\firmware.elf
Checking size .pio\build\ch32v003f4p6_evt_r0\firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM: [=== ] 25.8% (used 528 bytes from 2048 bytes)
Flash: [== ] 19.9% (used 3260 bytes from 16384 bytes)
and it works during runtime.
Question is, do we want this? Should this be allowed usage on a chip with this little memory?
With the "main branch" / no malloc, a blinky sketch of
#include <Arduino.h>
#define LED C1
void setup() { pinMode(LED, OUTPUT); }
void loop() {
digitalWrite(LED, HIGH);
delay(1000);
digitalWrite(LED, LOW);
delay(1000);
}
uses
RAM: [== ] 18.4% (used 376 bytes from 2048 bytes)
Flash: [= ] 8.7% (used 1420 bytes from 16384 bytes)
and with the malloc branch it uses
RAM: [== ] 24.6% (used 504 bytes from 2048 bytes)
Flash: [= ] 11.2% (used 1832 bytes from 16384 bytes)
So.. even though this sketch shouldn't use malloc, the compiler still adds some baggage, probably because of the nosys and nano specs linking.. :(