Comments 24
Вы правы в вашей статье в принципе во всем. Но иногда все же первый вариант может оказаться предпочтительнее. Например: если какое-либо действие необходимо выполнить после того, как байт был фактически передан по аппаратному интерфейсу.
Вы скажете, что для этих целей можно реализовать отдельную функцию ожидания завершения работы интерфейса, а код вывода следует оставить как есть. И будете правы. Во всем, кроме одного маленького момента. Иногда на этих крохах можно сэкономить критически необходимые такты быстродействия или байтики ПЗУ. Когда на счету каждый такт или каждый байт — то не до жиру в плане красоты программ и их абстрактной надежности. А единственное, что играет роль — это характеристики программы и ее фактическая надежность в тех условиях, в которых она будет работать, без учета фантазий, а с учетом только реальных обстоятельств.
А общий смысл поста был именно в том, что есть более удачное по всем параметрам решение и следует привыкать использовать именно его, хотя истина всегда конкретна.
встроенном программировании
Наверное, всё-таки, программирование встроенно в человека, а тут речь о железках.
Народ подскажет верный термин, пока что получается «программирование встроенного» или «программирование встраиваемых систем». Можно ещё выделить или заключить в скобки. что бы было понятно, что это термин или придумать какой-нибудь жаргонизм, типа встрой-программинг.
Объясните пожалуйста, что даёт const в передаваемом функции параметре? Почему использование static в конкретном примере — правильное применение?
Может я конечно неправильно понял суть проблемы, но нельзя ли тут попользовать прерывания, если не хотим в while ожидать флага? Кстати boolean в чистом си нет, или это от wiring сюда попало?
static вообще полезен, чтобы не загромождать глобальное пространство имен и не вызвать по ошибке функцию, которую вызывать не собирались — это в общем. Но многие компиляторы (например IAR) inline без static просто не разрешат, чтобы не было соблазна вызвать его из другой единицы компиляции.
И Вы правы, прерывание будет правильным, речь шла исключительно о разных вариантах ожидания флага.
boolean этот мой enum (False=0,True=1), я о нем в предыдущих постах говорил, вот и использую.
Я в программировании недавно, но мне кажется, что именно здесь const не удобен, и возможно даже помешает. Возможно ведь, что мне потребуется передать не какой-нибудь константный объект, а например полученный из датчика массив байтов или еще что-то подобное. Обычно такие функции, лично я использую, чтобы потом их попользовать уже например в более серьезной функции передачи того же массива. Тут кстати и static уже не грех применить, типа такой инкапсуляции чтоли) Вобщем думаю еслиб указатель передавался, то const бы мог уже на этапе компиляции, поругать, если мы захотим его изменить. А так один фиг передача по значению, как вы правильно заметили.
Я пишу в AtmelStudio чаще всего, там inline без static работает(точнее компилятор не ругается), но честно говоря не проверял, реально ли inline там работает, или все же происходит именно вызов функции.
Вставлять проверки и до и после тоже не вариант, Часто нужно сделать что-то и не ждать когда оно выполнится — заняться другой работой, в т.ч. подготовкой следующей порции данных пока передаётся очередная.
Учитывая что в контроллерах достаточно строгий контроль когда и что происходит, применяются оба варианта не по принципу правильно/неправильно а исходя из необходимого поведения в конкретном месте. Часто бывает такое что применяют и первый и второй варианты, просто надо знать что нужен строгий контроль над тем что и когда происходит и может произойти с объектами в программе.
chipSelect();
writeSPI(0x0a);
chipUnselect();
однако, если использовать второй вариант, мне придется явно добавлять ожидание, в лучшем случае так:
chipSelect();
writeSPI(0x0a);
waitReadySpi();
chipUnselect();
chipSelect();
writeSPI(0x0a);
writeSPI(0x0b);
writeSPI(0x0c);
chipUnselect();
При использовании второй реализации, 0x0c в устройство записан не будет — кого винить?
То, что программируется на МЭКоских языках обычно называется PLC/ПЛК (программируемый логический контроллер). Это не микроконтроллеры, про которые речь в статье. Внутри PLC содержит тот же микроконтроллер, на котором крутится программа, почти всегда написанная на C или C++. Это просто совершенно разные уровни.
Если вы сталкиваетесь с микроконтроллерами, то стоит не просто знать синтаксис Си, а понимать его. Также как уметь читать datasheet'ы, всякие временные диаграммы, простые логические схемы (используются, например, при описании мультиплексируемых входов и выходов микроконтроллера) и т. п.
В случае PLC у вас не возникнет проблемы контроля за состоянием бита занятости в контрольном регистре какого-нибудь SPI перед или после записи байта в data register. Вы просто запишете значение в глобальную переменную или подадите на вход специального атома/блока.
Си — lingua franca для системщины и прочего низкоуровнего. Его не избежать, если хочется с пониманием делать что-то на микроконтоллерах. Всякие заходы python, js, lua на контроллерах забавны, но абстракции там текут очень сильно, так что рано или поздно может понадобится заглянуть в потроха интерпретатора, а там опять же Си.
При использовании busy-wait'а, как в статье, я обычно пишу функцию, которая пишет указанный байт, а считанный возвращает и две обёртки для записи (которая игнорирует считанный байт) и для чтения (которая пишет dummy байт). В рамках базовой функции делается синхронизация на возможность записи в DR в начале, и на возможность чтения перед возвратом результата. дерганье CS/nCS происходит в более высокоуровневых функциях. Описываемые функции являются по возможности static inline
.
К вопросу о порядке операторов