Перейти к содержанию
    

jcxz

Свой
  • Постов

    13 731
  • Зарегистрирован

  • Посещение

  • Победитель дней

    38

Весь контент jcxz


  1. В том примере инита SPI для работы с flash, что я приводил ранее, как раз она используется: Эта: AtomicOrI(&DLR.LNEN, 1 << nDMALINE_df_TX); Здесь как раз производится операция '|=' между регистром DLR.LNEN и константой (1 << nDMALINE_df_TX), но не с помощью обычных команд RMW, а с помощью команд эксклюзивного доступа ARM. Т.е. - атомарно. Регистр DLR.LNEN - содержит линии DMA-запросов к разным каналам DMA. Используемым разными драйверами периферии в разных задачах/ISR. Поэтому доступ к нему нужен атомарный. Почитать можете в мануалах на ядро Cortex-M3/M4. Описание команд LDREX/STREX/CLREX. PS: AtomicOr...() у меня - это набор макросов, для атомарного '|='. На встроенном ассемблере. PPS: Вот как раз в данном конкретном случае - использование операции эксклюзивной модификации оптимальнее, чем критическая секция. О чём я и говорил. Хотя можно было конечно и критическую секцию использовать.
  2. Не знаю конкретно насчёт STM32F405, но в других МК обычно для CAN настраиваются различные заданные моменты внутри периода одного бита CAN. Которые программист может варьировать. Например поля SJW,TSEG1,TSEG2 в XMC4700: Почти точно такие же поля есть и у LPC17xx: Качать и читать мануал STM32F405 мне лень, но думаю - что-то аналогичное должно быть и в нём. Если есть, то возможно проблема в том, что какая-то из таких настроек находится на грани работоспособности. А в температуре уходит за эту грань. Можно попробовать покрутить её чуть-чуть в обе стороны и протестить в температуре.
  3. Лекция от гуру диванного программирования. Вот тут то Штирлиц и понял, что провалился!.... По постам всё видно. Видно, человек никогда на практике разработкой не занимался. Потому он и всякие советы интернетных "гуру" воспринимает догматически. Так как не может оценить их на своём опыте. А все практические вопросы заметьте - игнорирует. Или несёт какую-то чушь, вообще никак не относящуюся к делу. Ну-ну.... каждый мнит себя Наполеоном... В очередной раз (уже в 5-й?) от вас слышу про "гумно". Хотя вроде я вас не оскорблял - это вы начали и продолжаете про некое "гумно". Причём совершенно безосновательно - даже не видев моего кода(!), уже оцениваете его. Это оценивает вас как человека (как раз на аналогичную оценку). Как "специалист" вы уже себя давно "показали" во всей "красе". PS: Не буду опускаться на ваш уровень и более вступать с вами в полемику, просто буду ставить соответствующие отметки вашим словоизвержениям. Сразу пишу что оценка вам - за прямую ложь (про мой код), провокации и безосновательные оскорбления. PPS: Надеюсь в этот раз не побежите снова регить новый аккаунт и с него мстить? И требую конкретного примера (с цитатой) - где именно у меня вы увидели: "встраивать "предохранители" в виде критических секций на уровне общения с регистрами"? Цитату в студию! Иначе буду считать вас лжецом!
  4. Не обязательно. И даже иногда вредно в случае однократной операции RMW (или даже нескольких подряд). Часто лучше использовать эксклюзивную RMW и спин-блокировку на её основе.
  5. Ну да: "Миллион мух не могут заблуждаться. Если они туда летят, значит там действительно что-то вкусное." Подумал Вася, направляясь к объекту "М/Ж". Все калы и кубы пишутся для начинающих. А значит - пишутся так, чтобы быть доступными для понимания даже ребёнком. Точно так же, как детские игрушки делаются из безопасных материалов, которые можно хоть жевать без вреда, и без острых углов. Но это ведь не повод, чтобы вообще запретить всякие острые и тяжёлые инструменты. Взрослый сам может решить - какой инструмент ему лучше. На то он и взрослый. Так и эти ваши правила, которым вы слепо поклоняетесь, как религиозный фанатик, не вникая - они придуманы для начинающих. Чтобы помочь им сделать первые шаги. Когда ещё ноги не уверенно стоят на земле и голова не соображает куда идти. Чтобы не пропал этот карапуз, не заблудился, не попал в беду. А профессионал - он уже как взрослый - он сам волен решать - как ему действовать. Так как набрался жизненного опыта, он знает что и с чем едят. Он дееспособен. Он сам волен принимать решения и отвечать за свои поступки. И как для дела удобнее - так и следует оформлять исходники. А не как "гуру" из инетика посоветовал. Если своя голова на плечах есть, то никакие указания всяческих "гуру" не нужны. Тем более смешно слышать аргументы типа: "Все же так делают, значит это правильно". Подавляющее большинство этих всех - это чайники. И правила ваши пишутся - для этого большинства. А знающий человек - сам знает как ему поступать. Без советов сопливых... Я выше приводил конкретный пример. Который как раз иллюстрирует преимущество использования числовых констант. С вопросом: "Как то же самое написать без привязки к конкретным номерам битов?" Вы что-то сказали по нему (по делу)? Показали как это можно реализовать в соответствии с вашими проповедями? Нет, ничего не предложили. А треплетесь бесцельно уже сколько времени.... Скорее всего - типичный копи-паст fail. Но не факт конечно.
  6. Если в том холодильнике он найдёт пивас, то может долго там её искать.
  7. Да - может быть что угодно: И некорректная реакция на какие-то значения измеренной температуры; и неучёт разброса частот тактирования от температуры, из-за чего что-то начинает неуспевать или наоборот - успевать слишком много. Идти (имхо) можно методом пошагового исключения вероятных факторов: Отключать по очереди куски кода. В первую очередь - узнать что такое "виснет"? И где?
  8. Советую вам выбирать выражения. Это вы тут уже многократно и совершенно безосновательно назвали мой код говнокодом, даже не видев его. Я же ваш называл только конкретно и по делу. С конкретным указанием где и что. Надеюсь ясно прояснил? А ваш опыт всем прекрасно виден по вашему "коду".
  9. Вообще напоминает как водила Камаза пытается научить лётчика как правильно летать. И где во феншую должно висеть ведро - у какого крыла. Т.е. - вы это говорите даже не видя его и не зная как он работает??? Я так весь ваш код могу говнокодом назвать. И кстати - буду прав. Ибо вот это: конкретно ГОВНОКОД! 1. Операция поразрядной инверсии над bool? Ну-ну... Индусам у вас нужно поучиться! 2. Передача по SPI даже без выдержки необходимой (по даташиту) паузы между CS-low и началом передачи? 3. То же самое относительно временных задержек между DC и CS и началом передачи. 4. Блокирующие ожидания готовности а-ля ардуино-стайл? 5. Отсутствие выдержки от предыдущей закончившейся передачи по SPI до начала новой? И выкладывая такое, вы ещё пытаетесь меня учить программировать???? В одной короткой функции количество говнокода просто зашкаливает! Как тот деятель, который недавно тут где-то писал как правильно читать UART, сам даже не заглянув в мануал. Мнение автора быдлокода приведённого выше конечно "ценно"... PS: Научитесь сперва хотя бы что-то примитивное грамотно писать. Прежде чем опытных дядек учить.
  10. У меня практически во всех драйверах есть такие аппаратные связки сигналов. Так как XMC4xxx позволяет. А если хотя-бы один регистр в функции прописывается так, как выше показал, то писать остальные через символьные имена (имхо) - не комильфо. Так как стиль должен быть единым. Я кстати раньше тоже пытался смешивать. Частично - использовал символьные имена. Но выглядит это ужасно. Такая каша. Кстати - драйвер UART на STM32 у меня написан насколько помню - с символьными именами битов. Там так нагляднее. И битов там мало и функции их - понятны по названиям. Но даже на STM32, например DMA - уже нагляднее выглядит с численными позициями битов. Когда у вас будет много вычисляемых позиций битов, то заметите как станет удобнее мой способ. На простых примерах этого не понять....
  11. И как тут помогут символьные имена битов? Там я некорректно процитировал. Хотел сказать, что наличие линуха не обязательно говорит о сложности внутренней периферии МК. МК-то конечно есть разные, и весьма сложные тож.
  12. И всё???! Серьёзно??? Я же писал: Примитивный код да на простой периферии - он будет читаемым и с символьными именами. И даже более читаем с ними. Мой драйвер транзакций SPI-флешь (точнее - его нижний уровень по абстракции) = ~800 строк (только .cpp, без .h). И это с численными битами. С символьными именами был бы намного тяжелее. Попробуете написать что-то подобное ему со своим подходом - утонете.
  13. Ок. а теперь расскажите мне, как с "задефайненными именами" сделать то, что я могу у себя? Например есть описание распределения 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 и всё - код переезжает на новую плату. Покажите - как это сделать без вычисляемых битовых позиций. Можно конечно наворотить макросов. Но это будет намного сложнее. И только с одной целью - побороть невозможность прямого вычисления битовых позиций. А тогда - нафига они сдались эти символьные имена битов??? Посложнее по периферии??? Вот уж не уверен. Работал некогда с OMAP-L137. 4-ядерном. На котором линух тоже бегает. Так скажу вам - по многой периферии XMC4xxx даст ему 100 очков вперёд.
  14. Все колёса уже пропинаны, зеркала - протираны, осталось - искать программные баги. Т.е. - отделения мух от котлет ещё даже не пытались делать? Почему не пришла логичная мысль, что портится что-то в программе и поэтому зависает? Например - портится память где-то, и сперва некритичные данные, а потом - например уже портится что-то, от чего зависит ход выполнения программы? PS: Конечно - искать программную ошибку у себя много сложнее, чем валить всё на контроллер. Но может стоит попробовать? Можно ведь написать простейший код, использующий тот-же источник тактирования, но из которого вырезан почти весь функционал. И проверить его работу в тех же условиях. А также можно выяснить - что такое "зависает"? Подключить отладочный эмулятор к примеру и выяснить.
  15. Сперва вы - пример "правильного" кода SPI-драйвера флешки для XMC4700 - в студию! Я ведь первый спросил. Ждём, готовим попкорн. PS: Хотя к чему это спрашивать? Сразу же видно что вы - диванный теоретик.
  16. С чего вы взяли??? Где я её отвергал? Я писал, что вы со своими интернетными гуру не понимаете, что такое "абстракция" и где её нужно делать. И делается она не на уровнях битов регистров. Есть такая поговорка: "Слышал звон, да не знаю где он". Вот это как раз о вашем понимании абстрагирования. Боюсь, что вы даже десятой части того объёма кода и коммерческих проектов не сделали, что я. А значит - значимость вашего мнения о моей концепции - на уровне погрешности округления. Концепция моя построена на собственном многолетнем практическом опыте, а не на мнении диванных экспердов, вчера только узнавших, что "ARM" - это не всегда рука. И изделия мои работают по всему миру миллионами экземпляров уже много лет. Вот когда вы сможете создать что-то своё, стоящее. И это будет работать. И будет продаваться и пользоваться людьми, вот тогда ваше мнение будет иметь хоть какое-то значение. Ну или - покажите нам как правильно? Сможете?... Этот код по дорогам ездит. Сейчас прямо. И не один год. А скоро будет и по ветрякам лазить. А ваш? Аналогичные коды работают вполне возможно и в вашем городе - рядом, считают электроэнергию по всей РФ, управляют насосами на северах, общаются со спутниками, диагностируют пациентов в клиниках и т.п. А что делают ваши? Или ваших экспертов из инетика?
  17. Вы всё время сравниваете с простой периферией 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, ... ? Всё равно придётся лезть в мануал и смотреть. А там смотреть удобнее по номерам битов. И строки хоть в ширину экрана влазят - исходник компактнее, значит в нём ориентироваться проще. В случае простых контроллеров с простой периферией - да, наверное. Но не в случае сложной периферии. Просто попробуйте сами на практике. Потом будете говорить. Мне и не нужно отражать. Пока я пишу драйвер - я их помню. А потом всё равно нужно лезть в мануал. А ориентироваться в более коротком коде - намного проще.
  18. У меня в универе был одногруппник. Он на все экзамены писал шпоры на все билеты. Полностью. Целую кипу шпор. А потом сам их не использовал - раздавал. Когда его спрашивал: "На кой так делаешь, раз сам почти не пользуешь?" Он говорил: "Пока их пишу, я их выучиваю и потом уже помню, даже без шпор". Так и тут - пока пишу описания регистров, я их функционал запоминаю. Вот например кусок 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 (контроллер). Как видно - все битовые поля заданы численно. Что там пишут диванные эксперды, никогда не занимавшиеся реальными проектами - мне совершенно по-барабану. А вот если бы они реально что-то писали сами (а не таскали кубиками из чужих проектов), то как бы им помогло описание битов регистров? Вот читаем описание битов одного из регистров 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: Когда-то по-дурости, наслушавшись подобных "экспердов" переписал некоторые драйвера с использованием именованных позиций бит. Потом, когда пришлось через некоторое время что-то там переделывать, долго плевался. Понял - насколько удобнее с числовыми номерами битов. Когда пишу, что-то связанное с периферией, у меня всегда открыт мануал на неё. И искать в нём гораздо удобнее по номерам битов. А у некоторых производителей ещё и имена битов в мануале отличаются от имён, заданных в хидерах. Тут вообще задница была бы. Вот! И эти выводы вы делаете по простой периферии STM32. А теперь возьмём например XMC4700, в котором регистров и битов в них - кратно больше. Там вам придётся всё время держать мануал перед глазами. Выше написал уже. В тех исходниках, что я видел (от 3D-принтера) всё было свалено в одну кучу. И там была куча перекрёстных ссылок. И кусков хидеров, в которых идут ссылки на всё и вся. И выдирание любого описания периферии (даже не используемой) приводило к несборке всего проекта. Так просто там взять и заменить описание периферии ядра на своё никак не получалось. А какой смысл её менять??? Вы думаете этот бит дрейфует по регистру? В чём именно "стреляю"? Ничего не понял.... уже лет 20 как программирую разные МК и ноги мои почему-то до сих пор целые. Вижу - начитались вы диванных экспердов.... Которые никогда ничего сложнее абдуриновского кода не видели.... Все эти биты в регистрах периферии - это как раз и есть тот самый нижний "hardware"-уровень. Который меняется полностью при переходе на другой МК. Вместо с этими битами. Поэтому это никак не мешает абстракции. Абстракция - она не на уровне битов должна быть. А выше.
  19. Ок, например - возьмём описания регистров периферии ядра. NVIC, MPU, etc. Взяли вы от STM32 описания всех регистров. Там и эти есть. А завтра вам нужно писать код на NXP или Infineon или TI. Там тоже берёте описание "от производителя". Но ведь там описание регистров ядра почти наверняка отличается. Даже имена регистров там могут быть другими. Как будете тут поступать? А у меня, с моими описаниями - проблем нет, так как описание регистров ядра просто одинаковы. Соответственно и код, работающий с этой периферией я просто копирую из проекта в проект. Почти ничего не меняя. А там довольно большой объём кода. На одном только этом, я экономлю времени больше, чем потрачу даже на десять самостоятельных описаний регистров.
  20. Вот блоков описания битов и не нужно. Одни минусы в этом. Нужны только регистры.
  21. Так и описания регистров приходится перечитывать многократно. Пока пишешь и отлаживаешь проект. На перечитывание их тратиться времени кратно больше, чем на начальное описание. Вот не поверю, что вы прочитали один раз описание какой-то периферии и больше не обращаетесь к нему - всё помните. А также я часто использую куски кода из своих предыдущих проектов.
  22. Ну вот те индусы, что изначально писали код для моего 3D-принтера и взяли стандартные описания. 2 или 3 разных. Но все "стандартные". Это чему-то помогло?
  23. Важно самому программисту. Сами же писали: "Чем гуще лес, тем проще в нём заблудиться". Или вам никогда не приходится потом читать собственных исходников? Чего-то в них переделывать или искать?
  24. Когда сам пишешь, то понимаешь логику по которой это всё построено. И согласен с ней. А значит - просто многократно быстрее находишь баги и проблемы. Иногда достаточно только увидеть внешнее проявление, как уже знаешь где причина. А в чужом лесу даже широкую просеку бывает трудно заметить, не то что узкую тропинку. И я знаю, что написание и отладка логики программы занимает многократно (даже на порядки) больше времени, чем описание регистров периферии. И в процессе этого мне 100500 раз придётся обратиться к описаниям регистров периферии. Если на каждом таком обращении я сэкономлю хотя-бы 20% времени (потому как быстрее найду и прочитаю что нужно в удобном мне стиле), то по суммарном результату я могу сэкономить часы если не дни отладки потом. Скажу даже более - я чаще всего функции ног МК, или распределение других ресурсов (линий прерываний и т.п.) смотрю по своим хидерам, чем по мануалу. Просто - так быстрее получается. Я же сам его составлял. А значит составил так, как мне удобнее с ним работать. А индусы, писавшие мануал, писали его как им удобнее. Но не всегда удобнее мне.
  25. Я же вроде и писал же, что против "надёргивательно-кусочного программирования". Мой код не нужно бездумно выдёргивать кусками. С чего бы это??? Я их ниоткуда не выдёргивал. Сам писал. Да и не код это. А всего лишь заголовочный файл.
×
×
  • Создать...