
рд╕рднреА рдХреЛ рдЕрдЪреНрдЫрд╛ рд╕реНрд╡рд╛рд╕реНрдереНрдп!
рдЖрдЬ рдореИрдВ рдЖрдкрдХреЛ рдпрд╣ рдмрддрд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдХреИрд╕реЗ рдЫрд╛рддреНрд░ рдзреАрд░реЗ-рдзреАрд░реЗ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ STM32F411 рдкрд░ UART рдбреНрд░рд╛рдЗрд╡рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдорд╛рдЗрдХреНрд░реЛрдХрдВрдЯреНрд░реЛрд▓рд░ рдХреЗ рд▓рд┐рдП рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдирд╛ рд╕реАрдЦрддреЗ рд╣реИрдВред рдореИрдВ рдЕрдкрдиреЗ рдЫреЛрдЯреЗ рдмрджрд▓рд╛рд╡реЛрдВ рдФрд░ рд╕реБрдзрд╛рд░реЛрдВ рдХреЗ рд╕рд╛рде рдпрд╣рд╛рдВ рдХреЛрдб рдФрд░ рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рджреЗрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реВрдВрдЧрд╛ред
, , :) ( , , - , ), . , , .
, , Uart ++.
:
, UART .

тАФ UART, , .
, :

:
WriteData(const uint8_t *pData, uint8_t size)
тАФReadData(uint8_t size)
тАФ
:
OnTransmit()
тАФ UARTOnTransmitComplete()
тАФ UARTOnReceive()
тАФ UART
. 2 :
UartDriverTransmitCompleteObservers
тАФ OnTransmitComplete()
OnTransmitComplete()
UartDriverTransmitCompleteObserverstemplate<typename ...Observers>
struct UartDriverTransmitCompleteObservers
{
__forceinline static void OnWriteComplete()
{
(Observers::OnTransmitComplete(), ...) ;
}
};
UartDriverReceiveObservers
тАФ OnReceiveComplete()
OnReceiveComplete()
UartDriverReceiveObserverstemplate<typename ...Observers>
struct UartDriverReceiveCompleteObservers
{
__forceinline static void OnReadComplete(tBuffer& buffer, std::size_t bytesReceived)
{
(Observers::OnReceiveComplete(buffer, bytesReceived), ...) ;
}
};
, OnReceiveComplete()
OnTransmitComplete()
. SomeProtocol
OtherObserver
.
WriteData()
, . :
:
:
static void WriteData(const std::uint8_t *pData, std::uint8_t bytesTosend)
{
assert(bytesTosend < txRxBuffer.size()) ;
const CriticalSection cs;
if ((status != Status::Write) && (status != Status::Read))
{
bufferIndex = 0U;
bufferSize = bytesTosend;
std::memcpy(txRxBuffer.data(), pData, static_cast<std::size_t>(bytesTosend));
Uart::WriteByte(txRxBuffer[bufferIndex]);
bufferIndex++;
status = Status::Write;
Uart::StartTransmit();
}
}
OnTransmit()
, , ( ) UART OnTransmit()
UartDriver
. OnTransmit()
тАФ .
__forceinline static void OnTransmit()
{
if(bufferIndex < bufferSize)
{
Uart::WriteByte(txRxBuffer[bufferIndex]) ;
bufferIndex ++ ;
} else
{
Uart::EnableTcInterrupt() ;
}
};
OnTransmitComplete()
UART : , (.. ), , , .
OnTransmitComplete() :
- ,
OnTransmitComplete()
, UartDriverTransmitCompleteObservers
static void OnTransmitComplete() {
bufferIndex = 0U;
bufferSize = 0U;
Uart::DisableTcInterrupt();
Uart::DisableTxInterrupt() ;
Uart::DisableTransmit();
status = Status::WriteComplete;
UartDriverTransmitCompleteObservers::OnWriteComplete() ;
}
ReadData()
.
:
:
static auto ReadData(std::uint8_t size) {
assert(size < txRxBuffer.size()) ;
const CriticalSection cs;
if ((status != Status::Write) && (status != Status::Read))
{
Uart::DisableTcInterrupt();
Uart::DisableTxInterrupt();
Uart::DisableTransmit();
bufferIndex = 0U;
bufferSize = size;
status = Status::Read;
Uart::EnableReceive();
Uart::EnableRxInterrupt();
}
OnReceive()
UART , . , , .
static void OnReceive()
{
txRxBuffer[bufferIndex] = Uart::ReadByte() ;
bufferIndex ++ ;
if (bufferIndex == bufferSize)
{
status = Status::ReadComplete ;
const auto length = bufferIndex ;
bufferIndex = 0U;
UartDriverReceiveObservers::OnReadComplete(txRxBuffer, bufferIndex) ;
}
}
uartdriver.hpp#ifndef REGISTERS_UARTDRIVER_HPP
#define REGISTERS_UARTDRIVER_HPP
#include "susudefs.hpp"
#include "hardwareuarttx.hpp"
#include "hardwareuarttc.hpp"
#include "hardwareuartrx.hpp"
#include <cstring> // for memcpy
#include "criticalsectionconfig.hpp"
#include "uartdriverconfig.hpp"
template<typename UartModule, typename UartDriverTransmitCompleteObservers, typename UartDriverReceiveObservers>
struct UartDriver
{
using Uart = UartModule ;
enum class Status: std::uint8_t
{
None = 0,
Write = 1,
WriteComplete = 2,
Read = 3,
ReadComplete = 4
} ;
static void WriteData(const std::uint8_t *pData, std::uint8_t bytesTosend)
{
assert(bytesTosend < txRxBuffer.size()) ;
const CriticalSection cs;
if ((status != Status::Write) && (status != Status::Read))
{
bufferIndex = 0U;
bufferSize = bytesTosend;
std::memcpy(txRxBuffer.data(), pData, static_cast<std::size_t>(bytesTosend));
Uart::WriteByte(txRxBuffer[bufferIndex]);
bufferIndex++;
status = Status::Write;
Uart::StartTransmit();
if constexpr (!std::is_base_of<UartTxInterruptable, typename Uart::Base>::value)
{
for(; bufferIndex < bytesTosend; ++bufferIndex)
{
while (!Uart::IsDataRegisterEmpty())
{
}
Uart::WriteByte(txRxBuffer[bufferIndex]);
}
while (!Uart::IsTransmitComplete())
{
}
status = Status::WriteComplete ;
UartDriverTransmitCompleteObservers::OnWriteComplete() ;
} else
{
}
}
}
__forceinline static void OnTransmit()
{
if(bufferIndex < bufferSize)
{
Uart::WriteByte(txRxBuffer[bufferIndex]) ;
bufferIndex ++ ;
}
else
{
Uart::EnableTcInterrupt() ;
}
};
static void OnTransmitComplete()
{
bufferIndex = 0U;
bufferSize = 0U;
status = Status::WriteComplete;
Uart::DisableTcInterrupt();
Uart::DisableTxInterrupt() ;
Uart::DisableTransmit();
UartDriverTransmitCompleteObservers::OnWriteComplete() ;
}
static auto ReadData(std::uint8_t size)
{
assert(size < txRxBuffer.size()) ;
const CriticalSection cs;
if ((status != Status::Write) && (status != Status::Read))
{
Uart::DisableTcInterrupt();
Uart::DisableTxInterrupt();
Uart::DisableTransmit();
bufferIndex = 0U;
bufferSize = size;
status = Status::Read;
Uart::EnableRxInterrupt();
Uart::EnableReceive();
}
}
static void OnReceive()
{
txRxBuffer[bufferIndex] = Uart::ReadByte() ;
bufferIndex ++ ;
if (bufferIndex == bufferSize)
{
status = Status::ReadComplete ;
const auto length = bufferIndex ;
bufferIndex = 0 ;
UartDriverReceiveObservers::OnReadComplete(txRxBuffer, static_cast<std::size_t>(length)) ;
}
}
static Status GetStatus()
{
return status ;
}
static void ResetAll()
{
Uart::DisableTcInterrupt();
Uart::DisableTxInterrupt();
Uart::DisableTransmit();
Uart::DisableReceive();
Uart::DisableRxInterrupt() ;
bufferIndex = 0U;
bufferSize = 0U;
status = Status::None;
}
friend UartDriver& operator<<(UartDriver &rOs, const char* pString)
{
WriteData(reinterpret_cast<const std::uint8_t*>(pString), strlen(pString)) ;
return rOs;
}
friend UartDriver& operator<<(UartDriver &rOs, float value)
{
WriteData(reinterpret_cast<const std::uint8_t*>(&value), sizeof(float)) ;
return rOs;
}
private:
inline static tBuffer txRxBuffer = {} ;
inline static std::uint8_t bufferSize = 0U ;
inline static std::uint8_t bufferIndex = 0U ;
inline static Status status = Status::None ;
};
#endif
?
, SomeProtocol
, 10 10 . тАФ , тАФ . 8 , .. , 10, . ( , , , )
OnTransmitComplete()
OnReceiveComplete()
.
:template <typename UartDriver>
struct SomeProtocol
{
__forceinline static void OnTransmitComplete()
{
Proceed() ;
}
__forceinline static void OnReceiveComplete(tBuffer& buffer, std::size_t length)
{
assert(length <= buffer.size()) ;
if (CheckData(buffer))
{
cmds::ProceedCmd(buffer[0], buffer);
UartDriver::WriteData(buffer.data(), length) ;
} else
{
UartDriver::ResetAll() ;
}
}
__forceinline static void Proceed()
{
UartDriver::ReadData(10) ;
}
using cmds = CmdContainer<
Singleton<CmdWriteSomeData>::GetInstance(),
Singleton<CmdReadSomeData>::GetInstance()
> ;
};
struct TestObserver
{
__forceinline static void OnTransmitComplete()
{
Led1::Toggle() ;
}
};
- UartDriver
struct MyUartDriver: UartDriver<
HardwareUart,
UartDriverTransmitCompleteObservers<SomeProtocol<MyUartDriver>, TestObserver>,
UartDriverReceiveCompleteObservers<SomeProtocol<MyUartDriver>>
> { };
using MyProtocol = SomeProtocol<MyUartDriver> ;
, . , TestObserver
SomeProtocol
, тАФ SomeProtocol
. UART .
:
int main()
{
MyProtocol::Proceed() ;
while(true) { }
return 1 ;
}
UART
, , HardwareUart
UART . :

тАФ UART , 3 :
HardwareUartTx
тАФ , ,HardwareUartTc
тАФ , ,HardwareUartRx
тАФ , ,
HandleInterrupt()
HardwareUartBase
,
template<typename... Modules>
struct InterruptsList
{
__forceinline static void OnInterrupt()
{
(Modules::HandleInterrupt(), ...) ;
}
} ;
template<typename UartModule, typename InterruptsList>
struct HardwareUartBase
{
static void HandleInterrupt()
{
InterruptsList::OnInterrupt() ;
}
...
} ;
HardwareUartTx , HardwareUartRx, HardwareUartTxtemplate<typename UartModule, typename UartTransmitObservers>
struct HardwareUartTx
{
using Uart = typename UartModule::Uart ;
static void HandleInterrupt()
{
if(Uart::SR::TXE::DataRegisterEmpty::IsSet() &&
Uart::CR1::TXEIE::InterruptWhenTXE::IsSet())
{
UartTransmitObservers::OnTxDataRegEmpty();
}
}
};
template<typename UartModule, typename UartReceiveObservers>
struct HardwareUartRx
{
using Uart = typename UartModule::Uart ;
static void HandleInterrupt()
{
if(Uart::CR1::RXNEIE::InterruptWhenRXNE::IsSet() &&
Uart::SR::RXNE::DataRecieved::IsSet() )
{
UartReceiveObservers::OnRxData();
}
}
};
template<typename UartModule, typename UartTransmitCompleteObservers>
struct HardwareUartTc
{
using Uart = typename UartModule::Uart ;
static void HandleInterrupt()
{
if(Uart::SR::TC::TransmitionComplete::IsSet() &&
Uart::CR1::TCIE::InterruptWhenTC::IsSet())
{
UartTransmitCompleteObservers::OnComplete();
Uart::SR::TC::TransmitionNotComplete::Set() ;
}
}
};
HardwareUartBase#ifndef REGISTERS_UART_HPP
#define REGISTERS_UART_HPP
#include "susudefs.hpp"
#include <array> // for std::array
#include <cassert> // for assert
#include <cstring> // for memcpy
#include "criticalsectionguard.hpp"
template<typename UartModule, typename InterruptsList>
struct HardwareUartBase
{
using Uart = UartModule ;
using Base = Interface ;
__forceinline static void EnableTransmit()
{
UartModule::CR1::TE::Enable::Set();
};
static void DisableTransmit()
{
UartModule::CR1::TE::Disable::Set();
};
static void EnableReceive()
{
UartModule::CR1::RE::Enable::Set();
};
static void DisableReceive()
{
UartModule::CR1::RE::Disable::Set();
};
static void EnableTxInterrupt()
{
UartModule::CR1::TXEIE::InterruptWhenTXE::Set();
};
static void EnableRxInterrupt()
{
UartModule::CR1::RXNEIE::InterruptWhenRXNE::Set();
};
static void DisableRxInterrupt()
{
UartModule::CR1::RXNEIE::InterruptInhibited::Set();
};
static void DisableTxInterrupt()
{
UartModule::CR1::TXEIE::InterruptInhibited::Set();
};
static void EnableTcInterrupt()
{
UartModule::CR1::TCIE::InterruptWhenTC::Set();
};
static void DisableTcInterrupt()
{
UartModule::CR1::TCIE::InterruptInhibited::Set();
};
static void HandleInterrupt()
{
InterruptsList::OnInterrupt() ;
}
__forceinline static void ClearStatus()
{
UartModule::SR::Write(0);
}
static void WriteByte(std::uint8_t chByte)
{
UartModule::DR::Write(static_cast<std::uint32_t>(chByte)) ;
}
static std::uint8_t ReadByte()
{
return static_cast<std::uint8_t>(UartModule::DR::Get()) ;
}
static void StartTransmit()
{
EnableTransmit() ;
if constexpr (std::is_base_of<UartTxInterruptable, Interface>::value)
{
EnableTxInterrupt() ;
}
}
static bool IsDataRegisterEmpty()
{
return UartModule::SR::TXE::DataRegisterEmpty::IsSet() ;
}
static bool IsTransmitComplete()
{
return UartModule::SR::TC::TransmitionComplete::IsSet() ;
}
};
#endif
UART :
struct HardwareUart : HardwareUartBase<
USART2,
InterruptsList<
HardwareUartTx<HardwareUart,
UartTransmitObservers<MyUartDriver>>,
HardwareUartTc<HardwareUart,
UartTransmitCompleteObservers<MyUartDriver>>,
HardwareUartRx<HardwareUart,
UartReceiveObservers<MyUartDriver>>
>
>
{
};
. , UartDriver, - . UART, USART2.
Uart , . Uart .
struct MyUartDriver: UartDriver<
HardwareUart,
UartDriverTransmitCompleteObservers<SomeProtocol<MyUartDriver>, TestObserver>,
UartDriverReceiveCompleteObservers<SomeProtocol<MyUartDriver>>
> { };
using MyProtocol = SomeProtocol<MyUartDriver> ;
.
inline, 1600 . : 12 Flash . , , , . , UART. :)
, 2 ( 20 ). , - , , тАФ .
рдХреЛрдб рдореЗрд░реЗ рджреНрд╡рд╛рд░рд╛ рдкреАрд╡реАрдПрд╕-рд╕реНрдЯреВрдбрд┐рдпреЛ рдореЗрдВ рдЪреЗрдХ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рд╢реБрд░реБрдЖрдд рдореЗрдВ 4 рдЪреЗрддрд╛рд╡рдиреА рдорд┐рд▓реАрдВред
рдореБрдЭреЗ рд╕рднреА рдЪреЗрддрд╛рд╡рдирд┐рдпрд╛рдБ рдпрд╛рдж рдирд╣реАрдВ рд╣реИрдВ, рдореИрдВрдиреЗ рд░рд┐рдкреЛрд░реНрдЯ рдХреЛ рд╕рд╣реЗрдЬрд╛ рдирд╣реАрдВ рдерд╛: рд▓реЗрдХрд┐рди рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ V2516 рдФрд░ V519 рдереЗ, рддреНрд░реБрдЯрд┐рдпрд╛рдВ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдирд╣реАрдВ рдереАрдВ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдРрд╕рд╛ рдирд╣реАрдВ рдХрд░рдирд╛ рдерд╛ :) рд╕рдм рдХреБрдЫ рддрдп рд╣реЛ рдЧрдпрд╛ рдерд╛, V2516 рдХреЛ рдЫреЛрдбрд╝рдХрд░, рдпрд╣ рдбреАрдмрдЧрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП рдХреЛрдб рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рдиреЗ FIXME рдХреЛ рд╕реЗрдЯ рдХрд┐рдпрд╛: ред
рдЖрдк IAR8.40.2 рдкрд░ рдХрд╛рдо рдХрд░ рд░рд╣реЗ рдЙрджрд╛рд╣рд░рдг рдХреЛрдб рдХреЛ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ , рдЕрддрд┐рд░рд┐рдХреНрдд рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдиреНрдпреВрдХреНрд▓рд┐рдпреЛ-рдПрдл 411 рдЖрд░рдИ рдмреЛрд░реНрдб рдХреА рдЬрд░реВрд░рдд рд╣реИ, рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╕реНрд╡рдпрдВ рдлреНрд▓реИрд╢рдЖрд░реНрдЯ \ _ рдбрд╛рдЗрдирд╛рдорд┐рдХрд╕реНрдЯреИрдВрдб рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рд╣реИ ред
рдореБрдЦреНрдп рдЪрд╛рд▓рдХ рдФрд░ Uart рдореЙрдбреНрдпреВрд▓ рдХреЛрдб github рдкрд░ рд╣реИ ред
рдкреБрдирд╢реНрдЪ: рдзрдиреНрдпрд╡рд╛рдж fougasse, Apro, gleb_l рддрдерд╛ besitzeruf рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП