EdgeAligned 86 7 сентября Опубликовано 7 сентября · Жалоба Так в любом случае код уровня Hardware не совместим между разными производителями микроконтроллеров. Где-то может быть и совпадение, но не везде будет всё одинаково, несмотря на одно и то же ядро Cortex. И особенно вы ставите себе палки в колеса тем, что не используете битовые описания. То есть, когда #define SPI_CR1_SPE (1 << 0), позицию бита нужно поправить в одном месте. А когда в тексте вместо SPI_CR1_SPE везде стоит (1 << 0), изменить позицию бита очень непросто. Вы стреляете себе в ногу. От таких ошибок предостерегали в книгах. Ну и я уже писал - нужны абстракции уровней. Уровень Hardware меняете, а остальное - остается или подвергается значительно меньшим переделкам. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 190 7 сентября Опубликовано 7 сентября · Жалоба 11 минут назад, EdgeAligned сказал: Так в любом случае код уровня Hardware не совместим между разными производителями микроконтроллеров. Где-то может быть и совпадение, но не везде будет всё одинаково, несмотря на одно и то же ядро Cortex. И особенно вы ставите себе палки в колеса тем, что не используете битовые описания. То есть, когда #define SPI_CR1_SPE (1 << 0), позицию бита нужно поправить в одном месте. А когда в тексте вместо SPI_CR1_SPE везде стоит (1 << 0), изменить позицию бита очень непросто. Вы стреляете себе в ногу. От таких ошибок предостерегали в книгах. Ды нет, думаю коллега выше просто пишет свои описания. Я как-то напоролся на то, что в двух разных МК одного производителя (STM32) биты с одним назначением лежали в разных позициях. Заметить такое при переносе своих самописных дефайнов практически не реально. А при использовании готовых поставляемых определений, об этом даже не придется задуматься, с 99.999% вероятностью. STM32F0 STM32F4 Подстава, которой не ждали. И такого вполне себе хватает, чтобы на ровном месте застрять в отладке. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 7 сентября Опубликовано 7 сентября · Жалоба 49 минут назад, EdgeAligned сказал: Тяжело в ученье, не спорю. Я тоже вот многократно перечитываю, пока изучаю. На одном мониторе открыта IDE, на другом мониторе - пдф-ка мануала. Еще и 12-дюймовый планшетник использую, чтобы не крутить во все стороны. Ну а че поделать, приходится. У меня в универе был одногруппник. Он на все экзамены писал шпоры на все билеты. Полностью. Целую кипу шпор. А потом сам их не использовал - раздавал. Когда его спрашивал: "На кой так делаешь, раз сам почти не пользуешь?" Он говорил: "Пока их пишу, я их выучиваю и потом уже помню, даже без шпор". Так и тут - пока пишу описания регистров, я их функционал запоминаю. 49 минут назад, EdgeAligned сказал: странный подход, странный. А как вы пишите? Магические цифры? Тоесть, не SPI_CR1_SPE, а (1 << 0)? прикольно конечно, экстравагантно. Вот например кусок SPI-драйвера: case F_TRA: spiC->TRBSCR = B0 | B14; if (!(n = faz.tra.dlast)) { if (i & 1 << SO_ER) { faza = i += F_TRA_STOP - F_TRA << SO_n; PingMain(); } else EndTra(); return; } if (n >= BURST_SPI_R * 2) { IntDis(concat(NVIC_USIC, USIC_UNIT(nUSIC_spi), _, SRUSIC_SR(nUSIC_SR_spi_RX))); AtomicOrI(&DLR.LNEN, 1 << nDMALINE_spi_RX); spiC->RBCTR_b[1] = BURST_SPI_R * 2 - 1 - 1; __DMB(); rdmaU->CHEN = (1 << (nDMALINE_spi_RX & 7)) * (B0 | B8); } else { spiC->RBCTR_b[1] = USIC_FIFO_SIZE; __DMB(); } tdmaU->CHEN = (1 << (nDMALINE_spi_TX & 7)) * (B0 | B8); spiC и tdmaU - это соответственно USIC (последовательный порт) и DMA-unit (контроллер). Как видно - все битовые поля заданы численно. 49 минут назад, EdgeAligned сказал: Но именно от такого подхода предостерегают многие именитые программисты в своих книгах, которые мне доводилось читать. Что там пишут диванные эксперды, никогда не занимавшиеся реальными проектами - мне совершенно по-барабану. А вот если бы они реально что-то писали сами (а не таскали кубиками из чужих проектов), то как бы им помогло описание битов регистров? Вот читаем описание битов одного из регистров SPI: /*USICx_C0_PCR_SSC*/ /*USICx_C1_PCR_SSC*/ struct { __REG32 MSLSEN : 1; __REG32 SELCTR : 1; __REG32 SELINV : 1; __REG32 FEM : 1; __REG32 CTQSEL1 : 2; __REG32 PCTQ1 : 2; __REG32 DCTQ1 : 5; __REG32 PARIEN : 1; __REG32 MSLSIEN : 1; __REG32 DX2TIEN : 1; __REG32 SELO : 8; __REG32 TIWEN : 1; __REG32 : 6; __REG32 MCLK : 1; } ssc; И видите вы в коде что-то типа: spiC->SSC = 1 << SELCTR | 2 << CTQSEL1 | 1 << DX2TIEN; Т.е. - ранее вы сами написали это, но потом, через год нужно что-то изменить. Вы это читаете.... Вы сразу понимаете что означают эти SELCTR, CTQSEL1, DX2TIEN? Вот так сразу, не заглядывая в мануал сможете сказать, что означают эти значения записываемые в эти биты? Если нет - зачем тогда давать им эти символьные имена? Или всё-таки придётся открывать мануал? А в мануале ведь эти биты описаны по порядку - по номерам битов. И искать их там удобнее по номерам битов, чем по этим зубодробительным именам. И это ещё я короткие имена привел. А загляните например в EthernetMAC: /* ETH0_MMC_Receive_Interrupt_Mask */ typedef struct { __REG32 RXGBFRMIM : 1; __REG32 RXGBOCTIM : 1; __REG32 RXGOCTIM : 1; __REG32 RXBCGFIM : 1; __REG32 RXMCGFIM : 1; __REG32 RXCRCERFIM : 1; __REG32 RXALGNERFIM : 1; __REG32 RXRUNTFIM : 1; __REG32 RXJABERFIM : 1; __REG32 RXUSIZEGFIM : 1; __REG32 RXOSIZEGFIM : 1; __REG32 RX64OCTGBFIM : 1; __REG32 RX65T127OCTGBFIM : 1; __REG32 RX128T255OCTGBFIM : 1; __REG32 RX256T511OCTGBFIM : 1; __REG32 RX512T1023OCTGBFIM : 1; __REG32 RX1024TMAXOCTGBFIM : 1; __REG32 RXUCGFIM : 1; __REG32 RXLENERFIM : 1; __REG32 RXORANGEFIM : 1; __REG32 RXPAUSFIM : 1; __REG32 RXFOVFIM : 1; __REG32 RXVLANGBFIM : 1; __REG32 RXWDOGFIM : 1; __REG32 RXRCVERRFIM : 1; __REG32 RXCTRLFIM : 1; __REG32 : 6; } __eth_mmc_receive_interrupt_mask_bits; Это один из регистров MAC. Как вам такие имена??? Искать описание по номеру позиции бита гораздо удобнее и быстрее, чем искать что-то типа "RX512T1023OCTGBFIM". PS: Когда-то по-дурости, наслушавшись подобных "экспердов" переписал некоторые драйвера с использованием именованных позиций бит. Потом, когда пришлось через некоторое время что-то там переделывать, долго плевался. Понял - насколько удобнее с числовыми номерами битов. Когда пишу, что-то связанное с периферией, у меня всегда открыт мануал на неё. И искать в нём гораздо удобнее по номерам битов. А у некоторых производителей ещё и имена битов в мануале отличаются от имён, заданных в хидерах. Тут вообще задница была бы. 45 минут назад, Arlleex сказал: Касательно другой периферии: да, я подсматриваю в референс. А как без этого? Никак. Разве что если это уже было когда-то написано, а сейчас надо перетянуть в другой проект, поправив максимум какой-нибудь DMA-канал или лапы МК. Вот! И эти выводы вы делаете по простой периферии STM32. А теперь возьмём например XMC4700, в котором регистров и битов в них - кратно больше. Там вам придётся всё время держать мануал перед глазами. 45 минут назад, Arlleex сказал: Почему? Выше написал уже. 45 минут назад, Arlleex сказал: При разработке CMSIS-заголовков авторы не лепили описание всего и вся в один хедер. Описание регистров разделено, поэтому описание регистров ядра МК берется из файла, который не поставляется вендором МК. Он един для всех МК на этом ядре. В тех исходниках, что я видел (от 3D-принтера) всё было свалено в одну кучу. И там была куча перекрёстных ссылок. И кусков хидеров, в которых идут ссылки на всё и вся. И выдирание любого описания периферии (даже не используемой) приводило к несборке всего проекта. Так просто там взять и заменить описание периферии ядра на своё никак не получалось. 36 минут назад, EdgeAligned сказал: И особенно вы ставите себе палки в колеса тем, что не используете битовые описания. То есть, когда #define SPI_CR1_SPE (1 << 0), позицию бита нужно поправить в одном месте. А когда в тексте вместо SPI_CR1_SPE везде стоит (1 << 0), изменить позицию бита очень непросто. А какой смысл её менять??? Вы думаете этот бит дрейфует по регистру? 36 минут назад, EdgeAligned сказал: Вы стреляете себе в ногу. От таких ошибок предостерегали в книгах. В чём именно "стреляю"? Ничего не понял.... уже лет 20 как программирую разные МК и ноги мои почему-то до сих пор целые. 36 минут назад, EdgeAligned сказал: Ну и я уже писал - нужны абстракции уровней. Уровень Hardware меняете, а остальное - остается или подвергается значительно меньшим переделкам. Вижу - начитались вы диванных экспердов.... Которые никогда ничего сложнее абдуриновского кода не видели.... Все эти биты в регистрах периферии - это как раз и есть тот самый нижний "hardware"-уровень. Который меняется полностью при переходе на другой МК. Вместо с этими битами. Поэтому это никак не мешает абстракции. Абстракция - она не на уровне битов должна быть. А выше. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EdgeAligned 86 7 сентября Опубликовано 7 сентября · Жалоба Видимо, вы не знакомы с принятыми в CMSIS правилами именования и оформления 🙂 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 190 7 сентября Опубликовано 7 сентября · Жалоба 8 минут назад, jcxz сказал: spiC->SSC = 1 << SELCTR | 2 << CTQSEL1 | 1 << DX2TIEN; Т.е. - ранее вы сами написали это, но потом, через год нужно что-то изменить. Вы это читаете.... Вы сразу понимаете что означают эти SELCTR, CTQSEL1, DX2TIEN? Вот так сразу, не заглядывая в мануал сможете сказать, что означают эти значения записываемые в эти биты? Если нет - зачем тогда давать им эти символьные имена? Мозг штука интересная, конечно, все он не запоминает. Но имена битов (дефайны), такие же как в мануале, запомнить проще, нежели непонятные номера битов-ноунэймов вида B0, B10, и т.д. И часто бывает как раз так, что имя бита не требует заглядывания в мануал. Я понятия не имею и даже через час не вспомнил бы, что значит spiC->TRBSCR = B0 | B14; Я не понимаю, как это для Вас нагляднее, например, этого USART2->CR1 = USART_CR1_OVER8 | USART_CR1_TE | USART_CR1_RE; Все-таки, даже спустя большое количество времени мозг, глядя на эти биты TE, RE, не подсвечивает их "не знакомыми" - с большой вероятностью программист вспомнит, что это Transmitter Enable и Receiver Enable. Но когда там будет написано USART2->CR1 = B3 | B2; Вы тут же полезете в мануал, т.к. даже пару минут спустя уже забудете, что эти биты значат. Да, не все биты по их имени отражают, что они делают. Но многие. А у вас - ноль. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 7 сентября Опубликовано 7 сентября · Жалоба шутка юмора в тему: 2 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EdgeAligned 86 7 сентября Опубликовано 7 сентября · Жалоба 18 минут назад, jcxz сказал: Вижу - начитались вы диванных экспердов.... Ого! Прикольно! Впервые встречаю человека, отвергающего концепцию уровней абстракции, которая была сформулирована еще на заре программирования вообще, в прошлом тысячелении. Вы наверно прямо из main() дергаете биты в регистрах. Мдяяя. пичалька, пичалька. Не знаю, является ли для вас "диванным экспертом" автор языка Си, но то, что вы изобрели "альтернативную концепцию" - это точно 🙂 Однако, боюсь, что ваша концепция мало кому из мэтров программирования подходит. Они то как раз наоборот, стоят за идеей отделения мух от котлет. Читайте ПРАВИЛЬНЫЕ книги. 11 минут назад, Forger сказал: шутка юмора в тему: хахаха! 🙂 прочитал. Да, я путал TX и RX, и не только регистры, но и провода. Дома есть три паяльника, от старого советсткого 65-ваттного до паяльной станции. Ардуину хоть не пробовал, но просматривал ихние скетчи и даже лазил по ихнему форуму ради прикола. Чето даже отвечал там, поржав. Правда, забанили, ибо "шипко умный и дерзкий". Полярность питания путал, сжег дисплей и несколько микроконтроллеров. Но не работал в НИИ. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 7 сентября Опубликовано 7 сентября · Жалоба 2 минуты назад, Arlleex сказал: И часто бывает как раз так, что имя бита не требует заглядывания в мануал. Я понятия не имею и даже через час не вспомнил бы, что значит spiC->TRBSCR = B0 | B14; Я не понимаю, как это для Вас нагляднее, например, этого USART2->CR1 = USART_CR1_OVER8 | USART_CR1_TE | USART_CR1_RE; Вы всё время сравниваете с простой периферией STM32. В которой всего 5 регистров в UART и несколько бит. И где легко запомнить функции бит и ассоциировать их с названиями. А попробуйте как-нить поработать на сложном МК. Типа XMC. Где в том же UART битов - раз в десять больше. И, так как их функционал очень богатый, то и функции очень заковыристые. А потом расскажите - что вам скажут названия: 1 << SELCTR | 2 << CTQSEL1 | 1 << DX2TIEN через неделю хотя-бы? Сможете? Если битов этих не десяток, а штук 100? Я же уже писал: "уже пробовал давать символьные имена битам" - потом всё пришлось переделывать. Так как с номерами - гораздо быстрее и понятнее разобраться. Вот для справки типичный начальный инит SPI+DMA для внешней флешки на XMC4700: void InitDflash() { static TPinSel const tPinmux[] = { PINSEL_I(PIN_DF_MISO, PINSEL_USIC(nUSIC_df, DATA), STRONG_SOFT, PU), PINSEL_O(PIN_DF_MOSI, PINSEL_USIC(nUSIC_df, DOUT0), PINSEL_USIC(nUSIC_df, DATA), STRONG_SOFT), PINSEL_O(PIN_DF_SCLK, PINSEL_USIC(nUSIC_df, SCLKOUT), NONE, STRONG_SHARP, SET1), PINSEL_O(PIN_DF_CS0, PINSEL_USIC_SELO(nUSIC_df, PIN_DF_CS0), NONE, STRONG_SOFT, SET1), PINSEL_O(PIN_DF_CS1, PINSEL_USIC_SELO(nUSIC_df, PIN_DF_CS1), NONE, STRONG_SOFT, SET1) }; int i = DFLASH_CHIP_N - 1; do { chipStat[i] = CHIP_ERASE; chipWait[i] = 0; } while (--i >= 0); i = ncell(ops) - 1; do { ops[i].cmd = Op::OP_NOP; OsSemCreate1(&ops[i].sem); } while (--i >= 0); PeripheralOn(concat(SCU_PERIPH_USIC, USIC_UNIT(nUSIC_df))); spiC->KSCFG = B0 | B1 | B7 | B11; { int dummy = spiC->KSCFG; } if (~spiC->CCFG & (B0 | B6 | B7)) trap(TRAP_DFLASH | ERR_UNEMPLEMENTED << 16); spiC->CCR = 0; spiC->DXCR[0] = USIC_DXn(PIN_DF_MISO, nUSIC_df, 0) | B4; spiC->DXCR[3] = B4; spiC->FDR = B10 - 1 | 1 << 14; //Normal divider mode selected, FD_CLK = PBCLK spiC->BRG = T_LD_TD - 1 << 10 | DFLASH_PBCLK_DIV - 1 << 16 | 1 << 30; spiC->SCTR = B0 | B1 | 1 << 8 | 63 << 16 | 7 << 24; spiC->TCSR = B0 | B8 | 1 << 10; spiC->PCR = B0 | B1 | B2 | B3 | 2 << 4 | F2F_SPLIT - 1 << 8; spiC->RBCTR = spiC->TBCTR = 0; spiC->TRBSCR = B0 | B1 | B2 | B8 | B9 | B10 | B14 | B15; spiC->INPR = SRUSIC_SR(nUSIC_SR_df_ERR) * (B0 | B4 | B8 | B12 | B16); spiC->TBCTR = USIC_CH(nUSIC_df) * USIC_FIFO_SIZE * 2 | 1 << 8 | SRUSIC_SR(nUSIC_SR_df_TX) << 16 | SRUSIC_SR(nUSIC_SR_df_ERR) << 19 | concat(USIC_FIFO_SIZE_, USIC_FIFO_SIZE) << 24 | B30 | B31; spiC->RBCTR = USIC_CH(nUSIC_df) * USIC_FIFO_SIZE * 2 + USIC_FIFO_SIZE | SRUSIC_SR(nUSIC_SR_df_RX) << 16 | SRUSIC_SR(nUSIC_SR_df_ERR) << 19 | concat(USIC_FIFO_SIZE_, USIC_FIFO_SIZE) << 24 | B28 | B30 | B31; spiC->PSCR = -1; spiC->CCR = 1 | B11; DMAon(1 << nDMALINE_df_TX | 1 << nDMALINE_df_RX); rdmaC->SAR = (u32)&spiC->OUTR; rdmaC->CFG[0] = DMAPRI_SPI_RX << 5 | B10; rdmaC->CFG[1] = B1 | 1 << 2 | (nDMALINE_df_RX & 7) << 7; tdmaC->CFG[0] = DMAPRI_SPI_TX << 5 | B11; tdmaC->CFG[1] = B0 | B1 | 1 << 2 | (nDMALINE_df_TX & 7) << 11; AtomicOrI(&DLR.LNEN, 1 << nDMALINE_df_TX); PinSelN(tPinmux); } Теперь заменяем все численные позиции битов на символьные. Этот исходник распухает раз так в ~5. И заполняется всякими: Сможете через неделю вспомнить назначение всех этих RBERIEN, SRBIEN, ARBIEN, ... ? Всё равно придётся лезть в мануал и смотреть. А там смотреть удобнее по номерам битов. И строки хоть в ширину экрана влазят - исходник компактнее, значит в нём ориентироваться проще. 2 минуты назад, Arlleex сказал: Все-таки, даже спустя большое количество времени мозг, глядя на эти биты TE, RE, не подсвечивает их "не знакомыми" - с большой вероятностью программист вспомнит, что это Transmitter Enable и Receiver Enable. В случае простых контроллеров с простой периферией - да, наверное. Но не в случае сложной периферии. Просто попробуйте сами на практике. Потом будете говорить. 2 минуты назад, Arlleex сказал: Да, не все биты по их имени отражают, что они делают. Но многие. А у вас - ноль. Мне и не нужно отражать. Пока я пишу драйвер - я их помню. А потом всё равно нужно лезть в мануал. А ориентироваться в более коротком коде - намного проще. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EdgeAligned 86 7 сентября Опубликовано 7 сентября · Жалоба Нет, ну мы уже поняли про ваш "путь джедая". Спасибо, нам понятно. Это нам (лично мне, и наверняка многим другим) НЕ ПОДХОДИТ. СПАСИБО! Спасибо, достаточно. Ну нет, правда, спасибо, но вот это: spiC->TRBSCR = B0 | B1 | B2 | B8 | B9 | B10 | B14 | B15; не подходит. Спасибо, не стоит ЭТО предлагать. это один из самых ужасных кодов, которые мне приходилось видеть. Честно. На мой личный взгляд. Если вам нравится - пользуйтесь, никто не запрещает. Всё дело в привычке. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 7 сентября Опубликовано 7 сентября · Жалоба 29 минут назад, EdgeAligned сказал: Ого! Прикольно! Впервые встречаю человека, отвергающего концепцию уровней абстракции, которая была сформулирована еще на заре программирования вообще, в прошлом тысячелении. С чего вы взяли??? Где я её отвергал? Я писал, что вы со своими интернетными гуру не понимаете, что такое "абстракция" и где её нужно делать. И делается она не на уровнях битов регистров. Есть такая поговорка: "Слышал звон, да не знаю где он". Вот это как раз о вашем понимании абстрагирования. 29 минут назад, EdgeAligned сказал: Однако, боюсь, что ваша концепция мало кому из мэтров программирования подходит. Они то как раз наоборот, стоят за идеей отделения мух от котлет. Боюсь, что вы даже десятой части того объёма кода и коммерческих проектов не сделали, что я. А значит - значимость вашего мнения о моей концепции - на уровне погрешности округления. Концепция моя построена на собственном многолетнем практическом опыте, а не на мнении диванных экспердов, вчера только узнавших, что "ARM" - это не всегда рука. И изделия мои работают по всему миру миллионами экземпляров уже много лет. 14 минут назад, EdgeAligned сказал: не подходит. Спасибо, не стоит ЭТО предлагать. это один из самых ужасных кодов, которые мне приходилось видеть. Честно. На мой личный взгляд. Вот когда вы сможете создать что-то своё, стоящее. И это будет работать. И будет продаваться и пользоваться людьми, вот тогда ваше мнение будет иметь хоть какое-то значение. Ну или - покажите нам как правильно? Сможете?... Этот код по дорогам ездит. Сейчас прямо. И не один год. А скоро будет и по ветрякам лазить. А ваш? Аналогичные коды работают вполне возможно и в вашем городе - рядом, считают электроэнергию по всей РФ, управляют насосами на северах, общаются со спутниками, диагностируют пациентов в клиниках и т.п. А что делают ваши? Или ваших экспертов из инетика? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EdgeAligned 86 7 сентября Опубликовано 7 сентября · Жалоба 2 минуты назад, jcxz сказал: не понимаете, что такое "абстракция" и где её нужно делать. И делается она не на уровнях битов регистров. хорошо. На уровне чего она делается? Научите нас, о великий программист! С удовольствием послушаем. (поржем конечно потом, но послушаем) 🙂 чего только не наслушаешься в этих ваших интернетах. 🙂 чисто из любопытства. 3 минуты назад, jcxz сказал: Концепция моя построена на собственном многолетнем ...заблуждении 🙂 Да, "не все йогурты одинаково полезны" Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 7 сентября Опубликовано 7 сентября · Жалоба 5 минут назад, EdgeAligned сказал: хорошо. На уровне чего она делается? Научите нас, о великий программист! С удовольствием послушаем. (поржем конечно Сперва вы - пример "правильного" кода SPI-драйвера флешки для XMC4700 - в студию! Я ведь первый спросил. Ждём, готовим попкорн. PS: Хотя к чему это спрашивать? Сразу же видно что вы - диванный теоретик. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 190 7 сентября Опубликовано 7 сентября · Жалоба 27 минут назад, jcxz сказал: В случае простых контроллеров с простой периферией - да, наверное. Но не в случае сложной периферии. Просто попробуйте сами на практике. Потом будете говорить. Есть контроллеры и посложнее XMC. Чего уж - линукс поддерживает зоопарк процессоров с разными архитектурами и окружением, и под них люди тоже пишут драйвера. Залез вот в дебри какого-то исходника - и что я вижу... задефайненные имена битов. https://github.com/rockchip-linux/kernel/blob/9ed2be4b9c001ca8006cb4c72928c09927c44f89/drivers/net/ethernet/nxp/lpc_eth.c#L632 А они (кто там пилит линукс) тоже кода пишут километры в день. Такая себе метрика, на самом деле. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EdgeAligned 86 7 сентября Опубликовано 7 сентября · Жалоба 18 минут назад, jcxz сказал: Сперва вы - пример "правильного" кода SPI-драйвера флешки для XMC4700 - в студию! С XMC4700 не работаю, нет в нем нужды. Но на примере STM32, пожалста (в сокращенном виде, разумеется): HAL: static void Write(uint16_t data) { constexpr SPI_TypeDef *spi = getBase(); while(!(spi->SR & SPI_SR_TXE)); spi->DR = data; } BSP на примере дисплея template<typename SPI, typename CS, typename DC> class ST75256 { public: static bool PowerOn(bool on) { if(SPI::IsBusy()) return false; CS::Low(); DC::Low(); SPI::Write(0x95 & ~on); WaitComplete(); CS::High(); return true; } Не претендую на прям стопудовую правильность в деталях, но в общем и целом, считаю это правильно. Потому что оно работает, и хорошо работает. И если нужно будет пересесть на какой-нить XMC, то заменить здесь нужно будет то, что написано внутри HAL, и это, я считаю, правильно. Уровень BSP остается практически неизменным, за исключением возможной разницы в структуре микроконтроллера в целом. Голова программисту на то и дана, чтобы гибко подстраиваться под изменчивый мир железок. И еще до перехода на ++ писал в аналогичном стиле. Так то я тоже ведь порядка 20 лет в эмбедде. Еще ПИКи на асме прогал жеж. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 7 сентября Опубликовано 7 сентября · Жалоба 33 минуты назад, Arlleex сказал: Есть контроллеры и посложнее XMC. Чего уж - линукс поддерживает зоопарк процессоров с разными архитектурами и окружением, и под них люди тоже пишут драйвера. Залез вот в дебри какого-то исходника - и что я вижу... задефайненные имена битов. Ок. а теперь расскажите мне, как с "задефайненными именами" сделать то, что я могу у себя? Например есть описание распределения event-ов и ног для таймера: #define PIN_MLX1 1, 1 //Sch signal "TiredPWM_1", Melexis IR sensor input, used for measure rotor temperature (PWM coded) #define PIN_MLX2 3, 15 //Sch signal "TiredPWM_2", Melexis IR sensor input, used for measure rotor temperature (PWM coded) #define nCCU_mlx1 40, 2 //захват ШИМ-сигнала 1-го ИК-термометра MLX90614 #define nCCU_mlx2 42, 0 //захват ШИМ-сигнала 2-го ИК-термометра MLX90614 enum { //распределение номеров event-ов в nCCU_mlx1 и nCCU_mlx2 EVENT_MLX_start = 0, //event используемый для синхронного старта EVENT_MLX_rise = 1, //event используемый для сигнала захвата таймера по фронту PIN_MLX1 и PIN_MLX2 EVENT_MLX_fall = 2 //event используемый для сигнала захвата таймера по спаду PIN_MLX1 и PIN_MLX2 }; Макросы поддержки связывания: //преобразование индекса входной линии CCU в её буквенное обозначение #define CCU_LETTER_IN(letter) concat(CCU_MUX_LETTER_, letter) //номер выхода CCU для данного CCU/slice на данном порту/пине #define CCU_SLICE_OUT4(unit, slice, port, pin) concat(PINMUXO_P, port, _, pin, _CCU, unit, _SLICE, slice) #define CCU_SLICE_OUT(nCCU_slice, port_pin) CCU_SLICE_OUT4(nCCU_slice, port_pin) //номер(буква) входа CCU для данного CCU/slice на данном порту/пине #define CCU_PIN_IN4(unit, slice, port, pin) CCU_LETTER_IN(concat(CCU, unit, _IN, slice, _PIN, port, _, pin)) #define CCU_PIN_IN(nCCU_slice, port_pin) CCU_PIN_IN4(nCCU_slice, port_pin) И далее я пишу в регистр, привязывающий эти event-ы к событиям в таймере: CCU_MLX1_S.INS = CCU_GSC_IN(nCCU_mlx1) << EVENT_MLX_start * 4 | 1 << EVENT_MLX_start * 2 + 16 | CCU_PIN_IN(nCCU_mlx1, PIN_MLX1) << EVENT_MLX_rise * 4 | 1 << EVENT_MLX_rise * 2 + 16 | 3 << EVENT_MLX_rise * 2 + 25 | CCU_PIN_IN(nCCU_mlx1, PIN_MLX1) << EVENT_MLX_fall * 4 | 2 << EVENT_MLX_fall * 2 + 16 | 3 << EVENT_MLX_fall * 2 + 25; CCU_MLX2_S.INS = CCU_GSC_IN(nCCU_mlx2) << EVENT_MLX_start * 4 | 1 << EVENT_MLX_start * 2 + 16 | CCU_PIN_IN(nCCU_mlx2, PIN_MLX2) << EVENT_MLX_rise * 4 | 1 << EVENT_MLX_rise * 2 + 16 | 3 << EVENT_MLX_rise * 2 + 25 | CCU_PIN_IN(nCCU_mlx2, PIN_MLX2) << EVENT_MLX_fall * 4 | 2 << EVENT_MLX_fall * 2 + 16 | 3 << EVENT_MLX_fall * 2 + 25; CCU_MLX2_S.CMC = CCU_MLX1_S.CMC = EVENT_MLX_start + 1 | EVENT_MLX_rise + 1 << 4 | EVENT_MLX_fall + 1 << 6; Это простой пример. И я тут могу быстро поменять список event-ов. Как то же самое сделать с символьными именами? Есть гораздо более сложные связи. Там, где номера каких-то периферийных узлов (номера пинов, номера service request-ов внутри чипа, номера DMA-каналов и DMA-запросов) используются для вычисления позиций битов. Иногда - по весьма сложным формулам. И такое - почти везде. И это даёт мне возможность быстро поменять номера пинов, к которым привязана какая-то периферийная функция, поменять распределение service request-ов или DMA-каналов при переезде на новую плату или простой доработке схемы. Практически не трогая код драйвера. Вышеприведённый код драйвера SPI-флешь у меня работает на разных XMC4xxx в разных проектах. Практически без изменений! А вот ноги, номера SPI, номера прерываний и прочих цепей - разные. Я просто меняю соответствующие номера в bsp.h и всё - код переезжает на новую плату. Покажите - как это сделать без вычисляемых битовых позиций. Можно конечно наворотить макросов. Но это будет намного сложнее. И только с одной целью - побороть невозможность прямого вычисления битовых позиций. А тогда - нафига они сдались эти символьные имена битов??? 33 минуты назад, Arlleex сказал: Есть контроллеры и посложнее XMC. Посложнее по периферии??? Вот уж не уверен. Работал некогда с OMAP-L137. 4-ядерном. На котором линух тоже бегает. Так скажу вам - по многой периферии XMC4xxx даст ему 100 очков вперёд. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться