STM32F746GDISCOVERY.
Cortex®­M7, организация памяти.
Документация на русском языке

На сегодняшний день эта публикация, скорее не набор решений, а некий тестовый стенд, на котором эти решения можно попробовать

STM32F746GDISCOVERY – уже не новая, но очень серьезная железка, которая умеет все, ну или почти все.

Сказка начинается уже в CubeMX.
System Core
CORTEX_M7

Cortex interface Setting
Flash Interface
ART ACCLERATOR
Instruction Prefetch
CPU ICache
CPU DCache

Cortex Memory Protection Unit…

Все и везде пишут по-разному от моего древнего перевода LCD-TFT display controller (LTDC) on STM32 MCUs (Rus) стр. 47 «Пример конфигурации MPU…» до видео уроков narodstream.ru/programmirovanie-mk-stm32/. Если что-то поменять, то либо перестает работать, либо ничего особо не меняется. Что, почему? – Никто не пишет!

Читаем:

RM0385 Reference manual
STM32F75xxx and STM32F74xxx advanced Arm®-based 32-bit MCUs.
2 System and memory overview
3 Embedded Flash memory (FLASH)

 

Ищем:

И, собственно, все… Ясности это все мне, особенно, не добавило.

Есть интересная статья:

AN4667 Application note
STM32F7 Series system architecture and performance

«Это примечание по применению предоставляется со встроенным программным пакетом X-CUBE-32F7PERF…» То есть содержит не только примеры кода и файлы компоновщика, но и «…советы о том, как разделить код и данные в памяти STM32F7, чтобы получить наилучшую компромиссную производительность в зависимости от кода и размеров данных.»

Что делать! )))

Все недоумение в начале статьи вызвали примеры, где вся память объединена:

define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__ = 0x2004FFFF;

Действительно, в рамках используемых ресурсов, визуально не заметно как дисплей выводит строчку чуть быстрее или чуть медленнее.

Однако мы знаем, что плата умеет считать и выводить на экран быстрое преобразование Фурье и цифровые фильтры. Примеры этих решений есть в библиотеке X-CUBE-DSPDEMO.

 

В идеале нужно разделить команды и данные. Дальше можно использовать кэширование, разные интерфейсы и DMA.

 

Есть мнение, что можно все это изящно попробовать и на простом примере.

Воспользуемся навыками написания файлов компоновщика из предыдущей статьи:  «IAR C/C++ Development Guide» и напишем файл, разбив память правильно.

Мне не удалось здесь сохранить расширение *.icf. Поэтому придется переименовать из *.txt.

 

В публикации «CCM (core coupled memory) data RAM» я рассказал, как можно использовать память ядра, декларируемую, но де факто не используемую в примерах для STM32F407.

Посмотрим еще раз документ AN4296 (Use STM32F3/STM32G4 CCM SRAM with IAR™ EWARM, Keil® MDK-ARM and GNU-based toolchains).
В нем подробно описано, как перенести таблицу прерываний в память ядра и сделаем тоже самое для Cortex®­M7.

Где особенно изящно будет выглядеть:

Поскольку память ядра команд именно так и должна использоваться.

И уже никого не будем обманывать со схемой управления памятью heap_5.

// IAR C/C++ Development Guide
// Compiling and Linking for Arm
// Linking your application pg. 116

static uint8_t* p_heap1;
static uint8_t* p_heap2;
#pragma section = "HEAP1"
__no_init uint8_t heap_DTCM[16*1024];
#pragma section = "HEAP2"
__no_init uint8_t heap_SRAM1[16*1024];
// Используйте эту директиву pragma для определения имени раздела, которое может использоваться операторами раздела __section_begin, __section_end и __section_size.
// Все объявления разделов для определенного раздела должны иметь одинаковое выравнивание.
// Примечание. Чтобы разместить переменные или функции в определенном разделе, используйте директиву #pragma location или оператор @.
// Use this pragma directive to define a section name that can be used by the __section_begin, __section_end, and __section_size section operators.
// All section declarations for a specific section must have the same alignment.
// Note. To place variables or functions in a specific section, use the #pragma location directive or the @ operator.




/* USER CODE BEGIN 1 */

p_heap1 = __section_begin("HEAP1"); // 0x2000'8000 ""
p_heap2 = __section_begin("HEAP2"); // 0x2004'4000 ""

HeapRegion_t xHeapRegions[] =
{
{ p_heap1, sizeof(heap_DTCM) },
{ p_heap2, sizeof(heap_SRAM1) },
{ NULL, 0 }
};
vPortDefineHeapRegions( xHeapRegions );
// Используется для определения нескольких областей кучи для использования heap_5.c.
// Эта функция должна вызываться перед любыми вызовами pvPortMalloc () - отсутствие создания задачи,
// очереди, семафора, мьютекса, программного таймера, группы событий и т. д. Приведет к вызову pvPortMalloc.
//
// pxHeapRegions передает массив структур HeapRegion_t, каждая из которых определяет область памяти,
// которую можно использовать в качестве кучи. Массив завершается структурой HeapRegions_t, размер которой равен 0.
// Область с наименьшим начальным адресом должна появляться первой в массиве.

// Used to define multiple heap areas to use heap_5.c.
// This function must be called before any calls to pvPortMalloc () - no task creation,
// queue, semaphore, mutex, program timer, event group, etc. Will call pvPortMalloc.
//
// pxHeapRegions passes an array of HeapRegion_t structures, each of which defines a memory area,
// which can be used as a heap. The array ends with a HeapRegions_t structure of size 0.
// The area with the lowest start address should appear first in the array.

/* USER CODE END 1 */

Есть смысл отметить, что кучу таким образом можно организовать и в SDRAM

К сожалению, на сегодняшний день у меня нет интересного проекта, реализующего эти моменты. Однако все, описанное выше, проверено и работает в тестовом примере.

С уважением Петр.

Реализуем коммерческие проекты.
Возможна работа по договору подряда.

t654rk@mail.ru

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.