Как использовать прерывания для передачи данных через периферию SPI - PullRequest
0 голосов
/ 16 июня 2020

Я реализовал драйвер устройства для периферийного устройства SPI MCU на языке C. Я хотел бы использовать механизм прерывания для приема, а также для передачи.

Что касается части приема, я думаю, что могу реализовать это, выставив функцию SpiRegisterCallback в интерфейс драйвера SPI. Эта функция позволяет клиенту зарегистрировать свою функцию, которая будет вызываться, как только будет получен байт данных (вызывается прерывание при полном буфере приема).

Что касается передачи, я бы хотел использовать SpiTransmit функция, которая будет получать указатель на байты данных, которые должны быть переданы, и количество байтов, которые должны быть переданы. Что касается реализации, я собираюсь определить некоторую внутреннюю функцию обратного вызова драйвера SPI. Этот внутренний обратный вызов будет зарегистрирован для прерывания пустого буфера передачи. В этой функции обратного вызова переданные байты данных будут постепенно помещаться в буфер передачи. Я не уверен, уместен ли такой подход. Может ли кто-нибудь дать мне совет, как реализовать периферийный драйвер SPI, который использует прерывания для передачи данных? Заранее благодарим за любые предложения.

Ответы [ 2 ]

1 голос
/ 16 июня 2020

SPI часто очень критичен в реальном времени, введение обратного вызова с указателями функций означает ненужный служебный код. Фактическое копирование данных из SPI в ОЗУ должно выполняться вашим драйвером внутри. Это все, что должна делать ISR. Некоторые общие рекомендации можно найти здесь .

Итак, ваш ISR должен заполнять буфер, а затем поменять местами указатели на буферы (не медленные memcpy!) В защищенный способ, так что вызывающий всегда имеет один буфер с действительными данными, а ISR всегда имеет один рабочий буфер для заполнения. Позвольте вызывающему абоненту опрашивать флаг, а не вызывать обратный вызов изнутри ISR. Мне нравится использовать тройную буферизацию, если я могу сэкономить оперативную память. То есть: один буфер для ISR, один буфер для вызывающего и один резервный, с которым ISR может поменяться местами, не нарушая работу вызывающего.

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

0 голосов
/ 16 июня 2020

Запрос «любых предложений» на самом деле не делает его отличным вопросом, потому что может быть допустимо несколько ответов, и немногие из них будут исчерпывающими. Он требует комментариев, а не ответов. Однако я позволю себе потакать:

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

При высоких тактовых частотах в некоторых случаях задержка прерывания и время переключения контекста, участвующие в обработке прерываний, могут быть менее эффективными, чем простое ожидание занятости. Если за один раз передается более двух или трех байтов, вам в любом случае следует рассмотреть возможность использования DMA, если он доступен - так что прерывание будет прерыванием DMA для полной передачи, а не одного символа. Для приложений, таких как интерфейс SD-карты или EEPROM, DMA будет иметь значительное влияние на производительность и освободить ЦП для одновременного выполнения другой полезной работы. Оптимальным может быть драйвер, который использует ожидание занятости для передачи отдельных байтов / слов и DMA для передачи блоков. Это особенно верно, возможно, если вы используете RTOS, а ISR запускает контекст задачи для обработки данных - накладные расходы на переключение контекста могут быть почти такими же или большими, чем ожидание занятости для одного байта. Например, если ваши часы SPI> 1 МГц, вы будете ждать 8 мкс для передачи байта, ваш ISR и обратные вызовы могут легко быть больше, чем это, и в этом случае это не стоит.

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...