Заголовок сообщения: Как объявить глобальную переменную в PSRAM?
Добавлено: Вс янв 25, 2026 10:06:04
Открыл глаза
Зарегистрирован: Чт сен 03, 2009 16:42:39 Сообщений: 65
Рейтинг сообщения:0
Перед использованием PSRAM надо выполнить psramInit() Тогда каким образом объявить глобальные переменные? В void setup() они же не будут глобальными… В примерах кода нашёл только это:
Код:
void setup() { Serial.begin(115200); //PSRAM Initialisation if(psramInit()){ Serial.println("\nThe PSRAM is correctly initialized"); }else{ Serial.println("\nPSRAM does not work"); }
//Create an integer int *var_int = (int *) ps_malloc(sizeof(int)); *var_int = 42; }
Привет! Its depend - как говорят наши западные коллеги. Так как линкер не знает что существует PSRAM на этапе компиляции/сборки, фокус с размещением глобальных переменных там, в понимании Ардуинщика, не пройдет. Еще трудность в том что PSRAM обычно не является продолжением ОЗУ в контроллере, и выделение памяти в этой области имеет особенности. Это зависит от карты памяти конкретного микроконтроллера. Есть конечно ухищрения связанные с модификацией ld файла и ассемблерного стартапа, но это не для слабонервных. Где то на гитхабах встречал продвинутые методики работы с PSRAM, поищите.
Заголовок сообщения: Re: Как объявить глобальную переменную в PSRAM?
Добавлено: Вт мар 24, 2026 09:52:55
Родился
Зарегистрирован: Вт мар 24, 2026 09:45:52 Сообщений: 6
Рейтинг сообщения:0
Чтобы переменная была доступна во всем скетче (была глобальной), но память под нее выделялась в PSRAM после инициализации, используйте указатели. Вот как это реализуется на практике: 1. Объявление (вне функций) В начале скетча вы объявляете только «адрес» (указатель), изначально равный NULL. На этом этапе память еще не выделяется. cpp int *myGlobalInt = NULL; // Указатель на будущее целое число float *myDataArray = NULL; // Указатель на будущий массив Используйте код с осторожностью.
2. Инициализация (в setup) После того как psramInit() прошел успешно, вы выделяете физическое место в PSRAM и присваиваете этот адрес вашему глобальному указателю. cpp void setup() { Serial.begin(115200);
if (psramInit()) { // Выделяем память под 1000 чисел типа float в PSRAM myDataArray = (float *) ps_malloc(1000 * sizeof(float));
if (myDataArray != NULL) { myDataArray[0] = 25.5; // Теперь это доступно везде } } }
3. Использование (в loop или других функциях) Теперь вы можете обращаться к этим данным из любой части программы, так как сам указатель определен глобально. cpp void loop() { if (myDataArray != NULL) { Serial.println(myDataArray[0]); } delay(1000); }
Важный нюанс: Ключевое слово EXT_RAM_ATTR Если ваша среда разработки (IDE) и плата поддерживают атрибуты, можно объявить глобальную переменную в PSRAM статически (без ps_malloc). В этом случае система сама выделит память при старте: cpp EXT_RAM_ATTR int myStaticGlobalArray[10000];
void setup() { psramInit(); // Массив уже готов к работе, malloc не нужен }
Даже намного проще: int* ptr = (int*)0хAABBCCDD, где 0xAABBCCDD - конкретный адрес в области PSRAM. Однако, здесь надо учитывать систему адресации микроконтроллера. Если адресация линейная и PSRAM может быть подключена к линейному адресному пространству с назначением ей диапазона адресов, то показанный вариант имеет место быть. В противном случае, при косвенной (относительной) адресации такой вариант не проканает.
Эта тема была создана в разделе Ардуино. И скорее всего, здесь имеется ввиду микросхема PSRAM на SPI-интерфейсе с относительной адресацией. При таком раскладе для работы с внешней PSRAM используется кэширование блока некоторого размера. И разумеется, никакого вообще выделения памяти, хоть через malloc, хоть через указатель, хоть статически, в PSRAM здесь быть не может.
int* ptr = (int*)0хAABBCCDD, где 0xAABBCCDD - конкретный адрес в области PSRAM.
таким способом объявлять глобальную переменную нельзя, потому что компилятор ничего не будет знать про такую переменную, и может затереть ее своими данными. такая переменная не может быть инициализирована значением по умолчанию, которое сохраняется в .data-секции. правильно это делается через создание дополнительной секции в скрипте компоновщика.
Так адрес задается вручную, вне диапазона адресов описанных секций. И указатель - это отдельная переменная, которая указывает на некоторый адрес. И если уж работаете с секциями, тогда не нужны никакие указатели. Просто объявите переменную или массив с атрибутом указанной секции: int var __attribute__((section(".MySection"))); int array[100] __attribute__((section(".MySection")));
И во-вторых, и это самое главное - нужно было прочитать не только первую строчку моего предыдущего поста. Если микроконтроллер не имеет выделенного диапазона адресов для внешней PSRAM, то работа с переменными хоть через указатели, хоть через секции, будет невозможна. Внешняя PSRAM будет работать в режиме кэша с отображением кэшированного блока во внутренней SRAM микроконтроллера.
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения