Как эффективно декодировать нестандартный последовательный сигнал

11

Я являюсь членом исследовательской группы, работающей над проектом, который включает в себя ASIC, передающую RF, и его беспроводной приемник, который должен в конечном итоге отправлять данные на ПК.

Приемник выводит быстрый , непрерывный, асинхронный, нестандартный последовательный сигнал (т. Е. Не SPI, I2C, UART и т. Д.), Поэтому моя работа заключается в написании программного обеспечения микроконтроллера для сопряжения приемника с компьютером. В настоящее время мой подход заключается в использовании инициируемых фронтом прерываний для помещения данных в кольцевой буфер и выполнения всего процесса побитового декодирования в основном цикле. Микроконтроллер должен одновременно выводить эти данные через USB (виртуальный com-порт) на компьютер.

Вот проблема, которую я имею, и одна, которую я ожидаю:

  1. Я не могу обработать буферизованные данные достаточно быстро даже с моим довольно мощным процессором ARM Cortex M3 72 МГц. Скорость передачи составляет 400 кбит / с (2,5 мкс / бит). Для справки, это оставляет только 180 циклов на бит (включая декодирование И ISR, которое имеет ~ 30 циклов служебных данных!). MCU также должен выполнять множество других задач, которые он запрашивает в основном цикле.

  2. Драйвер виртуального USB-порта USB также основан на прерываниях. Это делает меня почти уверенным, что драйвер в конечном итоге будет прерывать процессор так долго, что он пропускает окно 2,5 микросекунды (180 циклов), в котором может передаваться бит. Я не уверен, как обычно разрешаются конфликты / гонки прерываний.

Таким образом, вопрос заключается в том, что можно сделать, чтобы решить эти проблемы, или это неправильный подход вообще? Я готов рассмотреть и менее программно-ориентированные подходы. Например, использование выделенного USB-чипа с каким-то аппаратным конечным автоматом для декодирования, но это незнакомая территория.

Киган Джей
источник
Я должен сказать, что редко я вижу, что многие предложения, которые мне нравятся, быстро отвечают на них, хорошо отражают ваш вопрос. Мне было бы интересно узнать больше о пакетах данных. Являются ли они прерывистыми, внезапно на полной скорости, а затем - периодами с низким уровнем данных, или же возможно, что вы продолжите работать с непрерывными данными?
Кортук
Пока ASIC имеет питание, он отправляет непрерывный поток данных. Не пачкается вообще. Это медицинское приложение в режиме реального времени с компьютерным считыванием. Вы когда-нибудь видели ЭКГ?
Киган Джей
Здесь так много отличных ответов. Я видел четкое разделение между решениями, связанными с изменениями прерываний, и решениями, использующими выделенную аппаратную / цифровую логику. Такие вещи, как ПЛИС и Verilog, с которыми я знаком, но еще не сталкивался, поэтому это означает, что они должны быть сохранены на длительный срок. В краткосрочном @rocketmagnets менее интенсивный метод прерывания хорош. Мне нравится элегантность, отводящая простые задачи цифровой логике и сохраняющая ARM для настоящих вычислений. В будущем мощность ARM будет использоваться для анализа и фильтрации беспроводных последовательных данных.
Киган Джей
Сигнал синхронный или асинхронный?
markrages
Асинхронный. 4 начальных бита, 10 битов данных, 2 стоповых бита. Из-за природы ASIC, которая передает, времена HI и LO сильно варьируются от чипа к чипу. Я уже написал алгоритм для определения скорости передачи.
Киган Джей

Ответы:

5

Другой ответ: прекратите использовать прерывания.

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

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

loop
{
    if (serial_bit_ready)
    {
        // shift serial bit into a byte
    }

    if (serial_byte_ready)
    {
        // decode serial data
    }

    if (enough_serial_bytes_available)
    {
        // more decoding
    }        

    if (usb_queue_not_empty)
    {
        // handle USB data
    }        
}

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

loop
{
    if (serial_bit_ready)
    {
        // shift serial bit into a byte
    }

    if (serial_byte_ready)
    {
        // decode serial data
    }

    if (serial_bit_ready)
    {
        // shift serial bit into a byte
    }

    if (enough_serial_bytes_available)
    {
        // more decoding
    }        

    if (serial_bit_ready)
    {
        // shift serial bit into a byte
    }

    if (usb_queue_not_empty)
    {
        // handle USB data
    }        
}

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

Rocketmagnet
источник
Мне нравится ваш ответ больше, чем другой ответ Rocketmagnet человек. Вместо того, чтобы тратить больше аппаратных средств, использовать более быстрое оборудование и многое другое, вы, Rocketmagnet, предлагаете: делать меньше, лучше, проще.
Хорошо, я видел много случаев, когда прерывания делают решение намного лучше. Они делают отличные вещи, позволяют хорошо структурированный код, низкие задержки и многие другие преимущества, но я должен согласиться с вами здесь. Похоже, процесс настолько интенсивный, что 1 контроллеру, возможно, придется посвятить каждый бит своего внимания обработке последовательного потока. Цифровой интерфейс звучит идеально для меня, но во многих случаях, когда это школьный проект, у вас есть несколько микросхем и нет ПЛИС, я бы, вероятно, посвятил бы микроконтроллер для меня в первую очередь, а позже попытался бы вписаться в ПЛИС, чтобы заменить его на Стоимость.
Кортук
Это, вероятно, решение, которое я пойду в краткосрочной перспективе. Я надеялся избежать этого, потому что это предполагает переписывание довольно большого количества существующих драйверов последовательного порта, но это изящное решение, которое в моих силах в течение короткого периода времени.
Киган Джей
1
@JayKeegan - Да, это, вероятно, самый быстрый путь к решению. PSoC и FPGA могут быть подходом для следующего проекта.
Ракетный магнит
6

Вы можете использовать FPGA вместо микроконтроллера для декодирования и буферизации беспроводного потока данных. Затем используйте процессор ARM для очистки буферов FPGA (например, с помощью интерфейса SPI) и отправьте содержимое через порт USB Comm. Это работает, но FPGA должна быть в состоянии легко поддерживать, пока вы можете обслуживать его достаточно часто, чтобы гарантировать, что его аппаратные буферы не переполняются (или если вы можете иметь дело с отброшенными данными на более высоком уровне протокола ).

vicatcu
источник
Это может быть отличным решением в долгосрочной перспективе. Я надеялся, что получил много цифровых логических / аппаратных решений в дополнение к программным решениям, потому что теперь у меня есть повод узнать об этих вещах! У меня пока нет опыта работы с FPGA.
Киган Джей
6

Легко: использовать микроконтроллер PSoC5 .

PSoC

Вы имеете простоту использования микроконтроллера, плюс он содержит CPLD, так что вы можете создавать свои собственные аппаратные периферийные устройства в Verilog. Просто напишите свой декодер последовательных данных в verilog и используйте DMA для потоковой передачи на порт USB.

Между тем, мощное 32-разрядное ядро ​​ARM может сбивать с толку инструкции Thumb.

Rocketmagnet
источник
На странице обзора нет списка тактовых частот, что вызвало у меня подозрения. В спецификации указано 40 МГц (я также отметил 6 мА при 6 МГц). Это половина того, что сейчас есть у ОП. «MCU также должен выполнять множество других задач», поэтому он может зависеть от того, что это, хорошая идея или нет.
stevenvh
Они идут до 67 МГц. Так что это почти так же быстро, как текущий процессор OP, за исключением того, что большая часть работы будет выполняться аппаратно, оставляя процессору гораздо больше свободного времени.
Ракетный магнит
1
Я не смотрел на все таблицы. Первый, который я выбрал, сказал 40MHz.
Stevenvh
@stevenvh - у них разные скорости. Третье число в PN - оценка скорости. (4 = 48 МГц, 6 = 67 МГц).
Ракетный магнит
1
Это также фантастическое решение в долгосрочной перспективе, очень похожее на идею FPGA. Я никогда не слышал об этом типе чипа, но он объединяет большую часть функциональности остальной части моей платы в один чип. В будущем это может означать, что весь ресивер умещается на чем-то размером с флеш-накопитель, что является целью моего руководителя проекта. Я буду изучать Verilog в следующем семестере.
Киган Джей
4

Я думаю, у вас есть классический выбор инженеров: быстро, дешево, работает: выберите два.

Решение @ vicatcu, безусловно, хорошее, но если вы не можете или не хотите добавлять к нему больше оборудования (включая более быстрый процессор), вам придется сделать выбор. Если это последовательное соединение является наиболее важным, чем вы должны сидеть в ISR, пока все биты не будут собраны. 180 инструкций на бит на самом деле совсем неплохо, но не пытайтесь делать все. Когда вы обнаружите начало передачи, вращайте, пока передача не будет завершена. Заполните результат в FIFO и затем возобновите нормальную обработку.

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

akohlsmith
источник
Это решение как бы дополняет программный подход rocketman с уменьшением числа драйверов на основе прерываний. Я могу оставить основной последовательный драйвер, который я упомянул, как основанный на прерываниях. Также я попробую вращаться, пока весь кадр не будет прочитан, как вы упоминаете.
Киган Джей
3

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

Но просто для того, чтобы добавить другое возможное решение: учитывая ограничения вашего проекта, будет ли плохо добавлять второй микроконтроллер (будет ли это включать в себя еще одну работу платы)? Может быть, простой 8-битный микроконтроллер, который подключается к вашему Cortex-M3 через быструю периферию, такую ​​как SPI. Выбранный вами 8-битный контроллер будет запрашивать биты и байты формы так же, как в выбранном ответе, но когда у него есть байт, он может вывести его в регистр данных SPI для передачи.

Сторона Cortex-M3 будет просто прерывать полученные данные SPI. Это сокращает ваше предыдущее внешнее прерывание, инициируемое по фронту 400 кГц, до 50 кГц.

Я полагаю, что это объясняется двумя причинами того, что некоторые другие методы (PSoC или добавленная FPGA) немного дороги (хотя это, вероятно, не имеет значения для академического проекта с небольшим объемом), и потому что это может позволить вам сохранить некоторые из структура вашего текущего кода.

Кроме этого, я думаю, что идея PSoC удивительна, если вы используете собственную периферийную периферию, которая передает данные через DMA на USB.

Джон Л
источник
Это на самом деле план, который я имел в виду прямо после публикации этого. Если я не могу упростить программное обеспечение, уменьшив зависимость от прерываний (выбранный ответ), то, безусловно, это то, что я буду делать. Но да, это потребует еще одного запуска платы, возможно, двух, потому что я неудачен в том, чтобы сделать свои проекты правильно с первого раза.
Киган Джей
@JayKeegan, хаха, добро пожаловать в клуб!
Джон Л
2

Если ваш формат данных аналогичен формату UART, но с непредсказуемой, но согласованной скоростью передачи данных, я бы хотел использовать CPLD для преобразования каждого слова входящих данных в формат SPI или стандартную асинхронность. Я не думаю, что есть необходимость продвигаться полностью в сферу CPLD. На самом деле, даже дискретная логика может быть почти работоспособной. Если бы вы могли сгенерировать тактовую частоту, более чем в 5 раз превышающую желаемую скорость передачи данных, вы могли бы использовать счетчик деления на пять и деления на 16 с несколькими входами. Расположите счетчик деления на пять так, чтобы он удерживался в режиме сброса всякий раз, когда вход простаивает, а счетчик деления на 16 равен нулю. В противном случае генерируйте тактовый импульс SPI и увеличивайте счетчик деления на 16 каждый раз, когда счетчик деления на пять достигает 2.

Учитывая 5-кратную тактовую частоту, можно генерировать тактовую частоту SPI, используя 16V8 (наименьшее и самое дешевое в настоящее время доступное программируемое логическое устройство). Второй 16V8 или 22V10 может быть использован в качестве делителя дробной частоты для генерации тактовой частоты 5x, или можно использовать немного больший чип (CPLD) и делать все в одном.

Редактировать / Добавление

При дальнейшем рассмотрении, если кто-то собирается использовать CPLD, можно легко добавить несколько дополнительных улучшений в схему. Например, можно довольно легко добавить логику, чтобы схема остановилась до тех пор, пока она не получит как минимум 1,5-битные времена стопового бита, а затем 3,5-битные времена стартового бита; если он получает слишком короткий стартовый бит, он должен вернуться к поиску стопового бита. Кроме того, если используется SPI, можно использовать сигнал / CS, чтобы гарантировать, что принимающее устройство увидит данные в правильном кадре. Если устройство, принимающее данные SPI, может обрабатывать 10-битные кадры, можно отправлять такие кадры напрямую. В противном случае каждый десятибитный кадр может быть отправлен как 8-битный кадр с набором LSB (7 битов данных) и кадр со всеми свободными LSB (3 бита данных); тактовый сигнал SPI будет ускоряться во время стоп-битов, поэтому все данные будут отправлены.

Некоторые микроконтроллеры имеют довольно универсальные модули генерации ШИМ, которые включают в себя такие вещи, как возможность удерживать в сбросе внешним сигналом и синхронизировать их синхронизацию с выпуском такого сигнала. Если ваш микроконтроллер может сделать это, в зависимости от его точных функций, это может значительно упростить схемы CPLD или синхронизации.

Другой подход, который несколько коснулся Rocketmagnet, заключался бы в том, чтобы иметь небольшой микроэлемент, единственная цель которого - декодировать последовательные данные и преобразовывать их в формат, используемый основным микро. Ваша скорость передачи данных 400 кГц довольно высока для программного декодирования, но что-то вроде PIC могло бы справиться с этим, если бы не нужно было ничего делать одновременно. В зависимости от того, с какими устройствами вы знакомы, это может быть проще или сложнее, чем с использованием CPLD.

Supercat
источник
Все это будет очень ценно при разработке цифровой логики для декодирования. Я действительно буду выводить как SPI. На данный момент я просто делаю декодирование с использованием автономного MCU (ограничения по времени). Спасибо!
Киган Джей