YS, хочу еще ваших статей по Си в том же ключе разжевывания по железу, а не абстрактно для любого компа! С уклоном для STM32. Где-то читал ваш блог, там тоже много интересного.
Когда-то, когда я был моложе, меня удивлял вопрос - куда деваются онлайн-авторы? А теперь я понял.
С одной стороны, у людей рано или поздно наступает момент, когда им приходится всерьез приступить к зарабатыванию денег, а это сильно уменьшает количество свободного времени.
С другой стороны, зарабатывание денег, связанное с профессией, дает достаточно возможностей для самореализации, что уменьшает мотивацию что-то писать.
С третьей стороны, примерно в тот же момент на первый план выходят проблемы, связанные с организацией своей судьбы вообще, никак не связанные с профессией, но от этого не менее важные.
Например, если много и интересно писать про контроллеры, в какой-то момент можно обнаружить, что все девушки вокруг кончились, и твои способности ответить на любой вопрос по Си вообще и применительно к STM32 в частности не помогут тебе вернуть упущенное.
Ссылка на блог есть в моем профиле. Но я уже практически забросил его.
Вот здесь тоже интересно почему?
y = *((uint8_t *)(&x));
ARV верно объяснил про горошины. Как я писал два года назад, тип - это по сути правило обращения к области памяти. Приводя тип, мы инструктируем компилятор временно, для конкретно этого доступа, поменять это правило.
И как я теперь понимаю
long y = (long*)&x;
Тоже неоднозначно скопирует. Может перевернуть все как попало.
В рамках одной платформы скопирует однозначно, а как код может выполняться на нескольких платформах одновременно, мне понять сложно.
Разберем эту запись.
x - именованная область памяти, переменная. Пускай она будет типа int16_t. Т.е., компилятор где-то заготовил два байта, и знает, что к ним надо обращаться как к двухбайтному числу.
&x - извлечь стартовый адрес, начиная с которого эти два байта расположены.
(long *)(&x) - переопределить правило доступа, как если бы по этому адресу лежало значение long, то есть, число четыре байта длиной.
long y = *((long *)(&x)) - фактически, скопировать четыре байта, начиная с адреса &x, в переменную y. Да, в x у нас два байта. Но мы принуждаем компилятор работать с &x как с long, и он повинуется. В старших байтах y будет что-то, что лежит за x в памяти.
если вместо +1 поставить +6 вылетит за приделы переменной Х и запишет в Z то, что находится дальше по памяти? Или компилятор это отследит и ограничит (выдаст ошибку)?
Компилятор Си - не ограничит. Он сделает то, что заказано - в этом заключается сила Си, этот язык дает полную свободу программисту. Правда, при этом требуется, чтобы программист знал, что делает.
что будет в STM32, увы, не знаю...
В чипах без MMU или, вообще, без использования MMU - то же самое. Прочтет.
а то, что в это самое время в массив можно "без DMA" писать - совсем не страшно!
Не страшно, конечно.
Во-первых, DMA получает доступ к памяти через арбитр, который гарантирует распределение пропускной способности между ядром и DMA.
Во-вторых, DMA в STM32 поддерживает кольцевой режим - буфер делится на два, и пока одна часть улетает куда-то при помощи DMA, второй может заниматься ядро (потом наоборот). Есть специальное прерывание, которое вызывается, когда блок DMA добрался до половины. В нем удобно менять указатели на части массива.
Если механизм завел двигатель и стоит на светофоре, то двигатель же не глушат... А в МК мне не понятно становится, зачем его усыплять на миллисекунды, если опять будить потом для выполнения задачи, которая продлится пару миллисекунд, а потом опять усыплять.
На то, чтобы запустить двигатель, тратится время и моторесурс. На включение/выключение МК не тратится почти ничего.
Надо ли усыплять МК или нет, определяется в каждом случае индивидуально - в зависимости от того, сколько энергии сэкономим и стоит ли оно того. Но смысл, конечно, в энергосбережении, чтобы увеличить время работы от батарей, например.
Разница между теорией и практикой на практике гораздо больше, чем в теории.