Skip to content

Commit 521a41f

Browse files
mjs513facchinm
authored andcommitted
Added SDRAM + Lib + llext_export changes
1 parent 00ec495 commit 521a41f

File tree

9 files changed

+772
-2
lines changed

9 files changed

+772
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
How to interact with external SDRAM on Portenta H7
3+
4+
The board comes with an hefty 8MB of external fast RAM, which can be used:
5+
- as a framebuffer (raw mode)
6+
- as an expansion of on-chip RAM to store "standard" data
7+
8+
This example shows both the usages
9+
*/
10+
11+
#include "SDRAM.h"
12+
13+
void nonFrameBuffer() {
14+
// Initilize SDRAM for non-framebuffer operations
15+
SDRAM.begin(); // is the same as SDRAM.begin(SDRAM_START_ADDRESS);
16+
17+
// Now we can malloc() and free() in the whole RAM space
18+
// For example, let's create a 7MB array
19+
uint8_t* myVeryBigArray = (uint8_t*)SDRAM.malloc(7 * 1024 * 1024);
20+
21+
// and a small one
22+
uint8_t* mySmallArray = (uint8_t*)SDRAM.malloc(128);
23+
24+
// and use then as usual
25+
for (int i = 0; i<128; i++) {
26+
myVeryBigArray[i] = i;
27+
mySmallArray[i] = i*2;
28+
}
29+
30+
// free the memory when you don't need them anymore
31+
SDRAM.free(myVeryBigArray);
32+
}
33+
34+
void frameBuffer() {
35+
// In case we want a framebuffer-like area at the beginning of the flash,
36+
// simply initialize the memory as
37+
38+
SDRAM.begin(SDRAM_START_ADDRESS + 2 * 1024 * 1024);
39+
// 2MB of contiguous memory available at the beginning
40+
41+
uint32_t* framebuffer = (uint32_t*)SDRAM_START_ADDRESS;
42+
43+
// We can't allocate anymore the huge 7MB array
44+
45+
uint8_t* myVeryBigArray = (uint8_t*)SDRAM.malloc(7 * 1024 * 1024);
46+
if (myVeryBigArray == NULL) {
47+
Serial.println("Oops, too big :)");
48+
}
49+
50+
}
51+
52+
void setup() {
53+
Serial.begin(115200);
54+
while (!Serial);
55+
56+
frameBuffer();
57+
// Uncomment to test the other functionality
58+
// nonFrameBuffer();
59+
60+
// Sort of memtest for stability, useful for testing when overclocking
61+
if (SDRAM.test()) {
62+
Serial.println("SDRAM completely functional");
63+
}
64+
}
65+
66+
void loop() {
67+
68+
}

Diff for: libraries/Zephyr_SDRAM/library.properties

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
name=Portenta_SDRAM
2+
version=1.0
3+
author=Arduino
4+
maintainer=Arduino <[email protected]>
5+
sentence=Interact with external SDRAM chip on Portenta H7
6+
paragraph=
7+
category=Other
8+
url=https://github.com/arduino/ArduinoCore-mbed/tree/master/libraries/Portenta_SDRAM
9+
architectures=*

Diff for: libraries/Zephyr_SDRAM/src/SDRAM.cpp

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#include "SDRAM.h"
2+
#include "Arduino.h"
3+
4+
int SDRAMClass::begin(uint32_t start_address) {
5+
if (start_address) {
6+
malloc_addblock((void*)start_address, SDRAM_END_ADDRESS - start_address);
7+
}
8+
9+
return 1;
10+
}
11+
12+
void* SDRAMClass::malloc(size_t size) {
13+
return ea_malloc(size);
14+
}
15+
16+
void SDRAMClass::free(void* ptr) {
17+
ea_free(ptr);
18+
}
19+
20+
bool SDRAMClass::test(bool fast, Stream& _serial) {
21+
uint8_t const pattern = 0xaa;
22+
uint8_t const antipattern = 0x55;
23+
uint8_t *const mem_base = (uint8_t*)SDRAM_START_ADDRESS;
24+
25+
/* test data bus */
26+
for (uint8_t i = 1; i; i <<= 1) {
27+
*mem_base = i;
28+
if (*mem_base != i) {
29+
_serial.println("data bus lines test failed! data (" + String(i) + ")");
30+
__asm__ volatile ("BKPT");
31+
}
32+
}
33+
34+
/* test address bus */
35+
/* Check individual address lines */
36+
for (uint32_t i = 1; i < HW_SDRAM_SIZE; i <<= 1) {
37+
mem_base[i] = pattern;
38+
if (mem_base[i] != pattern) {
39+
_serial.println("address bus lines test failed! address ("+ String((uint32_t)&mem_base[i], HEX) + ")");
40+
__asm__ volatile ("BKPT");
41+
}
42+
}
43+
44+
/* Check for aliasing (overlaping addresses) */
45+
mem_base[0] = antipattern;
46+
for (uint32_t i = 1; i < HW_SDRAM_SIZE; i <<= 1) {
47+
if (mem_base[i] != pattern) {
48+
_serial.println("address bus overlap! address ("+ String((uint32_t)&mem_base[i], HEX) + ")");
49+
__asm__ volatile ("BKPT");
50+
}
51+
}
52+
53+
/* test all ram cells */
54+
if (!fast) {
55+
for (uint32_t i = 0; i < HW_SDRAM_SIZE; ++i) {
56+
mem_base[i] = pattern;
57+
if (mem_base[i] != pattern) {
58+
_serial.println("address bus test failed! address ("+ String((uint32_t)&mem_base[i], HEX) + ")");
59+
__asm__ volatile ("BKPT");
60+
}
61+
}
62+
} else {
63+
memset(mem_base, pattern, HW_SDRAM_SIZE);
64+
}
65+
66+
return true;
67+
}
68+
69+
SDRAMClass SDRAM;

Diff for: libraries/Zephyr_SDRAM/src/SDRAM.h

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#ifndef __SDRAM_H
2+
#define __SDRAM_H
3+
4+
#include "ea_malloc.h"
5+
6+
#ifdef __cplusplus
7+
8+
#include "Arduino.h"
9+
10+
#define SDRAM_END_ADDRESS (0xc0800000)
11+
#define SDRAM_START_ADDRESS (0xc0000000)
12+
#define HW_SDRAM_SIZE (8 * 1024 * 1024)
13+
14+
class SDRAMClass {
15+
public:
16+
SDRAMClass() {}
17+
int begin(uint32_t start_address = SDRAM_START_ADDRESS);
18+
void* malloc(size_t size);
19+
void free(void* ptr);
20+
bool test(bool fast = false, Stream& _serial = Serial);
21+
private:
22+
23+
};
24+
extern SDRAMClass SDRAM;
25+
26+
#endif
27+
#endif // __SDRAM_H

Diff for: libraries/ea_malloc/ea_malloc.h

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright © 2017 Embedded Artistry LLC.
3+
* License: MIT. See LICENSE file for details.
4+
*/
5+
6+
#ifndef MALLOC_H_
7+
#define MALLOC_H_
8+
9+
#ifdef __cplusplus
10+
extern "C" {
11+
#endif //__cplusplus
12+
13+
#include <stdlib.h>
14+
15+
/**
16+
* @brief Assign blocks of memory for use by malloc().
17+
*
18+
* Initializes the malloc() backend with a memory address and memory pool size.
19+
* This memory is assumed to be owned by malloc() and is vended out when memory is requested.
20+
* Multiple blocks can be added.
21+
*
22+
* NOTE: This API must be called before malloc() can be used. If you call malloc() before
23+
* allocating memory, malloc() will return NULL because there is no available memory
24+
* to provide to the user.
25+
*
26+
* @param addr Pointer to the memory block address that you are providing to malloc()
27+
* @param size Size of the memory block that you are providing to malloc()
28+
*/
29+
void malloc_addblock(void* addr, size_t size);
30+
31+
/**
32+
* @brief Initialize Malloc
33+
*
34+
* Weakly linked, can be overridden based on your needs.
35+
* Each malloc implementation contains a different set of initialization requirements
36+
*/
37+
void malloc_init(void);
38+
39+
void* ea_malloc(size_t size);
40+
void ea_free(void* ptr);
41+
42+
#ifdef __cplusplus
43+
}
44+
#endif //__cplusplus
45+
46+
#endif //MALLOC_H_

0 commit comments

Comments
 (0)