Как стать автором
Обновить

Разглядывая JTAG: самый быстрый программный JTAG на Arduino

Уровень сложностиСредний
Время на прочтение26 мин
Количество просмотров9.2K
Всего голосов 40: ↑40 и ↓0+55
Комментарии23

Комментарии 23

(картинка с троллейбусом)

Прекрасная реализация..! :) Правда, как мне кажется, правильный вопрос на предложенный вопрос должен быть "А вам зачем?!" потому что должно быть незачем... :)

Размышляя над задачей, я предположил как минимум одно непротиворечивое (но достаточно надуманное) практическое оправдание.

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

P.S. Субъективно, я не слишком положительно отношусть к людям, с разбегу спрашивающих "А вам зачем?". На эту тему у меня есть отделтная статья.

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

А если не секрет, какой непротиворечивый юзкейс может быть? (впрочем, один я знаю -- обязательное соответствие определённому, неизменяемому, чек-листу; вообще он уже достаточно весом чтоб делать "надо так надо").

От слова "статья" ссылка отвалилась -- можно повторить?

p.s.: я всегда спрашиваю "а вам зачем?" даже когда есть идеи зачем -- потому, что я ни раз делал что-то, что оказывалось совсем не тем, что требуется; как в том анекдоте про кастрацию...

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

В этой статье - всё прекрасно. Пожалуйста, продолжайте.

Если допустить перерасход памяти программ, то можно "усушить" лишнюю таблицу переходов

switch_label:

rjmp case_0

rjmp case_1

rjmp case_2

rjmp case_3

при использовании ijmp, использовав грануляцию памяти согласно максимальному размеру ветви и используя

add ZL, r18*case_chunk_size

adc ZH, zero_register

В этой статье - всё прекрасно. Пожалуйста, продолжайте.

Спасибо :) Я и не собирался останавливаться ;)

"В скобках после switch пишется выражение, которое даёт целочисленный
результат. Этот результат поочерёдно сравнивается со значениями,
прописанными после каждого блока case." Возможно для микроконтроллера это так (я не знаю, нужно проверять). А в общем случае это не так. Конструкция switch предназначена для перехода, за одно сравнение, на соответствующий вариант case. Если вариантов мало (например меньше 4-х), то очевидно последовательное сравнение с каждой меткой case не будет сильно дольше и компилятор не генерирует код перехода за одно сравнение. Вообще статья хорошая, интересная.

Конструкция switch предназначена для перехода, за одно сравнение, на соответствующий вариант case

С точки зрения ассемблерных инструкций, если используются инструкции сравнения, то они производят сравнение только пары операндов. И тут два варианта:
1) последовательный перебор вариантов
2) бинарное древо/бинарный поиск

Бинарное древо имеет определённые накладные расходы и в сравнении с последовательным перебором оно начинает выигрывать начиная лишь с определённого количества case.

Но. При этом количестве case-ов бинарное древо, выиграв у последовательного перебора, проиграет (по скорости) конструкции на основе косвенного перехода.

Если же в конструкции switch-case используется инструкция косвенного перехода, то здесь не будет никаких сравнений.

Именно в приведённом в статье примере switch-case на косвенном переходе работает великолепно. Однако в общем случае у него есть ахиллесова пята - что если у нас совокупность возможных значений тестируемой переменной является сильно разреженной? Что если предполагается, например, три case: 1, 2 и 100500? В таком случае switch-case, конечно, сработает столь же быстро, но таблица переходов получится огромного размера. Причём на 99,999% она будет заполнена пустотой.

Поэтому я не вполне понимаю написанное вами. Что значит "за одно сравнение" перейти на "соответствующий вариант case"? Что вы имеете ввиду?

Когда-то давным давно, когда земля была раскаленным шаром, а C -- макроассемблером на стероидах, switch это был способ задать таблицу переходов в исходнике (а не просто синтаксическим сахаром). Но да, даже тогда, это не было "за одно сравнение", те же проверки на на отрицательные, на больше максимума и так далее необходимы для хотя бы default.

Сейчас разницы между switch с breakами и if/else if/else if не должно быть, так как оптимизаторы стараются выжать максимум вне зависимости от исходника.

Товарищ datacompboy прояснил для вас ситуацию, в общих чертах. Дискутировать с ним не буду, достаточно посмотреть исполняемый файл, что бы убедится в том, что switch и if принципиально разные конструкции. Простейший пример это массив меток, результат ключевого выражения это индекс в массиве. Далее выбор метки по индексу и переход. Именно для этого и существует конструкция switch, что бы не перебирать (например) сто ключей. В тривиальных случаях (мало веток case) компилятор считает, что последовательного сравнения хватит и накладные расходы, в виде объёма кода, не нужны. Никакие оптимизации не помогут сделать быстрее чем переход сразу на нужную ветку (если веток много). Ума не приложу, кто вбивает в голову людям, что switch и if это одно и тоже. Вы сами об этом пишете в своём комментарии. А тонкости, что мол сравнения нет... Ну к чему это? Поспорить? Повторюсь , статья хорошая. А тема switch для меня как красная тряпка. Интересуют тонкости компиляции (ну про разряженные таблицы и их огромный размер т.д.), есть интернет, читайте.

А тонкости, что мол сравнения нет... Ну к чему это?

В смысле, тонкости? ))))))))) Вы пишете:

Конструкция switch предназначена для перехода, за одно сравнение, на соответствующий вариант case.

...я вас спрашиваю, как такое возможно? Вы выдаёте абзац экзальтированного текста с вкраплениями "Дискутировать не буду".
Ну такое себе )))) Я бы охарактеризовал это как неконструктивное общение :)

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

Где бы я был без таких советов )

Тссс ))) Не разрушайте картину ))))

Если серьёзно, то большое спасибо за столь оперативно составленные примеры. В такие моменты хочется сказать: Хабр - тот!

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

Сохранение регистра в стек - это 2 машинных цикла, а в ячейку ОЗУ - 1. Поэтому я на AVR сохранял в ОЗУ. Для контроллера без вытесняющих прерываний это допустимо. И обязательно надо сохранять регистр с флагами SREG, чтобы вызов прерывания в момент между арифметической/логической операцией и проверкой результата операции (по флагам SREG) не нарушал работу программы.

Весьма полезный комментарий! Спасибо. Ваше замечание про SREG я внёс в статью.

а в ячейку ОЗУ - 1

У межек/тинек 2 такта. Только у xmega ST/LD 1/2 такта.

При грамотном использовании регистров (то что С должен бы делать, но не сделает) вообще ничего можно не сохранять, кроме SREG (и то не всегда): прерывание использует только свои регистры, основной цикл - свои.

Красивое! Я что то даже не вижу как бы здесь использовать сдвиговый регистр от SPI

На более новых avr появилась куча интересной периферии - там может еще чего то можно придумать.

Я что то даже не вижу как бы здесь использовать сдвиговый регистр от SPI

Штатный SPI сдвигает только один байт. А в JTAG регистр IDCODE в обязательном порядке 32-битный. Так что да. Но с другой стороны - тем лучше этот пример в качестве бенчмарка :)

На более новых avr появилась...

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

Хм-м-м... Возможно, упустил нить. Но что с того, что только один байт? Ну, пусть будет 4 прерывания на 32 бита.

да там такие скорости что он только и делать что прерываться будет, оверхед на прерывания немалый, и самое главное - ничего особо полезного "в свободное время" делать то и ничего. У новых контроллеров avr есть dma - на полном автомате как минимум 4 байта можно послать, плюс usb аппаратный во "втором потоке" - получаем отладчик.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории