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

Пользователь

Отправить сообщение

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

Спасибо за статью! Есть идеи как управлять установкой тока нескольких драйверов в статическом режиме при помощи одного потенциометра?

Пожалуйста, посоветуйте что почитать на тему lock-free и списков. Мне сложно представить связные списки в логике без блокировок.
Согласен.
Как «скорее читатель, чем писатель», могу добавить, что хорошей идеей является написание комментариев для Doxygen. Желетельно, с разбиением на группы.
Где про эту штуку подробнее можно почитать?
Очень интересно. Буду ждать статью.
Надо думать в сторону static_defer — такого варианта, чтобы формировать список команд на этапе компиляции. Конечно, использование static_defer в циклах будет под запретом, за что, по всей видимости, меня тут и минусуют, но это возможный вариант использования defer заранее определенным образом.
Чем и занимаемся сейчас…

Занимались и будем продолжать, «работа такой».
Хе, а для нас они «маленькие» :-)

Даже не знаю как на это реагировать, прям разрыв шаблона, видать, засиделся я на эмбэде.
Просто поною.

ИМХО: юнитов надо немного, только проверить параметры-результат в десяток-полтора вариантов. А как этот код выше юнитов может завалить тест? За примеры кода — человеческое спасибо, хоть посмотрел как бывает в других областях.
Не всё мне тут нравится, но я за определённость. OK, синтаксис K&R убрали, но… Или уже POSIX, или ну в пень эти виляния.

Согласен, с POSIX можно будет работать, по крайней мере «отфильтровать» функционал по платформам и дальше разбираться как с этим жить. Тут, конечно, начинает попахивать расколом (как в C++), но куда деваться.
P.S. Прекрасно понимаю ваши проблемы. Но и у нас их тоже до фига. А стандарт… Он для всех (читай для большинства) :)
Начинаю понимать Ваши. Вот бы стандарт был не для «большинства», а для всех. Но это так, поныть в такт.
Хорошо, в чем я заблуждаюсь?
Согласен, ошибаюсь, все не так просто.
Мысли в порядок:
В
MPLAB XC8 C Compiler User’s Guide for AVR® MCU
явно сказано:
The volatile qualifier does not guarantee that any access will be atomic, which is often not the case, since the 8-bit AVR architecture can typically access only 1 byte of data per instruction.
Even when objects are marked as volatile, the compiler cannot guarantee that they will be accessed atomically. This is particularly true of operations on multi-byte objects.
С учетом переупорядочивания последовательности выполнения команд, описанного в статье по приведенной Вами ссылке действительно можно утверждать, что volatile uint8_t не является атомарным для записи, кроме того, может быть изменена последовательность выполнения, что приведет к бардаку.
Если мое представление о мироздании имеет отношение к реальности, то на 8ми битной архитектуре можно безопасно читать память длиной в 1 байт любых переменных (volatile или нет — не имеет решающего значения). Писать так не получится, теперь понятно почему.
При попытке читать память длиной более 1 байта могут быть сложности, например:
— начинаем читать uint32_t в основном коде
— прочитали 2 байта
— в этот момент вызывается обработчик прерывания и меняет значение
— прочитали еще 2 байта
получили смесь двух значений, это плохо. Для решения этой проблемы можно при чтении использовать обычный вариант из cli… sei, для переменной стоит воткнуть volatile, поскольку она меняется в обработчике прерывания и не должна «кэшироваться». При записи имеет смысл отключать прерывания:
— в основном коде при записи в переменную, которая используется в обработчиках прерываний;
— в контексте обработчика прерываний на xmega для переменных, которые используются в других обработчиках прерываний (в xmega обработчики прерываний могут вытесняться другими обработчиками прерываний).
Для всего этого хорошо подходит ATOMIC_BLOCK, тут про использование, тут про магию, которая удивительно похожа на defer, кстати, пока писал ответ появилась статья на эту тему.
Если я правильно понял из «MPLAB XC8 C Compiler User’s Guide for AVR® MCU» вот это:
Interrupts should be disabled around any main-line code that modifies an object that is used by interrupt functions, unless you can guarantee that the access is atomic. Macros are provided in <avr/atomic.h> to assist you access these objects.
то макросы в <avr/atomic.h> только помогают получить атомарный доступ, но не позволяют создать атомарные типы. Эти помогающие макросы, скорее всего, обертки над запретом/разрешением прерываний.
Допустим, с AVR понятно, разрядность архитектуры равна октету, это все упрощает.
Теперь краткие соображения про ARM(32).
По аналогии, можно считать, что чтение памяти ведется по 4 байта(32бита), таким образом кажется, что можно безопасно читать переменные размером в 4 байта, но только в «общем случае в вакууме». В упакованных (packed) структурах все может работать по другому. Самый интересный для меня момент тут — как будут работать packed структуры при наличии не выравненного volatile поля при записи в него из обработчика прерывания и чтении из основного кода. С одной стороны — volatile исключает оптимизацию, что не противоречит упаковке структуры, с другой — это может нарушить выравнивание, что помешает чтению поля за одну инструкцию. Получается, на процессоре любой разрядности невозможно гарантировать атомарное неблокирующее чтение памяти размером более 1 байта, но я не очень-то в этом уверен.

Что-то я отвлекся, теперь про _Atomic. По результатам моих поисков все сводится к compare-and-swap в цикле «до тех пор, пока не получилось». Без этой инструкции процессора реализация всего _Atomic возможна только через блокировку прерываний (и блокировку контроллера памяти для многоядерных/многопроцессорных систем). Это, в теории, не противоречит неблокирующему выполнению, но на самом деле ведет к остановке выполнения других потоков, хоть они этого и не заметят. Такой подход все еще противоречит моему представлению об упакованных структурах, тут я вообще не понимаю как оно должно работать с памятью длиной более 1 байта.

Близкое по теме:
Про реализацию test-and-set на xmega тут.
Про укаковку структур тут.

Пойду изучать fixed point…
Ибо «по фану».
Ну вот не кажутся мне исключения в плюсах совсем логичными. Они нормальны для плюсов и многих других высокоуровневых языков, но мы то о C, тут или нормально или совсем goto, без полумер.
Меньшее зло оно такое… притягательное :). Избавиться от goto — это точно верное направление, но вот является ли defer лучшим (в рамках осознаваемого) вариантом — это вопрос открытый, во всяком случае, для меня. Получается, меняем явный goto(очень плохо, вплоть до запрета на использование) на неявный многошаговый «goto» или «сборник команд»(чуть лучше). Я не за запрет подобных решений, я за вдумчивый и последовательный подход к развитию языка. Давайте попробуем придумать другие варианты решения проблемы, так явно не ломающих последовательность выполнения. Давайте подумаем о «навеске» выполняемого кода на выход из скоупа, ведь это давно просится.
Чуть поясню для наблюдателей: на входе в блок или функцию воткнуть дополнительный код просто, поскольку точка входа(совсем почти всегда) одна, а вот выходов может быть много, каждый выход надо отдельно контролировать, это одна из главных проблем освобождения ресурсов.
Угу. Инструмент классный, но нет ли способа его как-то упихнуть в более сишный вид. Я уже предлагал вариант с накоплением в макроопределении. Сразу скажу, согласен с тем, что это не решает проблему с выполнением кода при выходе за пределы области, придется перед выходом явно вызывать. Но такой подход позволяет «нагрузить» на это выполнение дополнительный функционал. Возможно, имеет смысл рассмотреть (в рамках текущего мысленного эксперимента) создание аж целых двух новых инструментов: дополняемых макроопределений и привязки исполнения «функции» при выходе из скоупа, причем записывать вызов этой «функции» в конце скоупа (чтобы логику не ломать, после условного return перемещаемся в конец скоупа, а там нас ждет кусок накопленного кода, это уже можно представить и визуализировать). В таком случае можно не только получить полноценный функционал defer, но и расширить его для сложных случаев.
AVR. Очень интересный вопрос, надо будет поковырять. Самый очевидный путь — посмотреть во что оно там компилируется. Скорее всего — будет запрет прерываний.
ARM. Еще более интересный вопрос, особенно в случае многоядерности. Хотя с многоядерностью можно пойти на volatile, блокировку контроллера памяти и запрет прерываний, но это совсем не точно.
Некоторые типы являются атомарными (на чтение или запись) напрямую, например volatile uint8_t в AVR. В ARM таких типов больше, где-то встречал утверждение, что uint8_t, uint16_t, uint32_t с volatile атомарны. Про uint32_t понятно, а вот с остальными все будет зависеть от логики работы контроллера памяти, что не очевидно.

В fixed point я никак, так что будем вместе ждать знающего комментатора. Есть еще ссылки на эту тему?
Поэтому пополнения стандартной библиотеки C очень даже приветствуются.

Да, вот бы все нужное включили в стандартную библиотеку и не пришлось бы это таскать за собой :D! Но вот будет с точностью до наоборот :(, в типовом коде для ПК, который надо портировать эти функции будут, а на нужной платформе — нет. И придется кроме своих костылей таскать еще и стандартно-библиотечные, так и перенапрячься не долго :). Ну или как предлагалось выше — переписывать каждое вхождение подобных функций на решение для конкретной платформы, поскольку ну вот не получается так на раз-два перенести strdup в таком виде на статическое выделение памяти.
Вот тут я не совсем понял. Зачем править код, если можно изначально обходиться без той же strndup()? Как-то жили ведь до этого.

Жили. И дальше будем жить без этого. Вот только появится больше кода, который использует эти функции. И с этим будем жить, просто портировать код с «больших» платформ станет чуть сложнее.
В C его нет, существует он только в виде мысленного эксперимента. По моему воображению — не очень, поскольку рушит последовательность выполнения по строчкам. С другой стороны, если его введут, то станет чуть проще ориентироваться по командам освобождения ресурсов, сложнее будет забыть сделать free перед return и подобное. Тогда дебажить надо будет меньше. Подождем, может появится в виде расширения в каком-нибудь компиляторе, можно будет потрогать, тогда и оценивать.

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность