Инструменты пользователя

Инструменты сайта


prog:extbus:extbus_memattr

Типы памяти при работе с внешней шиной

Адресное пространство в Cortex-M3 (МК 1986ВЕ9х)

Адреса Назначение Тип Памяти XN Описание
0x0000_0000 - 0x1FFF_FFFF Code Normal - Код программы и данные
0x2000_0000 - 0x3FFF_FFFF SRAM Normal - Данные и код программы
0x4000_0000 - 0x5FFF_FFFF Peripheral Device XN Периферия Milandr
0x6000_0000 - 0x9FFF_FFFF Ext RAM Normal - Внешнее ОЗУ
0xA000_0000 - 0xDFFF_FFFF Ext Device Device XN Внешние Устройства
0xE000_0000 - 0xE000_FFFF Core Bus Strongly Ordered - Периферия ядра - NVIC, SysTimer, регистры ядра
0xE001_0000 - 0xFFFF_FFFF Reserved Device XN Зарезервировано

XN - Execute Never, обращение за инструкциями для исполнения в данные области не возможен.

Доступ к контроллеру внешней шины возможен через различные области адресного пространства. Эти области имеют разные типы памяти, которые могут быть изменены в блоке MPU. Всего типов памяти три:

  • Normal
  • Device
  • Strongly Ordered

Обращение к внешней шине через эти области происходит с некоторыми нюансами. Предположим, что в коде есть подряд несколько записей во внешнюю память. Например, последовательность из статьи - Работа с Flash памятью 1636РР1У по внешней шине 1986ВЕ91Т.

//  Стирание всей памяти
FlashStatus EraseFullFLASH(void)
{
  ...
  //	Командная последовательность EraseFull
  HWEXTBUS(0x555) = 0xAAAAAAAA;
  HWEXTBUS(0x2AA) = 0x55555555;
  HWEXTBUS(0x555) = 0x80808080;
  HWEXTBUS(0x555) = 0xAAAAAAAA;
  HWEXTBUS(0x2AA) = 0x55555555;
  HWEXTBUS(0x555) = 0x10101010
  ...
}  

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

Процессор же, получив такую последовательность команд, должен либо остановиться пока не закончится текущая операция на шине (режим Strongly Ordered), либо записать обращения в некий внутренний буфер и продолжить выполнение прочих инструкций, не снижая общую производительность.

Затем, команды из буфера (параллельно с работой ядра) будут выводиться на контроллер внешней шины - и здесь есть два варианта:

  1. Если типа памяти Normal, то последовательность исполнения команд из буфера может быть изменена для повышения быстродействия. Не знаю, как происходит оптимизация исполнения в ядре на самом деле, но например, для снижения количества переключений сначала можно выполнить все чтения, а затем все записи. Ведь для переключения режима Read/Write необходимо дополнительное время на переключение сигналов шины nOE и WE, а так-же режима линий данных In/Out. Такой режим работы подходит, например, для чтения внешнего ОЗУ, где очередность выборки данных не имеет значения.
  2. Если тип памяти Device, то последовательность команд сохраняется неизменной. Этот режим необходим там, где последовательность команд является важной.

В данном коде выбор режима, в котором будет работать ядро, определяется старшими разрядами адреса при обращении в адресное пространство.

//  Макрос обращения к памяти
#define HWREG(x)            (*((volatile uint32_t *)(x)))

//  Макрос обращения к внешней шине
#define EXTBUS_START_ADDR   0x60000000   // Normal
  или
#define EXTBUS_START_ADDR   0xA0000000   // Device

#define EXTBUS_ADDR(x)      (EXTBUS_START_ADDR + ((x) << 2))
#define HWEXTBUS(x)         HWREG(EXTBUS_ADDR(x))

Для управлением записью в 1636РР1У необходимо четко соблюдать последовательность команд, поэтому необходимо осуществлять обращения к внешней шине через регион с типом памяти Device. То-есть, адреса должны быть в диапазоне начинающимся с 0xA000_0000.

prog/extbus/extbus_memattr.txt · Последнее изменение: 2022/04/03 23:09 (внешнее изменение)