ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
21 ноября
965488 Топик полностью
evgeniy1294 (17.12.2019 10:00, просмотров: 455) ответил Chum_A на Тоже хочу бутылку :). Наметилась дискуссия (см. 1-ю ссылку) "о роли и месте С++". Прошу знатоков и прежде всего fk0 прокомментировать материал (см. 2-ю ссылку). Моё ИМХО, что это как-то уже слишком заабстрагировалось, "или нет?" (с).
Оно?  template<UartList uart, uint32_t Fclk, uint32_t baudrate, DataBits databits, Parity parity, StopBit stb, Function func, Interrupt irq, FifoThreshold rxfifo, FifoThreshold txfifo, bool use_rxdma, bool use_txdma> struct UART { static constexpr UartList uart_ = uart; static constexpr uint32_t Fclk_ = Fclk; static constexpr uint32_t baudrate_ = baudrate; static constexpr Parity parity_ = parity; static constexpr StopBit stb_ = stb; static constexpr DataBits databits_ = databits; static constexpr Function func_ = func; static constexpr Interrupt irq_ = irq; static constexpr FifoThreshold rxfifo_ = rxfifo; static constexpr FifoThreshold txfifo_ = txfifo; static constexpr bool use_rxdma_ = use_rxdma; static constexpr bool use_txdma_ = use_txdma; static constexpr uint32_t timeout = static_cast<uint32_t>((static_cast<float>(Fclk)/static_cast<float>(baudrate))*32.0f); static __forceinline void Init() { UART_TypeDef* U{reinterpret_cast<UART_TypeDef*>(uart_)}; constexpr float div = static_cast<float>(Fclk_)/(static_cast<float>(16*baudrate_)); static_assert ((div > 1.0f)&&(div < 65535.0f), "Bad UART clk divider"); constexpr uint16_t ibrd = static_cast<uint16_t>(div); constexpr uint8_t fbrd = static_cast<uint8_t>((div - static_cast<float>(ibrd))*64.0f+0.5f)&0b111111; static_assert ((ibrd != 0xFFFF)&&(fbrd != 0), "Illegal DIVFRAC"); // LCRH Register constexpr uint32_t PEN = (parity_ != Parity::none) ? 1 << 1 : 0; constexpr uint32_t EPS = (parity_ == Parity::even) ? 1 << 2 : 0; constexpr uint32_t STP2 = (stb_ == StopBit::_2) ? 1 << 3 : 0; constexpr uint32_t FEN = ((rxfifo_ != FifoThreshold::unused)&& (txfifo_ != FifoThreshold::unused)) ? 1 << 4 : 0; constexpr uint32_t WLEN = static_cast<uint32_t>(databits_) << 5; constexpr uint32_t SPS = (parity_ == Parity::stick) ? 1 << 7 : 0; constexpr uint32_t lcrh = PEN | EPS | STP2 | FEN | WLEN | SPS; // IFLS Register constexpr uint32_t RXSEL = (rxfifo_ != FifoThreshold::unused) ? static_cast<uint32_t>(rxfifo) << 3 : 0; constexpr uint32_t TXSEL = (txfifo_ != FifoThreshold::unused) ? static_cast<uint32_t>(txfifo) : 0; constexpr uint32_t ifls = TXSEL | RXSEL; // DMACTL constexpr uint32_t RXDMAE = (use_rxdma_) ? 1 << 0 : 0; constexpr uint32_t TXDMAE = (use_txdma_) ? 1 << 1 : 0; constexpr uint32_t dmactl = RXDMAE | TXDMAE; // Config UART U->CTL = static_cast<uint32_t>(func_) | 0b01; U->IBRD = ibrd; U->FBRD = fbrd; U->LCRH = lcrh; U->IFLS = ifls; U->IMSC = static_cast<uint32_t>(irq_); U->ICR = static_cast<uint32_t>(Interrupt::all); U->DMACTL = dmactl; } }; int main() { using U = UART<UartList::_0, 48'000'000, 115200, DataBits::_8, Parity::none, StopBit::_1, Function::rxen | Function::txen, Interrupt::end_of_transmission | Interrupt::receive_timeout | Interrupt::receive_complete, FifoThreshold::_1_8, FifoThreshold::_4_8, false, false>; U::Init(); ... } Вот только смысл, который я вкладываю в подобное несколько отличается от описанного в статье на хабре. Я просто хочу получить компактный результат с проверками на этапе компиляции, автор статьи с хабра заморочился на столько, что сделал абстракции над отдельными битами! (он видимо не в курсе что под некоторые чипы, те же cc1352, вендоры не поставляют svd-файлы) Потому как если бит RO, то писать в него нельзя, нужно же максимально защитить пользователя либины. А если тупой программист будет писать в порт, настроенный на вход? Это же ужас! А то, что такие проблемы составляют 0.1% от общего числа и вычищаются почти сразу никого не волнует. Нужно защитить тупого программиста от тупых ошибок. Парень молодец, сам себе придумал проблему, сам её решил.