Как завершить прерывание с более низким приоритетом?

У меня есть одно прерывание с высоким приоритетом, которое отправляет данные USB, и одна задача с более низким приоритетом, которая уже выбирает следующие данные для отправки.

Иногда для прерывания с высоким приоритетом требуются некоторые данные, которые все еще выбираются, и в этом случае мне нужно проинструктировать MCU завершить задачу с более низким приоритетом, прежде чем продолжить выполнение в прерывании с высоким приоритетом.

Я не могу понять, как заставить это работать. Можно ли с помощью NVIC_SetPriority поднять приоритет фоновой задачи выше и сразу вызвать NVIC_SetPendingIRQ из задачи USB, а после этого снова понизить? Или как это сделать проще всего?


person Muis    schedule 13.02.2014    source источник
comment
Я считаю очень невежливым не оставлять отзывов после того, как кто-то потратил свое время на то, чтобы попытаться помочь вам с проблемой.   -  person Adi    schedule 14.02.2014
comment
@Adi Я считаю очень невежливым отрицать вопросы, если ваш ответ не будет принят через пару часов. Я должен по крайней мере сначала подумать о вашем ответе, прежде чем я смогу решить, помогает ли он мне дальше, но в настоящее время это не так.   -  person Muis    schedule 14.02.2014


Ответы (2)


Сколько времени у вас есть, чтобы ответить на запрос данных, и сколько времени потребуется на предварительную выборку для следующего запроса? Если время предварительной выборки невелико, я бы изменил ваш приоритет прерываний - это сохраняет буфер заполненным для прерывания запроса данных.

В противном случае нет чистого способа делать то, что вы хотите, с нуля - это то, для чего нужны операционные системы. Если вы работаете в операционной системе, процедура прерывания запроса данных может запросить сигнал из процедуры прерывания предварительной выборки и вернуться из прерывания и ждать, пока программа прерывания запроса данных не отправит сигнал о завершении блока.

В чистом виде вы можете попробовать заставить подпрограмму предварительной выборки вызывать прерывание запроса данных после того, как каждый буфер готов. Затем DRIR выполняет серию проверок, когда просыпается.

  • Was I woken by a Data Request?
    • yes: Do I have data to send?
      • yes: Send data, clear interrupt request, return from interrupt
      • нет: увеличение счетчика «необходимых блоков» на 1, очистка запроса прерывания, возврат из прерывания
    • no: must have been woken by a Prefetch complete, is "blocks needed" zero?
      • yes: buffer has data, but not needed yet, return
      • нет: отправьте 1 блок данных, уменьшите количество «необходимых блоков» до нуля или пока буфер не станет пустым, возврат

Нет никакой гарантии, что вы получите данные вовремя, но, по крайней мере, так есть шанс, что прерывание с более низким приоритетом завершится.

Кстати, я не думаю, что NVIC может принудительно остановить выполняющееся в данный момент прерывание для другого с более высоким приоритетом. Приоритеты действительно имеют значение, когда прерывания происходят одновременно (или когда прерывания уже замаскированы, т. Е. При обслуживании другого прерывания).

Многие операционные системы предоставляют двухэтапный процесс прерывания, в котором процедура прямого прерывания минимальна, насколько это возможно, чтобы очистить прерывание, и уведомляет отдельный поток прерывания для обработки более длинных и подробных частей запроса. См. http://en.wikipedia.org/wiki/Interrupt_handler.

Поскольку процедура прямого прерывания небольшая и быстрая, она позволяет назначать приоритеты соответствующим потокам прерывания для управления порядком выполнения.

person Rich Hendricks    schedule 04.03.2014

Я не знаю, есть ли у вас веская причина запускать RX и TX в двух разных контекстах, но обычно это можно очень просто реализовать только в одном контексте. Однако, если вы действительно хотите следовать своему первоначальному дизайну, вам необходимо ввести какой-то механизм для синхронизации операций этих двух контекстов. Обычно, если вы используете ОСРВ, вы должны использовать флаг события, двоичный семафор или какую-либо другую аналогичную службу, которая предоставляется данной ОСРВ.

Вы бы не хотели (и не могли) отправлять какие-либо данные, пока не получили их, верно? Вот почему вам нужно будет дождаться уведомления (в контексте TX), которое должно быть установлено из контекста RX после получения данных.

Выполнение такого типа туннелирования без использования этой техники очень скоро приведет к рассинхронизации.

person Adi    schedule 13.02.2014
comment
Это не столько RX / TX. Прерывание с высоким приоритетом исходит из выборки секторов диска Windows (моя прошивка - это запоминающее устройство USB), а прерывание с низким приоритетом запускается мной вручную для буферизации следующих нескольких секторов на случай, если они будут запрошены позже. Однако иногда Windows запрашивает их слишком быстро, и моя «умная буферизация» еще не завершена. В этом случае я хочу подождать, пока задача с более низким приоритетом не будет завершена, но я не могу просто ждать прерывания с высоким приоритетом, потому что оно блокирует более низкое. Я надеялся, что была какая-то инструкция ARM, чтобы позволить этому закончить. - person Muis; 16.02.2014
comment
Вы можете просто отключить прерывания, связанные с USB, пока вы выполняете задачу с более низким приоритетом, и снова включить их после того, как вы закончите с ней. Однако это, очевидно, приведет к тому, что поступившие тем временем запросы USB не будут обслуживаться. Если вы хотите избежать и этого, я бы подумал о перепроектировании архитектуры FW. - person Adi; 17.02.2014
comment
Вот как я это делаю сейчас, я даю им одинаковый приоритет, чтобы они блокировали друг друга, но это снижает производительность передачи, потому что ничего не может быть записано из памяти в конечную точку USB, пока я извлекаю следующий блок. Мне нужно чередовать два прерывания, и если для этого нет инструкции ARM, я не понимаю, как RTOS может иметь какое-либо значение для этого варианта использования. - person Muis; 18.02.2014
comment
Вместо того, чтобы блокировать прерывание с более высоким приоритетом, пусть оно решит, может ли оно продолжить или должно дождаться результата другого. Если он должен подождать, то либо не предпринимайте никаких действий в это время и ждите еще одной попытки чтения, либо настройте что-то для запуска после завершения другого (вам нужно будет выяснить, что является законным / оптимальным для USB-накопителя или чего-то еще. это вы реализуете) - person Chris Stratton; 18.02.2014
comment
@ChrisStratton Я не могу игнорировать запрос чтения, драйвер USB (который находится в ПЗУ, поэтому его нельзя изменить) запрашивает указатель на данные сектора. Если я не заполню данные, он вернет в Windows сектор с нулями, и Windows сочтет его действительным. Невозможно вернуть код ошибки или позволить ОС повторить попытку. Я думаю, что это ограничение драйвера, встроенного NXP в свои микроконтроллеры Cortex, но я должен с этим разобраться. Боюсь, или написать новый стек USB с нуля, что является сложной задачей. - person Muis; 19.02.2014
comment
Вы также должны были указать эту информацию в своем вопросе. Я думал, что у вас нормальный стек USB, и поэтому предложил изменить архитектуру FW. Имея стек USB с ПЗУ и пытаясь оптимизировать пропускную способность USB-MSD, вы легко можете столкнуться с (не) гибкостью этого стека. Вам нужно будет выяснить, спроектирован ли стек так, чтобы его можно было настроить таким образом. - person Adi; 19.02.2014
comment
В противном случае можно было бы предложить попробовать просто другой стек USB и посмотреть, соответствует ли он вашим ожиданиям по пропускной способности. Я наткнулся на несколько USB-стеков с открытым исходным кодом, связанных с LPC uC, которые, как я полагаю, вы используете. - person Adi; 19.02.2014
comment
@Adi Это определенно ограничение стека, потому что раньше я использовал nxpUSBlib (основанный на LUFA), и у меня не было этой проблемы, потому что он запрашивал блоки секторов большего размера. Затем я переключился на драйверы ROM и столкнулся с этой проблемой. Но я пытался найти обходной путь вместо того, чтобы вернуться к стеку на основе LUFA. - person Muis; 05.03.2014