Таблица векторов прерываний в микроконтроллерах серии К1986ВЕ1x всегда расположена с нулевого адреса и не может быть перенесена. При разработке программного обеспечения, исполняющегося из ОЗУ, нужно это учитывать и для возможности использования прерываний применять следующие методы:
1. Во Flash-памяти расположить программу, в которой описать функции-подпрограммы обработки прерываний, например, для
Timer 1 это может выглядеть так:
TIMER1_IRQHandler(void); Фрагмент кода 1
Эта функция описана в файле startup (
startup_MDR32F1QI.S для микросхем К1986ВЕ1QI,
startup_K1986VE1xI.S для микросхем К1986ВЕ1FI, К1986ВЕ1GI, и
startup_MDR1986VE1T.S для микросхем К1986ВЕ1(А)Т). А уже внутри этой функции (
TIMER1_IRQHandler) должен вызываться реальный обработчик прерываний, расположенный в памяти ОЗУ.
2. Обработчики прерываний расположены в ОЗУ, а во Flash-памяти, в таблице векторов прерываний указать верные адреса этих обработчиков. Тогда при возникновении прерывания процессор обратится к таблице во Flash память, в которой возьмёт адрес обработчика прерывания, расположенного в ОЗУ.
1. Реализация первого метода
В качестве примера работы возьмем проект для отладочной платы
К1986ВЕ1Т из
этой статьи для IDE Keil. Этот проект будет загружаться в ОЗУ и использоваться, как основа: прерывания в проекте возникают по приёму данных через ИК-порт (отправить данные можно со второй такой же платы или со смартфона). По аналогии можно настроить работу с любыми прерываниями.
Дополнительно для скачивания
в конце статьи доступен проект, загружаемый во Flash-память, чтобы наладить корректную работу прерываний.
Нужно не забыть прикрепить к основному проекту файл
Setup.ini для запуска из ОЗУ согласно
этой статье. Для удобства запуск производится с начального адреса
0x2010_0000.
После первичного запуска проекта из ОЗУ и отправки на отладочную плату данных прерывания не возникают. Обработчик в программе называется
UART1_Handler.
Теперь во Flash-память необходимо записать программу, которая будет считывать значение адреса этого прерывания и "прыгать" на него после его возникновения.
Программа исполняется в микроконтроллере К
1986ВЕ1Т с адресов
0x2010_0000, для
UART1_IRQHandler необходимо считать значение памяти по адресу
0x2010_0058 (адрес высчитывается согласно таблице "Принцип формирования прерываний" из спецификации на микросхему), а затем перейти по полученному адресу. Таким образом произойдет выполнение обработчика прерывания из ОЗУ.
Код программы, записываемой во Flash-память:
#include <MDR32F9Qx_port.h> // Здесь и далее - при использовании микросхем в пластмассовых корпусах названия драйверов изменить с MDR32F9Qx_... на MDR32FxQI_...
#include <MDR32F9Qx_rst_clk.h>
#define HWREG(x) (*((volatile uint32_t *)(x))) // Макрос для считывания значения по определенному адресу
void UART1_IRQHandler(void);
int main()
{
NVIC_EnableIRQ(UART1_IRQn); //Enable UART1 interrupt
while(1) {
UART1_IRQHandler();
}
}
//--- UART1 interrupt routine ---
void UART1_IRQHandler()
{
int A;
A = HWREG(0x20100058); // Занести в переменную А значение памяти по адресу 0x20100058 (UART1_IRQHandler), чтобы корректно прыгнуть в обработчик прерывания в программе ОЗУ
typedef void (*funcptr)();
funcptr funcInRAM = (funcptr) (A);
funcInRAM(); // Прыжок
}
Фрагмент кода 2
2. Реализация второго метода
Второй метод менее мобильный, но тоже имеет право на жизнь.
Внесём следующие изменения в проект для Flash-памяти:
- Необходимо в main.c оставить только следующие строки кода:
#include <MDR32F9Qx_port.h>
#include <MDR32F9Qx_rst_clk.h>
void UART1_IRQHandler(void);
int main()
{
NVIC_EnableIRQ(UART1_IRQn); //Enable UART1 interrupt
while(1) {
UART1_IRQHandler();
}
} Фрагмент кода 3
- В файле startup*.S (стартовый файл) необходимо изменить строчку "DCD UART1_IRQHandler" на "DCD address", где address - значение адреса, которое нужно считать в режиме отладки проекта под ОЗУ по адресу 0x2010_0058. Теперь программа из Flash-памяти будет отправлять процессор на выполнение обработчика прерывания в ОЗУ. Подробнее на рисунке 1:
.png)
Рисунок 1 - Значение address в окне Memory
Минусы этого метода в том, что значение address может изменяться, и необходимо это отслеживать.