[i] Настройка проекта в IDE Keil для запуска К1986ВЕ8Т из внешней ОЗУ К1645РУ5У на отладочной плате

ID статьи: 61480
Дата последнего изменения: 05.12.2025 12:17:40

Микроконтроллер (МК) К1986ВЕ8Т может работать в режиме микропроцессора и выполнять программу из внешней памяти. В загрузочной программе для старта МК из внешней памяти предусмотрено 4 режима работы:

На отладочной плате МК К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.

Микросхема К1645РУ5У имеет шину адреса А[18:0], однако МК в режиме EXTBUS_8_ECC настраивает шину адреса А[15:0], поэтому линии адреса A[18:16] доопределены на плате до низкого логического уровня напряжения с помощью резисторов доопределения.
Получившийся файл инициализации приведён в фрагменте кода 1.

Фрагмент кода 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".


Контактная информация

Сайт:https://support.milandr.ru
E-mail:support@milandr.ru
Телефон: +7 495 221-13-55