2024-03-02 19:33:18 +01:00
|
|
|
#include "system.h"
|
2024-03-07 12:23:44 +01:00
|
|
|
#include "usart.h"
|
|
|
|
static Usart * pInstance = nullptr;
|
2024-03-02 19:33:18 +01:00
|
|
|
static constexpr unsigned HCLK = 48'000'000u;
|
2024-03-07 12:23:44 +01:00
|
|
|
|
2024-03-02 19:33:18 +01:00
|
|
|
extern "C" void USART1_IRQHandler (void) __attribute__((interrupt));
|
|
|
|
void USART1_IRQHandler (void) {
|
|
|
|
if (pInstance) pInstance->irq();
|
|
|
|
};
|
|
|
|
|
2024-03-07 12:23:44 +01:00
|
|
|
Usart::Usart(const uint32_t _baud) noexcept : BaseLayer (), tx_ring () {
|
2024-03-02 19:33:18 +01:00
|
|
|
pInstance = this;
|
|
|
|
// 1. Clock Enable
|
|
|
|
RCC.APB2PCENR.modify([](RCC_Type::APB2PCENR_DEF & r) -> auto {
|
|
|
|
r.B.USART1EN = SET;
|
|
|
|
r.B.IOPDEN = SET;
|
|
|
|
return r.R;
|
|
|
|
});
|
|
|
|
// 2. GPIO Alternate Config - default TX/PD5, RX/PD6
|
|
|
|
GPIOD.CFGLR.modify([](GPIOA_Type::CFGLR_DEF & r) -> auto {
|
|
|
|
r.B.MODE5 = 1u;
|
|
|
|
r.B.CNF5 = 2u; // or 3u for open drain
|
|
|
|
r.B.MODE6 = 0u;
|
|
|
|
r.B.CNF6 = 1u; // floating input
|
|
|
|
return r.R;
|
|
|
|
});
|
|
|
|
// 4. NVIC
|
|
|
|
NVIC.EnableIRQ (USART1_IRQn);
|
|
|
|
// 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.R = 0;
|
|
|
|
//USART1.CTLR3.B.OVRDIS = SET;
|
|
|
|
const uint32_t tmp = HCLK / _baud;
|
|
|
|
USART1.BRR.R = tmp;
|
|
|
|
USART1.CTLR1.B.UE = SET; // nakonec povolit globálně
|
|
|
|
}
|
2024-03-07 12:23:44 +01:00
|
|
|
void Usart::irq () {
|
2024-03-02 19:33:18 +01:00
|
|
|
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
|
|
|
|
// Předpoklad je half-duplex i.e. RS485, jinak jen zakázat TXEIE
|
|
|
|
rdata = (USART1.DATAR.B.DR); // dummy read
|
|
|
|
USART1.CTLR1.modify([](USART1_Type::CTLR1_DEF & r) -> auto {
|
|
|
|
r.B.RE = SET; // povol prijem
|
|
|
|
r.B.TXEIE = RESET; // je nutné zakázat přerušení od vysílače
|
|
|
|
return r.R;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
2024-03-07 12:23:44 +01:00
|
|
|
uint32_t Usart::Down(const char * data, const uint32_t len) {
|
2024-03-02 19:33:18 +01:00
|
|
|
unsigned n = 0u;
|
|
|
|
for (n=0u; n<len; n++) {
|
|
|
|
if (!tx_ring.Write(data[n])) break;
|
|
|
|
}
|
|
|
|
USART1.CTLR1.modify([](USART1_Type::CTLR1_DEF & r) -> auto {
|
|
|
|
r.B.RE = RESET;
|
|
|
|
r.B.TXEIE = SET; // po povolení přerušení okamžitě přeruší
|
|
|
|
return r.R;
|
|
|
|
});
|
|
|
|
return n;
|
|
|
|
}
|
2024-03-07 12:23:44 +01:00
|
|
|
void Usart::SetRS485 (const bool polarity) const {
|
|
|
|
}
|
|
|
|
void Usart::SetHalfDuplex (const bool on) const {
|
|
|
|
}
|
2024-03-02 19:33:18 +01:00
|
|
|
|