Teensy 4.1 с чипами PSRAM объемом 2x8 МБ: external_psram_size=0, но EXTMEM[] char[] работает так, как ожидалось?

Поэтому я купил 2 чипа PSRAM от PJRC с Teensy 4.1 и припаял их (это отвратительная работа, так как я потерял свои чаевые), но все это проверено мультиметром, и соединения прочные.

Я запустил здесь скетч memtest, составленный как в Teensyduino, так и в PlatformIO: https://www.pjrc.com/store/psram.html

Aaaaand external_psram_size в обоих случаях равен 0. Установка размера памяти вручную в программе также не удается (даже при 8 МБ).

Однако... Дополнительные параметры работают, как и ожидалось. Я также не уверен, как адресация mem на самом деле работает с предоставленной программой memtest - она, безусловно, нигде не использует EXTMEM.

Вот мой тестер памяти (запуск до сбоя):

EXTMEM char bigBuf[10000000];
//char bigBuf[10000];
int c = 0;
void setup() {
  c = 0;
}

void loop() {
  bigBuf[c] = 'a';
  Serial.println(bigBuf[c]);
  Serial.println(String(c));
  c = c + 1000;  
  delay(1);
}

Вывод с помощью EXTMEM char[]: (как и ожидалось, переполнено до 16 МБ)

a
0
a
100
...
a
16777100
a
16777200

Вывод с внутренним символом mem[]: (как и ожидалось, переполнен при 512K - максимум оперативной памяти 1)

a
0
a
100
...
a
488081
a
489081

В любом случае, я рад, что EXTMEM работает.. Но может ли кто-нибудь объяснить, что происходит с предоставленным memtest? Я признаю, что не очень хорошо прочитал это, но я думал, что доступ к PSRAM возможен только через EXTMEM; как это решается иначе?

, 👍2


2 ответа


Лучший ответ:

4

Боюсь, ваша тестовая программа работает не так, как вы задумали. Я протестировал его с T4.1 без впаянной оперативной памяти, и он дает тот же результат, что и в вашем вопросе.

  1. Вы не объявили свой массив изменчивым. Таким образом, компилятор может (и, вероятно, будет) просто оптимизировать чтение обратно.
  2. Даже если вы объявите переменную изменчивой, процессор считывает значение из строки кэша, т. е. вы всегда получаете правильное значение обратно, даже без какой-либо внешней оперативной памяти.

Вот простая тестовая программа, показывающая эффект. Он всегда включает светодиод, даже если на плате нет внешней оперативной памяти.

EXTMEM volatile int test;

void setup()
{
    pinMode(13, OUTPUT);

    test = 42;
    if(test == 42)
    {
        digitalWriteFast(13, HIGH);
    }
}

void loop(){   
}

Здесь разборка функции настройки. Это ясно показывает, что процессор пытается сохранить 42 в (несуществующей) внешней оперативной памяти и считывает ее оттуда. Очевидно, что значение обратного чтения берется из строки кэша. (комментарии, добавленные мной)

void setup()
{
      7c:   push    {r3, lr}                         // pinMode code
    pinMode(13, OUTPUT);                             //
      7e:   movs    r1, #1                           //
      80:   movs    r0, #13                          //
      82:   bl  160c <pinMode>                       //-------------          

    test = 42;
      86:   ldr r3, [pc, #20]   ; (9c <setup+0x20>)  // load r3 with address of 'test' (0x70000000, stored at 0x9C)
      88:   movs    r2, #42 ; 0x2a                   // load r2 with #42
      8a:   str r2, [r3, #0]                         // store content of r2 at address stored in r3. i.e., store #42 0x7000'0000 (EXTRAM)
    
    if(test == 42)
      8c:   ldr r3, [r3, #0]                         // volatile forces the compiler to read back 'test' (store it in r3)
      8e:   cmp r3, r2                               // check if equals r2 (contains #42)
      90:   bne.n   9a <setup+0x1e>                  // goto 0x9A if not equal  
    
CORE_PIN13_PORTSET = CORE_PIN13_BITMASK;             // digitalwritefast code (next 3 lines) 
      92:   ldr r3, [pc, #12]   ; (a0 <setup+0x24>)  // ... 
      94:   movs    r2, #8                           // ...
      96:   str.w   r2, [r3, #132]  ; 0x84           // -------

      9a:   pop {r3, pc}                             // return from setup()

      9c:   .word   0x70000000                       // Address of 'test'; EXTRAM starts at 0x7000'000
      a0:   .word   0x42004000                       // Address of GPIO register for LED
,

Спасибо за информацию; странно, что EXTMEM решает выйти из строя только при 16 МБ, но, похоже, именно это и происходит. Вы были правы - я попытался на самом деле прочитать значение, присвоенное в начале массива EXTMEM объемом 14 МБ, и ничего не получил. Я прочитал кое-что в теме бета-тестирования Teensy4.1 (я думаю, на форуме Arduino) о паре цифровых выводов, используемых для обнаружения микросхем PSRAM... Мне придется как - то разобраться в этом или надеяться, что у кого-то есть другие идеи (я предполагаю, что я, возможно, поджарил одну пайку-я отпаяю ее и посмотрю, поможет ли это). Thx опять же, никогда не используйте C, поэтому даже не рассматривал volatile., @CSoft


5

Пол слушает. Я автор этой программы memtest, а также создатель Teensy. Хотя luni64 уже очень хорошо ответил о вашей тестовой программе, надеюсь, я смогу внести некоторую ясность в официальную программу memtest.

Что касается "Я думал, что к PSRAM можно получить доступ только через EXTMEM", действительно, использование массивов или переменных EXTMEM является нормальным способом. Но это не единственный путь. Программа memtest использует указатели с известным диапазоном адресов этих микросхем памяти. Поскольку провода физически подключаются к периферийному устройству "FlexSPI2" внутри чипа, память всегда будет начинаться с адреса 0x70000000. Вы можете найти эту информацию на странице 35 справочного руководства по чипу.

https://www.pjrc.com/teensy/IMXRT1060RM_rev2.pdf

К сожалению, руководство трудно читать и во многом сбивает с толку. Даже на странице 35 он описывает память как "зашифрованный текст", что могло бы иметь место, если бы механизм шифрования шины (упомянутый на странице 184) использовался определенным образом. Шифрование не используется, и если вы прочтете страницу 184, вы увидите, что движок выполняет только дешифрование, поэтому его действительно можно использовать только для памяти, доступной только для чтения, которая предварительно загружена зашифрованными данными.

Дело в том, что мы знаем, что оперативная память всегда начинается с 0x70000000 из-за того, как спроектировано оборудование. Если вы посмотрите на код memtest, вы увидите, что он создает 2 переменные, называемые "memory_begin" и "memory_end", которые являются указателями, используемыми для прямого доступа к памяти в этом известном диапазоне адресов.

Идея теста памяти заключается в том, что вся память заполнена известным шаблоном данных. Такого рода тестирование предназначено для выявления любых (очень маловероятных) внутренних проблем внутри микросхем памяти, когда запись в одно место внутри чипа может привести к повреждению данных в другом месте того же чипа.

Используемый указатель объявлен с "изменчивым", что не позволяет компилятору пытаться оптимизировать фактический доступ к памяти.

После того, как память будет полностью заполнена, вы увидите, что используется функция arm_dcache_flush_delete (). Даже если вы используете volatile, чтобы компилятор не оптимизировал доступ к удаленной памяти, аппаратное обеспечение Cortex-M7 имеет кэш 1-го уровня 32 КБ. Эта функция заставляет процессор ARM Cortex-M7 полностью записывать любые кэшированные данные в сам чип памяти, а затем удалять данные из своего кэша. Обычно эти специальные функции кэша используются только низкоуровневым кодом драйвера, использующим прямой доступ к памяти (DMA), где вам нужно убедиться, что записанные вами данные действительно находятся в памяти, прежде чем давать периферийному устройству указание использовать DMA для прямого извлечения их из памяти (обычно периферийные устройства на основе DMA не могут получить доступ к кэшу), или перед чтением данных, которые периферийное устройство помещает в память с помощью DMA. Обычно вам не нужно возиться с кэшем, но такого рода тестирование оборудования и специальный бенчмаркинг-это другой вид приложений, в которых важно уделять особое внимание кэшу процессора.

Затем вся память считывается обратно, используя указатель volatile, чтобы компилятор не пытался сделать что-то слишком умное. По мере чтения данных каждое 32-разрядное слово сравнивается с написанным исходным шаблоном. Опять же, идея состоит в том, чтобы проверить довольно маловероятный случай, когда память, по-видимому, работает, но теоретически может возникнуть внутренняя проблема, когда запись в одно место вызывает повреждение где-то еще внутри чипа.

Весь тест повторяется много раз. Используются различные фиксированные 32-битные шаблоны. Многие тесты заполняют всю память псевдослучайной последовательностью, конечно, выполняя ту же проверку, когда любое изменение даже на 1 бит во всем диапазоне памяти будет обнаружено и сообщено как сбой. Возможно, это излишне, но я попытался разработать программу memtest в соответствии с лучшими практиками, описанными для тестирования памяти ПК, и именно так эксперты рекомендуют проверять память (на самом деле они рекомендуют еще более сложные и сложные шаблоны... может быть, когда-нибудь я их добавлю).

Надеюсь, это поможет ответить на вопрос "может ли кто-нибудь объяснить, что происходит с предоставленным memtest?"

Что касается пайки, проблема, с которой сталкивались другие люди, связана с тем, что припой прилипает только к контакту микросхемы памяти. Несмотря на то, что при взгляде сверху это выглядит нормально, возможно, что припой представляет собой каплю, расположенную чуть выше поверхности прокладки на печатной плате. Я бы рекомендовал повторно нагреть припой. Дайте ему время полностью нагреться и стечь на подушку. Хотя дополнительное время нагрева не является замечательным для чипа PSRAM, эти чипы имеют довольно большой размер тепла, и если память не работает, вам действительно нечего терять. Подсчет до 10 при повторном нагреве припоя обычно работает. Если у вас есть какое-либо жидкое химическое вещество, нанесение его перед повторным нагревом также может помочь.

Сначала сосредоточьте свои усилия по ремонту на чипе, установленном на меньшем наборе прокладок рядом с краем печатной платы. Код запуска ищет первый чип размером 8 МБ в этом месте. If даже не будет искать другой чип, если в первом месте не будет обнаружено памяти.

,

Забавно, что АСЕ заставил меня просмотреть ваш "поздний ответ". Ну, знаете, чтобы убедиться, что это соответствует стандартам. Боже, я не знаю... Я думаю, все в порядке. =), @timemage