Forger 24 14 декабря, 2018 Опубликовано 14 декабря, 2018 · Жалоба 1 hour ago, AlexandrY said: Это типичный код в стиле C ... В стиле C++ будет так ... Но все же вы - молодец: продемонстрировали умение перегружать оператор "=", нынче без этого ну никак нельзя делать читаемый код. Похоже, что далеко не каждый способен усложнить и запутать простой код на совершенно ровном месте, используя при этом самые необычные способы. Quote И не забываем про критические секции. Не все в стиле суперлуп программируют. На всякий случай напомню: в моих проектах НЕТ глобальных объектов, в том числе пинов, к которым может обращаться каждый кому ни лень. 99,9% моих проектов под осью. Вы умеете отличать примеры от кусков кода? Подсказка: выше был лишь ПРИМЕР. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Darth Vader 0 16 декабря, 2018 Опубликовано 16 декабря, 2018 · Жалоба On 11/28/2018 at 5:01 PM, Forger said: оверхеда по скорости почти нет, разве что небольшой по объему памяти Сколько в итоге в памяти занимает один объект класса пина порта? В первом приближении: pinIndex - 1 байт; pinMask - 2 байта *port - 4 байта Итого, как минимум 7 байт на каждый объект класса пин. Предположим, имеется 6 портов по 16 пинов. Итого 96 пинов. В памяти объекты всех пинов займут 96*7=672 байта. Я правильно понимаю? Я не ругаю и не хвалю данный способ. Просто хочу понять для себя его достоинства, недостатки, накладные расходы, возможные ограничения при применении. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 24 16 декабря, 2018 Опубликовано 16 декабря, 2018 · Жалоба 1 hour ago, Darth Vader said: Сколько в итоге в памяти занимает один объект класса пина порта? В первом приближении: pinIndex - 1 байт; pinMask - 2 байта *port - 4 байта Итого, как минимум 7 байт на каждый объект класса пин. Предположим, имеется 6 портов по 16 пинов. Итого 96 пинов. В памяти объекты всех пинов займут 96*7=672 байта. Да, все верно (хотя от pinIndex можно отказаться и вычислять его при необходимости на месте, но это мелочи и на них не заморачиваюсь). Однако, ситуация такова, что такое огромное число пинов (под сотню) объявляется только в толстых проектах, соотв. в толстых камнях, где ОЗУ далеко НЕ несколько кБ. Т.е. чем больше пинов нам нужно, тем более многоногий корпус приходится выбирать, а многоногий корпус = жирный камень = много ОЗУ. Мелкие камни в жирных корпусах практически не делают. В итоге эти жалкие пара сотен байт ОЗУ, отводимых на пины, - лишь капля в море ОЗУ, которое в таких проектах в реальности требуется. Для себя я давно решил, что читаемость и сопровождаемость кода для меня лично имеют на порядок большую цену нежели некая мифическая экономии ОЗУ на практически ровном месте :) При особом желании экземпляры пинов (Pin) можно создавать локально (в стеке), инициализировать (по сути однкратно) и при выходе из функции место, занятое пинами, из стека будет освобождено, для других целей. Например, это удобно при инициализации пинов под внешнюю память, где это приходится делать лишь при старте приложения. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Darth Vader 0 16 декабря, 2018 Опубликовано 16 декабря, 2018 · Жалоба А в чём смысл (преимущество) использования в этом способе именно шаблонов? Почему нельзя описать класс пина и конструктор для него с enum-параметром типа PinName. При создании объекта пина по значению этого параметра для него в конструкторе будут заполняться поля pinIndex, pinMask и *port. Вроде всё то же самое, что вы описываете. В чём минус такого подхода и плюс использования шаблонов? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 24 16 декабря, 2018 Опубликовано 16 декабря, 2018 · Жалоба 58 minutes ago, Darth Vader said: А в чём смысл (преимущество) использования в этом способе именно шаблонов? Почему нельзя описать класс пина и конструктор для него с enum-параметром типа PinName. При создании объекта пина по значению этого параметра для него в конструкторе будут заполняться поля pinIndex, pinMask и *port. Вроде всё то же самое, что вы описываете. В чём минус такого подхода и плюс использования шаблонов? Тогда научите меня как объявить экземпляр Pin в списке данных (полей) некого класса-владельца этого Pin, если у конструктора Pin есть как минимум один параметр (PA0, PC10 ... и т.п.), тогда есть вероятность, что откажусь от шаблонов в этой реализации Pin :) Если же отказаться от конструктора с входными параметрами, то придется это делать в коде отдельным методом (функцией), что вызывает нагромождения доп. кода и заметно ухудшает читаемость. Для меня это - пройденный этап. К тому же в плане экономии кода и памяти это ничего толком не даст, т. к. все шаблонные виды Pin в целом наследуются от одного базового класса AbstractPin, который НЕ шаблонный. Т.е. инстанцирования шаблона Pin - хоть и порождает новые классы (по сути на каждый пин - свой уникальный класс), но тут все они настолько примитивные, что оверхеда практически не дают. Нынче компиляторы идут весьма умные и догадливые // Pin.hpp: class DigitalOutputPinBase : public AbstractPin { public: DigitalOutputPinBase(PinName pin) : AbstractPin(pin) { setAsDigitalOutputPin(); setAsPushPull(); } }; template <PinName pin = NONE> class DigitalOutputPin : public DigitalOutputPinBase { public: DigitalOutputPin() : DigitalOutputPinBase(pin) { } }; // код Hardware::DigitalOutputPin<PD3> pinCH_01; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 178 19 декабря, 2018 Опубликовано 19 декабря, 2018 (изменено) · Жалоба Возвращаясь к теме. Теоретически (и практически) возможно ли каким-то образом сделать макрос, который будет формировать другой макрос? Что-то типа #define DEFINE_CREATE(NAME, VALUE) ... который сделал бы мне из DEFINE_CREATE(CRG_BIT_0, 0x10) вот это #define CRG_BIT_0 0x10 и дальше по коду мог пользоваться значением CRG_BIT_0? Хочу сделать что-то наподобие удобной таблицы назначения бит в регистрах по их именам без непосредственного описания каждого бита отдельным #define-ом. Изменено 19 декабря, 2018 пользователем Arlleex Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 234 20 декабря, 2018 Опубликовано 20 декабря, 2018 · Жалоба 10 часов назад, Arlleex сказал: Теоретически (и практически) возможно ли каким-то образом сделать макрос, который будет формировать другой макрос? Что-то типа Вряд-ли. 10 часов назад, Arlleex сказал: Хочу сделать что-то наподобие удобной таблицы назначения бит в регистрах по их именам без непосредственного описания каждого бита отдельным #define-ом. Из этой фразы толком не понятно что именно нужно. В 16.12.2018 в 23:07, Forger сказал: Тогда научите меня как объявить экземпляр Pin в списке данных (полей) некого класса-владельца этого Pin, если у конструктора Pin есть как минимум один параметр (PA0, PC10 ... и т.п.), тогда есть вероятность, что откажусь от шаблонов в этой реализации Pin :) Не надо заниматься кододрочерством. Все эти назначения/конфигурирование пинов нормально решаются макросами. Без лишних расходов кода и ОЗУ. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexandrY 3 20 декабря, 2018 Опубликовано 20 декабря, 2018 · Жалоба 35 minutes ago, jcxz said: Не надо заниматься кододрочерством. Все эти назначения/конфигурирование пинов нормально решаются макросами. Без лишних расходов кода и ОЗУ. Макросы то зачем? Все можно решить простыми таблицами, где собрана абсолютно вся информация о всех пинах. Даже перечислены все альтернативные функции на пине, имена цепей на схеме, номера пинов на процессоре и номера пинов на процессорном модуле. Эт нужно тем кто занимается отладкой железа и программированием одновременно. По сравнению с любыми разрозненными объявлениями раскиданными по разным файлам тут все в одном месте и охватывается одним взглядом. Таблица генерится прямо из схемы. Т.е. ошибки назначения пинов исключены. Пинов может быть несколько сотен и трудоемкости при этом не добавляется. Если надо, то редактируются такие таблицы прямоугольными блоками, т.е. редактируем за раз весь выделенный столбец. не надо проходить по каждой строке отдельно. Одна только проблемка. Разработчику как минимум надо знать еще пару языков программирования и техник чтобы умело применять скрипты и писать конвертеры исходников. Я б даже сказал, что анахронизмом будет все решать средствами C++ const T_IO_pins_configuration LNDC01_pins_conf[] = { // gpio port num irqc lock mux DSE ODE PFE PUPD dir init { GPIOA, PORTA, 0, IRQ_DIS, 0, ALT0, DSE_HI, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP, 0 }, //- 79 PTA0 Def=ADC0_SE0/ACMP0_IN0 ALT0=ADC0_SE0/ACMP0_IN0 ALT1=PTA0 ALT2=FTM2_CH1 ATL3=LPI2C0_SCLS ALT4=FXIO_D2 ALT5=FTM2_QD_PHA ALT6=LPUART0_CTS ALT7=TRGMUX_OUT3 { GPIOA, PORTA, 1, IRQ_DIS, 0, ALT0, DSE_HI, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP, 0 }, //- 78 PTA1 Def=ADC0_SE1/ACMP0_IN1 ALT0=ADC0_SE1/ACMP0_IN1 ALT1=PTA1 ALT2=FTM1_CH1 ATL3=LPI2C0_SDAS ALT4=FXIO_D3 ALT5=FTM1_QD_PHA ALT6=LPUART0_RTS ALT7=TRGMUX_OUT0 { GPIOA, PORTA, 2, IRQ_DIS, 0, ALT6, DSE_HI, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP, 0 }, //UART0_RX 73 PTA2 Def=ADC1_SE0 ALT0=ADC1_SE0 ALT1=PTA2 ALT2=FTM3_CH0 ATL3=LPI2C0_SDA ALT4=EWM_OUT_b ALT5= ALT6=LPUART0_RX ALT7= { GPIOA, PORTA, 3, IRQ_DIS, 0, ALT6, DSE_HI, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP, 0 }, //UART0_TX 72 PTA3 Def=ADC1_SE1 ALT0=ADC1_SE1 ALT1=PTA3 ALT2=FTM3_CH1 ATL3=LPI2C0_SCL ALT4=EWM_IN ALT5= ALT6=LPUART0_TX ALT7= //{ GPIOA, PORTA, 4, IRQ_DIS, 0, ALT0, DSE_HI, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP, 0 }, //SWD_DIO 98 PTA4 Def=JTAG_TMS/SWD_DIO ALT0= ALT1=PTA4 ALT2= ATL3= ALT4=ACMP0_OUT ALT5=EWM_OUT_b ALT6= ALT7=JTAG_TMS/SWD_DIO //{ GPIOA, PORTA, 5, IRQ_DIS, 0, ALT0, DSE_HI, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP, 0 }, //Reset 97 PTA5 Def=RESET_b ALT0= ALT1=PTA5 ALT2= ATL3=TCLK1 ALT4= ALT5= ALT6=JTAG_TRST_b ALT7=RESET_b { GPIOA, PORTA, 6, IRQ_DIS, 0, ALT0, DSE_HI, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP, 0 }, //INESC3 58 PTA6 Def=ADC0_SE2/ACMP1_IN0 ALT0=ADC0_SE2/ACMP1_IN0 ALT1=PTA6 ALT2=FTM0_FLT1 ATL3=LPSPI1_PCS1 ALT4= ALT5= ALT6=LPUART1_CTS ALT7= { GPIOA, PORTA, 7, IRQ_DIS, 0, ALT0, DSE_HI, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP, 0 }, //INESC4 57 PTA7 Def=ADC0_SE3/ACMP1_IN1 ALT0=ADC0_SE3/ACMP1_IN1 ALT1=PTA7 ALT2=FTM0_FLT2 ATL3= ALT4=RTC_CLKIN ALT5= ALT6=LPUART1_RTS ALT7= { GPIOA, PORTA, 8, IRQ_DIS, 0, ALT0, DSE_HI, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP, 0 }, //- 100 PTA8 Def=DISABLED ALT0= ALT1=PTA8 ALT2= ATL3= ALT4=FXIO_D6 ALT5=FTM3_FLT3 ALT6= ALT7= { GPIOA, PORTA, 9, IRQ_DIS, 0, ALT0, DSE_HI, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP, 0 }, //- 99 PTA9 Def=DISABLED ALT0= ALT1=PTA9 ALT2= ATL3= ALT4=FXIO_D7 ALT5=FTM3_FLT2 ALT6=FTM1_FLT3 ALT7= //{ GPIOA, PORTA, 10, IRQ_DIS, 0, ALT0, DSE_HI, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP, 0 }, //SWO 92 PTA10 Def=JTAG_TDO/noetm_Trace_SWO ALT0= ALT1=PTA10 ALT2=FTM1_CH4 ATL3=LPUART0_TX ALT4=FXIO_D0 ALT5= ALT6= ALT7=JTAG_TDO/noetm_Trace_SWO { GPIOA, PORTA, 11, IRQ_DIS, 0, ALT0, DSE_HI, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP, 0 }, //- 91 PTA11 Def=DISABLED ALT0= ALT1=PTA11 ALT2=FTM1_CH5 ATL3=LPUART0_RX ALT4=FXIO_D1 ALT5= ALT6= ALT7= { GPIOA, PORTA, 12, IRQ_DIS, 0, ALT0, DSE_HI, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP, 0 }, //LNDSV 90 PTA12 Def=ADC2_SE5 ALT0=ADC2_SE5 ALT1=PTA12 ALT2=FTM1_CH6 ATL3=CAN1_RX ALT4=LPI2C1_SDAS ALT5= ALT6= ALT7= { GPIOA, PORTA, 13, IRQ_DIS, 0, ALT0, DSE_HI, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP, 0 }, //SLNDV 89 PTA13 Def=ADC2_SE4 ALT0=ADC2_SE4 ALT1=PTA13 ALT2=FTM1_CH7 ATL3=CAN1_TX ALT4=LPI2C1_SCLS ALT5= ALT6= ALT7= { GPIOA, PORTA, 14, IRQ_DIS, 0, ALT0, DSE_HI, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP, 0 }, //- 88 PTA14 Def=DISABLED ALT0= ALT1=PTA14 ALT2=FTM0_FLT0 ATL3=FTM3_FLT1 ALT4=EWM_IN ALT5= ALT6=FTM1_FLT0 ALT7=BUSOUT { GPIOA, PORTA, 15, IRQ_DIS, 0, ALT0, DSE_HI, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP, 0 }, //SLNDI 83 PTA15 Def=ADC1_SE12 ALT0=ADC1_SE12 ALT1=PTA15 ALT2=FTM1_CH2 ATL3=LPSPI0_PCS3 ALT4= ALT5= ALT6= ALT7= { GPIOA, PORTA, 16, IRQ_DIS, 0, ALT0, DSE_HI, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP, 0 }, //CANCTRL 82 PTA16 Def=ADC1_SE13 ALT0=ADC1_SE13 ALT1=PTA16 ALT2=FTM1_CH3 ATL3=LPSPI1_PCS2 ALT4= ALT5= ALT6= ALT7= { GPIOA, PORTA, 17, IRQ_DIS, 0, ALT0, DSE_HI, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP, 0 }, //- 62 PTA17 Def=DISABLED ALT0= ALT1=PTA17 ALT2=FTM0_CH6 ATL3=FTM3_FLT0 ALT4=EWM_OUT_b ALT5= ALT6= ALT7= { GPIOB, PORTB, 0, IRQ_DIS, 0, ALT0, DSE_HI, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP, 0 }, //INESC1 54 PTB0 Def=ADC0_SE4 ALT0=ADC0_SE4 ALT1=PTB0 ALT2=LPUART0_RX ATL3=LPSPI0_PCS0 ALT4=LPTMR0_ALT3 ALT5=PWT_IN3 ALT6= ALT7= { GPIOB, PORTB, 1, IRQ_DIS, 0, ALT0, DSE_HI, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP, 0 }, //INESC2 53 PTB1 Def=ADC0_SE5 ALT0=ADC0_SE5 ALT1=PTB1 ALT2=LPUART0_TX ATL3=LPSPI0_SOUT ALT4=TCLK0 ALT5= ALT6= ALT7= { GPIOB, PORTB, 2, IRQ_DIS, 0, ALT0, DSE_HI, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP, 0 }, //INVPWR 48 PTB2 Def=ADC0_SE6 ALT0=ADC0_SE6 ALT1=PTB2 ALT2=FTM1_CH0 ATL3=LPSPI0_SCK ALT4=FTM1_QD_PHB ALT5= ALT6=TRGMUX_IN3 ALT7= { GPIOB, PORTB, 3, IRQ_DIS, 0, ALT0, DSE_HI, OD_DIS, PFE_DIS, PUPD_DIS, GP_INP, 0 }, //IN5V 47 PTB3 Def=ADC0_SE7 ALT0=ADC0_SE7 ALT1=PTB3 ALT2=FTM1_CH1 ATL3=LPSPI0_SIN ALT4=FTM1_QD_PHA ALT5= ALT6=TRGMUX_IN2 ALT7= { GPIOB, PORTB, 4, IRQ_DIS, 0, ALT1, DSE_HI, OD_DIS, PFE_DIS, PUPD_DIS, GP_OUT, 0 }, //SEG_A 28 PTB4 Def=ACMP1_IN2 ALT0=ACMP1_IN2 ALT1=PTB4 ALT2=FTM0_CH4 ATL3=LPSPI0_SOUT ALT4= ALT5= ALT6=TRGMUX_IN1 ALT7= Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 20 декабря, 2018 Опубликовано 20 декабря, 2018 · Жалоба 11 часов назад, Arlleex сказал: Возвращаясь к теме. Теоретически (и практически) возможно ли каким-то образом сделать макрос, который будет формировать другой макрос? Нет. Но в плюсах можно использовать практически с той же семантикой constexpr вместо определяемого макроса. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 234 20 декабря, 2018 Опубликовано 20 декабря, 2018 · Жалоба 1 час назад, AlexandrY сказал: Все можно решить простыми таблицами, где собрана абсолютно вся информация о всех пинах. Даже перечислены все альтернативные функции на пине, имена цепей на схеме, номера пинов на процессоре и номера пинов на процессорном модуле. Эт нужно тем кто занимается отладкой железа и программированием одновременно. Такая таблица - это для конфигурирования пинов. У меня это так и делается примерно аналогично: Спойлер //PINSEL_I() - цифровой вход; 1й аргумент - имя пина, 2й арг. - наличие аппаратной input-функции и её имя, 3й - скорострельность пина, 4й - наличие и направление подтяжки или инверсии; //PINSEL_O() - цифровой выход; 1й аргумент - имя пина, 2й арг. - имя функции пина, 3й арг. - наличие аппаратной output-функции и её имя, 3й - скорострельность пина, 4й и 5й - наличие open-drain и/или начального значения 0/1 (для GPIO); //PINSEL_A() - аналоговая нога АЦП; 1й аргумент - имя пина, 2й арг. - группа/канал АЦП. static TPinSel const tPinmux[] = { PINSEL_I(PIN_ENET_CLK, NONE, MEDIUM), PINSEL_O(PIN_ENET_TX_EN, GPIO, NONE, MEDIUM, SET0), PINSEL_O(PIN_ENET_TXD0, GPIO, NONE, MEDIUM), PINSEL_O(PIN_ENET_TXD1, GPIO, NONE, MEDIUM), PINSEL_I(PIN_ENET_MD, NONE, MEDIUM, PU), PINSEL_O(PIN_ENET_MDC, GPIO, NONE, MEDIUM, SET0), PINSEL_I(PIN_ENET_CRS_DV, NONE, MEDIUM), PINSEL_I(PIN_ENET_RXER, NONE, MEDIUM), PINSEL_I(PIN_ENET_RXD0, NONE, MEDIUM), PINSEL_I(PIN_ENET_RXD1, NONE, MEDIUM), PINSEL_I(PIN_SERV_RX, NONE, STRONG_SOFT, PU), PINSEL_O(PIN_SERV_TX, GPIO, NONE, STRONG_SOFT, SET1), PINSEL_I(PIN_SDP_RX, NONE, STRONG_SOFT, PD), PINSEL_O(PIN_SDP_TX, GPIO, NONE, STRONG_SOFT, SET0), PINSEL_O(PIN_SDP_TERM, GPIO, NONE, WEAK), PINSEL_I(PIN_MRAM_MISO, NONE, STRONG_SOFT, PU), PINSEL_O(PIN_MRAM_MOSI, GPIO, NONE, STRONG_SOFT), PINSEL_O(PIN_MRAM_SCLK, GPIO, NONE, STRONG_SOFT, SET1), PINSEL_O(PIN_MRAM_CS, GPIO, NONE, STRONG_SOFT, SET1), PINSEL_O(PIN_DF_SCLK, GPIO, NONE, STRONG_SOFT, SET1), PINSEL_O(PIN_DF_MOSI, GPIO, NONE, STRONG_SOFT), PINSEL_I(PIN_DF_MISO, NONE, STRONG_SOFT, PU), PINSEL_O(PIN_DF_CS0, GPIO, NONE, STRONG_SOFT, SET1), PINSEL_O(PIN_DF_CS1, GPIO, NONE, STRONG_SOFT, SET1), PINSEL_I(PIN_CAN_INT_RX, NONE, STRONG_SOFT), PINSEL_O(PIN_CAN_INT_TX, fCAN(nCAN_int, TXD), NONE, STRONG_SOFT), PINSEL_O(PIN_CAN_INT_OFF, GPIO, NONE, WEAK, SET1), PINSEL_O(PIN_CAN_INT_TERM, GPIO, NONE, WEAK), PINSEL_I(PIN_CAN_EXT_RX, NONE, STRONG_SOFT), PINSEL_O(PIN_CAN_EXT_TX, fCAN(nCAN_ext, TXD), NONE, STRONG_SOFT), PINSEL_O(PIN_CAN_EXT_OFF, GPIO, NONE, WEAK, SET1), PINSEL_O(PIN_CAN_EXT_TERM, GPIO, NONE, WEAK), PINSEL_O(PIN_TERM_EN, GPIO, NONE, WEAK, SET0), PINSEL_O(PIN_LED, GPIO, NONE, STRONG_SOFT), PINSEL_O(PIN_TST0_10, GPIO, NONE, STRONG_SOFT), PINSEL_O(PIN_TST0_14, GPIO, NONE, STRONG_SOFT), PINSEL_I(PIN_MLX1, NONE, STRONG_SOFT), PINSEL_I(PIN_MLX2, NONE, STRONG_SOFT), PINSEL_O(PIN_SYNC_33, GPIO, NONE, WEAK, SET0), PINSEL_I(PIN_UVWfault, NONE, STRONG_SOFT, PU), PINSEL_O(PIN_USWL, GPIO, NONE, STRONG_SOFT, SET0), PINSEL_O(PIN_USWH, GPIO, NONE, STRONG_SOFT, SET0), PINSEL_O(PIN_VSWL, GPIO, NONE, STRONG_SOFT, SET0), PINSEL_O(PIN_VSWH, GPIO, NONE, STRONG_SOFT, SET0), PINSEL_O(PIN_WSWL, GPIO, NONE, STRONG_SOFT, SET0), PINSEL_O(PIN_WSWH, GPIO, NONE, STRONG_SOFT, SET0), PINSEL_I(PIN_UFAULTH, NONE, STRONG_SOFT, PD), PINSEL_I(PIN_UFAULTL, NONE, STRONG_SOFT, PD), PINSEL_I(PIN_VFAULTH, NONE, STRONG_SOFT, PD), PINSEL_I(PIN_VFAULTL, NONE, STRONG_SOFT, PD), PINSEL_I(PIN_WFAULTH, NONE, STRONG_SOFT, PD), PINSEL_I(PIN_WFAULTL, NONE, STRONG_SOFT, PD), PINSEL_O(PIN_UVWEN, GPIO, NONE, STRONG_SOFT, SET1), PINSEL_O(PIN_DSDMOD, fCCU_OUT(nCCU_dsd_mod, PIN_DSDMOD), NONE, STRONG_SHARP), PINSEL_I(PIN_FAN3, NONE, WEAK, PU), PINSEL_I(PIN_FAN2, NONE, WEAK, PU), PINSEL_I(PIN_FAN1, NONE, WEAK, PU), PINSEL_O(PIN_DSD_CARRIER_N, DSD_CGPWMN, NONE, STRONG_SOFT), PINSEL_O(PIN_DSD_CARRIER_P, DSD_CGPWMP, NONE, STRONG_SOFT), PINSEL_I(PIN_DSD_SIN_DATA, NONE, STRONG_SOFT, PU), PINSEL_I(PIN_DSD_COS_DATA, NONE, STRONG_SOFT, PU), PINSEL_I(PIN_DSD_SIN_MCLK, NONE, STRONG_SOFT, PU), PINSEL_I(PIN_DSD_COS_MCLK, NONE, STRONG_SOFT, PU), PINSEL_O(PIN_DIFFRSV, GPIO, NONE, STRONG_SOFT), PINSEL_I(PIN_INPRND1, NONE, STRONG_SOFT), PINSEL_I(PIN_INPRND2, NONE, STRONG_SOFT), PINSEL_I(PIN_INDIGITAL, NONE, STRONG_SOFT), PINSEL_I(PIN_INHVON, NONE, STRONG_SOFT), PINSEL_O(PIN_TST0_11, GPIO, NONE, STRONG_SOFT), PINSEL_O(PIN_TST0_9, GPIO, NONE, STRONG_SOFT), PINSEL_O(PIN_TST3_2, GPIO, NONE, STRONG_SOFT), PINSEL_O(PIN_REVLAMP, GPIO, NONE, STRONG_SOFT), PINSEL_I(PIN_SW8_MISO, NONE, STRONG_SOFT, PU), PINSEL_O(PIN_SW8_MOSI, GPIO, NONE, STRONG_SOFT), PINSEL_O(PIN_SW8_SCLK, GPIO, NONE, STRONG_SOFT, SET0), PINSEL_O(PIN_SW8_CS, GPIO, NONE, STRONG_SOFT, SET1), PINSEL_O(PIN_I2C_SCL, GPIO, NONE, STRONG_SOFT, OD), PINSEL_O(PIN_I2C_SDA, GPIO, NONE, STRONG_SOFT, OD), PINSEL_A(PIN_ADC_T1NTC, nADC_t1ntc), PINSEL_A(PIN_ADC_T2NTC, nADC_t2ntc), PINSEL_A(PIN_ADC_T3NTC, nADC_t3ntc), PINSEL_A(PIN_ADC_T4NTC, nADC_t4ntc), PINSEL_A(PIN_ADC_T5PT, nADC_t5pt), PINSEL_A(PIN_ADC_T6PT, nADC_t6pt), PINSEL_A(PIN_ADC_T7IRED, nADC_t7ired), PINSEL_A(PIN_ADC_TSWU, nADC_tswU), PINSEL_A(PIN_ADC_TSWV, nADC_tswV), PINSEL_A(PIN_ADC_TSWW, nADC_tswW), PINSEL_A(PIN_ADC_TPCB, nADC_tpcb), PINSEL_A(PIN_ADC_VOLT10, nADC_volt10), PINSEL_A(PIN_ADC_VOLT12, nADC_volt12), PINSEL_A(PIN_ADC_VOLT14, nADC_volt14), PINSEL_A(PIN_ADC_VOLT5S1, nADC_volt5S1), PINSEL_A(PIN_ADC_VOLT5S2, nADC_volt5S2), PINSEL_A(PIN_ADC_ACCFULL, nADC_accFull), PINSEL_A(PIN_ADC_ACCHALF, nADC_accHalf), PINSEL_A(PIN_ADC_BRAKE, nADC_brake), PINSEL_A(PIN_ADC_FREAR, nADC_frear), PINSEL_A(PIN_ADC_HSDIAG, nADC_hsDiag), PINSEL_A(PIN_ADC_AMPHV, nADC_ampHv), PINSEL_A(PIN_ADC_AMPU, nADC_iu), PINSEL_A(PIN_ADC_AMPV, nADC_iv), PINSEL_A(PIN_ADC_AMPW, nADC_iw), PINSEL_A(PIN_ADC_VOLTH, nADC_uh) }; А также в каждом драйвере устройства есть аналогичная таблица конфигурирования пинов. Например для SPI-FLASH (два CS): Спойлер static TPinSel const tPinmux[] = { PINSEL_I(PIN_DF_MISO, concat(U, USIC_UNIT(nUSIC_df), C, USIC_CH(nUSIC_df), _DATA), STRONG_SOFT, PU), PINSEL_O(PIN_DF_MOSI, concat(U, USIC_UNIT(nUSIC_df), C, USIC_CH(nUSIC_df), _DOUT0), concat(U, USIC_UNIT(nUSIC_df), C, USIC_CH(nUSIC_df), _DATA), STRONG_SOFT), PINSEL_O(PIN_DF_SCLK, concat(U, USIC_UNIT(nUSIC_df), C, USIC_CH(nUSIC_df), _SCLKOUT), NONE, STRONG_SHARP, SET1), PINSEL_O(PIN_DF_CS0, concat(U, USIC_UNIT(nUSIC_df), C, USIC_CH(nUSIC_df), _SELO, SELO0), NONE, STRONG_SOFT, SET1), PINSEL_O(PIN_DF_CS1, concat(U, USIC_UNIT(nUSIC_df), C, USIC_CH(nUSIC_df), _SELO, SELO1), NONE, STRONG_SOFT, SET1) }; Но сами имена пинов задаются макросами в .h-файле. Как и последующие операции с ними: установка/сброс/чтение/... GPIO-ного пина; или задание задефайненного макросом имени пина при выборе его в качестве входа/выхода для какой-то функции какого-то из периферийных блоков. В .h-файле конфига платы делается распределение всех ресурсов платы и МК (пинов, периферийных блоков (таймеров, последовательных каналов, ...), сигналов прерываний (service request), каналов DMA, каналов АЦП и т.п.): Спойлер //Распределение USIC-ов #define nUSIC_mram 1, 0 //номер USIC/канала для SPI-MRAM #define nUSIC_df 2, 1 //номер USIC/канала для SPI-FLASH #define nUSIC_sdp 0, 1 //номер USIC/канала для SDP //Распределение CCU-таймеров/слайсов #define nCCU_sdp 41, 0 //номер таймера/слайса защёлкивания момента начала приёма кадра по SDP #define nCCU_mlx1 40, 2 //Use for measurement of T rotor PWM signal from Melexis IR temperature sensor MLX90614 (first) #define nCCU_mlx2 42, 0 //Use for measurement of T rotor PWM signal from Melexis IR temperature sensor MLX90614 (second) #define nCCU_adc_fast 81, 2 //Triggers fast ADC //Распределение GPDMA lines (DMALINEx_...) для DLR. Каналы распределяются так же. #define nDMALINE_adc_fast 0 #define nDMALINE_adc_slow 1 #define nDMALINE_mram_RX 4 #define nDMALINE_mram_TX 6 #define nDMALINE_df_RX 8 #define nDMALINE_df_TX 9 //Распределение Service Requests для всех CCU. Каждый элемент также нужно добавить в список CHK_SRCCU! #define nCCU_SR_sdp_START 0, nCCU_phaseW //SR для старта передачи по SDP ///временно #define nCCU_SR_sdp_TX 1, nCCU_phaseW //SR от одного из nCCU_phaseU/nCCU_phaseV/nCCU_phaseW к DX2 в nCCU_sdp для старта передачи USIC //Распределение Service Requests для USIC. Каждый элемент также нужно добавить в список CHK_SRUSIC! #define nUSIC_SR_sdp_RX 0, nUSIC_sdp #define nUSIC_SR_sdp_ERR 1, nUSIC_sdp #define nUSIC_SR_mram_RX 0, nUSIC_mram #define nUSIC_SR_mram_TX 1, nUSIC_mram #define nUSIC_SR_mram_ERR 2, nUSIC_mram #define nUSIC_SR_df_RX 0, nUSIC_df #define nUSIC_SR_df_TX 1, nUSIC_df #define nUSIC_SR_df_ERR 2, nUSIC_df //Распределение каналов ADC (группа, канал_внутри_группы) #define nADC_t1ntc 0, 0 //Resistive thermal sensor 1 #define nADC_t2ntc 2, 2 //Resistive thermal sensor 2 #define nADC_t3ntc 1, 2 //Resistive thermal sensor 3 //Распределение пинов #define PIN_SDP_RX 2, 5 #define PIN_SDP_TX 3, 13 #define PIN_SDP_TERM 2, 4 #define PIN_MRAM_MOSI 2, 14 //SCLK для nUSIC_mram #define PIN_MRAM_MISO 2, 15 //MOSI для nUSIC_mram #define PIN_MRAM_SCLK 5, 8 //MISO для nUSIC_mram #define PIN_MRAM_CS 5, 11 //CS для MR25H10 на nUSIC_mram #define PIN_DF_SCLK 3, 6 //SCLK для nUSIC_df #define PIN_DF_MOSI 4, 7 //MOSI для nUSIC_df #define PIN_DF_MISO 4, 6 //MISO для nUSIC_df #define PIN_DF_CS0 4, 1 //CS0 для S70FL01GS (мл.половина) на nUSIC_df #define PIN_DF_CS1 4, 3 //CS1 для S70FL01GS (ст.половина) на nUSIC_df Таким образом: чтобы перебросить какую-то функцию например с одного таймера на другой, мне нужно в этом файле всего-лишь поменять назначения таймеров, также другие связанные с ним ресурсы (если используются). Только в одном файле. Остальные исходники пересоберутся автоматом - все переназначится автоматом (вектора прерываний, имена периферии - всё макросами переназначится на другие периферийные блоки). Также макросы у меня проверяют на допустимость заданную комбинацию ресурсов и, если она недопустимая, или если есть конфликт по занятым ресурсам - будет ошибка компиляции. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexandrY 3 20 декабря, 2018 Опубликовано 20 декабря, 2018 · Жалоба 56 minutes ago, jcxz said: Такая таблица - это для конфигурирования пинов. У меня это так и делается примерно аналогично: В .h-файле конфига платы делается распределение всех ресурсов платы и МК (пинов, периферийных блоков (таймеров, последовательных каналов, ...), сигналов прерываний (service request), каналов DMA, каналов АЦП и т.п.): Тут самой главное не в том есть это или нет, а то каким способом это написано. Автоматизация генерации сорсов - вот показатель. Только автоматизация гарантирует безошибочность. Скажем у меня и функции обращения к пинам на полуавтомате генерятся: int32_t Get_LEDESC1 (void) { return (PTA_BASE_PTR->PDIR & BIT( 4)) >> 4;} int32_t Get_LEDESC2 (void) { return (PTA_BASE_PTR->PDIR & BIT( 5)) >> 5;} int32_t Get_LEDESC3 (void) { return (PTA_BASE_PTR->PDIR & BIT( 6)) >> 6;} int32_t Get_LEDESC4 (void) { return (PTA_BASE_PTR->PDIR & BIT( 7)) >> 7;} int32_t Get_LEDESC5 (void) { return (PTA_BASE_PTR->PDIR & BIT( 8)) >> 8;} int32_t Get_LEDESC7 (void) { return (PTA_BASE_PTR->PDIR & BIT( 9)) >> 9;} int32_t Get_LEDESC8 (void) { return (PTA_BASE_PTR->PDIR & BIT(26)) >> 26;} int32_t Get_LEDESC9 (void) { return (PTA_BASE_PTR->PDIR & BIT(27)) >> 27;} int32_t Get_STOPL_O (void) { return (PTA_BASE_PTR->PDIR & BIT(28)) >> 28;} int32_t Get_LEDCAN0 (void) { return (PTB_BASE_PTR->PDIR & BIT( 8)) >> 8;} int32_t Get_I2CEXT_EN (void) { return (PTC_BASE_PTR->PDIR & BIT( 5)) >> 5;} int32_t Get_LCD_RST (void) { return (PTC_BASE_PTR->PDIR & BIT(12)) >> 12;} int32_t Get_LCD_RS (void) { return (PTC_BASE_PTR->PDIR & BIT(13)) >> 13;} int32_t Get_BMI160_EN (void) { return (PTC_BASE_PTR->PDIR & BIT(18)) >> 18;} Макросы вызывают неоходимость в дополнительных кликах при отладке и анализе чтобы вспомнить их контекст, так же и с классами и шаблонами. Прямые функции сильно экономят время при отладке поскольку разгружается память и экономятся действия. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 178 20 декабря, 2018 Опубликовано 20 декабря, 2018 · Жалоба 2 часа назад, jcxz сказал: Из этой фразы толком не понятно что именно нужно. Допустим, есть структура описания регистров периферии. И нужно описывать каждый бит каждого регистра. Обычно это что-то вроде: typedef struct { #define SCU_GCR_SWIMDIS 0x01 #define SCU_GCR_AL 0x02 ... u8 GCR; }sSCU; Так вот, хотелось бы сделать этакий макрос, в который можно было бы просто записать названия битов (SWIMDIS, AL, и т.д.), а определения формировались сами с соответствующими значениями: SCU_GCR_SWIMDIS, равный 0x01, SCU_GCR_AL, равный 0x02 и т.д. Таким образом, вместо описания всех битов отдельным #define-ом, можно было бы написать в одну строку: #define ХИТРЫЙ_МАКРОС(REG_NAME, START_VALUE, BIT_LIST) ... ... typedef struct { ХИТРЫЙ_МАКРОС(SCU_GCR, 0x1, SWIMDIS, AL) // -> #define SCU_GCR_SWIMDIS 0x01, #define SCU_GCR_AL 0x02 u8 GCR; }sSCU; Смотрел тут статейку, народ по-своему извращается. Но, ИМХО, там намудрено, у меня задача попроще. Но не уверен, что она решается в том виде, в котором я ее тут показал Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 234 20 декабря, 2018 Опубликовано 20 декабря, 2018 · Жалоба 8 минут назад, AlexandrY сказал: Макросы вызывают неоходимость в дополнительных кликах при отладке и анализе чтобы вспомнить их контекст Так делайте "говорящие" имена. 7 минут назад, Arlleex сказал: Так вот, хотелось бы сделать этакий макрос, в который можно было бы просто записать названия битов (SWIMDIS, AL, и т.д.), а определения формировались сами с соответствующими значениями: SCU_GCR_SWIMDIS, равный 0x01, SCU_GCR_AL, равный 0x02 и т.д. Так можно сделать, только назначать через enum. Если enum подходит. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexandrY 3 20 декабря, 2018 Опубликовано 20 декабря, 2018 · Жалоба 13 minutes ago, jcxz said: Так делайте "говорящие" имена. Имена несут в себе опасность попадания в социо-культурную ловушку. Вчера слово "новичок" значило одно, а завтра значит уже совершенно другое. Если говорить о программерах, то здесь сбить смысл имен может просто переход на другой фреймворк. Скажем в MODBUS биты называются идиотским термином coil. Вот возьми вы такой термин за правило и вас все станут ненавидеть. Поэтому в отладчике надо видеть сорсы до самого корня. С макросами , классами и шаблонами это делать сильно труднее. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 24 20 декабря, 2018 Опубликовано 20 декабря, 2018 · Жалоба Quote С макросами , классами и шаблонами это делать сильно труднее. Это сугубо индивидуально, равно как, например, предпочтения в пище/ Но существуют некие тенденции, они формируются на основе интересов, опыта и знаний большинства. Если код пишется исключительно для себя любимого, то можно как угодно писать, если же для людей, то следует ориентироваться на эти самые тенденции. Ведь, если вдруг вздумаете выйти на улицу без одежды, голышом, то соседи вызовут полицию. Доказывать свою "правоту" в такой ситуации - бессмысленно Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться