Материал из настоящей статьи, относящийся к микросхеме К1986ВЕ1QI, распространяется в том числе на микроконтроллеры К1986ВЕ1FI и К1986ВЕ1GI
Таблица векторов прерываний в микроконтроллере К1986ВЕ1QI всегда расположена с нулевого адреса и не может быть перенесена. При разработке программного обеспечения, исполняющегося из ОЗУ, нужно это учитывать и для возможности использования прерываний применять следующие методы:
1. Во Flash-памяти расположить программу, в которой описать функции-подпрограммы обработки прерываний, например, для
Timer 1 это может выглядеть так:
TIMER1_IRQHandler(void);
Фрагмент кода 1
Эта функция описана в файле
startup_MDR32F1QI.s. А уже внутри этой функции (
TIMER1_IRQHandler) должен вызываться реальный обработчик прерываний, расположенный в памяти ОЗУ.
2. Обработчики прерываний расположены в ОЗУ, а во Flash-памяти, в таблице векторов прерываний указать верные адреса этих обработчиков. Тогда при возникновении прерывания процессор обратится к таблице во Flash память, в которой возьмёт адрес обработчика прерывания, расположенного в ОЗУ.
Реализация первого метода
В качестве примера работы возьмем проект для отладочной платы
К1986ВЕ1QI из
этой статьи для IDE Keil. Этот проект будет загружаться в ОЗУ и использоваться, как основа: прерывания в проекте возникают по приёму данных через ИК-порт (отправить данные можно со второй такой же платы или со смартфона). По аналогии можно настроить работу с любыми прерываниями.
Дополнительно для скачивания
в конце статьи доступен проект, загружаемый во Flash-память, чтобы наладить корректную работу прерываний.
Нужно не забыть прикрепить к основному проекту файл
Setup.ini для запуска из ОЗУ согласно
этой статье. Для удобства запуск производится с начального адреса
0x20100000.
После первичного запуска проекта из ОЗУ и отправки на отладочную плату данных прерывания не возникают. Обработчик в программе называется
UART1_Handler.
Теперь во Flash-память необходимо записать программу, которая будет считывать значение адреса этого прерывания и "прыгать" на него после его возникновения.
Программа исполняется в микроконтроллере К
1986ВЕ1QI с адресов
0x20100000, для
UART1_IRQHandler необходимо считать значение памяти по адресу
0x20100058 (адрес высчитывается согласно таблице "Принцип формирования прерываний" из спецификации на микросхему), а затем перейти по полученному адресу. Таким образом произойдет выполнение обработчика прерывания из ОЗУ.
Код программы, записываемой во Flash-память:
#include <MDR32FxQI_port.h>
#include <MDR32FxQI_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
Реализация второго метода
Второй метод менее мобильный, но тоже имеет право на жизнь.
Внесём следующие изменения в проект для Flash-памяти:
- Необходимо в main.c оставить только следующие строки кода:
#include <MDR32FxQI_port.h>
#include <MDR32FxQI_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 - значение адреса, которое нужно считать в режиме отладки проекта под ОЗУ по адресу 0x20100058. Теперь программа из Flash-памяти будет отправлять процессор на выполнение обработчика прерывания в ОЗУ. Подробнее на рисунке 1:
Рисунок 1 - Значение address в окне Memory
Минусы этого метода в том, что значение address может изменяться, и необходимо это отслеживать.