вівторок, 29 жовтня 2019 р.

STM32: Використання CCMRAM

Передмова

Почавши експериментувати і навчатись з такою платою на чипі STM32F407VE, я помітив що цей чип має в наявності два банки пам'яті: стандартний SRAM 0x20000000 - 0x20020000, та інший банк пам'яті Core-Coupled-Memory (CCM) 0x10000000 - 0x10010000. Це мене зацікавило і я трішечки почитав і розібрався, що то за пам'ять і як її задіяти в своїх проектах. Бо за замовчуванню вона не задіяна. Як комусь буде ця інформація корисною і стане в нагоді, то буду тільки радий цьому.

Трішки теорії

Деякі мікроконтролери STM32 мають два банки пам'яті: стандартний SRAM та інший банк пам'яті Core-Coupled-Memory (CCM) який може бути швидшим ніж стандартний SRAM, але зазвичай меншого об'єма. Інколи розміщення даних в цей регіон пам'яті може бути вигідним в плані швидкості і економії стандартної пам'яті. Пам'ять CCM під'єднана безпосередньо до шини D-Bus процесора. DMA не має доступу до цієї пам'яті. Тому є можливість розпаралелити дані свого проекту.

Як задіяти

Існує декілька способів. Але я опишу ті способи, що мені підійшли. Я використовую Atolic Truestudio + CubeMX і все що описано нижче - випробувано на цій IDE з генератором коду ініціалізації. Як на інших IDE буде, я не в курсі. Певен, що і на CubeIDE буде працювати все так само, бо є нащадком Atolic Truestudio з інтегрованим CubeMX.

Розміщення всіх ініціалізованих даних у CCM:

У вашому проекті буде файл з розширенням *.ld, наприклад, STM32F407VE_FLASH.ld. Відкрийте його на редагування та зробіть такі зміни в кінці секції ".data":
} >RAM AT> FLASH
На такий рядок:
} >CCMRAM AT> FLASH

Розміщення всіх нульових ініціалізованих даних у CCM:

У вашому проекті буде файл з розширенням "*.ld", наприклад, "STM32F407VE_FLASH.ld". Відкрийте його на редагування та зробіть такі зміни в кінці секції ".bss":
} >RAM
На такий рядок:
} >CCMRAM

Розміщення окремих не ініціалізованих змінних у CCM:

Ви можете дуже просто помістити не ініціалізовані змінні в CCM, додаючи до їх оголошення атрібут розділу CCMRAM. Наприклад масив "array_in_ccm" з 1024 байт даних типу "char":
char array_in_ccm[1024] __attribute__((section(".ccmram")));
Або таким чином:
__attribute__((section(".ccmram"))) char array_in_ccm[1024];
А зробивши перевизначення на початку файлу:
#define CCMRAM __attribute__((section(".ccmram")))
Можна оголошувати не ініціалізовані дані вже таким чином:
CCMRAM char array_in_ccm[1024];
Або так:
char array_in_ccm[1024] CCMRAM;
Щоб це працювало, перевірте наявність секції ".ccmram" в скрипті "STM32F407VE_FLASH.ld". За відсутності цієї секції - додайте:
/* CCM-RAM section 
  * 
  * IMPORTANT NOTE! 
  * If initialized variables will be placed in this section,
  * the startup code needs to be modified to copy the init-values.  
  */
  .ccmram :
  {
    . = ALIGN(4);
    _sccmram = .;       /* create a global symbol at ccmram start */
    *(.ccmram)
    *(.ccmram*)
    
    . = ALIGN(4);
    _eccmram = .;       /* create a global symbol at ccmram end */
  } >CCMRAM
Але будьте обережні, щоб не ініціалізувати змінну навіть з нулем. Оскільки це займе місце у FLASH.

Розміщення окремих ініціалізованих змінних у CCM:

І навпаки, ви можете створити ініціалізовані дані в розділі CCMRAM переконавшись що в скрипті "STM32F407VE_FLASH.ld" присутній такий запис:
 _siccmram = LOADADDR(.ccmram);

  /* CCM-RAM section 
  * 
  * IMPORTANT NOTE! 
  * If initialized variables will be placed in this section,
  * the startup code needs to be modified to copy the init-values.  
  */
  .ccmram :
  {
    . = ALIGN(4);
    _sccmram = .;       /* create a global symbol at ccmram start */
    *(.ccmram)
    *(.ccmram*)
    
    . = ALIGN(4);
    _eccmram = .;       /* create a global symbol at ccmram end */
  } >CCMRAM AT> FLASH
Секція CCM-RAM в такому вигляді, дозволяє оголошувати і ініціалізовані дані, наприклад:
char array_in_ccm[1024] CCMRAM = {0,1,2,3,4,5,6,7,8,9,0};
Або так:
CCMRAM char array_in_ccm[1024] = {0,1,2,3,4,5,6,7,8,9,0};
Масив даних розташувався в пам'яті CCM:
Зазначу, що використовуючи Atolic TrueStudio разом з CubeMX, в скрипті "STM32F407VE_FLASH.ld" секція, для розміщення ініціалізованих змінних в пам'ять CCM, вже була в наявності. І додавати чи правити нічого не знадобилось. Достатньо додати атрибут "__attribute__((section(".ccmram")))" до змінної для розміщення певних ініціалізованих даних до розділу пам'яті CCM.

Джерело знань тут, або де інде. Шукайте, читайте, експериментуйте. 

4 коментарі:

  1. Привіт, можна якось з тобою зв'язатись?
    Я починаю вивчати стм 32 , і хотів запитатись деякі речі.

    Якщо є можливість, стукни мені в вазап або телеграм +393297332752

    ВідповістиВидалити
    Відповіді
    1. Привет, Андрей. Вычитал в документации, что в CCM можно разместить стек и heap (если есть), чтобы при обмене память-периферия через DMA меньше задержек было.

      Видалити
    2. Купу не рекомендують розміщувати в CCMRAM. Стеки процесів, керуючі структури ОС, ще щось акуратно. Те з чим треба працювати швидко і багато.

      Видалити