-
New PCB's
02/19/2020 at 18:48 • 0 commentsNew set of PCB's have just arrived, waiting to become gifts to friends and items on tindie.
-
Using external memory as heap storage
05/05/2019 at 15:37 • 0 commentsAccording to avr-libc documentation the most flexible way to manage the different memories of AVR mcu is linker script. But if Arduino IDE is being used, this way is not obvious to implement, because there is no Makefile.
Therefore, there are two simplest ways to use external memory on Arduino MEGA.
1. The low-level way of readings and writings, based on volatile pointer to external memory area. Test program from this page gives an example.
External memory occupies area of 0x8000 to 0xFFFF in Atmega2560 address space.
Suppose we need an array of 8192 float values to write values from some probes. Then simply declare:
volatile float* dataBuffer = reinterpret_cast<volatile float*>(0x8000);
Then it's possible to use dataBuffer as pointer to array of 8192 float numbers (8192 * 4 = 32768, the size of external memory):
... dataBuffer[i] = analogRead(N); ... Serial.println(dataBuffer[j]); ...
2. The second way is to place heap memory area to external memory:
void setup() { Serial.begin(115200); XMCRA |= 1ul<<7; // Switch ext mem iface on XMCRB = 0; __malloc_heap_start = 0x8000; __malloc_heap_end = 0xFFFF; uint32_t* dataBuffer = new uint32_t[1024]; Serial.print("Dynamic buffer of 4096 bytes created, address: "); Serial.println((uintptr_t)dataBuffer, HEX); for (size_t i=0; i<1024; ++i) { dataBuffer[i] = i*16; } for (size_t i=0; i<1024; i+=4) { Serial.println(); Serial.print(i, DEC); Serial.print('\t'); Serial.print(dataBuffer[i], DEC); Serial.print('\t'); Serial.print(dataBuffer[i+1], DEC); Serial.print('\t'); Serial.print(dataBuffer[i+2], DEC); Serial.print('\t'); Serial.print(dataBuffer[i+3], DEC); } delete [] dataBuffer; } void loop() { delay(1000); }
At the begining we set 2 internal avr-libc variables to the external memory boundaries:
__malloc_heap_start = 0x8000; __malloc_heap_end = 0xFFFF;
After that simple variables and objects, declared at the module level or inside functions will be placed at the 8192 bytes of AVR internal RAM, but all dynamic variables and objects will be placed at external memory.
You can declare multiple arrays or simple variables:
float tempBuffer = new float[512]; assert(tempBuffer != nullptr); ... tempBuffer[i] = readData(source); ... delete [] tempBuffer; ...
It's possible to use external memory for example with some libraries:
https://bitbucket.org/starling13/libps2
include "ps2_keyboardstream.hpp" #define DATA_PIN 5 #define CLK_PIN 2 static PS2::Keyboard* kbd; static PS2::KeyboardStream* kstream; void setup() { XMCRA <<= 1<<7; XMCRB = 0; __malloc_heap_start = 0x8000; __malloc_heap_end = 0xFFFF; kbd = new PS2::Keyboard; kstream = new PS2::KeyboardStream(*kbd); Serial.begin(115200); kbd->begin(DATA_PIN, CLK_PIN); } void loop() { while (kstream->available() > 0) Serial.write(kstream->read()); }