Адреса | Назначение | Тип Памяти | 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. Всего типов памяти три:
Обращение к внешней шине через эти области происходит с некоторыми нюансами. Предположим, что в коде есть подряд несколько записей во внешнюю память. Например, последовательность из статьи - Работа с 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), либо записать обращения в некий внутренний буфер и продолжить выполнение прочих инструкций, не снижая общую производительность.
Затем, команды из буфера (параллельно с работой ядра) будут выводиться на контроллер внешней шины - и здесь есть два варианта:
В данном коде выбор режима, в котором будет работать ядро, определяется старшими разрядами адреса при обращении в адресное пространство.
// Макрос обращения к памяти #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.