Прошу помощи знатоков внутренней кухни работы ардуино. Нужно понять как работает некоторый код, написанный под ардуино. Сам я не знаком с её внутренней кухней.
Как я понимаю: Пользовательский код в ардуино должен быть описан внутри loop(), которая платформой вызывается итеративно, в супер-цикле. А пользовательский обработчик прерывания handleInterrupt(), регистрируемый вызовом attachInterrupt(..., handleInterrupt, ...) - он в каком контексте будет вызван? В отдельном контексте аппаратного ISR (как обычное прерывание на микроконтроллере)? Или он будет вызван в контексте супер-цикла, в котором итеративно выполняется loop()?
Погуглив, нашёл следующую инфу, что среда исполнения Ардуино реализована в виде си-шного:
Код:
int main(void) { init(); initVariant(); #if defined(USBCON) USBDevice.attach(); #endif setup(); for (;;) { loop(); if (serialEventRun) serialEventRun(); } return 0; }
Получается - serialEventRun() вызывается из контекста главного цикла. handleInterrupt() зарегистрированная attachInterrupt() будет также вызвана (последовательно рядом с serialEventRun())? Или она будет вызвана непосредственно из контекста аппаратного ISR?
Или она будет вызвана непосредственно из контекста аппаратного ISR?
attachInterrupt - это чисто железячное прерывание. Поэтому в некоторых туториалах рекомендуют минимум кода в присоединенном обработчике прерывания. Например взведение каких либо флагов и немедленный выход. А флаги уже обрабатываются в супер цикле loop()
attachInterrupt - это чисто железячное прерывание. Поэтому в некоторых туториалах рекомендуют минимум кода в присоединенном обработчике прерывания. Например взведение каких либо флагов и немедленный выход. А флаги уже обрабатываются в супер цикле loop()
Это точно???
Почему сомнения: Тот код, в котором разбираюсь, внутри handleInterrupt() содержит кучу кода. В handleInterrupt() есть не только функции типа delayMicroseconds(...), но и даже записи/чтения массивов байт в SPI. Т.е. - блокирующий доступ к разделяемым ресурсам. В главном цикле (loop()) есть такой доступ к этим ресурсам и в handleInterrupt() - тоже. Получается одно из двух: 1) или этот handleInterrupt() не может вызываться из ISR, а вызывается из контекста главного цикла; 2) или это говнокод.
Компиляторы и IDE не помешают вам писать плохой код. Но некоторые из них выдадут предупреждения. Даже если просто попытались тестировать. Ответственность за происходящее несет автор кода, даже если код бесполезен.
Карма: 1
Рейтинг сообщений: 20
Зарегистрирован: Пн сен 15, 2025 08:43:23 Сообщений: 436 Откуда: Маленький СССР посреди шариатской республики
Рейтинг сообщения:0
jcxz, если тебе так хочется на аврке древней писать, то зачем абдурина? Ну и пиши себе на сях. И не будет никаких вопросов к "внутренней кухне", т.к. вся она будет самодельной. Но таки лучше 32-битные приличные ARM'ы или RISC-V взять, у которых шикарная периферия (хотя, все равно всегда не хватает каналов DMA, количества таймеров или еще чего). Главное - пиши сам код, а не генерируй калокубами всякими!
jcxz, если тебе так хочется на аврке древней писать, то зачем абдурина? Ну и пиши себе на сях.
Для вас персональный совет: Учитесь читать тему, на которую отвечаете! Ни на какой "аврке" я не пишу. Так же как не пишу на абдурине. Вопрос был про попытку понять: Как работает некий готовый чужой код написанный на ардуино.
PS: Если вам нечего сказать по теме - прошу не засорять её бесполезным мусором! Чукчи-нечитатели - проходите пожалуйста мимо!
Обработчик serial уже встроен "внутри" по умолчанию. А вот функция attachInterrupt() добавляется по желанию/необходимости. Можно и чего то своего добавить, но с оглядкой на возможные проблемы при "наложении" ресурсов IDE, добавляемых по умолчанию и собственноручно написанных самоделок. В принципе... Или пользуйтесь "чистым СИ" или принимайте правила/ограничения референса ардуино. можно еще и тут посмотреть: https://alexgyver.ru/lessons/ Особое внимание к "чужим кодам" - чтоб что то "свое" встраивать за рамками предоставленных в IDE правил надо очень детально разбираться как в структуре самой IDE, так и в Си да в придачу и в С++. Довольно неблагодарная задача с учетом отношения к ардуиноIDE у местных обитателей...
Карма: 1
Рейтинг сообщений: 20
Зарегистрирован: Пн сен 15, 2025 08:43:23 Сообщений: 436 Откуда: Маленький СССР посреди шариатской республики
Рейтинг сообщения:0
Цитата:
Ни на какой "аврке" я не пишу. Так же как не пишу на абдурине. Вопрос был про попытку понять: Как работает некий готовый чужой код написанный на ардуино.
Абдурина === быдлокод. Если он еще и чужой, то единственный правильный вариант - выбросить его в мусорку! Да и самому в этой говно-среде писать ни в коем случае не стоит. Как и во всяких калокубах и им подобных говногенераторах.
Карма: 1
Рейтинг сообщений: 20
Зарегистрирован: Пн сен 15, 2025 08:43:23 Сообщений: 436 Откуда: Маленький СССР посреди шариатской республики
Рейтинг сообщения:0
BOB51, не отрицаю, среди абдуринщиков может затесаться 0.01% грамотных. Но это - скорей исключение, чем правило. Обычно этой "средой" пользуются лишь совсем уж безграмотные. И почерпнуть из их кода что-либо полезное не получится. Кстати, было как-то дело: перенесли эту гадость под STM32 и некоторые другие 32-битные МК. Доходило до абсурда: на МК есть аппаратный USB, а пользуются софтовым. Или, как они любят: МК не умеет делений даже, а в него флоаты пихают. Ну и самый цимус: I2C ногодрыгом. Или ШИМ. Или неиспользование DMA там, где он очень даже не помешал бы.
За АРМы ничего сказать не могу поскольку таковыми не пользуюсь. Относительно АВР под ардуино - то более известная тематика, имеющая прикладное применение и относительно хорошо проработаны по различным источникам информации.
jcxz, предоставьте весь код. Потому что то, что вы показали, не является Arduino - там нет ни USBDevice, ни for (;;), ни пустой loop(); и setup(); Ето просто код на C/C++, скомпилированный компилятором Arduino (GCC).
jcxz, предоставьте весь код. Потому что то, что вы показали, не является Arduino
Опять нечитатель... Я ничего не "предоставлял". Я спрашивал об общей структуре процесса выполнения кода. И привёл нагугленный вариант описания такой структуры. Схематичный вариант. Просто иллюстрирующий схему выполнения кода в ардуино.
jcxz, предоставьте весь код. Потому что то, что вы показали, не является Arduino
Опять нечитатель... Я ничего не "предоставлял". Я спрашивал об общей структуре процесса выполнения кода. И привёл нагугленный вариант описания такой структуры. Схематичный вариант. Просто иллюстрирующий схему выполнения кода в ардуино.
УПС... А что это за платформа такая: "Библиотека, предоставляющая базовые функции для использования чипов/модулей DW1000 от Decawave с Arduino"?? СпойлерDecawave теперь является частью Qorvo Узнайте больше о технологии сверхширокополосной связи, продуктах и многом другом на сайте Qorvo: Сверхширокополосный концентратор: Технологии Рынки и сферы применения Продукты: Решения UWB, совместимые с чипом Apple U1 Оценочные комплекты UWB Модули UWB Микросхемы UWB Ресурсы: Часто задаваемые вопросы Инструкции по применению Официальные документы Видео Партнеры UWB Форум сообщества Брошюра о сверхширокополосной связи Пресс-релиз: Qorvo завершает сделку по приобретению Decawave Это ведь специализированный модуль со своими специфическими библиотеками. Его рассматривать то надо имея знания по соответствующим микросхемам/МК, там применяемым... В среде ардуино достаточно много разнообразных МК с собственными особыми правилами (а бывает и с дополнительными компиляторами). То уж точно не для начинающих разбор кодов устраивать. Если простенькое UNO(нано или про-мини) то структура программы к примеру по симулятору (и в рамках GCC): Спойлер
А что это за платформа такая: "Библиотека, предоставляющая базовые функции для использования чипов/модулей DW1000 от Decawave с Arduino"??
Это код для работы с DW1000. Для измерения расстояния между двумя приёмо-передатчиками с точностью не хуже 10 см (заявлена производителем) и дальностью до 200-300 м.
Это ведь специализированный модуль со своими специфическими библиотеками. Его рассматривать то надо имея знания по соответствующим микросхемам/МК, там применяемым...
Это готовый проект кода для DW1000. На youtube есть ролики пользователей, которые использовали его и получали примерно заявленную точность. "Знание применяемых микросхем" - это юзер-мануал на более чем сотню регистров. Со сложным и запутанным программированием. Хочется взять этот проект и портировать его на свой МК. А не устраивать "закат солнца вручную" длительностью в несколько месяцев самостоятельных кувырканий с нуля. С негарантированным результатом.
Но после даже поверхностного анализа кода этого проекта, заметил, что функция обработчика прерываний handleInterrupt() в этом проекте обращается ко множеству разделяемых ресурсов (глобальные переменные, SPI-канал и т.п.) параллельно фоновому процессу в loop(). Без каких-либо видимых средств синхронизации/cериализации доступа. Что недопустимо в принципе. Или я не вижу этих средств синхронизации/cериализации. Тогда просьба - указать мне на них. Т.е. - допустимо такое только если handleInterrupt() будет вызываться платформой ардуино из контекста фонового процесса loop(), а не из контекста аппаратного ISR. Отсюда и возник исходный вопрос. Судя по роликам на youtube, код должен прекрасно работать.
PS: Ещё раз повторяю для нечитающих исходный вопрос: Я не спрашиваю как правильно делать! Не спрашиваю как работать с прерываниями и в многопоточной среде. И не просил меня поучать на эту тему. Я это сам прекрасно знаю и умею писать код для МК. Может даже получше вас, поучатели. Мой вопрос только о том: Как в среде ардуино реализовано исполнение пользовательского обработчика handleInterrupt()? Всё! Не более. Не знаете - проходите мимо.
Такие библиотеки анализируют по другому. Прикладные для спецкрсталлов могут быть написаны в рамках и по правилам стандартного GCC да плюс подключение файлов на ассемблере внутри. Не надо путать с теми функциями, что "референсом" предоставляются. И раскапывать там ничего смысла нет - или используем "как есть" или своё по даташитам пишем (ежли достаточно знаний и навыков).
Для всезнайки - ISR всегда выполняется средствами ISR (обработка прерывания) вне зависимости где и как лежит код. Для любого процессора. Иное невозможно. Выполнение кода может прерываться другими прерываниями, если контроллер прерываний это позволяет. Но выполнение кода ISR не может быть перенесено в фоновый процесс (USER). В некоторых процессорах это вообще два типа пространства - системное и user. Ваша тема не имеет смысла. Хватит флудить.
Ну уж так и не может обслуживание прерывания идти фоновым. К примеру основная программа и псевдо параллельный обработчик на прерываниях по таймеру (клавиатура, динамическая индикация)... Переключение на другую часть программы с последующим возвратом в основную (обработчик аппаратного прерывания выполняет только подстановку в стек адреса возврата и reti). Это только адрес вектора точки запуска обработчика прерывания жестко аппаратно определен. А что там дальше будет выполняться и где сам обработчик прерывания будет размещён - на усмотрение автора программы...
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 21
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения