#include "system.h" #include "../common/usart.h" static Usart * pInstance = nullptr; extern "C" { [[gnu::interrupt]] void USART1_IRQHandler (void); }; void USART1_IRQHandler (void) { if (pInstance) pInstance->irq(); }; Usart::Usart(const uint32_t _baud) noexcept : BaseLayer (), tx_ring () { pInstance = this; // 1. Clock Enable RCC.APB2PCENR.modify([](RCC_Type::APB2PCENR_DEF & r) -> auto { r.B.USART1EN = SET; r.B.IOPAEN = SET; //r.B.AFIOEN = SET; // není nutné return r.R; }); // 2. GPIO Alternate Config - default TX/PA9, RX/PA10 GPIOA.CFGHR.modify([](GPIOA_Type::CFGHR_DEF & r) -> auto { r.B.MODE9 = 1u; r.B.CNF9 = 2u; // or 3u for open drain r.B.MODE10 = 0u; r.B.CNF10 = 1u; // floating input return r.R; }); RCC.APB2PRSTR.B.USART1RST = SET; RCC.APB2PRSTR.B.USART1RST = RESET; // 5. USART registry 8.bit bez parity USART1.CTLR1.modify([] (USART1_Type::CTLR1_DEF & r) -> auto { r.B.RE = SET; r.B.TE = SET; r.B.RXNEIE = SET; return r.R; }); USART1.CTLR2.modify ([](USART1_Type::CTLR2_DEF & r) -> auto { r.B.STOP = 0u; return r.R; }); SetBaud(_baud); // NVIC NVIC.EnableIRQ (USART1_IRQn); USART1.CTLR1.B.UE = SET; // nakonec povolit globálně } void Usart::irq () { volatile USART1_Type::STATR_DEF status (USART1.STATR); // načti status přerušení char rdata, tdata; if (status.B.TXE) { // od vysílače if (tx_ring.Read (tdata)) { // pokud máme data USART1.DATAR.B.DR = (uint8_t) tdata; // zapíšeme do výstupu } else { // pokud ne USART1.CTLR1.B.TXEIE = RESET; } } if (status.B.RXNE) { // od přijímače rdata = (USART1.DATAR.B.DR); // načteme data Up (&rdata, 1u); // a pošleme dál } } uint32_t Usart::Down(const char * data, const uint32_t len) { unsigned n = 0u; for (n=0u; n(data); SetBaud(lc->baud); // Pouze změníme rychlost, ostatní parametry ingorujme } return true; // Ostatní IOCtrl zatím nebudeme obsluhovat, je to celkem zbytečné default : break; }; return false; }