LINUX.ORG.RU
ФорумTalks

Почему так не любят писать кросс-платформенный код?

 ,


0

2

Всякие библиотеки для работы с девайсами, подключаемыми к микроконтроллерам, в 99% случаев будут привязаны к конкретной архитектуре микроконтроллера и (например в случае с stm32) к конкретной библиотеке, HAL, CMSIS, итд. Хотя само по себе устройство работает по I2C, SPI, GPIO, итд, и от архитектуры микроконтроллера не зависит вообще никак.

Казалось бы, зачем завязываться на конкретную архитектуру? Ну попроси пользователя при инициализации предоставить ссылки на функции i2c_read и i2c_write и всё, библиотека моментально становится абсолютно кроссплатформенна, и ее можно элементарно использовать абсолютно где угодно. Но нет. Это слишком сложно, видимо. И в итоге имеем «драйвер такого-то то i2c устройства для ардуины», «драйвер такого-то то i2c устройства для для stm32 с библиотекой HAL», итп.

Я, когда что-то такое сам пишу, всегда стараюсь вынести логику драйвера отдельно, а функции для работы с i2c, gpio, spi - извне предоставлять либе. И в итоге код легко и просто портируется.

★★★★★

А писать будешь в байтах? А в байте у тебя сколько бит? А порядок у них какой будет для разных процессоров и разной переферии? То-то же. И про накладные расходы на кросплатформенность не забудь.

Там, где скорость не важна, мы пишем высокий уровень кросплатформенно, а низкий - через указатели на функции. И унифицированный код организуем в подмодули. Но местами все равно «попадалово неизбежно».

aiqu6Ait ★★★★
()
Последнее исправление: aiqu6Ait (всего исправлений: 1)
Ответ на: комментарий от aiqu6Ait

А в байте у тебя сколько бит?

За исключением всяких странных DSP от TI, 99% случаев байт это 8 бит. Но даже в этом случае по I2C/SPI все равно передаюся байты по 8 бит. И это уже задача пользователя преобразовать это в то, что понимает микроконтроллер

А порядок у них какой будет для разных процессоров и разной переферии?

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

cvs-255 ★★★★★
() автор топика
Последнее исправление: cvs-255 (всего исправлений: 1)

Почему так не любят писать кросс-платформенный код?

Потому что это чаще всего дополнительная работа, в "эмбеддед"-среде – ещё и в обязательном порядке. К тому же, такого "понаварюють" в плане архитектуры, что портирование на какой-нибудь новый контроллер превращается в натуральный сЭкс.

Korchevatel ★★★★★
()
Ответ на: комментарий от Korchevatel

Ну код общего назначения вменяемые люди все равно пишут один раз - настройки, логи, калибровочные таблицы и прочая мутотень, файловые системы, обработка событий, сетевые стеки, работа с индустриальными протоколами…. ой, у нас получилась RTOS.

aiqu6Ait ★★★★
()
Ответ на: комментарий от Korchevatel

портирование на какой-нибудь новый контроллер превращается в натуральный сЭкс.

Так если разделять логику и функции для работы с i2c/spi/etc, то это будет в разы просто легче

cvs-255 ★★★★★
() автор топика
Ответ на: комментарий от cvs-255

До недавних событий это работало, зачем заморачиваться?

Это сейчас реально купить только gowin

shalom_ ★★
()

Начнем с простого вопроса - зачем кроссплатформенность вообще нужна?

Микроконтроллеры - это про ембеддед. Вставил и оно работает десятилетиями.

А вообще, этим должен заниматься IDE\компилятор, и он вполне себе занимается, вот смотри.

void setup {
pin_mode(13, OUTPUT);
}

void loop {
digitalWrite(13,HIGH);
delay(1000);
digitalWrite(13,LOW);
delay(1000);
}

Вот тебе пожалуйста, кроссплатформенный код, который будет работать на атмеге328, на атмеге168, на атмеге2560, на есп8266 и еще десятке платформ. Но даже в таком простом коде, начнется дроч, если у какой-то платформы например на 13-й ноге будет ресет, или еще что-нибудь.

windows10 ★★★★★
()
Ответ на: комментарий от cvs-255

Так если разделять логику и функции для работы с i2c/spi/etc, то это будет в разы просто легче

Не всегда. Надо конкретные случаи смотреть.

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

windows10 ★★★★★
()

Я далёк от встройки, но почти уверен, что все эти драйвера - так и начинаются, вот будет 2 виртуальных функции, всё же просто и элегантно. А теперь, кроме записи - нам надо ещё научиться менять режимы устройства. А вот сейчас у некоторых устройств есть возможность писать асинхронно, а у других нет. И т.п., не успеешь оглянуться а у тебя уже целый драйвер.

pon4ik ★★★★★
()

Ну попроси пользователя при инициализации предоставить ссылки на функции i2c_read и i2c_write и всё

Этим должен линкер заниматься. «Предоставление ссылок» реализуется как extern i2c_read() в .h и и её реализация в одном из линкуемых модулей. Модуль может быть не частью драйвера.

firkax ★★★★★
()
Ответ на: комментарий от Legioner

А ещё оно повышает вероятность code execution уязвимостей, ведь указатель в секции данных перезаписать проще чем код в read-only секции кода или в read-only прошивке контроллера.

firkax ★★★★★
()
Ответ на: комментарий от windows10

«Начнем с простого вопроса - зачем кроссплатформенность вообще нужна?» - чтобы не писать код инициализации какого нибудь дисплея по 10 раз, а написать 1 раз

cvs-255 ★★★★★
() автор топика
Ответ на: комментарий от windows10

«Вставил и оно работает десятилетиями.» - азатем ты захотел подключить тот же датчик или еще какой девайс к другому мк. И все заново писать?

cvs-255 ★★★★★
() автор топика
Ответ на: комментарий от Legioner

По сравнению с временем работы периферии - экономия на спичках

cvs-255 ★★★★★
() автор топика

для ардуины

А ардуиновский код кстати получается весьма кроссплатформенным, переносим между ардуинами на avr, ардуинами на арме, ардуинами на stm32, ардуинами на ESP8266 и возможно ещё какими.

PolarFox ★★★★★
()

Потому что он и так пишется, в алгоритмах и протоколах высокого уровня? Тем более что CMSIS это как раз кросплатформенный стандарт и кросплатформенная стандартная библиотека от ARM и расшифровывается как Common Microcontroller Software Interface Standard и это значит, что ты не в теме вообще, а тред создал чтобы позвездеть и выглядеть умным, но не получилось.
HAL у STM32 тоже достаточно высокого уровня, она в основном скрывает прямую работу с регистрами. Для байтоёбства у STM32 есть LL.

Чаще всего кросплатформенный код в Embedded никому не упал. Слава роботам здесь никто не пишет геттеры для абстрактных фабрик фабрик и прочий мусор, а за лишний оверхед бьют по лицу ногами. Ведь ограниченные ресурсы куда дороже переносимости, а в 90% случаев низкоуровневый, непереносимый код имеет свои жесткие привязки: специфическая инициализация, и/или работа с специфическими только для этого железа регистрами, способом доступа к памяти и т.д., или места критически чувствительные к производительности/задержкам.

Код, который не влез в камень и потребовал камень более дорогой приносит значительно большие убытки в производстве, чем никому не упавшая переносимость.
Тем более что у тех же STM32 между всеми сериями ​полная совместимость, даже распиновка одна - не влезло в F4, возьми F7 и впаяй на то же место. И в то же время влезло в F4 и много осталось - молодец, сэкономил бабки, возьми F1.
А если у тебя прямо по ходу разработки возникла потребность сменить STM32 на Freescale, то ты делаешь что-то не так или просто дебил.

Проблема из пальца высосана и обсуждать тут нечего.

soslow
()
Последнее исправление: soslow (всего исправлений: 2)
Ответ на: комментарий от PolarFox

Ардуинщики делятся на 2 типа: одни байтоёбят регистры AVR-ки в своих библиотеках и срали на всех остальных, другой тип пишет врапперы и потом сильно удивляется почему же у них прерывания по 50 мс срабатывают, чего же это, а? Мааам, ну скажи им!

soslow
()
Последнее исправление: soslow (всего исправлений: 1)

Просто переходи уже на раст, там норм пацаны пишут дрова для своей переферии один раз (а потом переписывают, но это не так важно).

CYB3R ★★★★★
()

Я протрезвел и прочитал твой пост еще раз. Можешь считать предыдущий мой пост частичнго невалидным.
Но ты хочешь крос-платформенность на таком глобальном уровне?! ЩИТО?
Тогда тебе тоже надо протрезветь.

Такой код никогда не будет иметь должную производительность, обертка обертки, а без этого с железом никак.
Да и нужен он только тем ардуинщикам, кто «програмиирует» МК с помощью копипасты сниппетов.

soslow
()
Ответ на: комментарий от soslow

Да и нужен он только тем ардуинщикам, кто «програмиирует» МК с помощью копипасты сниппетов.

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

cvs-255 ★★★★★
() автор топика
Ответ на: комментарий от cvs-255

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

sehellion ★★★★★
()
Ответ на: комментарий от sehellion

Я его еще вообще не написал, потому что совершенно не хочу все это писать.

Но да, когда мне приходится писать модули для работы с какой-либо подобной периферией, я сразу пишу их так, что логика отдельно, функции для работы с spi/i2c - отдельно. Так и отлаживать проще и использовать потом в других проектах

cvs-255 ★★★★★
() автор топика
Ответ на: комментарий от sehellion

где нужно только переопределить порты в заголовке

Ты же понимаешь, что это совсем не кроссплатформенно? Потому что на некоторых архитектурах это бессмысленно. Например, хочу я один и тот же датчик/девайс иметь возможность использовать и на малинке (где через i2c-dev идет взаимодействие), и на ардуине и на stm32

cvs-255 ★★★★★
() автор топика
Ответ на: комментарий от cvs-255

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

sehellion ★★★★★
()
Ответ на: комментарий от cvs-255

Ты наркоман, что ли?! Как ты себе это представляешь?!

soslow
()
Ответ на: комментарий от cvs-255

«Вставил и оно работает десятилетиями.» - азатем ты захотел подключить тот же датчик или еще какой девайс к другому мк. И все заново писать?

Ну да. Это же совершенно другая аппаратно-программная среда.

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

windows10 ★★★★★
()
Ответ на: комментарий от cvs-255

Но да, когда мне приходится писать модули для работы с какой-либо подобной периферией, я сразу пишу их так, что логика отдельно, функции для работы с spi/i2c - отдельно. Так и отлаживать проще и использовать потом в других проектах

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

Кроссплатформенность - это когда у тебя стоит десяток IFDEF’ов под десяток платформ, подставляющих тот или иной порт, тот или иной способ инициализации в ту или иную функцию, без изменений оной.

Там где это возможно - делается так. Например в либах того же самого adafruit’а. Но на кой хер это делать в либах девайсов, рассчитаных на работу с конкретным МК ?

windows10 ★★★★★
()
Ответ на: комментарий от windows10

Дисплей тот же самый, процедура инициализации та же самая, структура памяти, команды, итд те же самые. Все то же самое, только подключен он теперь не к аврке, а к стмке. Или еще куда

cvs-255 ★★★★★
() автор топика
Последнее исправление: cvs-255 (всего исправлений: 2)
Ответ на: комментарий от windows10

Толку от того, что ты вынес функции в отдельный блок ?

Толк тот, что не надо шариться по коду и под каждую архитектуру вставлять вызовы i2c

cvs-255 ★★★★★
() автор топика
Ответ на: комментарий от windows10

Ну вот смотрю я либы для работы с дисплеем, а они везде внутри понапихали функций работы с i2c для конкретных платформ.

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

cvs-255 ★★★★★
() автор топика

В embedded творится сплошное мракобесие и прибитость драйверов к конкретному железу далеко не самая большая проблема.

X512 ★★★★★
()
Последнее исправление: X512 (всего исправлений: 1)
Ответ на: комментарий от X512

Проблем там хватает, но прибитость там, где она не обязательна - одна из важнейших

cvs-255 ★★★★★
() автор топика
Ответ на: комментарий от cvs-255

В итоге я взял одну из либ, выкинул из нее аппаратно зависимое и теперь это можно использовать откуда угодно

Ну так ее и сейчас можно использовать откуда угодно.

windows10 ★★★★★
()
Ответ на: комментарий от cvs-255

Вообще, низкоуровневая работа с i2c - не задача драйвера дисплея. В том числе по озвученной причине.

Во-первых, почему не задача ?

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

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

Данная либа будет работать на любой платформе где есть i2c и библиотека для работы с i2c.

windows10 ★★★★★
()
Ответ на: комментарий от windows10

Ну так ее и сейчас можно использовать откуда угодно.

Нет, не откуда угодно, а только на той платформе, которую предусмотрел автор.

cvs-255 ★★★★★
() автор топика
Ответ на: комментарий от windows10

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

Потому что это не задача драйвера дисплея следить за, например, состоянием регистров I2C_SR1(I2C1) и I2C_SR2(I2C1) (которые в stm32 отвечают за текущий статус работы I2C), а его задача - записать в устройство с таким-то адресом на шине I2C такие то байты. А как именно происходит эта запись - не его забота

cvs-255 ★★★★★
() автор топика
Последнее исправление: cvs-255 (всего исправлений: 2)
Ответ на: комментарий от cvs-255

Потому что это не задача драйвера дисплея следить за, например, состоянием регистров I2C_SR1(I2C1) и I2C_SR2(I2C1) (которые в stm32 отвечают за текущий статус работы I2C), а его задача - записать в устройство с таким-то адресом на шине I2C такие то байты. А как именно происходит эта запись - не его забота

Те либы с которыми я сталкивался - так и делают.

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

Кроссплатформенность, повторюсь, это учитывание состояния регистров разных платформ. Кто это делает, либа№1, или либа№2 - значения не имеет. Унифицировать ембеддед все равно никто не будет, а без унификации у тебя все равно будет дроч, просто не в либе №1, а в либе №2.

windows10 ★★★★★
()

Я тебе даже больше скажу. Вот пишу я сейчас драйвер для условной DHT22 для ESP8266.

На кой хрен мне его делать кроссплатформенным, если мне он нужен под мое устройство на базе ESP8266 ?

windows10 ★★★★★
()
Ответ на: комментарий от windows10

Но я не вижу ничего плохого в том, что драйвер дисплея следит за состоянием регистров.

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

cvs-255 ★★★★★
() автор топика
Последнее исправление: cvs-255 (всего исправлений: 1)
Ответ на: комментарий от windows10

Те либы с которыми я сталкивался - так и делают.

Ну видимо у тебя какая-то специфическая выборка попадалась.

cvs-255 ★★★★★
() автор топика
Ответ на: комментарий от windows10

Кроссплатформенность, повторюсь, это учитывание состояния регистров разных платформ.

Драйверу i2c oled дисплея не должно быть никакого дела до состояние регистров микроконтроллера. Все что его должно заботить - регистры самого дисплея. Потому что все общение с дисплеем идет через i2c.

cvs-255 ★★★★★
() автор топика
Последнее исправление: cvs-255 (всего исправлений: 1)
Ответ на: комментарий от windows10

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

Это рассуждение из серии «а пускай HTTP сервер занимается парсингом Ethernet пакетов»

cvs-255 ★★★★★
() автор топика

в итоге имеем «драйвер такого-то то i2c устройства для ардуины», «драйвер такого-то то i2c устройства для для stm32 с библиотекой HAL», итп.

Это называется сегментация рынка на ниши для которых выпускаются разные товары по разным ценам.
И да, если это не вышло случайно, то это сделали намеренно.

torvn77 ★★★★★
()
Ответ на: комментарий от cvs-255

Но даже в этом случае по I2C/SPI все равно передаюся байты по 8 бит.

i2s смотрит на это сообщение как на говно.

Порядок передачи бит в байте по i2c

Замечательно. Если кроме i2c/spi переферии вы ничем не пользуетесь - то и говорить не о чем, пишите как знаете.

aiqu6Ait ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.