[i] Настройка проекта в IDE Keil для запуска К1986ВЕ8Т из внешней ОЗУ К1645РУ5У на отладочной плате
Микроконтроллер (МК) К1986ВЕ8Т может работать в режиме микропроцессора и выполнять программу из внешней памяти. В загрузочной программе для старта МК из внешней памяти предусмотрено 4 режима работы:
- EXTBUS_8_ECC+JA (MODE[7:0]=1101 0100) - запуск из 8-разрядной памяти с последовательной организацией ECC и отладкой через JTAG_A;
- EXTBUS_8_ECC+JB (MODE[7:0]=1100 0011) - запуск из 8-разрядной памяти с последовательной организацией ECC и отладкой через JTAG_B;
- EXTBUS_CFG+JA (MODE[7:0]=0110 0110) - запуск из внешней памяти с чтением конфигурации, отладка через JTAG_A;
- EXTBUS_CFG+JB (MODE[7:0]=1010 0101) - запуск из внешней памяти с чтением конфигурации, отладка через JTAG_B.
На отладочной плате МК К1986ВЕ8Т для ознакомления с данными режимами работы установлена внешняя память СОЗУ К1645РУ5У объёмом 512 Кбайт. МК может выполнять программу, расположенную в этой памяти. Для этого необходимо установить требуемый режим работы МК, соответствующим образом настроить проект и загрузить программу во внешнюю память.
В данной статье рассмотрено, как в IDE Keil настроить проект и загрузить программу во внешнюю память ОЗУ с использованием файла инициализации (*.ini).
Содержание
|
1. Настройка проекта в IDE Keil 2. Отладка программы для режима EXTBUS_8_ECC+JA(JB) 3. Отладка программы для режима EXTBUS_CFG+JA(JB) |
1. Настройка проекта в IDE Keil
В статье "[i] Запуск программы из ОЗУ в IDE Keil" было описано, как загрузить и запустить программу из внутренней памяти ОЗУ. Вся настройка проекта сводилась к тому, что необходимо было указать адреса внутреннего ОЗУ для размещения программы (IROM и IRAM) и настроить файл инициализации, в котором устанавливались указатель стека, счётчик команд и базовый адрес таблицы векторов прерываний. После этого при переходе в режим Debug (Ctrl+F5) программа загружалась по внутреннюю память ОЗУ и запускалась отладка.
Подробный процесс запуска режима отладки описан на сайте Keil, пункт "Sequence of Execution, а также в статье Что происходит при запуске отладки в IAR и Keil, и состоит из следующих действий:
1) Сброс МК в соответствии с настройками отладчика и остановка ядра, при этом выполнение начального загрузчика (загрузочной программы) в МК останавливается.
2) Если установлен пункт "Options for Target→Debug", "Load application at Startup", то происходит загрузка скомпилированной программы по адресам IROM, указанным в настройках проекта.
3) Восстановление параметров режима отладки, например, конфигурации окон и точек останова из предыдущей отладки.
4) Выполнение команд в файле инициализации (*.ini).
5) Запуск выполнения программы с адреса, указанного в регистре счётчика команд PC.
Для отладки из внешней памяти в Keil необходимо указать адреса внешней памяти ОЗУ для размещения программы, как показано на рисунке 1.
Рисунок 1 - Настройка разделов IROM и IRAM1 в опциях проекта "Options for target→Target"
Так как после сброса МК внешняя шина не настроена и доступа к внешней памяти ОЗУ нет, то загрузка программы в пункте 2 выполнена не будет, поэтому галочку "Options for Target→Debug", "Load appliacation at Startup" необходимо снять, как показано на рисунке 2.
Рисунок 2 - Настройка параметров запуска отладки в опциях проекта "Options for target→Debug"
Загрузку программы во внешнее ОЗУ будем выполнять с использованием файла инициализации (*.ini), который подключается в настройках проекта (рисунок 2). Для этого в данном файле необходимо сначала настроить внешнюю шину, а затем загрузить программу во внешнее ОЗУ. В Keil для первоначальной инициализации МК предусмотрены специальные команды, которые можно использовать в файле инициализации.
Для настройки внешней шины необходима команда _WDWORD, позволяющая записывать 32-разрядные слова по указанному адресу. Таким образом, можно записать необходимые значения в регистры контроллера портов ввода-вывода и регистры контроллера внешней шины.
После того, как внешняя шина настроена, и можно обращаться к внешней памяти, выполним загрузку программы во внешнюю память ОЗУ. Для это воспользуемся встроенной командой LOAD.
В конце инициализации необходимо установить указатель стека и счётчик команд, считав значение с таблицы векторов прерываний (чтение выполняется уже из внешней ОЗУ), а также указать базовый адрес таблицы векторов прерываний. После можно запускать выполнение программы с помощью команды Go, она же "g".
Таким образом загрузка программы во внешнее ОЗУ и её дальнейшее выполнение будет осуществляться при запуске режима отладки.
2. Отладка программы для режима EXTBUS_8_ECC+JA(JB)
Проект "led_button_EXTRAM_8_ECC", настроенный на запуск в режиме отладки из внешней памяти для режима "EXTBUS_8_ECC+JA(JB)", приложен к данному материалу. В проекте светодиоды VD7-VD14 загораются при нажатии на кнопки KEY1-KEY3. Для загрузки программы во внешнюю память необходимо запустить режим отладки (Ctrl + F5).
В режиме запуска "EXTBUS_8_ECC+JA(JB)" (MODE[7:0]=11010100, MODE[7:0]=11000011) для взаимодействия с микросхемой памяти МК настраивает шину данных D[7:0], шину адреса А[18:0] и сигнал nOE (сигнал nCE не формируется и задан с помощью внешнего резистора доопределения на плате). При этом контроллер внешней шины переводится в режим работы с последовательной организацией ECC с базового адреса 0x1000_9000, запуск осуществляется с адреса 0x1000_0000. Таким образом адресный диапазон для хранения программы составляет 0x1000_0000 - 0x1000_9000, что соответствует объёму памяти программы 36 Кбайт. Для работы с большим объёмом памяти необходимо использовать режим EXTBUS_CFG.
Фрагмент кода 1 - Файл инициализации для работы с режимом "EXTBUS_8_ECC+JA(JB)"
FUNC void Setup (unsigned int region)
{
region &= 0xFFFFF000;
SP = _RDWORD(region); // Setup Stack Pointer
PC = _RDWORD(region + 4); // Setup Program Counter
_WDWORD(0xE000ED08, region); // Setup Vector Table Offset Register
}
FUNC void Setup_EBC (void)
{
_WDWORD(0x40000000, 0x8555AAA1); // CLK_CNTR->KEY = 0x8555AAA1;
_WDWORD(0x4000000C, 0x00038000); /* CLK_CNTR->PER0_CLK = CLKCTRL_PER0_CLK_MDR_PORTC_EN |
CLKCTRL_PER0_CLK_MDR_PORTD_EN |
CLKCTRL_PER0_CLK_MDR_PORTE_EN;*/
_WDWORD(0x40005000, 0x8555AAA1); // EXT_BUS_CNTR->KEY = 0x8555AAA1;
_WDWORD(0x40005024, 0x10009000); // EXT_BUS_CNTR->RGN0_ECCBASE = 0x10009000;
_WDWORD(0x40005004, 0x04447F27); /* EXT_BUS_CNTR->RGN0_CNTRL = 1 << EBC_READ32_pos |
4 << EBC_WS_HOLD_pos |
4 << EBC_WS_SETUP_pos |
7F << EBC_WS_ACTIVE_pos|
2 << EBC_MODE_pos |
1 << EBC_ECCMODE_pos |
EB_CNTR_ECCEN | EB_CNTR_EN; */
_WDWORD(0x40082000, 0x8555AAA1); // PORTC->KEY = 0x8555AAA1;
_WDWORD(0x40083000, 0x8555AAA1); // PORTD->KEY = 0x8555AAA1;
_WDWORD(0x40084000, 0x8555AAA1); // PORTE->KEY = 0x8555AAA1; /* A[1:0] (PC[31:30]) */
_WDWORD(0x40082024, 0x22000000); // PORTC->SFUNC[3] = FUNCVAL(31, 2) | FUNCVAL(30, 2);
_WDWORD(0x40082038, 0xC0000000); // PORTC->SANALOG = PORT_Pin_31 | PORT_Pin_30;
_WDWORD(0x4008205C, 0xF0000000); // PORTC->SPWR[1] = PWRVAL(31, 3) | PWRVAL(30, 3);
/* A[18:2] (PD[16:0]), D[1:0] (PD[31:30]),
nOE (PD23), nWE (PD24) */
_WDWORD(0x40083018, 0x22222222); /* PORTD->SFUNC[0] = FUNCVAL(7, 2) | FUNCVAL(6, 2) |
FUNCVAL(5, 2) | FUNCVAL(4, 2) |
FUNCVAL(3, 2) | FUNCVAL(2, 2) |
FUNCVAL(1, 2) | FUNCVAL(0, 2); */
_WDWORD(0x4008301C, 0x22222222); /* PORTD->SFUNC[1] = FUNCVAL(15, 2) | FUNCVAL(14, 2) |
FUNCVAL(13, 2) | FUNCVAL(12, 2) |
FUNCVAL(11, 2) | FUNCVAL(10, 2) |
FUNCVAL(9, 2) | FUNCVAL(8, 2); */
_WDWORD(0x40083020, 0x20000002); /* PORTD->SFUNC[2] = FUNCVAL(23, 2) | FUNCVAL(16, 2); */
_WDWORD(0x40083024, 0x22000002); /* PORTD->SFUNC[3] = FUNCVAL(31, 2) | FUNCVAL(30, 2) |
FUNCVAL(24, 2); */
_WDWORD(0x40083038, 0xC181FFFF); /* PORTD->SANALOG = PORT_Pin_31 | PORT_Pin_30 | PORT_Pin_24 |
PORT_Pin_23 | PORT_Pin_16 | PORT_Pin_15 |
PORT_Pin_14 | PORT_Pin_13 | PORT_Pin_12 |
PORT_Pin_11 | PORT_Pin_10 | PORT_Pin_9 |
PORT_Pin_8 | PORT_Pin_7 | PORT_Pin_6 |
PORT_Pin_5 | PORT_Pin_4 | PORT_Pin_3 |
PORT_Pin_2 | PORT_Pin_1 | PORT_Pin_0;*/
_WDWORD(0x40083058, 0xFFFFFFFF); /* PORTD->SPWR[0] = PWRVAL(15, 3) | PWRVAL(14, 3) |
PWRVAL(13, 3) | PWRVAL(12, 3) |
PWRVAL(11, 3) | PWRVAL(10, 3) |
PWRVAL(9, 3) | PWRVAL(8, 3) |
PWRVAL(7, 3) | PWRVAL(6, 3) |
PWRVAL(5, 3) | PWRVAL(4, 3) |
PWRVAL(3, 3) | PWRVAL(2, 3) |
PWRVAL(1, 3) | PWRVAL(0, 3); */
_WDWORD(0x4008305C, 0xF003C003); // PORTD->SPWR[1] = PWRVAL(31, 3) | PWRVAL(30, 3) |
PWRVAL(24, 3) | PWRVAL(23, 3) |
PWRVAL(16, 3); /* D[7:2] (PE[5:0]) */
_WDWORD(0x40084018, 0x00222222); /* PORTE->SFUNC[0] = FUNCVAL(5, 2) | FUNCVAL(4, 2) |
FUNCVAL(3, 2) | FUNCVAL(2, 2) |
FUNCVAL(1, 2) | FUNCVAL(0, 2); */
_WDWORD(0x40084038, 0x0000003F); // PORTE->SANALOG = PORT_Pin_5 | PORT_Pin_4 | PORT_Pin_3 |
PORT_Pin_2 | PORT_Pin_1 | PORT_Pin_0;
_WDWORD(0x40084058, 0x00000FFF); /* PORTE->SPWR[0] = PWRVAL(5, 3) | PWRVAL(4, 3) |
PWRVAL(3, 3) | PWRVAL(2, 3) |
PWRVAL(1, 3) | PWRVAL(0, 3); */
}
RESET // Reset MCU
Setup_EBC(); // Config EBC
LOAD $L%L INCREMENTAL // Load program to external RAM
Setup(0x10000000); // Setup SP, PC, VT
g ,main // Go to main
Если на плате установлен режим "EXTBUS_8_ECC+JA(JB)" (MODE[7:0]=11010100, MODE[7:0]=11000011), то после выхода из режима отладки, можно нажать кнопки "RESET" (SW1 и SW2), после чего МК сбросится и запустится из внешней памяти. Во время старта МК загрузочная программа устанавливает временные параметры транзакции на шине в следующие значения: WS_HOLD[3:0] = 0x4, WS_SETUP[3:0] = 0x4, WS_ACTIVE[7:0] = 0x7F. Временные параметры обмена могут быть изменены в ходе выполнения программы. В проекте "led_button_EXTRAM_8_ECC" для этого требуется раскомментировать определение:
#define SET_CUSTOM_EBC_WS
После этого при старте программы будет выполнена настройка временных параметров обмена (WS_SETUP = 0x1, WS_ACTIVE = 0x2, WS_HOLD = 0x1), при этом скорость работы с внешней микросхемой памяти ОЗУ будет увеличена. Подробнее про настройку временных параметров транзакции на внешней шине указано в статье "[i] Запуск МК К1986ВЕ8Т в режимах EXTBUS_8_ECC и EXTBUS_CFG". 3. Отладка программы для режима EXTBUS_CFG+JA(JB)
Проекты "led_button_EXTRAM_CFG_with_ECC" и "led_button_EXTRAM_CFG_without_ECC", настроенные на запуск в режиме отладки из внешней шины для режима "EXTBUS_CFG+JA(JB)", приложены к данному материалу. В проектах светодиоды VD7-VD14 загораются при нажатии на кнопки KEY1-KEY3. Для загрузки программы во внешнюю память необходимо запустить режим отладки (Ctrl + F5).
В режиме "EXTBUS_CFG+JA(JB)" (MODE[7:0]=01100110, MODE[7:0]=10100101) для считывания конфигурационных бит CFG0-CFG9 МК настраивает шину данных D[7:0], шину адреса А[10:3] и сигнал nOE (сигнал nCE и не настраиваемые сигналы шины адреса не формируются и заданы с помощью внешних резисторов доопределения на плате). На основании считанных бит CFGx МК устанавливает необходимые настройки контроллера внешней шины, расширяет шину адреса до A[20:0], после чего выполняет запуск программы с адреса 0x1000_0000.
На отладочной плате для К1986ВЕ8Т установлена 8-разрядная микросхема памяти ОЗУ К1645РУ5У, поэтому конфигурационные биты CFG необходимо задать таким образом, чтобы шина данных была 8-разрядной (CFG0 = 1).
Если будет использоваться последовательная ECC (CFG1 = 2), то необходимо установить базовый адрес ECC в CFG2-CFG9. Например, можно установить базовый адрес ECC равным 0x1006_0000, таким образом 384 Кбайта будет доступно для программы, а оставшиеся 128 Кбайт будут отведены для ECC (использоваться будут только 384 Кбайт/4 = 96 Кбайт). Данная конфигурация приведена в примере "led_button_EXTRAM_CFG_with_ECC".
Если проверка ECC (CFG1 = 1) использоваться не будет, то конфигурационные биты CFG2-CFG9 считываться не будут, а потому их можно не задавать в проекте. В этом случае для программы будет доступен весь объём внешней памяти - 512 Кбайт. Данная конфигурация приведена в примере "led_button_EXTRAM_CFG_without_ECC".
Считывание конфигурационных бит CFG производится по адресам 0x1000_0400, 0x1000_0408, … 0x1000_0448. В среде Keil данные значения могут быть указаны с помощью команд в любом файле программы, например, в "main.c", как представлено в фрагменте кода 2.
Фрагмент кода 2 - Инициализация конфигурационных бит CFG в среде Keil
#define __ATTR_ADDR(ADDR) __attribute__((section(".ARM.__at_"#ADDR)))
const uint8_t Cfg_0 __ATTR_ADDR(0x10000400) = 0x71; // CFG0 - шина данных
const uint8_t Cfg_1 __ATTR_ADDR(0x10000408) = 0xB2; // CFG1 - контроль ECC
const uint8_t Cfg_2 __ATTR_ADDR(0x10000410) = 0x00; // CFG2 - ECCBASE[3:0]
const uint8_t Cfg_3 __ATTR_ADDR(0x10000418) = 0x00; // CFG3 - ECCBASE[7:4]
const uint8_t Cfg_4 __ATTR_ADDR(0x10000420) = 0x00; // CFG3 - ECCBASE[11:8]
const uint8_t Cfg_5 __ATTR_ADDR(0x10000428) = 0x00; // CFG3 - ECCBASE[15:12]
const uint8_t Cfg_6 __ATTR_ADDR(0x10000430) = 0x66; // CFG3 - ECCBASE[19:16]
const uint8_t Cfg_7 __ATTR_ADDR(0x10000438) = 0x00; // CFG3 - ECCBASE[23:20]
const uint8_t Cfg_8 __ATTR_ADDR(0x10000440) = 0x00; // CFG3 - ECCBASE[27:24]
const uint8_t Cfg_9 __ATTR_ADDR(0x10000448) = 0x71; // CFG3 - ECCBASE[31:28]
Для конфигурационных бит CFG также используется кодирование ECC, при этом каждое конфигурационное слово представляет собой байт данных DATA[7:0] = { ECC[3:0], CFGx[3:0] }, где ECC[3:0] - старший полубайт, а CFGx[3:0] - младший полубайт. Необходимые биты ECC[3:0] можно рассчитать либо с помощью специального алгоритма, либо по таблице, в зависимости от выбранных бит CFGx[3:0]. Подробнее про это описано в статье "[i] Начальные сведения о помехозащищенном кодировании на основе кода Хэмминга".
Получившийся файл инициализации аналогичен файлу для режима запуска "EXTBUS_8_ECC+JA(JB)" (фрагмент кода 1), за исключением следующих моментов:
- в проекте "led_button_EXTRAM_CFG_with_ECC" используется базовый адрес ECC - 0x1006_0000, поэтому в регистр RGN0_ECCBASE записывается значение 0x1006_0000;
- в проекте "led_button_EXTRAM_CFG_without_ECC" не используется проверка ECC, поэтому в бит ECCEN в регистре RGN0_CNTRL записывается 0, значение регистра RGN0_ECCBASE не изменяется.
Как и в предыдущем случае, если на отладочной плате установлен режим "EXTBUS_CFG+JA(JB)" (MODE[7:0]=01100110, MODE[7:0]=10100101), то после выхода из режима отладки, можно нажать кнопки "RESET" (SW1 и SW2), после чего МК сбросится и запустится из внешней памяти.
Во время старта МК загрузочная программа устанавливает временные параметры транзакции на шине в следующие значения: WS_HOLD[3:0] = 0x4, WS_SETUP[3:0] = 0x4, WS_ACTIVE[7:0] = 0x7F. Временные параметры обмена могут быть изменены в ходе выполнения программы. В проектах для этого требуется раскомментировать определение:
#define SET_CUSTOM_EBC_WS
После этого при старте программы будет выполнена настройка временных параметров обмена (WS_SETUP = 0x1, WS_ACTIVE = 0x2, WS_HOLD = 0x1), при этом скорость работы с внешней микросхемой памяти ОЗУ будет увеличена. Подробнее про настройку временных параметров транзакции на внешней шине указано в статье "[i] Запуск МК К1986ВЕ8Т в режимах EXTBUS_8_ECC и EXTBUS_CFG".
Сохранить статью в PDF