STM32 CCM

Есть у некоторых взрослых STM-ок такая дурная штука, как CCM (core coupled memory). Это отдельный регион памяти, не шуточного размера в 64K (для F4xx), который по-умолчанию вообще не используется. Выделена эта память в отдельный регион, потому что имеет подключение только к D-BUS ядра, что накладывает кое-какие ограничения. Главное — это невозможно использовать вместе с DMA и DMA2D и выполнять код (примечание: это для F40x, но вообще неплохо заглянуть в PDF, раздел «Архитектура системы»), а в остальном — память как память.
Есть несколько способов хоть как-то его начать использовать, самый простой способ — это положить туда стек.
Для этого нужно модифицировать всего одну строку скрипта линковки, ту что задает адрес _estack и положить в этот символ адрес конца CCM (0x10010000):

_estack = 0x10010000;    /* end of CCMRAM */

При этом весь стек переедет в CCM и как следствие все локальные переменные, аргументы функции итд.
Второй не менее простой, но довольно ручной способ — это указание секции при описании переменной:

__attribute__((section(".ccmram"))) int ccmvar;

однако, стоит при этом помнить, что без модификации startup-скрипта при инициализации там будет мусор, заполним нулями, добавив где-нибудь после FillZeroBSS

/* Zero fill the CCM segment. */
ldr  r2, =_sccmram
FillZeroCCM:
  movs  r3, #0
  str  r3, [r2], #4
 
LoopFillZeroCCM:
  ldr  r3, = _eccmram
  cmp  r2, r3
  bcc  FillZeroCCM

а заодно уберем в скрипте линковки из описания секции .ccmram запись инициализации во FLASH:

  .ccmram (NOLOAD):
  {
    . = ALIGN(4);
    _sccmram = .;       /* create a global symbol at ccmram start */
    *(.ccmram)
    *(.ccmram*)
 
    . = ALIGN(4);
    _eccmram = .;       /* create a global symbol at ccmram end */
   } >CCMRAM

теперь все переменные с attribute((section(«.ccmram»))) будут стартовать с нулевыми значениями.

Подробнее про переменные, секции и инициализацию можно почитать тут: ARM Without Magic. Урок 1.1 Переменные и инициализация.