From 840fc7484d748cf801b0030b31b4c9a2611cc3b1 Mon Sep 17 00:00:00 2001 From: KLASSENTS Date: Mon, 4 Aug 2025 11:17:48 +0700 Subject: [PATCH] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=B2=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE?= =?UTF-8?q?=D1=81=D1=82=D1=8C=20=D0=BF=D1=80=D0=BE=D0=BF=D1=83=D1=81=D0=BA?= =?UTF-8?q?=D0=B0=D1=82=D1=8C=20=D0=BA=D0=BE=D0=B4=20=D1=81=D1=82=D0=B0?= =?UTF-8?q?=D0=BD=D0=B4=D0=B0=D1=80=D1=82=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=BE?= =?UTF-8?q?=D0=B1=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D1=87=D0=B8=D0=BA=D0=B0=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B5=D1=80=D1=8B=D0=B2=D0=B0=D0=BD=D0=B8=D0=B9=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B8=20=D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B8=20=D0=BF=D0=BE=D0=BB=D1=8C?= =?UTF-8?q?=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D0=B5=D0=BB=D1=8C=D1=81=D0=BA?= =?UTF-8?q?=D0=BE=D0=B3=D0=BE=20=D0=BE=D0=B1=D1=80=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D1=87=D0=B8=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 27 ++++++++++++++++++++++++++- cores/arduino/trap_handler.c | 24 ++++++++++++++++++------ 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 475223b..115f514 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,32 @@ Общая функция-обработчик прерываний располагается в RAM памяти. Это позволяет устранить задержки, связанные с кэшированием при работе из FLASH памяти. Обработчики прерываний, назначаемые на цифровые выводы с помощью функции `void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode)`, и обработчик прерывания для функции `tone()` так же располагаются в памяти RAM. Глобальное разрешение прерываний активируется после завершения функции `setup()`. Если необходимо использовать прерывания внутри самой функции `setup()`, их можно включить вручную, вызвав функцию `interrupts()` перед вызовом функций, работающих с прерываниями. Прерывания используются для приема данных модулями `Serial`, `Wire`, для работы библиотеки `Servo`, функцией `tone()`. - + +В пакете поддержки доступна возможность дополнения или замены стандартного обработчика прерываний пользовательской функцией-обработчиком. Для этого в своем скетче необходимо определить функцию `extern "C" bool ISR()`, она вызывается первой в стандартном обработчике. Внутри функции можно проверять флаги прерываний и реагировать на нужные. Важно очищать флаги обрабатываемых прерываний, чтобы обработчик работал корректно. +Если функция возвращает `false`, после ее выполнения так же будет выполнен код стандартного обработчика прерываний. Если функция возвращает `true`, выполнение кода стандартного обработчика будет пропущено. +Пользовательскую функцию необходимо располагать в RAM памяти, так как стандартный обработчик памяти расположен именно там. +Ниже приведен пример пользовательской обработки прерывания по переполнению от 16-битного таймера 1: +``` +extern "C" __attribute__((section(".ram_text"))) bool ISR(void) +{ + // обработка прерывания от 16-битного таймера + if (EPIC_CHECK_TIMER16_1()) + { + if (TIM16_GET_ARRM_INT_STATUS(htimer16_1_)) + { + // необходимые действия при переполнении таймера + } + // очистить флаги прерывания от таймера 1 + TIM16_CLEAR_INT_MASK(htimer16_1_, 0xFFFFFFFF); + } + return false; +} +``` +Для корректной работы функции из примера необходимо подключить в скетче следующие файлы: +``` +#include "mik32_hal_timer16.h" +#include "wiring_LL.h" +``` ### Serial Для работы доступно два последовательных интерфейса. Нулевой интерфейс используется экземпляром класса `Serial`. Информации в Монитор порта в Arduino IDE поступает через него. Первый интерфейс используется экземпляром класса `Serial1`. Выводы, на которых доступны указанные интерфейсы, перечислены в описании отдельных плат. Доступны следующие макросы для настройки режима работы каждого интерфейса в функции `Serial.begin()`: `SERIAL_7N1`, `SERIAL_8N1`, `SERIAL_7N2`, `SERIAL_8N2`, `SERIAL_7E1`, `SERIAL_8E1`, `SERIAL_7E2`, `SERIAL_8E2`, `SERIAL_7O1`, `SERIAL_8O1`, `SERIAL_7O2`, `SERIAL_8O2`. Здесь длина данных - 7 или 8 бит; бит четности - нет(N), четный(E), нечетный(O); стоп бит - 1 или 2 бита. diff --git a/cores/arduino/trap_handler.c b/cores/arduino/trap_handler.c index e3c5901..a561880 100644 --- a/cores/arduino/trap_handler.c +++ b/cores/arduino/trap_handler.c @@ -18,12 +18,12 @@ void __attribute__((weak)) IRremote_interrupt_handler(void) // dummy function for case when IRremote library is not in use } -void __attribute__((weak)) ISR(void) -{ +bool __attribute__((section(".ram_text"), weak)) ISR(void) +{ /* A dummy function for the case when additional interrupts are not used in the project. In the project, you need to create a function of the form: - extern "C" void ISR() + extern "C" __attribute__((section(".ram_text"))) bool ISR(void) { if (EPIC_CHECK_TIMER16_1()) { @@ -35,20 +35,31 @@ void __attribute__((weak)) ISR(void) // reset timer interrupt flags TIM16_CLEAR_INT_MASK(htimer16_1_, 0xFFFFFFFF); } + return false; } + + If you don't need to call standard trap_handler() code, you can return true from this function + and trap_handler() code will be missed. But you must carefully clear interrupt flags by yourself + in your custom ISR() function. + libraries required to use this example: #include "mik32_hal_timer16.h" - #include "mik32_hal_irq.h" #include "wiring_LL.h" */ + return false; } // ---------------------------------------------- // void __attribute__((noinline, section(".ram_text"), optimize("O3"))) trap_handler (void) { // custom interrupt - ISR(); - + if(ISR()) + { + // reset all interrupts and miss trap_handler() code + EPIC_CLEAR_ALL(); + return; + } + // gpio interrupt if (EPIC_CHECK_GPIO_IRQ()) gpio_interrupt_handler(); @@ -77,6 +88,7 @@ void __attribute__((noinline, section(".ram_text"), optimize("O3"))) trap_handle if (EPIC_CHECK_I2C_0()) wire_interrupt_handler(0); + // i2c1 interrupt if (EPIC_CHECK_I2C_1()) wire_interrupt_handler(1);