November 10th, 2017

worklog: один макрос и поиск глубокого смысла

Наткнулся вот в одной библиотеке на конструкцию такого вида:

if ((reg & mask) == mask) {
...
}


при этом маска mask - это ОДИН бит, всегда.

Мне кажется, или сравнение == mask уже не нужно, ведь if() выполнится, если результат двоичного "&" ненулевой - и он будет таким, если в регистре установлен бит маски?

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

А вообще это я полез разбираться в потрохах библиотеки USB для STM32. Это ад.
Я не ищу в ней ошибки или ещё что-то (хотя кое-что вызывает некотрое замешательство: например, когда в описании функции сказано, что параметр может принимать значения от 1 до 15, внутри функции проверки на выход за границу отсутствует, а саму эту функцию где-то вызывают с параметром 16), просто хочу разобраться и, по возможности, предельно упростить, избавившись хотя бы от конструкций типа "обработчик прерывания вызывает коллбэк, который не делает ничего кроме вызова ещё одной функции" -- эту вложенность можно развинтить на один уровень, ничего не потеряв.

Восемь глаз, восемь ног.



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

А ещё такие паучки могут менять направление взгляда главной пары глаз, не шевелясь вообще (и сквозь полупрозрачные покровы видно, что глаз у них не круглый). Остальные глаза, скорее всего, нужны просто для детектирования изменения обстановки, нежели чем для высматривания чего-либо.

worklog: CMSIS-то ненастоящий!

Впрочем, нет, CMSIS настоящий, но сомнения гложут.

Дело вот в чём. Ковыряя STшную библиотеку и вкуривая STшный (истошный, лол) референс-мануал, поглядев самую бесполезную в мире презенташку, постепенно пришёл к нескольким выводам:
1) люди, писавшие RM, с функционированием блока USB знакомы, но поверхностно. Их описание того, как следует инициализировать блок, отличается от рабочего библиотечного кода. Не то чтобы как-то катастрофически, но ежели делать прямо по RM -- ничего не заработает. Даже не включится.
2) люди, писавшие CMSIS, лишились последних сил, дойдя до описания регистров USB OTG. Т.е. онеи описали их структуры и мнемоники, даже пришили пару структур к правильным адресам в памяти, но бросили это дело на полпути. Я уж было принялся самостоятельно всё дорисовывать, а затем обнаружил, что не хватает на самом деле только приколотить остальные структуры (они уже описаны) и один-два регистра, как-то так:
#define USB_OTG_FS_OutEP_1_5 \
    (*(USB_OTG_OUTEndpointTypeDef (*)[5])(USB_OTG_FS_PERIPH_BASE + USB_OTG_OUT_ENDPOINT_BASE))
...
    USB_OTG_FS_OutEP_1_5[i]->DOEPCTL = USB_OTG_DOEPCTL_SNAK; 
    /* не стоит забывать, что для OutEP0/InEP0 регистры немного отличаются! */

3) люди, писавшие STM32Cube USB device library, обладают, с одной стороны, тайным знанием о том, как оно всё функционирует (вернее, как вообще заставить что-то работать).. а с другой стороны, не жалеют процессорные такты и, например, вместо того, чтобы в обработчике прерывания один раз прочитать нужный регистр и пройтись по его битам, читают его каждый раз, когда смотрят на очередной бит. И не просто читают, а ажно при помощи полновесной функции - не какой-нибудь там static inline, а со всей свитой из стэка и х.з. почему так. Я вот щас упрощу всё, и когда оно заработает -- оно заработает!

Модуль USB - на текущий момент, самая сложная железяка из всего, что я видел. Что и понятно: протокол-то сионские мудрецы сочинили, не иначе...