Kinda works
This commit is contained in:
parent
f3d345e2e3
commit
662a7a9b12
40 changed files with 2851 additions and 26 deletions
173
components/f4ll_cpp/serialconsole.h
Normal file
173
components/f4ll_cpp/serialconsole.h
Normal file
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* interrupt.h
|
||||
*
|
||||
* Created on: Aug 29, 2019
|
||||
* Author: abody
|
||||
*/
|
||||
|
||||
#ifndef CONSOLEHANDLER_H_
|
||||
#define CONSOLEHANDLER_H_
|
||||
|
||||
#include <cstring>
|
||||
#include "usart.h"
|
||||
#include <f4ll_cpp/dmahelper.h>
|
||||
#include <f4ll_cpp/uartbase.h>
|
||||
|
||||
|
||||
namespace f4ll_cpp {
|
||||
|
||||
template<unsigned int bufSize> class SerialConsole : protected UartBase
|
||||
{
|
||||
public:
|
||||
struct Buffer {
|
||||
volatile bool busy = false;
|
||||
volatile bool error = false;
|
||||
uint8_t len;
|
||||
char buffer[bufSize];
|
||||
};
|
||||
|
||||
struct ISerialConsoleCallback {
|
||||
virtual void LineReceived(void *userParam, Buffer *buffer) = 0;
|
||||
virtual void TransmissionComplete(void *userParam, Buffer *buffer) = 0;
|
||||
};
|
||||
|
||||
SerialConsole(USART_TypeDef *uart, DMA_TypeDef *dma, uint32_t stream_rx, uint32_t stream_tx,
|
||||
ISerialConsoleCallback *callback, void *callbackUserParam);
|
||||
|
||||
void Send(char const *buffer, uint8_t length = 0);
|
||||
void SendLine(char const *buffer, uint8_t length = 0);
|
||||
|
||||
void HandleRxDmaIrq();
|
||||
void HandleTxDmaIrq();
|
||||
void HandleUsartIrq();
|
||||
|
||||
private:
|
||||
void SetupTransmit(void *buffer, uint16_t length);
|
||||
|
||||
bool m_activeRxBuffer = false;
|
||||
Buffer m_rxBuffers[2];
|
||||
Buffer m_txBuffer;
|
||||
|
||||
ISerialConsoleCallback *m_callback;
|
||||
void *m_callbackUserParam;
|
||||
};
|
||||
|
||||
template<unsigned int bufSize> SerialConsole<bufSize>::SerialConsole(
|
||||
USART_TypeDef *uart, DMA_TypeDef *dma, uint32_t stream_rx, uint32_t stream_tx,
|
||||
ISerialConsoleCallback *callback, void *callbackUserParam
|
||||
)
|
||||
: UartBase(uart, dma, stream_rx, stream_tx)
|
||||
, m_callback(callback), m_callbackUserParam(callbackUserParam)
|
||||
{
|
||||
LL_USART_EnableIT_IDLE(uart);
|
||||
SetupReceive(m_rxBuffers[m_activeRxBuffer].buffer, bufSize);
|
||||
}
|
||||
|
||||
template<unsigned int bufSize> void SerialConsole<bufSize>::SetupTransmit(void *buffer, uint16_t length)
|
||||
{
|
||||
m_txBuffer.busy = true;
|
||||
UartBase::SetupTransmit(buffer, length);
|
||||
}
|
||||
|
||||
template<unsigned int bufSize> void SerialConsole<bufSize>::HandleRxDmaIrq()
|
||||
{
|
||||
if(*m_rxDma.GetIsReg() & m_rxDma.GetTcMask()) {
|
||||
*m_rxDma.GetIfcReg() = m_rxDma.GetTcMask();
|
||||
m_rxBuffers[m_activeRxBuffer].busy = true;
|
||||
if(m_callback)
|
||||
m_callback->LineReceived(m_callbackUserParam, &m_rxBuffers[m_activeRxBuffer]);
|
||||
}
|
||||
|
||||
if(*m_rxDma.GetIsReg() & m_rxDma.GetTeMask()) {
|
||||
*m_rxDma.GetIfcReg() = m_rxDma.GetTeMask();
|
||||
}
|
||||
|
||||
m_activeRxBuffer = !m_activeRxBuffer;
|
||||
|
||||
SetupReceive(m_rxBuffers[m_activeRxBuffer].buffer, bufSize);
|
||||
}
|
||||
|
||||
template<unsigned int bufSize> void SerialConsole<bufSize>::HandleTxDmaIrq()
|
||||
{
|
||||
if(*m_txDma.GetIsReg() & m_txDma.GetTcMask()) { // DMA transfer complete
|
||||
*m_txDma.GetIfcReg() = m_txDma.GetTcMask();
|
||||
LL_USART_EnableIT_TC(m_uart);
|
||||
LL_DMA_DisableStream(m_txDma.GetDma(), m_txDma.GetStream());
|
||||
}
|
||||
if(*m_txDma.GetIsReg() & m_txDma.GetTeMask()) {
|
||||
*m_txDma.GetIfcReg() = m_txDma.GetTeMask();
|
||||
m_txBuffer.error = true;
|
||||
LL_USART_EnableIT_TC(m_uart);
|
||||
LL_DMA_DisableStream(m_txDma.GetDma(), m_txDma.GetStream());
|
||||
}
|
||||
}
|
||||
|
||||
template<unsigned int bufSize> void SerialConsole<bufSize>::HandleUsartIrq()
|
||||
{
|
||||
if(LL_USART_IsActiveFlag_IDLE(m_uart) && LL_USART_IsEnabledIT_IDLE(m_uart)) { // receiver idle
|
||||
// we assume that new line marker will arrive without an idle cycle even if it is CRLF
|
||||
LL_USART_ClearFlag_IDLE(m_uart);
|
||||
uint16_t rcvdLen = bufSize - LL_DMA_GetDataLength(m_rxDma.GetDma(), m_rxDma.GetStream());
|
||||
if(rcvdLen ) {
|
||||
bool newLine = false;;
|
||||
do {
|
||||
auto lastChar = m_rxBuffers[m_activeRxBuffer].buffer[rcvdLen-1];
|
||||
if( lastChar == '\r' || lastChar == '\n')
|
||||
newLine = true;
|
||||
else
|
||||
break;
|
||||
} while(--rcvdLen);
|
||||
|
||||
if(newLine) {
|
||||
m_rxBuffers[m_activeRxBuffer].buffer[rcvdLen] = 0;
|
||||
m_rxBuffers[m_activeRxBuffer].len = rcvdLen;
|
||||
LL_DMA_DisableStream(m_rxDma.GetDma(), m_rxDma.GetStream());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(LL_USART_IsActiveFlag_TC(m_uart) && LL_USART_IsEnabledIT_TC(m_uart)) { // transmission complete
|
||||
LL_USART_DisableIT_TC(m_uart);
|
||||
LL_USART_DisableDirectionTx(m_uart); // enforcing an idle frame
|
||||
LL_USART_EnableDirectionTx(m_uart);
|
||||
m_txBuffer.busy = false;
|
||||
if(m_callback)
|
||||
m_callback->TransmissionComplete(m_callbackUserParam, &m_txBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
template<unsigned int bufSize> void SerialConsole<bufSize>::Send(char const *buffer, uint8_t length)
|
||||
{
|
||||
if(!length) {
|
||||
auto computedLength = strlen(buffer);
|
||||
if(computedLength <= (uint8_t)-1)
|
||||
length = computedLength;
|
||||
}
|
||||
if(length) {
|
||||
while( m_txBuffer.busy );
|
||||
memcpy(m_txBuffer.buffer, buffer, length);
|
||||
SetupTransmit(m_txBuffer.buffer, length);
|
||||
}
|
||||
}
|
||||
|
||||
template<unsigned int bufSize> void SerialConsole<bufSize>::SendLine(char const *buffer, uint8_t length)
|
||||
{
|
||||
if(!length) {
|
||||
auto computedLength = strlen(buffer);
|
||||
if(computedLength <= (uint8_t)-1)
|
||||
length = computedLength;
|
||||
}
|
||||
if(length) {
|
||||
while( m_txBuffer.busy );
|
||||
memcpy(m_txBuffer.buffer, buffer, length);
|
||||
if(m_txBuffer.buffer[length-1] != '\n') {
|
||||
m_txBuffer.buffer[length++] = '\r';
|
||||
m_txBuffer.buffer[length++] = '\n';
|
||||
}
|
||||
SetupTransmit(m_txBuffer.buffer, length);
|
||||
}
|
||||
}
|
||||
|
||||
} // f4ll_cpp
|
||||
|
||||
#endif /* CONSOLEHANDLER_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue