Divided USART communication into core and protocol classes

This commit is contained in:
Attila Body 2019-11-07 08:33:48 +01:00
parent 9ff4e76623
commit f0c2ad69c9
7 changed files with 287 additions and 121 deletions

View file

@ -14,19 +14,11 @@ template<typename T> static inline T RoundUpTo4(T input)
return (input + 3) & (((T)-1) - 3);
}
LL_HsUsart::LL_HsUsart(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t streamRx, uint32_t streamTx)
: m_usart(usart)
, m_rxDma(dma, streamRx)
, m_txDma(dma, streamTx)
: LL_UsartCore(usart, dma, streamRx, streamTx)
{
LL_CrcHandler::Instance().AttachSlot(m_crcSlot);
LL_DMA_EnableIT_TC(dma, streamRx);
LL_DMA_EnableIT_TE(dma, streamRx);
LL_DMA_EnableIT_TC(dma, streamTx);
LL_DMA_EnableIT_TE(dma, streamTx);
LL_USART_EnableIT_IDLE(usart);
memset(&m_stats, 0, sizeof(m_stats));
}
@ -119,11 +111,7 @@ void LL_HsUsart::PostPacket(uint8_t const *payload, uint8_t length, bool waitFor
while(waitForCrcQueue && LL_CrcHandler::Instance().IsQueued(m_crcSlot, 0));
LL_DMA_ConfigAddresses(m_txDma.GetDma(), m_txDma.GetStream(), reinterpret_cast<uint32_t>(&m_txBuffer.packet),
LL_USART_DMA_GetRegAddr(m_usart), LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
LL_DMA_SetDataLength(m_txDma.GetDma(), m_txDma.GetStream(), m_txBuffer.requestedLength);
LL_USART_EnableDMAReq_TX(m_usart);
LL_DMA_EnableStream(m_txDma.GetDma(), m_txDma.GetStream());
SetupTransmit(&m_txBuffer.packet, m_txBuffer.requestedLength);
++m_stats.sent;
}
@ -131,67 +119,87 @@ void LL_HsUsart::PostPacket(uint8_t const *payload, uint8_t length, bool waitFor
void LL_HsUsart::SetupReceive()
{
int packetIndex = m_rxBufferSelector;
LL_DMA_ConfigAddresses(m_rxDma.GetDma(), m_rxDma.GetStream(), LL_USART_DMA_GetRegAddr(m_usart),
reinterpret_cast<uint32_t>(&m_rxBuffers[packetIndex]), LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
m_rxBuffers[packetIndex].requestedLength = sizeof(m_rxBuffers[packetIndex].packet);
LL_DMA_SetDataLength(m_rxDma.GetDma(), m_rxDma.GetStream(), m_rxBuffers[packetIndex].requestedLength); // payload already have extra room for hash
LL_USART_EnableDMAReq_RX(m_usart);
LL_USART_ClearFlag_ORE(m_usart);
LL_DMA_EnableStream(m_rxDma.GetDma(), m_rxDma.GetStream());
m_rxBuffers[m_rxBufferSelector].requestedLength = sizeof(m_rxBuffers[m_rxBufferSelector].packet);
LL_UsartCore::SetupReceive(&m_rxBuffers[m_rxBufferSelector], sizeof(m_rxBuffers[m_rxBufferSelector].packet));
}
void LL_HsUsart::UsartIrq(void)
void LL_HsUsart::ReceiverIdle(void)
{
if(LL_USART_IsActiveFlag_IDLE(m_usart) && LL_USART_IsEnabledIT_IDLE(m_usart)) { // receiver idle
LL_USART_ClearFlag_IDLE(m_usart);
uint16_t rcvdLen = m_rxBuffers[m_rxBufferSelector].requestedLength - LL_DMA_GetDataLength(m_rxDma.GetDma(), m_rxDma.GetStream());
if(rcvdLen >= sizeof(PacketHeader)) {
if(CheckHeader(m_rxBuffers[m_rxBufferSelector].packet.header)) {
if(rcvdLen >= sizeof(PacketHeader) +
RoundUpTo4((uint16_t)m_rxBuffers[m_rxBufferSelector].packet.header.payloadLength)
+ sizeof(uint32_t))
LL_DMA_DisableStream(m_rxDma.GetDma(), m_rxDma.GetStream());
else
++m_stats.premature_payload;
} else {
m_rxBuffers[m_rxBufferSelector].error = 1;
uint16_t rcvdLen = m_rxBuffers[m_rxBufferSelector].requestedLength - LL_DMA_GetDataLength(m_rxDma.GetDma(), m_rxDma.GetStream());
if(rcvdLen >= sizeof(PacketHeader)) {
if(CheckHeader(m_rxBuffers[m_rxBufferSelector].packet.header)) {
if(rcvdLen >= sizeof(PacketHeader) +
RoundUpTo4((uint16_t)m_rxBuffers[m_rxBufferSelector].packet.header.payloadLength)
+ sizeof(uint32_t))
LL_DMA_DisableStream(m_rxDma.GetDma(), m_rxDma.GetStream());
}
} else
++m_stats.premature_hdr;
}
else if(LL_USART_IsActiveFlag_TC(m_usart) && LL_USART_IsEnabledIT_TC(m_usart)) { // transmission complete
LL_USART_DisableIT_TC(m_usart);
LL_USART_DisableDirectionTx(m_usart); // enforcing an idle frame
LL_USART_EnableDirectionTx(m_usart);
m_txBuffer.busy = 0;
}
else
++m_stats.premature_payload;
} else {
m_rxBuffers[m_rxBufferSelector].error = 1;
LL_DMA_DisableStream(m_rxDma.GetDma(), m_rxDma.GetStream());
}
} else
++m_stats.premature_hdr;
}
void LL_HsUsart::RxDmaIrq()
void LL_HsUsart::TransmissionComplete(void)
{
LL_USART_DisableDirectionTx(m_usart); // enforcing an idle frame
LL_USART_EnableDirectionTx(m_usart);
m_txBuffer.busy = 0;
}
void LL_HsUsart::RxDmaTransferComplete(void)
{
if(CheckHeader(m_rxBuffers[m_rxBufferSelector].packet.header))
LL_CrcHandler::Instance().Enqueue(m_crcSlot, 1,
&m_rxBuffers[m_rxBufferSelector].packet,
sizeof(PacketHeader) + RoundUpTo4((uint16_t)m_rxBuffers[m_rxBufferSelector].packet.header.payloadLength),
this, m_rxBufferSelector);
else {
++m_stats.hdrError;
m_rxBuffers[m_rxBufferSelector].error = true;
}
SwitchRxBuffers();
}
void LL_HsUsart::RxDmaHalfTransfer(void)
{
}
void LL_HsUsart::RxDmaError(LL_DmaHelper::DmaErrorType reason)
{
m_rxBuffers[m_rxBufferSelector].error = 1;
++m_stats.rxDmaError;
SwitchRxBuffers();
}
void LL_HsUsart::TxDmaTransferComplete(void)
{
LL_USART_EnableIT_TC(m_usart);
LL_DMA_DisableStream(m_txDma.GetDma(), m_txDma.GetStream());
}
void LL_HsUsart::TxDmaHalfTransfer(void)
{
}
void LL_HsUsart::TxDmaError(LL_DmaHelper::DmaErrorType reason)
{
m_txBuffer.error = 1;
++m_stats.txDmaError;
}
void LL_HsUsart::SwitchRxBuffers(void)
{
++m_stats.rcvd;
if(*m_rxDma.GetIsReg() & m_rxDma.GetTcMask()) {
*m_rxDma.GetIfcReg() = m_rxDma.GetTcMask();
if(CheckHeader(m_rxBuffers[m_rxBufferSelector].packet.header))
LL_CrcHandler::Instance().Enqueue(m_crcSlot, 1,
&m_rxBuffers[m_rxBufferSelector].packet,
sizeof(PacketHeader) + RoundUpTo4((uint16_t)m_rxBuffers[m_rxBufferSelector].packet.header.payloadLength),
this, m_rxBufferSelector);
else {
++m_stats.hdrError;
m_rxBuffers[m_rxBufferSelector].error = true;
}
} else if(*m_rxDma.GetIsReg() & m_rxDma.GetTeMask()) {
*m_rxDma.GetIfcReg() = m_rxDma.GetTeMask();
m_rxBuffers[m_rxBufferSelector].error = 1;
++m_stats.dmaError;
}
m_rxBufferSelector = !m_rxBufferSelector;
if(m_rxBuffers[m_rxBufferSelector].busy)
@ -226,25 +234,4 @@ void LL_HsUsart::CrcFailed(uintptr_t callbackParam, uint32_t crc, int prio)
}
void LL_HsUsart::TxDmaIrq()
{
if(*m_txDma.GetIsReg() & m_txDma.GetTcMask()) { // DMA transfer complete
*m_txDma.GetIfcReg() = m_txDma.GetTcMask();
LL_USART_EnableIT_TC(m_usart);
LL_DMA_DisableStream(m_txDma.GetDma(), m_txDma.GetStream());
}
else if(*m_txDma.GetIsReg() & m_txDma.GetTeMask()) {
*m_txDma.GetIfcReg() = m_txDma.GetTeMask();
m_txBuffer.error = 1;
++m_stats.dmaError;
}
if(*m_txDma.GetIsReg() & m_txDma.GetFeMask())
*m_txDma.GetIfcReg() = m_txDma.GetFeMask();
if(*m_txDma.GetIsReg() & m_txDma.GetHtMask())
*m_txDma.GetIfcReg() = m_txDma.GetHtMask();
if(*m_txDma.GetIsReg() & m_txDma.GetDmeMask())
*m_txDma.GetIfcReg() = m_txDma.GetDmeMask();
}
} // namespace f4ll