Compare commits

..

No commits in common. "eaf7ebc1919533109b79e6dc9b9054bf992f0298" and "a4e25d702b65405c79073f289235ae14619932e1" have entirely different histories.

14 changed files with 257 additions and 254 deletions

View file

@ -11,5 +11,5 @@
#include <f4ll/packet_usart.h> #include <f4ll/packet_usart.h>
#include <inttypes.h> #include <inttypes.h>
extern f4ll::packet_usart *g_usarts[USARTCOUNT]; extern f4ll::PacketUsart *g_usarts[USARTCOUNT];
extern uint8_t g_statsBuf[256]; extern uint8_t g_statsBuf[256];

View file

@ -10,6 +10,6 @@
#include <f4ll/memcpy_dma.h> #include <f4ll/memcpy_dma.h>
#include <f4ll/packet_usart.h> #include <f4ll/packet_usart.h>
f4ll::packet_usart *g_usarts[USARTCOUNT]; f4ll::PacketUsart *g_usarts[USARTCOUNT];
uint8_t g_statsBuf[256]; uint8_t g_statsBuf[256];

View file

@ -8,46 +8,46 @@
void usart1_rx_dma_isr(void) void usart1_rx_dma_isr(void)
{ {
f4ll::packet_usart::rx_dma_isr(g_usarts[USART1_OFFSET]); f4ll::PacketUsart::rx_dma_isr(g_usarts[USART1_OFFSET]);
} }
void usart1_tx_dma_isr(void) void usart1_tx_dma_isr(void)
{ {
f4ll::packet_usart::tx_dma_isr(g_usarts[USART1_OFFSET]); f4ll::PacketUsart::tx_dma_isr(g_usarts[USART1_OFFSET]);
} }
void usart1_isr(void) void usart1_isr(void)
{ {
f4ll::packet_usart::usart_isr(g_usarts[USART1_OFFSET]); f4ll::PacketUsart::usart_isr(g_usarts[USART1_OFFSET]);
} }
// //
void usart2_rx_dma_isr(void) void usart2_rx_dma_isr(void)
{ {
f4ll::packet_usart::rx_dma_isr(g_usarts[USART2_OFFSET]); f4ll::PacketUsart::rx_dma_isr(g_usarts[USART2_OFFSET]);
} }
void usart2_tx_dma_isr(void) void usart2_tx_dma_isr(void)
{ {
f4ll::packet_usart::tx_dma_isr(g_usarts[USART2_OFFSET]); f4ll::PacketUsart::tx_dma_isr(g_usarts[USART2_OFFSET]);
} }
void usart2_isr(void) void usart2_isr(void)
{ {
f4ll::packet_usart::usart_isr(g_usarts[USART2_OFFSET]); f4ll::PacketUsart::usart_isr(g_usarts[USART2_OFFSET]);
} }
// //
void usart3_rx_dma_isr(void) void usart3_rx_dma_isr(void)
{ {
f4ll::packet_usart::rx_dma_isr(g_usarts[USART3_OFFSET]); f4ll::PacketUsart::rx_dma_isr(g_usarts[USART3_OFFSET]);
} }
void usart3_tx_dma_isr(void) void usart3_tx_dma_isr(void)
{ {
f4ll::packet_usart::tx_dma_isr(g_usarts[USART3_OFFSET]); f4ll::PacketUsart::tx_dma_isr(g_usarts[USART3_OFFSET]);
} }
void usart3_isr(void) void usart3_isr(void)
{ {
f4ll::packet_usart::usart_isr(g_usarts[USART3_OFFSET]); f4ll::PacketUsart::usart_isr(g_usarts[USART3_OFFSET]);
} }
// //
@ -64,16 +64,16 @@ void usart4_isr(void)
// //
void usart6_rx_dma_isr(void) void usart6_rx_dma_isr(void)
{ {
f4ll::packet_usart::rx_dma_isr(g_usarts[USART6_OFFSET]); f4ll::PacketUsart::rx_dma_isr(g_usarts[USART6_OFFSET]);
} }
void usart6_tx_dma_isr(void) void usart6_tx_dma_isr(void)
{ {
f4ll::packet_usart::tx_dma_isr(g_usarts[USART6_OFFSET]); f4ll::PacketUsart::tx_dma_isr(g_usarts[USART6_OFFSET]);
} }
void usart6_isr(void) void usart6_isr(void)
{ {
f4ll::packet_usart::usart_isr(g_usarts[USART6_OFFSET]); f4ll::PacketUsart::usart_isr(g_usarts[USART6_OFFSET]);
} }
void m2m1_dma_isr(void) void m2m1_dma_isr(void)

View file

@ -18,22 +18,22 @@ class console_handler : public usart_core, public singleton<console_handler>
friend class singleton<console_handler>; friend class singleton<console_handler>;
public: public:
void PrintStats(uint8_t id, packet_usart &usart); void PrintStats(uint8_t id, PacketUsart &usart);
private: private:
console_handler(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t stream_rx, uint32_t stream_tx); console_handler(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t streamRx, uint32_t streamTx);
// LL_UsartCore pure virtual function implementations // LL_UsartCore pure virtual function implementations
virtual void receiver_idle(void) override; virtual void receiver_idle(void);
virtual void transmission_complete(void) override; virtual void transmission_complete(void);
virtual void framing_error(void) override; virtual void framing_error(void);
virtual void overrun(void) override; virtual void overrun(void);
virtual void rx_dma_transfer_complete(void) override; virtual void rx_dma_transfer_complete(void);
virtual void rx_dma_half_transfer(void) override; virtual void rx_dma_half_transfer(void);
virtual void rx_dma_error(dma_helper::dma_error_type reason) override; virtual void rx_dma_error(dma_helper::dma_error_type reason);
virtual void tx_dma_transfer_complete(void) override; virtual void tx_dma_transfer_complete(void);
virtual void tx_dma_half_transfer(void) override; virtual void tx_dma_half_transfer(void);
virtual void tx_dma_error(dma_helper::dma_error_type reason) override; virtual void tx_dma_error(dma_helper::dma_error_type reason);
char m_buffer[128]; char m_buffer[128];
uint16_t m_used = 0; uint16_t m_used = 0;

View file

@ -84,7 +84,7 @@ private:
dma_helper m_dma; dma_helper m_dma;
slot_base volatile *m_first_slot = nullptr; slot_base volatile *m_first_slot = nullptr;
slot_base volatile *m_active_slot = nullptr; slot_base volatile *m_active_slot = nullptr;
int volatile m_active_task; int volatile m_activeTask;
}; };
} // namespace f4ll } // namespace f4ll

View file

@ -29,11 +29,11 @@ public:
inline uint32_t get_ht_mask() const { return m_ht_masks[m_stream]; } inline uint32_t get_ht_mask() const { return m_ht_masks[m_stream]; }
inline uint32_t get_tc_mask() const { return m_tc_masks[m_stream]; } inline uint32_t get_tc_mask() const { return m_tc_masks[m_stream]; }
inline bool is_enabled_it_ht() const { return LL_DMA_IsEnabledIT_HT(m_dma, m_stream) != 0; } inline bool is_enabled_it_ht() { return LL_DMA_IsEnabledIT_HT(m_dma, m_stream) != 0; }
inline bool is_enabled_it_te() const { return LL_DMA_IsEnabledIT_TE(m_dma, m_stream) != 0; } inline bool is_enabled_it_te() { return LL_DMA_IsEnabledIT_TE(m_dma, m_stream) != 0; }
inline bool is_enabled_it_tc() const { return LL_DMA_IsEnabledIT_TC(m_dma, m_stream) != 0; } inline bool is_enabled_it_tc() { return LL_DMA_IsEnabledIT_TC(m_dma, m_stream) != 0; }
inline bool is_enabled_it_dme() const { return LL_DMA_IsEnabledIT_DME(m_dma, m_stream) != 0; } inline bool is_enabled_it_dme() { return LL_DMA_IsEnabledIT_DME(m_dma, m_stream) != 0; }
inline bool is_enabled_it_fe() const { return LL_DMA_IsEnabledIT_FE(m_dma, m_stream) != 0; } inline bool is_enabled_it_fe() { return LL_DMA_IsEnabledIT_FE(m_dma, m_stream) != 0; }
enum class dma_error_type { transfer, direct_mode, fifo }; enum class dma_error_type { transfer, direct_mode, fifo };
@ -43,16 +43,11 @@ private:
volatile uint32_t *m_is_reg; volatile uint32_t *m_is_reg;
volatile uint32_t *m_ifc_reg; volatile uint32_t *m_ifc_reg;
static constexpr uint32_t const m_fe_masks[8] = {DMA_LISR_FEIF0, DMA_LISR_FEIF1, DMA_LISR_FEIF2, DMA_LISR_FEIF3, static const uint32_t m_fe_masks[8];
DMA_HISR_FEIF4, DMA_HISR_FEIF5, DMA_HISR_FEIF6, DMA_HISR_FEIF7}; static const uint32_t m_dme_masks[8];
static constexpr uint32_t const m_dme_masks[8] = {DMA_LISR_DMEIF0, DMA_LISR_DMEIF1, DMA_LISR_DMEIF2, DMA_LISR_DMEIF3, static const uint32_t m_te_masks[8];
DMA_HISR_DMEIF4, DMA_HISR_DMEIF5, DMA_HISR_DMEIF6, DMA_HISR_DMEIF7}; static const uint32_t m_ht_masks[8];
static constexpr uint32_t const m_te_masks[8] = {DMA_LISR_TEIF0, DMA_LISR_TEIF1, DMA_LISR_TEIF2, DMA_LISR_TEIF3, static const uint32_t m_tc_masks[8];
DMA_HISR_TEIF4, DMA_HISR_TEIF5, DMA_HISR_TEIF6, DMA_HISR_TEIF7};
static constexpr uint32_t const m_ht_masks[8] = {DMA_LISR_HTIF0, DMA_LISR_HTIF1, DMA_LISR_HTIF2, DMA_LISR_HTIF3,
DMA_HISR_HTIF4, DMA_HISR_HTIF5, DMA_HISR_HTIF6, DMA_HISR_HTIF7};
static constexpr uint32_t const m_tc_masks[8] = {DMA_LISR_TCIF0, DMA_LISR_TCIF1, DMA_LISR_TCIF2, DMA_LISR_TCIF3,
DMA_HISR_TCIF4, DMA_HISR_TCIF5, DMA_HISR_TCIF6, DMA_HISR_TCIF7};
}; };
} /* namespace f4ll */ } /* namespace f4ll */

View file

@ -10,35 +10,7 @@
extern "C" { extern "C" {
#endif #endif
typedef struct
{
uint32_t R0;
uint32_t R1;
uint32_t R2;
uint32_t R3;
uint32_t R4;
uint32_t R5;
uint32_t R6;
uint32_t R7;
uint32_t R8;
uint32_t R9;
uint32_t R10;
uint32_t R11;
uint32_t R12;
uint32_t SP;
uint32_t LR;
uint32_t PC;
uint32_t xPSR;
uint32_t PSP;
uint32_t MSP;
uint32_t EXC_RETURN;
uint32_t CONTROL;
} fault_context_t;
extern fault_context_t g_fault_context;
void app_fault_callback(uint32_t reason); void app_fault_callback(uint32_t reason);
__attribute__((noreturn)) void fault_handler(uint32_t type, fault_context_t *context);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -6,21 +6,22 @@
namespace f4ll { namespace f4ll {
class irq_lock class IrqLock {
{
public: public:
inline irq_lock() inline IrqLock() : m_primask(__get_PRIMASK()) {
: m_primask(__get_PRIMASK()) __disable_irq();
{ }
__disable_irq(); inline void Release() {
} __set_PRIMASK(m_primask);
inline void release() { __set_PRIMASK(m_primask); } }
inline ~irq_lock() { __set_PRIMASK(m_primask); }
inline ~IrqLock() {
__set_PRIMASK(m_primask);
}
private: private:
uint32_t m_primask; uint32_t m_primask;
}; };
} }
#endif // _IRQLOCK_H_INCLUDED #endif // _IRQLOCK_H_INCLUDED

View file

@ -15,35 +15,35 @@ namespace f4ll {
struct DMAINFO; struct DMAINFO;
class packet_usart : public crc_handler::icallback, public usart_core class PacketUsart : public crc_handler::icallback, public usart_core
{ {
// friend class UsartCore; // friend class UsartCore;
public: public:
packet_usart(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t stream_rx, uint32_t stream_tx); PacketUsart(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t stream_rx, uint32_t stream_tx);
struct packet_header struct PacketHeader
{ // !!! size should be multiple of 4 !!! { // !!! size should be multiple of 4 !!!
uint8_t start_byte; uint8_t startByte;
uint8_t serial; uint8_t serial;
uint8_t payload_length; uint8_t payloadLength;
uint8_t hash; uint8_t hash;
}; };
struct packet struct Packet
{ {
packet_header header; PacketHeader header;
uint8_t payload[256 + sizeof(uint32_t)]; // extra room for crc32 uint8_t payload[256 + sizeof(uint32_t)]; // extra room for crc32
} __attribute__((aligned)); } __attribute__((aligned));
struct stats struct Stats
{ {
uint32_t overrun = 0; uint32_t overrun = 0;
uint32_t hdr_error = 0; uint32_t hdrError = 0;
uint32_t payload_errror = 0; uint32_t payloadErrror = 0;
uint32_t pep1 = 0; uint32_t pep1 = 0;
uint32_t pep2 = 0; uint32_t pep2 = 0;
uint32_t rx_dma_error = 0; uint32_t rxDmaError = 0;
uint32_t tx_dma_error = 0; uint32_t txDmaError = 0;
uint32_t rcvd = 0; uint32_t rcvd = 0;
uint32_t premature_hdr = 0; uint32_t premature_hdr = 0;
uint32_t premature_payload = 0; uint32_t premature_payload = 0;
@ -51,71 +51,71 @@ public:
uint32_t skiped = 0; uint32_t skiped = 0;
}; };
struct ihs_usart_callback struct IHsUsartCallback
{ {
virtual bool packet_received(packet_usart *caller, uintptr_t user_param, packet const &packet) = 0; virtual bool PacketReceived(PacketUsart *caller, uintptr_t userParam, Packet const &packet) = 0;
}; };
// crc_handler::ICallback interface functions // crc_handler::ICallback interface functions
virtual void crc_succeeded(uintptr_t callback_param, uint32_t crc, uint8_t task) override; virtual void crc_succeeded(uintptr_t callbackParam, uint32_t crc, uint8_t task);
virtual void crc_failed(uintptr_t callback_param, uint32_t crc, uint8_t task) override; virtual void crc_failed(uintptr_t callbackParam, uint32_t crc, uint8_t task);
void post_packet(uint8_t const *payload, uint8_t length, bool wait_for_crc_queue = true); void PostPacket(uint8_t const *payload, uint8_t length, bool waitForCrcQueue = true);
void setup_receive(void); void SetupReceive(void);
void rx_processed(bool second); void RxProcessed(bool second);
// Getters // Getters
uint8_t *get_tx_packet_buffer(void) { return m_tx_buffer.pkt.payload; } uint8_t *GetTxPacketBuffer(void) { return m_txBuffer.packet.payload; }
uint8_t const *get_rx_packet_buffer(bool second) { return m_rx_buffers[second].pkt.payload; } uint8_t const *GetRxPacketBuffer(bool second) { return m_rxBuffers[second].packet.payload; }
USART_TypeDef *get_usart(void) const { return m_usart; } USART_TypeDef *GetUsart(void) const { return m_usart; }
stats const &get_stats(void) const { return m_stats; } Stats const &GetStats(void) const { return m_stats; }
inline bool is_tx_busy(void) const { return m_tx_buffer.busy; } inline bool IsTxBusy(void) const { return m_txBuffer.busy; }
inline bool is_tx_failed(void) const { return m_tx_buffer.error; } inline bool IsTxFailed(void) const { return m_txBuffer.error; }
inline bool is_rx_busy(bool second) const { return m_rx_buffers[second].busy; } inline bool IsRxBusy(bool second) const { return m_rxBuffers[second].busy; }
inline bool is_rx_failed(bool second) const { return m_rx_buffers[second].error; } inline bool IsRxFailed(bool second) const { return m_rxBuffers[second].error; }
void set_callback(ihs_usart_callback *callback, uintptr_t callback_param); void SetCallback(IHsUsartCallback *callback, uintptr_t callbackParam);
private: private:
void build_header(packet &packet, uint8_t serial_nr, uint8_t length); void BuildHeader(Packet &packet, uint8_t serialNo, uint8_t length);
bool check_header(packet_header &header); bool CheckHeader(PacketHeader &header);
void switch_rx_buffers(void); void SwitchRxBuffers(void);
// UsartCore pure virtual function implementations // UsartCore pure virtual function implementations
virtual void receiver_idle(void) override; virtual void receiver_idle(void);
virtual void transmission_complete(void) override; virtual void transmission_complete(void);
virtual void framing_error(void) override; virtual void framing_error(void);
virtual void overrun(void) override; virtual void overrun(void);
virtual void rx_dma_transfer_complete(void) override; virtual void rx_dma_transfer_complete(void);
virtual void rx_dma_half_transfer(void) override; virtual void rx_dma_half_transfer(void);
virtual void rx_dma_error(dma_helper::dma_error_type reason) override; virtual void rx_dma_error(dma_helper::dma_error_type reason);
virtual void tx_dma_transfer_complete(void) override; virtual void tx_dma_transfer_complete(void);
virtual void tx_dma_half_transfer(void) override; virtual void tx_dma_half_transfer(void);
virtual void tx_dma_error(dma_helper::dma_error_type reason) override; virtual void tx_dma_error(dma_helper::dma_error_type reason);
struct Buffer struct Buffer
{ {
packet pkt; Packet packet;
// transfer area ends here // transfer area ends here
bool volatile busy = 0; bool volatile busy = 0;
bool volatile error = 0; bool volatile error = 0;
uint16_t requested_length = 0; uint16_t requestedLength = 0;
uint32_t error_info = 0; uint32_t errorInfo = 0;
}; };
static const uint8_t STARTMARKER = 0x95; static const uint8_t STARTMARKER = 0x95;
uint8_t m_rx_serial_nr = -1; uint8_t m_rxSerialNo = -1;
uint8_t m_tx_serial_nr = -1; uint8_t m_txSerialNo = -1;
stats m_stats; Stats m_stats;
bool m_rx_buffer_selector = false; bool m_rxBufferSelector = false;
crc_handler::slot<2> m_crc_slot; crc_handler::slot<2> m_crcSlot;
ihs_usart_callback *m_user_callback = nullptr; IHsUsartCallback *m_userCallback = nullptr;
uintptr_t m_user_callback_param = 0; uintptr_t m_userCallbackParam = 0;
Buffer m_tx_buffer; Buffer m_txBuffer;
Buffer m_rx_buffers[2]; Buffer m_rxBuffers[2];
}; };
} }

View file

@ -10,8 +10,8 @@
namespace f4ll { namespace f4ll {
console_handler::console_handler(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t stream_rx, uint32_t stream_tx) console_handler::console_handler(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t streamRx, uint32_t streamTx)
: usart_core(usart, dma, stream_rx, stream_tx) : usart_core(usart, dma, streamRx, streamTx)
{ {
} }
@ -49,11 +49,11 @@ void console_handler::tx_dma_error(dma_helper::dma_error_type reason)
b += strcpy_ex(b, s); \ b += strcpy_ex(b, s); \
b += uitodec(b, u); b += uitodec(b, u);
void console_handler::PrintStats(uint8_t id, packet_usart &usart) void console_handler::PrintStats(uint8_t id, PacketUsart &usart)
{ {
char ids[] = " : "; char ids[] = " : ";
char *buffer = m_buffer; char *buffer = m_buffer;
packet_usart::stats const &stats(usart.get_stats()); PacketUsart::Stats const &stats(usart.GetStats());
ids[0] = id + '0'; ids[0] = id + '0';
buffer += strcpy_ex(buffer, ids); buffer += strcpy_ex(buffer, ids);
@ -61,14 +61,14 @@ void console_handler::PrintStats(uint8_t id, packet_usart &usart)
ADDINFO(buffer, " r: ", stats.rcvd); ADDINFO(buffer, " r: ", stats.rcvd);
ADDINFO(buffer, " sk: ", stats.skiped); ADDINFO(buffer, " sk: ", stats.skiped);
ADDINFO(buffer, " or: ", stats.overrun); ADDINFO(buffer, " or: ", stats.overrun);
ADDINFO(buffer, " he: ", stats.hdr_error); ADDINFO(buffer, " he: ", stats.hdrError);
ADDINFO(buffer, " pe: ", stats.payload_errror); ADDINFO(buffer, " pe: ", stats.payloadErrror);
buffer += strcpy_ex(buffer, ",0x"); buffer += strcpy_ex(buffer, ",0x");
buffer += uitohex(buffer, stats.pep1, 8); buffer += uitohex(buffer, stats.pep1, 8);
buffer += strcpy_ex(buffer, ",0x"); buffer += strcpy_ex(buffer, ",0x");
buffer += uitohex(buffer, stats.pep2, 8); buffer += uitohex(buffer, stats.pep2, 8);
ADDINFO(buffer, " rde: ", stats.rx_dma_error); ADDINFO(buffer, " rde: ", stats.rxDmaError);
ADDINFO(buffer, " tde: ", stats.tx_dma_error); ADDINFO(buffer, " tde: ", stats.txDmaError);
ADDINFO(buffer, " pmh: ", stats.premature_hdr); ADDINFO(buffer, " pmh: ", stats.premature_hdr);
ADDINFO(buffer, " pmp: ", stats.premature_payload); ADDINFO(buffer, " pmp: ", stats.premature_payload);
buffer += strcpy_ex(buffer, "\r\n"); buffer += strcpy_ex(buffer, "\r\n");

View file

@ -32,7 +32,7 @@ void crc_handler::attach_slot(slot_base &slot)
__set_PRIMASK(prim); __set_PRIMASK(prim);
} }
bool crc_handler::enqueue(slot_base &slot, uint8_t task, void const *address, uint16_t len, icallback *cb, uintptr_t cb_param) bool crc_handler::enqueue(slot_base &slot, uint8_t task, void const *address, uint16_t len, icallback *cb, uintptr_t cbParam)
{ {
uint32_t prim = __get_PRIMASK(); uint32_t prim = __get_PRIMASK();
bool immediate; bool immediate;
@ -47,10 +47,10 @@ bool crc_handler::enqueue(slot_base &slot, uint8_t task, void const *address, ui
slot[task].m_address = (!immediate) ? address : nullptr; slot[task].m_address = (!immediate) ? address : nullptr;
slot[task].m_word_count = (len + 3) / 4; slot[task].m_word_count = (len + 3) / 4;
slot[task].m_callback = cb; slot[task].m_callback = cb;
slot[task].m_callback_param = cb_param; slot[task].m_callback_param = cbParam;
if (immediate) { if (immediate) {
m_active_slot = &slot; m_active_slot = &slot;
m_active_task = task; m_activeTask = task;
} }
__set_PRIMASK(prim); __set_PRIMASK(prim);
@ -84,44 +84,44 @@ void crc_handler::dma_transfer_completed(void)
*m_dma.get_ifc_reg() = m_dma.get_tc_mask(); *m_dma.get_ifc_reg() = m_dma.get_tc_mask();
LL_DMA_DisableStream(m_dma.get_dma(), m_dma.get_stream()); LL_DMA_DisableStream(m_dma.get_dma(), m_dma.get_stream());
if (m_active_slot) { if (m_active_slot) {
if ((*m_active_slot)[m_active_task].m_callback) { if ((*m_active_slot)[m_activeTask].m_callback) {
(*m_active_slot)[m_active_task].m_callback->crc_succeeded( (*m_active_slot)[m_activeTask].m_callback->crc_succeeded(
(*m_active_slot)[m_active_task].m_callback_param, CRC->DR, m_active_task); (*m_active_slot)[m_activeTask].m_callback_param, CRC->DR, m_activeTask);
} else if ((*m_active_slot)[m_active_task].m_callback_param) { } else if ((*m_active_slot)[m_activeTask].m_callback_param) {
*reinterpret_cast<uint32_t *>((*m_active_slot)[m_active_task].m_callback_param) = CRC->DR; *reinterpret_cast<uint32_t *>((*m_active_slot)[m_activeTask].m_callback_param) = CRC->DR;
} }
} }
} else if (*m_dma.get_is_reg() & m_dma.get_te_mask()) { // DMA transfer error } else if (*m_dma.get_is_reg() & m_dma.get_te_mask()) { // DMA transfer error
*m_dma.get_ifc_reg() = m_dma.get_te_mask(); *m_dma.get_ifc_reg() = m_dma.get_te_mask();
LL_DMA_DisableStream(m_dma.get_dma(), m_dma.get_stream()); LL_DMA_DisableStream(m_dma.get_dma(), m_dma.get_stream());
if (m_active_slot) { if (m_active_slot) {
if ((*m_active_slot)[m_active_task].m_callback) { if ((*m_active_slot)[m_activeTask].m_callback) {
(*m_active_slot)[m_active_task].m_callback->crc_failed( (*m_active_slot)[m_activeTask].m_callback->crc_failed(
(*m_active_slot)[m_active_task].m_callback_param, CRC->DR, m_active_task); (*m_active_slot)[m_activeTask].m_callback_param, CRC->DR, m_activeTask);
} else if ((*m_active_slot)[m_active_task].m_callback_param) { } else if ((*m_active_slot)[m_activeTask].m_callback_param) {
*reinterpret_cast<uint32_t *>((*m_active_slot)[m_active_task].m_callback_param) = -1; *reinterpret_cast<uint32_t *>((*m_active_slot)[m_activeTask].m_callback_param) = -1;
} }
} }
} }
(*m_active_slot)[m_active_task].m_callback = nullptr; (*m_active_slot)[m_activeTask].m_callback = nullptr;
(*m_active_slot)[m_active_task].m_callback_param = 0; (*m_active_slot)[m_activeTask].m_callback_param = 0;
(*m_active_slot)[m_active_task].m_word_count = 0; (*m_active_slot)[m_activeTask].m_word_count = 0;
start_next_task(); start_next_task();
} }
void crc_handler::start_next_task(void) void crc_handler::start_next_task(void)
{ {
bool more_tasks; bool moreTasks;
uint8_t index = 0; uint8_t index = 0;
do { do {
slot_base volatile *slot = m_first_slot; slot_base volatile *slot = m_first_slot;
more_tasks = false; moreTasks = false;
while (slot) { while (slot) {
if (index < slot->m_task_count) { if (index < slot->m_task_count) {
if ((*slot)[index].m_address) { if ((*slot)[index].m_address) {
m_active_slot = slot; m_active_slot = slot;
m_active_task = index; m_activeTask = index;
CRC->CR = 1; CRC->CR = 1;
LL_DMA_SetM2MSrcAddress(m_dma.get_dma(), m_dma.get_stream(), reinterpret_cast<uint32_t>((*slot)[index].m_address)); LL_DMA_SetM2MSrcAddress(m_dma.get_dma(), m_dma.get_stream(), reinterpret_cast<uint32_t>((*slot)[index].m_address));
LL_DMA_SetDataLength(m_dma.get_dma(), m_dma.get_stream(), (*slot)[index].m_word_count); LL_DMA_SetDataLength(m_dma.get_dma(), m_dma.get_stream(), (*slot)[index].m_word_count);
@ -130,13 +130,13 @@ void crc_handler::start_next_task(void)
return; return;
} }
if (index + 1 < slot->m_task_count) { if (index + 1 < slot->m_task_count) {
more_tasks = true; moreTasks = true;
} }
} }
slot = slot->m_next; slot = slot->m_next;
} }
++index; ++index;
} while (more_tasks); } while (moreTasks);
m_active_slot = nullptr; m_active_slot = nullptr;
} }

View file

@ -9,6 +9,17 @@ q * ll_dmahelper.cpp
namespace f4ll { namespace f4ll {
const uint32_t dma_helper::m_fe_masks[8] = {DMA_LISR_FEIF0, DMA_LISR_FEIF1, DMA_LISR_FEIF2, DMA_LISR_FEIF3,
DMA_HISR_FEIF4, DMA_HISR_FEIF5, DMA_HISR_FEIF6, DMA_HISR_FEIF7};
const uint32_t dma_helper::m_dme_masks[8] = {DMA_LISR_DMEIF0, DMA_LISR_DMEIF1, DMA_LISR_DMEIF2, DMA_LISR_DMEIF3,
DMA_HISR_DMEIF4, DMA_HISR_DMEIF5, DMA_HISR_DMEIF6, DMA_HISR_DMEIF7};
const uint32_t dma_helper::m_te_masks[8] = {DMA_LISR_TEIF0, DMA_LISR_TEIF1, DMA_LISR_TEIF2, DMA_LISR_TEIF3,
DMA_HISR_TEIF4, DMA_HISR_TEIF5, DMA_HISR_TEIF6, DMA_HISR_TEIF7};
const uint32_t dma_helper::m_ht_masks[8] = {DMA_LISR_HTIF0, DMA_LISR_HTIF1, DMA_LISR_HTIF2, DMA_LISR_HTIF3,
DMA_HISR_HTIF4, DMA_HISR_HTIF5, DMA_HISR_HTIF6, DMA_HISR_HTIF7};
const uint32_t dma_helper::m_tc_masks[8] = {DMA_LISR_TCIF0, DMA_LISR_TCIF1, DMA_LISR_TCIF2, DMA_LISR_TCIF3,
DMA_HISR_TCIF4, DMA_HISR_TCIF5, DMA_HISR_TCIF6, DMA_HISR_TCIF7};
dma_helper::dma_helper(DMA_TypeDef *dma, uint32_t stream) dma_helper::dma_helper(DMA_TypeDef *dma, uint32_t stream)
: m_dma(dma), : m_dma(dma),
m_stream(stream), m_stream(stream),

View file

@ -15,14 +15,38 @@
extern "C" { extern "C" {
#endif #endif
fault_context_t g_fault_context; typedef struct {
uint32_t R0;
uint32_t R1;
uint32_t R2;
uint32_t R3;
uint32_t R4;
uint32_t R5;
uint32_t R6;
uint32_t R7;
uint32_t R8;
uint32_t R9;
uint32_t R10;
uint32_t R11;
uint32_t R12;
uint32_t SP;
uint32_t LR;
uint32_t PC;
uint32_t xPSR;
uint32_t PSP;
uint32_t MSP;
uint32_t EXC_RETURN;
uint32_t CONTROL;
} fault_context_t;
fault_context_t g_faultContext;
void __attribute__((weak)) app_fault_callback(uint32_t reason) void __attribute__((weak)) app_fault_callback(uint32_t reason)
{ {
(void)reason; (void)reason;
} }
void swo_send_str(char const *str, uint8_t len, uint8_t port) void SwoSendStr(char const *str, uint8_t len, uint8_t port)
{ {
while(len) { while(len) {
if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && // ITM enabled if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && // ITM enabled
@ -53,23 +77,24 @@ void swo_send_str(char const *str, uint8_t len, uint8_t port)
void fault_print_str(char const *fmtstr, uint32_t *values) void fault_print_str(char const *fmtstr, uint32_t *values)
{ {
char hex_str[9]={0}; char hex_str[9]={0};
char const *next_chunk = fmtstr; char const *nextChunk = fmtstr;
while(*fmtstr) { while(*fmtstr) {
if(*fmtstr == '%') { if(*fmtstr == '%') {
swo_send_str(next_chunk, fmtstr - next_chunk, 0); SwoSendStr(nextChunk, fmtstr-nextChunk, 0);
uitohex(hex_str, *values++, 8); uitohex(hex_str, *values++, 8);
swo_send_str(hex_str, 8, 0); SwoSendStr(hex_str, 8, 0);
next_chunk = fmtstr + 1; nextChunk = fmtstr +1;
} }
++fmtstr; ++fmtstr;
} }
if (next_chunk != fmtstr) { if(nextChunk != fmtstr)
swo_send_str(next_chunk, fmtstr - next_chunk, 0); SwoSendStr(nextChunk, fmtstr-nextChunk, 0);
}
} }
void fault_handler(uint32_t type, fault_context_t *context)
__attribute__((noreturn)) void FaultHandler(uint32_t type, fault_context_t *context)
{ {
uint32_t FSR[9] = { uint32_t FSR[9] = {
SCB->HFSR, SCB->HFSR,

View file

@ -9,80 +9,79 @@
namespace f4ll { namespace f4ll {
template <typename T> static inline T round_up_to_4(T input) template <typename T> static inline T RoundUpTo4(T input)
{ {
return (input + 3) & (((T)-1) - 3); return (input + 3) & (((T)-1) - 3);
} }
packet_usart::packet_usart(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t stream_rx, uint32_t stream_tx) PacketUsart::PacketUsart(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t streamRx, uint32_t streamTx)
: usart_core(usart, dma, stream_rx, stream_tx) : usart_core(usart, dma, streamRx, streamTx)
{ {
crc_handler::instance().attach_slot(m_crc_slot); crc_handler::instance().attach_slot(m_crcSlot);
LL_USART_EnableIT_IDLE(usart); LL_USART_EnableIT_IDLE(usart);
LL_USART_EnableIT_ERROR(usart); LL_USART_EnableIT_ERROR(usart);
} }
void packet_usart::rx_processed(bool second) void PacketUsart::RxProcessed(bool second)
{ {
m_rx_buffers[second].busy = false; m_rxBuffers[second].busy = false;
m_rx_buffers[second].error = false; m_rxBuffers[second].error = false;
} }
void packet_usart::set_callback(ihs_usart_callback *callback, uintptr_t callback_param) void PacketUsart::SetCallback(IHsUsartCallback *callback, uintptr_t callbackParam)
{ {
m_user_callback = callback; m_userCallback = callback;
m_user_callback_param = callback_param; m_userCallbackParam = callbackParam;
} }
void packet_usart::post_packet(uint8_t const *payload, uint8_t length, bool wait_for_crc_queue) void PacketUsart::PostPacket(uint8_t const *payload, uint8_t length, bool waitForCrcQueue)
{ {
uint16_t payload_length = round_up_to_4((uint16_t)length); uint16_t payloadLength = RoundUpTo4((uint16_t)length);
build_header(m_tx_buffer.pkt, m_tx_serial_nr++, length); BuildHeader(m_txBuffer.packet, m_txSerialNo++, length);
if (payload) { if (payload) {
memcpy(m_tx_buffer.pkt.payload, payload, length); memcpy(m_txBuffer.packet.payload, payload, length);
} }
m_tx_buffer.requested_length = sizeof(m_tx_buffer.pkt.header) + payload_length + sizeof(uint32_t); m_txBuffer.requestedLength = sizeof(m_txBuffer.packet.header) + payloadLength + sizeof(uint32_t);
m_tx_buffer.busy = true; m_txBuffer.busy = true;
m_tx_buffer.error = false; m_txBuffer.error = false;
crc_handler::instance().enqueue( crc_handler::instance().enqueue(
m_crc_slot, 0, &m_tx_buffer.pkt, sizeof(packet_header) + payload_length, nullptr, m_crcSlot, 0, &m_txBuffer.packet, sizeof(PacketHeader) + payloadLength, nullptr,
reinterpret_cast<uintptr_t>(m_tx_buffer.pkt.payload + payload_length)); reinterpret_cast<uintptr_t>(m_txBuffer.packet.payload + payloadLength));
while (wait_for_crc_queue && crc_handler::instance().is_queued(m_crc_slot, 0)) while (waitForCrcQueue && crc_handler::instance().is_queued(m_crcSlot, 0))
; ;
setup_transmit(&m_tx_buffer.pkt, m_tx_buffer.requested_length); setup_transmit(&m_txBuffer.packet, m_txBuffer.requestedLength);
++m_stats.sent; ++m_stats.sent;
} }
void packet_usart::setup_receive() void PacketUsart::SetupReceive()
{ {
m_rx_buffers[m_rx_buffer_selector].requested_length = sizeof(m_rx_buffers[m_rx_buffer_selector].pkt); m_rxBuffers[m_rxBufferSelector].requestedLength = sizeof(m_rxBuffers[m_rxBufferSelector].packet);
usart_core::setup_receive(&m_rx_buffers[m_rx_buffer_selector], sizeof(m_rx_buffers[m_rx_buffer_selector].pkt)); usart_core::setup_receive(&m_rxBuffers[m_rxBufferSelector], sizeof(m_rxBuffers[m_rxBufferSelector].packet));
} }
////////////////////////////////////// //////////////////////////////////////
// UsartCore pure virtual functions // // UsartCore pure virtual functions //
////////////////////////////////////// //////////////////////////////////////
void packet_usart::receiver_idle(void) void PacketUsart::receiver_idle(void)
{ {
uint16_t rcvdLen = uint16_t rcvdLen = m_rxBuffers[m_rxBufferSelector].requestedLength - LL_DMA_GetDataLength(m_rx_dma.get_dma(), m_rx_dma.get_stream());
m_rx_buffers[m_rx_buffer_selector].requested_length - LL_DMA_GetDataLength(m_rx_dma.get_dma(), m_rx_dma.get_stream());
if (rcvdLen >= sizeof(packet_header)) { if (rcvdLen >= sizeof(PacketHeader)) {
if (check_header(m_rx_buffers[m_rx_buffer_selector].pkt.header)) { if (CheckHeader(m_rxBuffers[m_rxBufferSelector].packet.header)) {
if (rcvdLen >= sizeof(packet_header) + round_up_to_4((uint16_t)m_rx_buffers[m_rx_buffer_selector].pkt.header.payload_length) + if (rcvdLen >= sizeof(PacketHeader) + RoundUpTo4((uint16_t)m_rxBuffers[m_rxBufferSelector].packet.header.payloadLength) +
sizeof(uint32_t)) { sizeof(uint32_t)) {
LL_DMA_DisableStream(m_rx_dma.get_dma(), m_rx_dma.get_stream()); LL_DMA_DisableStream(m_rx_dma.get_dma(), m_rx_dma.get_stream());
} else { } else {
++m_stats.premature_payload; ++m_stats.premature_payload;
} }
} else { } else {
m_rx_buffers[m_rx_buffer_selector].error = 1; m_rxBuffers[m_rxBufferSelector].error = 1;
LL_DMA_DisableStream(m_rx_dma.get_dma(), m_rx_dma.get_stream()); LL_DMA_DisableStream(m_rx_dma.get_dma(), m_rx_dma.get_stream());
} }
} else { } else {
@ -90,122 +89,122 @@ void packet_usart::receiver_idle(void)
} }
} }
void packet_usart::transmission_complete(void) void PacketUsart::transmission_complete(void)
{ {
LL_USART_DisableDirectionTx(m_usart); // enforcing an idle frame LL_USART_DisableDirectionTx(m_usart); // enforcing an idle frame
LL_USART_EnableDirectionTx(m_usart); LL_USART_EnableDirectionTx(m_usart);
m_tx_buffer.busy = 0; m_txBuffer.busy = 0;
} }
void packet_usart::framing_error(void) {} void PacketUsart::framing_error(void) {}
void packet_usart::overrun(void) {} void PacketUsart::overrun(void) {}
void packet_usart::rx_dma_transfer_complete(void) void PacketUsart::rx_dma_transfer_complete(void)
{ {
if (check_header(m_rx_buffers[m_rx_buffer_selector].pkt.header)) { if (CheckHeader(m_rxBuffers[m_rxBufferSelector].packet.header)) {
crc_handler::instance().enqueue( crc_handler::instance().enqueue(
m_crc_slot, 1, &m_rx_buffers[m_rx_buffer_selector].pkt, m_crcSlot, 1, &m_rxBuffers[m_rxBufferSelector].packet,
sizeof(packet_header) + round_up_to_4((uint16_t)m_rx_buffers[m_rx_buffer_selector].pkt.header.payload_length), this, sizeof(PacketHeader) + RoundUpTo4((uint16_t)m_rxBuffers[m_rxBufferSelector].packet.header.payloadLength), this,
m_rx_buffer_selector); m_rxBufferSelector);
} else { } else {
++m_stats.hdr_error; ++m_stats.hdrError;
m_rx_buffers[m_rx_buffer_selector].error = true; m_rxBuffers[m_rxBufferSelector].error = true;
} }
switch_rx_buffers(); SwitchRxBuffers();
} }
void packet_usart::rx_dma_half_transfer(void) {} void PacketUsart::rx_dma_half_transfer(void) {}
void packet_usart::rx_dma_error(dma_helper::dma_error_type reason) void PacketUsart::rx_dma_error(dma_helper::dma_error_type reason)
{ {
(void)reason; (void)reason;
m_rx_buffers[m_rx_buffer_selector].error = 1; m_rxBuffers[m_rxBufferSelector].error = 1;
++m_stats.rx_dma_error; ++m_stats.rxDmaError;
switch_rx_buffers(); SwitchRxBuffers();
} }
void packet_usart::tx_dma_transfer_complete(void) void PacketUsart::tx_dma_transfer_complete(void)
{ {
LL_USART_EnableIT_TC(m_usart); LL_USART_EnableIT_TC(m_usart);
LL_DMA_DisableStream(m_tx_dma.get_dma(), m_tx_dma.get_stream()); LL_DMA_DisableStream(m_tx_dma.get_dma(), m_tx_dma.get_stream());
} }
void packet_usart::tx_dma_half_transfer(void) {} void PacketUsart::tx_dma_half_transfer(void) {}
void packet_usart::tx_dma_error(dma_helper::dma_error_type reason) void PacketUsart::tx_dma_error(dma_helper::dma_error_type reason)
{ {
(void)reason; (void)reason;
m_tx_buffer.error = 1; m_txBuffer.error = 1;
++m_stats.tx_dma_error; ++m_stats.txDmaError;
} }
/////////////////////// ///////////////////////
// Private functions // // Private functions //
/////////////////////// ///////////////////////
void packet_usart::build_header(packet &packet, uint8_t serial_nr, uint8_t length) void PacketUsart::BuildHeader(Packet &packet, uint8_t serialNo, uint8_t length)
{ {
uint8_t hash = STARTMARKER; uint8_t hash = STARTMARKER;
packet.header.start_byte = STARTMARKER; packet.header.startByte = STARTMARKER;
packet.header.serial = serial_nr; packet.header.serial = serialNo;
hash ^= serial_nr; hash ^= serialNo;
packet.header.payload_length = length; packet.header.payloadLength = length;
hash ^= length; hash ^= length;
packet.header.hash = hash; packet.header.hash = hash;
} }
bool packet_usart::check_header(packet_header &header) bool PacketUsart::CheckHeader(PacketHeader &header)
{ {
return header.start_byte == STARTMARKER && (header.start_byte ^ header.serial ^ header.payload_length) == header.hash; return header.startByte == STARTMARKER && (header.startByte ^ header.serial ^ header.payloadLength) == header.hash;
} }
void packet_usart::switch_rx_buffers(void) void PacketUsart::SwitchRxBuffers(void)
{ {
++m_stats.rcvd; ++m_stats.rcvd;
m_rx_buffer_selector = !m_rx_buffer_selector; m_rxBufferSelector = !m_rxBufferSelector;
if (m_rx_buffers[m_rx_buffer_selector].busy) { if (m_rxBuffers[m_rxBufferSelector].busy) {
++m_stats.overrun; ++m_stats.overrun;
} }
setup_receive(); SetupReceive();
} }
/////////////////////////// ///////////////////////////
// crc_handler::ICallback // // crc_handler::ICallback //
/////////////////////////// ///////////////////////////
void packet_usart::crc_succeeded(uintptr_t callback_param, uint32_t crc, uint8_t task) void PacketUsart::crc_succeeded(uintptr_t callbackParam, uint32_t crc, uint8_t task)
{ {
(void)task; (void)task;
Buffer &buf(m_rx_buffers[static_cast<int>(callback_param)]); Buffer &buf(m_rxBuffers[static_cast<int>(callbackParam)]);
buf.busy = 1; buf.busy = 1;
if (*(uint32_t *)(buf.pkt.payload + round_up_to_4((uint16_t)buf.pkt.header.payload_length)) != crc) { if (*(uint32_t *)(buf.packet.payload + RoundUpTo4((uint16_t)buf.packet.header.payloadLength)) != crc) {
buf.error = 1; buf.error = 1;
buf.error_info = crc; buf.errorInfo = crc;
++m_stats.payload_errror; ++m_stats.payloadErrror;
} }
if (m_user_callback) { if (m_userCallback) {
buf.busy = !m_user_callback->packet_received(this, m_user_callback_param, buf.pkt); buf.busy = !m_userCallback->PacketReceived(this, m_userCallbackParam, buf.packet);
} }
} }
void packet_usart::crc_failed(uintptr_t callback_param, uint32_t crc, uint8_t task) void PacketUsart::crc_failed(uintptr_t callbackParam, uint32_t crc, uint8_t task)
{ {
(void)crc; (void)crc;
(void)task; (void)task;
Buffer &buf(m_rx_buffers[static_cast<int>(callback_param)]); Buffer &buf(m_rxBuffers[static_cast<int>(callbackParam)]);
buf.busy = buf.error = true; buf.busy = buf.error = true;
buf.error_info = 0; buf.errorInfo = 0;
++m_stats.payload_errror; ++m_stats.payloadErrror;
if (m_user_callback) { if (m_userCallback) {
buf.busy = !m_user_callback->packet_received(this, m_user_callback_param, buf.pkt); buf.busy = !m_userCallback->PacketReceived(this, m_userCallbackParam, buf.packet);
} }
} }