diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..6d24e95 --- /dev/null +++ b/.clang-format @@ -0,0 +1,33 @@ +BasedOnStyle: LLVM +UseTab: Never +IndentWidth: 4 +TabWidth: 4 +BreakBeforeBraces: Custom +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: true +AllowShortLambdasOnASingleLine: true +AllowAllArgumentsOnNextLine: true +IndentCaseLabels: true +AccessModifierOffset: -4 +NamespaceIndentation: None +FixNamespaceComments: false +PackConstructorInitializers: Never +AlignAfterOpenBracket: AlwaysBreak +InsertBraces: true +BraceWrapping: + AfterClass: true # false + AfterControlStatement: false + AfterEnum: false # false + AfterFunction: true # false + AfterNamespace: false + AfterObjCDeclaration: true # false + AfterStruct: true # false + AfterUnion: true # false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +ColumnLimit: 140 diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..0664851 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,19 @@ +add_library(f4ll STATIC + src/console_handler.cpp + src/crc_handler.cpp + src/dma_helper.cpp + src/fault.cpp + src/memcpy_dma.cpp + src/packet_usart.cpp + src/str_util.cpp + src/usart_core.cpp +) + +target_include_directories(f4ll PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/inc +) + +target_link_libraries(f4ll PUBLIC platform stm32cubemx) + +# ST code quality workaround - Suppres register storage class warning (C++17...) +target_compile_options(f4ll PRIVATE -Wno-register) diff --git a/component.mk b/component.mk deleted file mode 100644 index 28874d8..0000000 --- a/component.mk +++ /dev/null @@ -1,11 +0,0 @@ -#encoder -SELF_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) -REL_DIR := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST)))) -ifeq ($(MKDBG), 1) - $(info >>> $(REL_DIR)/component.mk) -endif -$(eval C_INCLUDES += -I$(REL_DIR)/inc) -$(eval CXX_SOURCES += $(wildcard $(REL_DIR)/src/*.cpp)) -ifeq ($(MKDBG), 1) - $(info <<<) -endif diff --git a/inc/f4ll/console_handler.h b/inc/f4ll/console_handler.h new file mode 100644 index 0000000..34da08c --- /dev/null +++ b/inc/f4ll/console_handler.h @@ -0,0 +1,44 @@ +/* + * ll_consolehandler.h + * + * Created on: Nov 7, 2019 + * Author: abody + */ + +#ifndef LL_CONSOLEHANDLER_H_ +#define LL_CONSOLEHANDLER_H_ + +#include +#include + +namespace f4ll { + +class console_handler : public usart_core, public singleton +{ + friend class singleton; + +public: + void PrintStats(uint8_t id, packet_usart &usart); + +private: + console_handler(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t stream_rx, uint32_t stream_tx); + + // LL_UsartCore pure virtual function implementations + virtual void receiver_idle(void) override; + virtual void transmission_complete(void) override; + virtual void framing_error(void) override; + virtual void overrun(void) override; + virtual void rx_dma_transfer_complete(void) override; + virtual void rx_dma_half_transfer(void) override; + virtual void rx_dma_error(dma_helper::dma_error_type reason) override; + virtual void tx_dma_transfer_complete(void) override; + virtual void tx_dma_half_transfer(void) override; + virtual void tx_dma_error(dma_helper::dma_error_type reason) override; + + char m_buffer[128]; + uint16_t m_used = 0; +}; + +} /* namespace f4ll */ + +#endif /* LL_CONSOLEHANDLER_H_ */ diff --git a/inc/f4ll/consolehandler.h b/inc/f4ll/consolehandler.h deleted file mode 100644 index aad2acc..0000000 --- a/inc/f4ll/consolehandler.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * ll_consolehandler.h - * - * Created on: Nov 7, 2019 - * Author: abody - */ - -#ifndef LL_CONSOLEHANDLER_H_ -#define LL_CONSOLEHANDLER_H_ - -#include "f4ll/packetusart.h" -#include "singleton.h" - - -namespace f4ll { - -class ConsoleHandler: public UsartCore, public Singleton -{ - friend class Singleton; - -public: - void PrintStats(uint8_t id, PacketUsart &usart); - -private: - ConsoleHandler(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t streamRx, uint32_t streamTx); - - // LL_UsartCore pure virtual function implementations - virtual void ReceiverIdle(void); - virtual void TransmissionComplete(void); - virtual void FramingError(void); - virtual void Overrun(void); - virtual void RxDmaTransferComplete(void); - virtual void RxDmaHalfTransfer(void); - virtual void RxDmaError(DmaHelper::DmaErrorType reason); - virtual void TxDmaTransferComplete(void); - virtual void TxDmaHalfTransfer(void); - virtual void TxDmaError(DmaHelper::DmaErrorType reason); - - char m_buffer[128]; - uint16_t m_used = 0; -}; - -} /* namespace f4ll */ - -#endif /* LL_CONSOLEHANDLER_H_ */ diff --git a/inc/f4ll/crc_handler.h b/inc/f4ll/crc_handler.h new file mode 100644 index 0000000..650eebb --- /dev/null +++ b/inc/f4ll/crc_handler.h @@ -0,0 +1,90 @@ +/* + * ll_crc_handler.h + * + * Created on: Oct 26, 2019 + * Author: compi + */ +#pragma once + +#include +#include +#include +#include + +namespace f4ll { + +class crc_handler : public singleton +{ + friend class singleton; + +public: + struct icallback + { + virtual void crc_succeeded(uintptr_t callback_param, uint32_t crc, uint8_t task) = 0; + virtual void crc_failed(uintptr_t callback_param, uint32_t crc, uint8_t task) = 0; + }; + + class slot_base + { + friend class crc_handler; + + public: + struct crc_task + { + void const *m_address; // changed to nullptr when execution starts + uint16_t m_word_count; + icallback *m_callback; + uintptr_t m_callback_param; + }; + + private: + slot_base volatile *m_next = nullptr; + uint8_t m_task_count; + + virtual crc_task volatile &operator[](int index) volatile = 0; + + protected: + slot_base(unsigned int task_count) + : m_task_count(task_count) + { + } + slot_base() = delete; + slot_base(slot_base const &other) = delete; + }; + + template class slot : public slot_base + { + public: + slot() + : slot_base(n) + { + } + virtual crc_task volatile &operator[](int index) volatile { return m_tasks[index]; } + + private: + slot::crc_task m_tasks[n]; + }; + + void attach_slot(slot_base &slot); + bool enqueue(slot_base &slot, uint8_t task, void const *address, uint16_t len, icallback *cb, uintptr_t cb_param); + uint32_t compute(slot_base &slot, uint8_t task, void const *address, uint16_t len); + + bool is_active(slot_base &slot, uint8_t task) const; + bool is_queued(slot_base &slot, uint8_t task) const; + bool is_running(slot_base &slot, uint8_t task) const; + + void dma_transfer_completed(void); + +private: + crc_handler(DMA_TypeDef *dma, uint32_t stream); + + void start_next_task(void); + void wait_results(slot_base &slot, uint8_t task) const; + + dma_helper m_dma; + slot_base volatile *m_first_slot = nullptr; + slot_base volatile *m_active_slot = nullptr; + int volatile m_active_task; +}; + +} // namespace f4ll diff --git a/inc/f4ll/crchandler.h b/inc/f4ll/crchandler.h deleted file mode 100644 index e338ba5..0000000 --- a/inc/f4ll/crchandler.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * ll_crchandler.h - * - * Created on: Oct 26, 2019 - * Author: compi - */ - -#ifndef LL_CRCHANDLER_H_ -#define LL_CRCHANDLER_H_ -#include -#include -#include "f4ll/dmahelper.h" -#include "singleton.h" - -extern "C" void _HandleCrcDmaIrq(void); - -namespace f4ll { - -class CrcHandler : public Singleton -{ - friend class Singleton; - -public: - struct ICallback - { - virtual void CrcSucceeded(uintptr_t callbackParam, uint32_t crc, uint8_t task) = 0; - virtual void CrcFailed(uintptr_t callbackParam, uint32_t crc, uint8_t task) = 0; - }; - - class SlotBase - { - friend class CrcHandler; - public: - struct CrcTask { - void const * m_address; // changed to nullptr when execution starts - uint16_t m_wordCount; - ICallback *m_callback; - uintptr_t m_callbackParam; - }; - - private: - SlotBase volatile *m_next = nullptr; - uint8_t m_taskCount; - - virtual CrcTask volatile & operator[](int index) volatile = 0; - - protected: - SlotBase(unsigned int taskCount) : m_taskCount(taskCount) {} - SlotBase() = delete; - SlotBase(SlotBase const &other) = delete; - }; - - template class Slot : public SlotBase - { - public: - Slot() : SlotBase(n) {} - virtual CrcTask volatile & operator[](int index) volatile { return m_tasks[index]; } - - private: - Slot::CrcTask m_tasks[n]; - }; - - void AttachSlot(SlotBase &slot); - bool Enqueue(SlotBase &slot, uint8_t task, void const *address, uint16_t len, ICallback *cb, uintptr_t cbParam); - uint32_t Compute(SlotBase &slot, uint8_t task, void const *address, uint16_t len); - - bool IsActive(SlotBase &slot, uint8_t task) const; - bool IsQueued(SlotBase &slot, uint8_t task) const; - bool IsRunning(SlotBase &slot, uint8_t task) const; - - void DmaTransferCompleted(void); - -private: - CrcHandler(DMA_TypeDef *dma, uint32_t stream); - - friend void ::_HandleCrcDmaIrq(void); - void StartNextTask(void); - void WaitResults(SlotBase &slot, uint8_t task) const; - - DmaHelper m_dma; - SlotBase volatile *m_firstSlot = nullptr; - SlotBase volatile *m_activeSlot = nullptr; - int volatile m_activeTask; -}; - - -} // namespace f4ll - -#endif /* LL_CRCHANDLER_H_ */ diff --git a/inc/f4ll/dma_helper.h b/inc/f4ll/dma_helper.h new file mode 100644 index 0000000..534b59f --- /dev/null +++ b/inc/f4ll/dma_helper.h @@ -0,0 +1,60 @@ +/* + * ll_dmahelper.h + * + * Created on: Oct 25, 2019 + * Author: abody + */ + +#ifndef LL_DMAHELPER_H_ +#define LL_DMAHELPER_H_ + +#include +#include + +namespace f4ll { + +class dma_helper +{ +public: + dma_helper(DMA_TypeDef *dma, uint32_t stream); + dma_helper(dma_helper const &base) = default; + + inline DMA_TypeDef *get_dma() const { return m_dma; } + inline uint32_t get_stream() const { return m_stream; } + inline volatile uint32_t *get_is_reg() const { return m_is_reg; } + inline volatile uint32_t *get_ifc_reg() const { return m_ifc_reg; } + inline uint32_t get_fe_mask() const { return m_fe_masks[m_stream]; } + inline uint32_t get_dme_mask() const { return m_dme_masks[m_stream]; } + inline uint32_t get_te_mask() const { return m_te_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 bool is_enabled_it_ht() const { 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_tc() const { 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_fe() const { return LL_DMA_IsEnabledIT_FE(m_dma, m_stream) != 0; } + + enum class dma_error_type { transfer, direct_mode, fifo }; + +private: + DMA_TypeDef *m_dma; + uint32_t m_stream; + volatile uint32_t *m_is_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, + DMA_HISR_FEIF4, DMA_HISR_FEIF5, DMA_HISR_FEIF6, DMA_HISR_FEIF7}; + static constexpr uint32_t const 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}; + static constexpr uint32_t const 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}; + 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 */ + +#endif /* LL_DMAHELPER_H_ */ diff --git a/inc/f4ll/dmahelper.h b/inc/f4ll/dmahelper.h deleted file mode 100644 index 2aac9e2..0000000 --- a/inc/f4ll/dmahelper.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * ll_dmahelper.h - * - * Created on: Oct 25, 2019 - * Author: abody - */ - -#ifndef LL_DMAHELPER_H_ -#define LL_DMAHELPER_H_ - -#include -#include - -namespace f4ll { - -class DmaHelper { -public: - DmaHelper(DMA_TypeDef *dma, uint32_t stream); - DmaHelper(DmaHelper const &base) = default; - - inline DMA_TypeDef* GetDma() const { return m_dma; } - inline uint32_t GetStream() const { return m_stream; } - inline volatile uint32_t* GetIsReg() const { return m_isReg; } - inline volatile uint32_t* GetIfcReg() const { return m_ifcReg; } - inline uint32_t GetFeMask() const { return m_FEMasks[m_stream]; } - inline uint32_t GetDmeMask() const { return m_DMEMasks[m_stream]; } - inline uint32_t GetTeMask() const { return m_TEMasks[m_stream]; } - inline uint32_t GetHtMask() const { return m_HTMasks[m_stream]; } - inline uint32_t GetTcMask() const { return m_TCMasks[m_stream]; } - - inline bool IsEnabledIt_HT() { return LL_DMA_IsEnabledIT_HT(m_dma, m_stream) != 0; } - inline bool IsEnabledIt_TE() { return LL_DMA_IsEnabledIT_TE(m_dma, m_stream) != 0; } - inline bool IsEnabledIt_TC() { return LL_DMA_IsEnabledIT_TC(m_dma, m_stream) != 0; } - inline bool IsEnabledIt_DME() { return LL_DMA_IsEnabledIT_DME(m_dma, m_stream) != 0; } - inline bool IsEnabledIt_FE() { return LL_DMA_IsEnabledIT_FE(m_dma, m_stream) != 0; } - - enum class DmaErrorType { - Transfer, - DirectMode, - Fifo - }; - -private: - DMA_TypeDef *m_dma; - uint32_t m_stream; - volatile uint32_t *m_isReg; - volatile uint32_t *m_ifcReg; - - static const uint32_t m_FEMasks[8]; - static const uint32_t m_DMEMasks[8]; - static const uint32_t m_TEMasks[8]; - static const uint32_t m_HTMasks[8]; - static const uint32_t m_TCMasks[8]; -}; - -} /* namespace f4ll */ - -#endif /* LL_DMAHELPER_H_ */ diff --git a/inc/f4ll/fault.h b/inc/f4ll/fault.h index b49ac42..b6787ea 100644 --- a/inc/f4ll/fault.h +++ b/inc/f4ll/fault.h @@ -10,7 +10,35 @@ extern "C" { #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); +__attribute__((noreturn)) void fault_handler(uint32_t type, fault_context_t *context); #ifdef __cplusplus } diff --git a/inc/f4ll/irq_lock.h b/inc/f4ll/irq_lock.h new file mode 100644 index 0000000..f5c03a5 --- /dev/null +++ b/inc/f4ll/irq_lock.h @@ -0,0 +1,26 @@ +#ifndef _IRQLOCK_H_INCLUDED +#define _IRQLOCK_H_INCLUDED + +#include +#include + +namespace f4ll { + +class irq_lock +{ +public: + inline irq_lock() + : m_primask(__get_PRIMASK()) + { + __disable_irq(); + } + inline void release() { __set_PRIMASK(m_primask); } + + inline ~irq_lock() { __set_PRIMASK(m_primask); } + +private: + uint32_t m_primask; +}; +} + +#endif // _IRQLOCK_H_INCLUDED diff --git a/inc/f4ll/irqlock.h b/inc/f4ll/irqlock.h deleted file mode 100644 index a2cda22..0000000 --- a/inc/f4ll/irqlock.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef _IRQLOCK_H_INCLUDED -#define _IRQLOCK_H_INCLUDED - -#include -#include - -namespace f4ll { - -class IrqLock { -public: - inline IrqLock() : m_primask(__get_PRIMASK()) { - __disable_irq(); - } - inline void Release() { - __set_PRIMASK(m_primask); - } - - inline ~IrqLock() { - __set_PRIMASK(m_primask); - } -private: - uint32_t m_primask; -}; - -} - -#endif // _IRQLOCK_H_INCLUDED diff --git a/inc/f4ll/memcpy_dma.h b/inc/f4ll/memcpy_dma.h new file mode 100644 index 0000000..2b078f6 --- /dev/null +++ b/inc/f4ll/memcpy_dma.h @@ -0,0 +1,27 @@ +/* + * llmemcpydma.h + * + * Created on: Nov 4, 2019 + * Author: abody + */ +#pragma once + +#include +#include + +namespace f4ll { + +class memcpy_dma : public singleton, private dma_helper +{ + friend class singleton; + +public: + void *copy(void *dst, void const *src, uint16_t length); + void dma_transfer_completed(); + +private: + memcpy_dma(DMA_TypeDef *dma, uint32_t stream); + bool volatile m_busy = false; +}; + +} /* namespace f4ll */ diff --git a/inc/f4ll/memcpydma.h b/inc/f4ll/memcpydma.h deleted file mode 100644 index 195fc5d..0000000 --- a/inc/f4ll/memcpydma.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * llmemcpydma.h - * - * Created on: Nov 4, 2019 - * Author: abody - */ - -#ifndef LL_MEMCPY_DMA_H_ -#define LL_MEMCPY_DMA_H_ -#include "f4ll/dmahelper.h" -#include "singleton.h" - -namespace f4ll { - -class MemcpyDma : public Singleton, private DmaHelper -{ - friend class Singleton; -public: - void* Copy(void *dst, void const *src, uint16_t length); - void DmaTransferCompleted(); -private: - MemcpyDma(DMA_TypeDef *dma, uint32_t stream); - bool volatile m_busy = false; -}; - -} /* namespace f4ll */ - -#endif /* LL_MEMCPY_DMA_H_ */ diff --git a/inc/f4ll/packet_usart.h b/inc/f4ll/packet_usart.h new file mode 100644 index 0000000..649a813 --- /dev/null +++ b/inc/f4ll/packet_usart.h @@ -0,0 +1,122 @@ +/* + * ll_HsUsart.h + * + * Created on: Oct 29, 2019 + * Author: abody + */ + +#ifndef LL_HSUSART_H_ +#define LL_HSUSART_H_ +#include +#include +#include + +namespace f4ll { + +struct DMAINFO; + +class packet_usart : public crc_handler::icallback, public usart_core +{ + // friend class UsartCore; +public: + packet_usart(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t stream_rx, uint32_t stream_tx); + + struct packet_header + { // !!! size should be multiple of 4 !!! + uint8_t start_byte; + uint8_t serial; + uint8_t payload_length; + uint8_t hash; + }; + + struct packet + { + packet_header header; + uint8_t payload[256 + sizeof(uint32_t)]; // extra room for crc32 + } __attribute__((aligned)); + + struct stats + { + uint32_t overrun = 0; + uint32_t hdr_error = 0; + uint32_t payload_errror = 0; + uint32_t pep1 = 0; + uint32_t pep2 = 0; + uint32_t rx_dma_error = 0; + uint32_t tx_dma_error = 0; + uint32_t rcvd = 0; + uint32_t premature_hdr = 0; + uint32_t premature_payload = 0; + uint32_t sent = 0; + uint32_t skiped = 0; + }; + + struct ihs_usart_callback + { + virtual bool packet_received(packet_usart *caller, uintptr_t user_param, packet const &packet) = 0; + }; + + // crc_handler::ICallback interface functions + virtual void crc_succeeded(uintptr_t callback_param, uint32_t crc, uint8_t task) override; + virtual void crc_failed(uintptr_t callback_param, uint32_t crc, uint8_t task) override; + + void post_packet(uint8_t const *payload, uint8_t length, bool wait_for_crc_queue = true); + void setup_receive(void); + + void rx_processed(bool second); + + // Getters + uint8_t *get_tx_packet_buffer(void) { return m_tx_buffer.pkt.payload; } + uint8_t const *get_rx_packet_buffer(bool second) { return m_rx_buffers[second].pkt.payload; } + USART_TypeDef *get_usart(void) const { return m_usart; } + stats const &get_stats(void) const { return m_stats; } + inline bool is_tx_busy(void) const { return m_tx_buffer.busy; } + inline bool is_tx_failed(void) const { return m_tx_buffer.error; } + inline bool is_rx_busy(bool second) const { return m_rx_buffers[second].busy; } + inline bool is_rx_failed(bool second) const { return m_rx_buffers[second].error; } + + void set_callback(ihs_usart_callback *callback, uintptr_t callback_param); + +private: + void build_header(packet &packet, uint8_t serial_nr, uint8_t length); + bool check_header(packet_header &header); + void switch_rx_buffers(void); + + // UsartCore pure virtual function implementations + virtual void receiver_idle(void) override; + virtual void transmission_complete(void) override; + virtual void framing_error(void) override; + virtual void overrun(void) override; + virtual void rx_dma_transfer_complete(void) override; + virtual void rx_dma_half_transfer(void) override; + virtual void rx_dma_error(dma_helper::dma_error_type reason) override; + virtual void tx_dma_transfer_complete(void) override; + virtual void tx_dma_half_transfer(void) override; + virtual void tx_dma_error(dma_helper::dma_error_type reason) override; + + struct Buffer + { + packet pkt; + // transfer area ends here + bool volatile busy = 0; + bool volatile error = 0; + uint16_t requested_length = 0; + uint32_t error_info = 0; + }; + + static const uint8_t STARTMARKER = 0x95; + + uint8_t m_rx_serial_nr = -1; + uint8_t m_tx_serial_nr = -1; + stats m_stats; + bool m_rx_buffer_selector = false; + + crc_handler::slot<2> m_crc_slot; + ihs_usart_callback *m_user_callback = nullptr; + uintptr_t m_user_callback_param = 0; + Buffer m_tx_buffer; + Buffer m_rx_buffers[2]; +}; + +} +#endif /* LL_HSUSART_H_ */ diff --git a/inc/f4ll/packetusart.h b/inc/f4ll/packetusart.h deleted file mode 100644 index 4031734..0000000 --- a/inc/f4ll/packetusart.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * ll_HsUsart.h - * - * Created on: Oct 29, 2019 - * Author: abody - */ - -#ifndef LL_HSUSART_H_ -#define LL_HSUSART_H_ -#include -#include "f4ll/usartcore.h" -#include "f4ll/crchandler.h" - -namespace f4ll { - -struct DMAINFO; - -class PacketUsart : public CrcHandler::ICallback, public UsartCore -{ -// friend class UsartCore; -public: - PacketUsart(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t stream_rx, uint32_t stream_tx); - - struct PacketHeader { // !!! size should be multiple of 4 !!! - uint8_t startByte; - uint8_t serial; - uint8_t payloadLength; - uint8_t hash; - }; - - struct Packet { - PacketHeader header; - uint8_t payload[256+sizeof(uint32_t)]; // extra room for crc32 - } __attribute__((aligned)); - - struct Stats { - uint32_t overrun = 0; - uint32_t hdrError = 0; - uint32_t payloadErrror = 0; - uint32_t pep1 = 0; - uint32_t pep2 = 0; - uint32_t rxDmaError = 0; - uint32_t txDmaError = 0; - uint32_t rcvd = 0; - uint32_t premature_hdr = 0; - uint32_t premature_payload = 0; - uint32_t sent = 0; - uint32_t skiped = 0; - }; - - struct IHsUsartCallback { - virtual bool PacketReceived(PacketUsart *caller, uintptr_t userParam, Packet const &packet) = 0; - }; - - // CRCHandler::ICallback interface functions - virtual void CrcSucceeded(uintptr_t callbackParam, uint32_t crc, uint8_t task); - virtual void CrcFailed(uintptr_t callbackParam, uint32_t crc, uint8_t task); - - void PostPacket(uint8_t const *payload, uint8_t length, bool waitForCrcQueue = true); - void SetupReceive(void); - - void RxProcessed(bool second); - - // Getters - uint8_t* GetTxPacketBuffer(void) { return m_txBuffer.packet.payload; } - uint8_t const * GetRxPacketBuffer(bool second) { return m_rxBuffers[second].packet.payload; } - USART_TypeDef* GetUsart(void) const { return m_usart; } - Stats const & GetStats(void) const { return m_stats; } - inline bool IsTxBusy(void) const { return m_txBuffer.busy; } - inline bool IsTxFailed(void) const { return m_txBuffer.error; } - inline bool IsRxBusy(bool second) const { return m_rxBuffers[second].busy; } - inline bool IsRxFailed(bool second) const { return m_rxBuffers[second].error; } - - void SetCallback(IHsUsartCallback* callback, uintptr_t callbackParam); - -private: - void BuildHeader(Packet &packet, uint8_t serialNo, uint8_t length); - bool CheckHeader(PacketHeader &header); - void SwitchRxBuffers(void); - - // UsartCore pure virtual function implementations - virtual void ReceiverIdle(void); - virtual void TransmissionComplete(void); - virtual void FramingError(void); - virtual void Overrun(void); - virtual void RxDmaTransferComplete(void); - virtual void RxDmaHalfTransfer(void); - virtual void RxDmaError(DmaHelper::DmaErrorType reason); - virtual void TxDmaTransferComplete(void); - virtual void TxDmaHalfTransfer(void); - virtual void TxDmaError(DmaHelper::DmaErrorType reason); - - struct Buffer { - Packet packet; - //transfer area ends here - bool volatile busy = 0; - bool volatile error = 0; - uint16_t requestedLength = 0; - uint32_t errorInfo = 0; - }; - - static const uint8_t STARTMARKER = 0x95; - - uint8_t m_rxSerialNo = -1; - uint8_t m_txSerialNo = -1; - Stats m_stats; - bool m_rxBufferSelector = false; - - CrcHandler::Slot<2> m_crcSlot; - IHsUsartCallback *m_userCallback = nullptr; - uintptr_t m_userCallbackParam = 0; - Buffer m_txBuffer; - Buffer m_rxBuffers[2]; -}; - -} -#endif /* LL_HSUSART_H_ */ diff --git a/inc/f4ll/singleton.h b/inc/f4ll/singleton.h new file mode 100644 index 0000000..e9a8fe8 --- /dev/null +++ b/inc/f4ll/singleton.h @@ -0,0 +1,33 @@ +#ifndef SINGLETON_H_ +#define SINGLETON_H_ + +#include + +namespace f4ll { + +template class singleton +{ +public: + static T &instance() + { + return *m_instance; + } + template static T &init(args_t &&...args) + { + static T instance{std::forward(args)...}; + m_instance = &instance; + return instance; + } + +protected: + singleton() = default; + singleton(const singleton &) = delete; + singleton &operator=(const singleton &) = delete; + static T *m_instance; +}; + +template T *singleton::m_instance = nullptr; + +} // namespace f1ll { + +#endif /* SINGLETON_H_ */ diff --git a/inc/f4ll/strutil.h b/inc/f4ll/str_util.h similarity index 100% rename from inc/f4ll/strutil.h rename to inc/f4ll/str_util.h diff --git a/inc/f4ll/usart_core.h b/inc/f4ll/usart_core.h new file mode 100644 index 0000000..f4f44be --- /dev/null +++ b/inc/f4ll/usart_core.h @@ -0,0 +1,54 @@ +/* + * ll_dmadrivenusartcore.h + * + * Created on: Nov 4, 2019 + * Author: abody + */ + +#ifndef LL_USARTCORE_H_ +#define LL_USARTCORE_H_ +#include + +#include + +namespace f4ll { + +class usart_core +{ +public: + static inline void usart_isr(usart_core *_this) { _this->usart_isr(); } + static inline void rx_dma_isr(usart_core *_this) { _this->rx_dma_isr(); } + static inline void tx_dma_isr(usart_core *_this) { _this->tx_dma_isr(); } + + void setup_transmit(void const *buffer, uint16_t length); + void setup_receive(void *buffer, uint16_t length); + +protected: + usart_core(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t stream_rx, uint32_t stream_tx); + + USART_TypeDef *m_usart; + dma_helper m_rx_dma; + dma_helper m_tx_dma; + +private: + virtual void receiver_idle(void) = 0; + virtual void transmission_complete(void) = 0; + virtual void framing_error(void) = 0; + virtual void overrun(void) = 0; + + virtual void rx_dma_transfer_complete(void) = 0; + virtual void rx_dma_half_transfer(void) = 0; + virtual void rx_dma_error(dma_helper::dma_error_type reason) = 0; + + virtual void tx_dma_transfer_complete(void) = 0; + virtual void tx_dma_half_transfer(void) = 0; + virtual void tx_dma_error(dma_helper::dma_error_type reason) = 0; + + void usart_isr(); + void rx_dma_isr(); + void tx_dma_isr(); +}; + +} /* namespace f4ll */ + +#endif /* LL_USARTCORE_H_ */ diff --git a/inc/f4ll/usartcore.h b/inc/f4ll/usartcore.h deleted file mode 100644 index fc587b3..0000000 --- a/inc/f4ll/usartcore.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * ll_dmadrivenusartcore.h - * - * Created on: Nov 4, 2019 - * Author: abody - */ - -#ifndef LL_USARTCORE_H_ -#define LL_USARTCORE_H_ -#include - -#include "f4ll/dmahelper.h" - -namespace f4ll { - -class UsartCore -{ -public: - static inline void HandleUsartIrq(UsartCore *_this) { _this->UsartIsr(); } - static inline void HandleRxDmaIrq(UsartCore *_this) { _this->RxDmaIsr(); } - static inline void HandleTxDmaIrq(UsartCore *_this) { _this->TxDmaIsr(); } - - void SetupTransmit(void const *buffer, uint16_t length); - void SetupReceive(void *buffer, uint16_t length); - -protected: - UsartCore(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t streamRx, uint32_t streamTx); - - USART_TypeDef *m_usart; - DmaHelper m_rxDma; - DmaHelper m_txDma; - -private: - virtual void ReceiverIdle(void) = 0; - virtual void TransmissionComplete(void) = 0; - virtual void FramingError(void) = 0; - virtual void Overrun(void) = 0; - - virtual void RxDmaTransferComplete(void) = 0; - virtual void RxDmaHalfTransfer(void) = 0; - virtual void RxDmaError(DmaHelper::DmaErrorType reason) = 0; - - virtual void TxDmaTransferComplete(void) = 0; - virtual void TxDmaHalfTransfer(void) = 0; - virtual void TxDmaError(DmaHelper::DmaErrorType reason) = 0; - - void UsartIsr(); - void RxDmaIsr(); - void TxDmaIsr(); - -}; - -} /* namespace f4ll */ - -#endif /* LL_USARTCORE_H_ */ diff --git a/src/console_handler.cpp b/src/console_handler.cpp new file mode 100644 index 0000000..02c990f --- /dev/null +++ b/src/console_handler.cpp @@ -0,0 +1,79 @@ +/* + * ll_consolehandler.cpp + * + * Created on: Nov 7, 2019 + * Author: abody + */ + +#include +#include + +namespace f4ll { + +console_handler::console_handler(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t stream_rx, uint32_t stream_tx) + : usart_core(usart, dma, stream_rx, stream_tx) +{ +} + +void console_handler::receiver_idle(void) {} + +void console_handler::transmission_complete(void) {} + +void console_handler::framing_error(void) {} + +void console_handler::overrun(void) {} + +void console_handler::rx_dma_transfer_complete(void) {} + +void console_handler::rx_dma_half_transfer(void) {} + +void console_handler::rx_dma_error(dma_helper::dma_error_type reason) +{ + (void)reason; +} + +void console_handler::tx_dma_transfer_complete(void) +{ + LL_USART_EnableIT_TC(m_usart); + LL_DMA_DisableStream(m_tx_dma.get_dma(), m_tx_dma.get_stream()); +} + +void console_handler::tx_dma_half_transfer(void) {} + +void console_handler::tx_dma_error(dma_helper::dma_error_type reason) +{ + (void)reason; +} + +#define ADDINFO(b, s, u) \ + b += strcpy_ex(b, s); \ + b += uitodec(b, u); + +void console_handler::PrintStats(uint8_t id, packet_usart &usart) +{ + char ids[] = " : "; + char *buffer = m_buffer; + packet_usart::stats const &stats(usart.get_stats()); + + ids[0] = id + '0'; + buffer += strcpy_ex(buffer, ids); + ADDINFO(buffer, " s: ", stats.sent); + ADDINFO(buffer, " r: ", stats.rcvd); + ADDINFO(buffer, " sk: ", stats.skiped); + ADDINFO(buffer, " or: ", stats.overrun); + ADDINFO(buffer, " he: ", stats.hdr_error); + ADDINFO(buffer, " pe: ", stats.payload_errror); + buffer += strcpy_ex(buffer, ",0x"); + buffer += uitohex(buffer, stats.pep1, 8); + buffer += strcpy_ex(buffer, ",0x"); + buffer += uitohex(buffer, stats.pep2, 8); + ADDINFO(buffer, " rde: ", stats.rx_dma_error); + ADDINFO(buffer, " tde: ", stats.tx_dma_error); + ADDINFO(buffer, " pmh: ", stats.premature_hdr); + ADDINFO(buffer, " pmp: ", stats.premature_payload); + buffer += strcpy_ex(buffer, "\r\n"); + + setup_transmit(m_buffer, buffer - m_buffer + 1); +} + +} /* namespace f4ll */ diff --git a/src/consolehandler.cpp b/src/consolehandler.cpp deleted file mode 100644 index 6eb9609..0000000 --- a/src/consolehandler.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * ll_consolehandler.cpp - * - * Created on: Nov 7, 2019 - * Author: abody - */ - -#include "f4ll/consolehandler.h" -#include "f4ll/strutil.h" - -namespace f4ll { - -ConsoleHandler::ConsoleHandler(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t streamRx, uint32_t streamTx) -: UsartCore(usart, dma, streamRx, streamTx) -{ -} - -void ConsoleHandler::ReceiverIdle(void) {} -void ConsoleHandler::TransmissionComplete(void) {} -void ConsoleHandler::FramingError(void) {} -void ConsoleHandler::Overrun(void) {} -void ConsoleHandler::RxDmaTransferComplete(void) {} -void ConsoleHandler::RxDmaHalfTransfer(void) {} -void ConsoleHandler::RxDmaError(DmaHelper::DmaErrorType reason) {} -void ConsoleHandler::TxDmaTransferComplete(void) -{ - LL_USART_EnableIT_TC(m_usart); - LL_DMA_DisableStream(m_txDma.GetDma(), m_txDma.GetStream()); -} -void ConsoleHandler::TxDmaHalfTransfer(void) {} -void ConsoleHandler::TxDmaError(DmaHelper::DmaErrorType reason) {} - - -#define ADDINFO(b,s,u) \ - b += strcpy_ex(b,s); \ - b += uitodec(b,u); - -void ConsoleHandler::PrintStats(uint8_t id, PacketUsart &usart) -{ - char ids[] = " : "; - char *buffer = m_buffer; - PacketUsart::Stats const &stats(usart.GetStats()); - - ids[0] = id + '0'; - buffer += strcpy_ex(buffer, ids); - ADDINFO(buffer, " s: ", stats.sent); - ADDINFO(buffer, " r: ", stats.rcvd); - ADDINFO(buffer, " sk: ", stats.skiped); - ADDINFO(buffer, " or: ", stats.overrun); - ADDINFO(buffer, " he: ", stats.hdrError); - ADDINFO(buffer, " pe: ", stats.payloadErrror); - buffer += strcpy_ex(buffer,",0x"); - buffer += uitohex(buffer, stats.pep1, 8); - buffer += strcpy_ex(buffer,",0x"); - buffer += uitohex(buffer, stats.pep2, 8); - ADDINFO(buffer, " rde: ", stats.rxDmaError); - ADDINFO(buffer, " tde: ", stats.txDmaError); - ADDINFO(buffer, " pmh: ", stats.premature_hdr); - ADDINFO(buffer, " pmp: ", stats.premature_payload); - buffer += strcpy_ex(buffer, "\r\n"); - - SetupTransmit(m_buffer, buffer - m_buffer + 1); -} - - -} /* namespace f4ll */ - diff --git a/src/crc_handler.cpp b/src/crc_handler.cpp new file mode 100644 index 0000000..8693a6f --- /dev/null +++ b/src/crc_handler.cpp @@ -0,0 +1,160 @@ +/* + * ll_crc_handler.cpp + * + * Created on: Oct 26, 2019 + * Author: compi + */ +#include + +namespace f4ll { + +crc_handler::crc_handler(DMA_TypeDef *dma, uint32_t stream) + : m_dma(dma, stream) +{ + LL_DMA_EnableIT_TC(dma, stream); + LL_DMA_EnableIT_TE(dma, stream); + LL_DMA_SetM2MDstAddress(dma, stream, (uint32_t)&CRC->DR); +} + +void crc_handler::attach_slot(slot_base &slot) +{ + for (unsigned int i = 0; i < slot.m_task_count; ++i) { + auto &task(slot[i]); + task.m_address = nullptr; + task.m_word_count = 0; + task.m_callback = nullptr; + task.m_callback_param = 0; + } + uint32_t prim = __get_PRIMASK(); + __disable_irq(); + slot.m_next = m_first_slot; + m_first_slot = &slot; + __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) +{ + uint32_t prim = __get_PRIMASK(); + bool immediate; + + // TODO: do we need sanity check here? (is slot attached, is task in range, + // etc...?) + + while (is_active(slot, task)) + ; + __disable_irq(); + immediate = m_active_slot == nullptr; + slot[task].m_address = (!immediate) ? address : nullptr; + slot[task].m_word_count = (len + 3) / 4; + slot[task].m_callback = cb; + slot[task].m_callback_param = cb_param; + if (immediate) { + m_active_slot = &slot; + m_active_task = task; + } + __set_PRIMASK(prim); + + if (immediate) { + CRC->CR = 1; + LL_DMA_SetM2MSrcAddress(m_dma.get_dma(), m_dma.get_stream(), (uint32_t)address); + LL_DMA_SetDataLength(m_dma.get_dma(), m_dma.get_stream(), (len + 3) / 4); + LL_DMA_EnableStream(m_dma.get_dma(), m_dma.get_stream()); + } + return immediate; +} + +bool crc_handler::is_active(slot_base &slot, uint8_t task) const +{ + return task < slot.m_task_count && slot[task].m_word_count != 0; +} + +bool crc_handler::is_queued(slot_base &slot, uint8_t task) const +{ + return task < slot.m_task_count && slot[task].m_address != nullptr; +} + +bool crc_handler::is_running(slot_base &slot, uint8_t task) const +{ + return task < slot.m_task_count && slot[task].m_word_count && !slot[task].m_address; +} + +void crc_handler::dma_transfer_completed(void) +{ + if (*m_dma.get_is_reg() & m_dma.get_tc_mask()) { // DMA transfer complete + *m_dma.get_ifc_reg() = m_dma.get_tc_mask(); + LL_DMA_DisableStream(m_dma.get_dma(), m_dma.get_stream()); + if (m_active_slot) { + if ((*m_active_slot)[m_active_task].m_callback) { + (*m_active_slot)[m_active_task].m_callback->crc_succeeded( + (*m_active_slot)[m_active_task].m_callback_param, CRC->DR, m_active_task); + } else if ((*m_active_slot)[m_active_task].m_callback_param) { + *reinterpret_cast((*m_active_slot)[m_active_task].m_callback_param) = CRC->DR; + } + } + } 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(); + LL_DMA_DisableStream(m_dma.get_dma(), m_dma.get_stream()); + if (m_active_slot) { + if ((*m_active_slot)[m_active_task].m_callback) { + (*m_active_slot)[m_active_task].m_callback->crc_failed( + (*m_active_slot)[m_active_task].m_callback_param, CRC->DR, m_active_task); + } else if ((*m_active_slot)[m_active_task].m_callback_param) { + *reinterpret_cast((*m_active_slot)[m_active_task].m_callback_param) = -1; + } + } + } + (*m_active_slot)[m_active_task].m_callback = nullptr; + (*m_active_slot)[m_active_task].m_callback_param = 0; + (*m_active_slot)[m_active_task].m_word_count = 0; + start_next_task(); +} + +void crc_handler::start_next_task(void) +{ + bool more_tasks; + uint8_t index = 0; + + do { + slot_base volatile *slot = m_first_slot; + more_tasks = false; + while (slot) { + if (index < slot->m_task_count) { + if ((*slot)[index].m_address) { + m_active_slot = slot; + m_active_task = index; + CRC->CR = 1; + LL_DMA_SetM2MSrcAddress(m_dma.get_dma(), m_dma.get_stream(), reinterpret_cast((*slot)[index].m_address)); + LL_DMA_SetDataLength(m_dma.get_dma(), m_dma.get_stream(), (*slot)[index].m_word_count); + LL_DMA_EnableStream(m_dma.get_dma(), m_dma.get_stream()); + (*slot)[index].m_address = nullptr; // marking as started + return; + } + if (index + 1 < slot->m_task_count) { + more_tasks = true; + } + } + slot = slot->m_next; + } + ++index; + } while (more_tasks); + m_active_slot = nullptr; +} + +void crc_handler::wait_results(slot_base &slot, uint8_t task) const +{ + while (is_queued(slot, task)) + ; + while (is_active(slot, task)) + ; +} + +uint32_t crc_handler::compute(slot_base &slot, uint8_t task, void const *address, uint16_t len) +{ + uint32_t result; + enqueue(slot, task, address, len, nullptr, reinterpret_cast(&result)); + while (is_active(slot, task)) + ; + return result; +} + +} // namespace f4ll diff --git a/src/crchandler.cpp b/src/crchandler.cpp deleted file mode 100644 index d3afad8..0000000 --- a/src/crchandler.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/* - * ll_crchandler.cpp - * - * Created on: Oct 26, 2019 - * Author: compi - */ -#include "f4ll/crchandler.h" - -namespace f4ll { - -CrcHandler::CrcHandler(DMA_TypeDef *dma, uint32_t stream) -: m_dma(dma, stream) -{ - LL_DMA_EnableIT_TC(dma, stream); - LL_DMA_EnableIT_TE(dma, stream); - LL_DMA_SetM2MDstAddress(dma, stream, (uint32_t)&CRC->DR); -} - - -void CrcHandler::AttachSlot(SlotBase &slot) -{ - for(unsigned int i = 0; i < slot.m_taskCount; ++i ) { - auto &task(slot[i]); - task.m_address = nullptr; - task.m_wordCount = 0; - task.m_callback = nullptr; - task.m_callbackParam = 0; - } - uint32_t prim = __get_PRIMASK(); - __disable_irq(); - slot.m_next = m_firstSlot; - m_firstSlot = &slot; - __set_PRIMASK(prim); -} - - -bool CrcHandler::Enqueue(SlotBase &slot, uint8_t task, void const *address, uint16_t len, ICallback *cb, uintptr_t cbParam) -{ - uint32_t prim = __get_PRIMASK(); - bool immediate; - - // TODO: do we need sanity check here? (is slot attached, is task in range, etc...?) - - while(IsActive(slot,task)); - __disable_irq(); - immediate = m_activeSlot == nullptr; - slot[task].m_address = (!immediate) ? address : nullptr; - slot[task].m_wordCount = (len+3)/4; - slot[task].m_callback = cb; - slot[task].m_callbackParam = cbParam; - if(immediate) { - m_activeSlot = &slot; - m_activeTask = task; - } - __set_PRIMASK(prim); - - if(immediate) { - CRC->CR = 1; - LL_DMA_SetM2MSrcAddress(m_dma.GetDma(), m_dma.GetStream(), (uint32_t)address); - LL_DMA_SetDataLength(m_dma.GetDma(), m_dma.GetStream(), (len+3)/4); - LL_DMA_EnableStream(m_dma.GetDma(), m_dma.GetStream()); - } - return immediate; -} - -bool CrcHandler::IsActive(SlotBase &slot, uint8_t task) const -{ - return task < slot.m_taskCount && slot[task].m_wordCount != 0; -} - -bool CrcHandler::IsQueued(SlotBase &slot, uint8_t task) const -{ - return task < slot.m_taskCount && slot[task].m_address != nullptr; -} - -bool CrcHandler::IsRunning(SlotBase &slot, uint8_t task) const -{ - return task < slot.m_taskCount && slot[task].m_wordCount && ! slot[task].m_address; -} - -void CrcHandler::DmaTransferCompleted(void) -{ - if(* m_dma.GetIsReg() & m_dma.GetTcMask()) { // DMA transfer complete - * m_dma.GetIfcReg() = m_dma.GetTcMask(); - LL_DMA_DisableStream(m_dma.GetDma(), m_dma.GetStream()); - if(m_activeSlot) { - if((*m_activeSlot)[m_activeTask].m_callback) - (*m_activeSlot)[m_activeTask].m_callback->CrcSucceeded((*m_activeSlot)[m_activeTask].m_callbackParam, CRC->DR, m_activeTask); - else if((*m_activeSlot)[m_activeTask].m_callbackParam) - *reinterpret_cast((*m_activeSlot)[m_activeTask].m_callbackParam) = CRC->DR; - } - } - else if(*m_dma.GetIsReg() & m_dma.GetTeMask()) { // DMA transfer error - *m_dma.GetIfcReg() = m_dma.GetTeMask(); - LL_DMA_DisableStream(m_dma.GetDma(), m_dma.GetStream()); - if(m_activeSlot) { - if((*m_activeSlot)[m_activeTask].m_callback) - (*m_activeSlot)[m_activeTask].m_callback->CrcFailed((*m_activeSlot)[m_activeTask].m_callbackParam, CRC->DR, m_activeTask); - else if((*m_activeSlot)[m_activeTask].m_callbackParam) - *reinterpret_cast((*m_activeSlot)[m_activeTask].m_callbackParam) = -1; - } - } - (*m_activeSlot)[m_activeTask].m_callback = nullptr; - (*m_activeSlot)[m_activeTask].m_callbackParam = 0; - (*m_activeSlot)[m_activeTask].m_wordCount = 0; - StartNextTask(); -} - - -void CrcHandler::StartNextTask(void) -{ - bool moreTasks; - uint8_t index = 0; - - do { - SlotBase volatile *slot = m_firstSlot; - moreTasks = false; - while(slot) { - if(index < slot->m_taskCount) { - if((*slot)[index].m_address) { - m_activeSlot = slot; - m_activeTask = index; - CRC->CR = 1; - LL_DMA_SetM2MSrcAddress(m_dma.GetDma(), m_dma.GetStream(), reinterpret_cast((*slot)[index].m_address)); - LL_DMA_SetDataLength(m_dma.GetDma(), m_dma.GetStream(), (*slot)[index].m_wordCount); - LL_DMA_EnableStream(m_dma.GetDma(), m_dma.GetStream()); - (*slot)[index].m_address = nullptr; // marking as started - return; - } - if(index + 1 < slot->m_taskCount) - moreTasks = true; - } - slot = slot->m_next; - } - ++index; - } while(moreTasks); - m_activeSlot = nullptr; -} - - -void CrcHandler::WaitResults(SlotBase &slot, uint8_t task) const -{ - while(IsQueued(slot, task)); - while(IsActive(slot, task)); -} - - -uint32_t CrcHandler::Compute( - SlotBase &slot, uint8_t task, void const *address, uint16_t len) -{ - uint32_t result; - Enqueue(slot, task, address, len, nullptr, reinterpret_cast(&result)); - while(IsActive(slot, task)); - return result; -} - -} // namespace f4ll diff --git a/src/dma_helper.cpp b/src/dma_helper.cpp new file mode 100644 index 0000000..42e2e11 --- /dev/null +++ b/src/dma_helper.cpp @@ -0,0 +1,24 @@ +/* +q * ll_dmahelper.cpp + * + * Created on: Oct 25, 2019 + * Author: abody + */ + +#include + +namespace f4ll { + +dma_helper::dma_helper(DMA_TypeDef *dma, uint32_t stream) + : m_dma(dma), + m_stream(stream), + m_is_reg( + (dma == DMA1) ? ((m_stream < LL_DMA_STREAM_4) ? &DMA1->LISR : &DMA1->HISR) + : ((m_stream < LL_DMA_STREAM_4) ? &DMA2->LISR : &DMA2->HISR)), + m_ifc_reg( + (dma == DMA1) ? ((m_stream < LL_DMA_STREAM_4) ? &DMA1->LIFCR : &DMA1->HIFCR) + : ((m_stream < LL_DMA_STREAM_4) ? &DMA2->LIFCR : &DMA2->HIFCR)) +{ +} + +} /* namespace f4ll */ diff --git a/src/dmahelper.cpp b/src/dmahelper.cpp deleted file mode 100644 index 4cd924e..0000000 --- a/src/dmahelper.cpp +++ /dev/null @@ -1,26 +0,0 @@ -/* -q * ll_dmahelper.cpp - * - * Created on: Oct 25, 2019 - * Author: abody - */ - -#include "f4ll/dmahelper.h" - -namespace f4ll { - -const uint32_t DmaHelper::m_FEMasks[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 DmaHelper::m_DMEMasks[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 DmaHelper::m_TEMasks[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 DmaHelper::m_HTMasks[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 DmaHelper::m_TCMasks[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}; - -DmaHelper::DmaHelper(DMA_TypeDef *dma, uint32_t stream) -: m_dma(dma) -, m_stream(stream) -, m_isReg((dma == DMA1) ? ((m_stream < LL_DMA_STREAM_4) ? &DMA1->LISR : &DMA1->HISR) : ((m_stream < LL_DMA_STREAM_4) ? &DMA2->LISR : &DMA2->HISR)) -, m_ifcReg((dma == DMA1) ? ((m_stream < LL_DMA_STREAM_4) ? &DMA1->LIFCR : &DMA1->HIFCR) : ((m_stream < LL_DMA_STREAM_4) ? &DMA2->LIFCR : &DMA2->HIFCR)) -{ -} - -} /* namespace f4ll */ diff --git a/src/fault.cpp b/src/fault.cpp index 149cc7b..2187ade 100644 --- a/src/fault.cpp +++ b/src/fault.cpp @@ -7,45 +7,22 @@ */ #include //#include -#include "stm32f4xx.h" -#include "f4ll/strutil.h" -#include "f4ll/fault.h" +#include +#include +#include #ifdef __cplusplus extern "C" { #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; - -fault_context_t g_faultContext; +fault_context_t g_fault_context; void __attribute__((weak)) app_fault_callback(uint32_t reason) { + (void)reason; } -void SwoSendStr(char const *str, uint8_t len, uint8_t port) +void swo_send_str(char const *str, uint8_t len, uint8_t port) { while(len) { if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && // ITM enabled @@ -76,24 +53,23 @@ void SwoSendStr(char const *str, uint8_t len, uint8_t port) void fault_print_str(char const *fmtstr, uint32_t *values) { char hex_str[9]={0}; - char const *nextChunk = fmtstr; + char const *next_chunk = fmtstr; - while(*fmtstr) { + while(*fmtstr) { if(*fmtstr == '%') { - SwoSendStr(nextChunk, fmtstr-nextChunk, 0); - uitohex(hex_str, *values++, 8); - SwoSendStr(hex_str, 8, 0); - nextChunk = fmtstr +1; - } - ++fmtstr; - } - if(nextChunk != fmtstr) - SwoSendStr(nextChunk, fmtstr-nextChunk, 0); + swo_send_str(next_chunk, fmtstr - next_chunk, 0); + uitohex(hex_str, *values++, 8); + swo_send_str(hex_str, 8, 0); + next_chunk = fmtstr + 1; + } + ++fmtstr; + } + if (next_chunk != fmtstr) { + swo_send_str(next_chunk, fmtstr - next_chunk, 0); + } } - - -__attribute__((noreturn)) void FaultHandler(uint32_t type, fault_context_t *context) +void fault_handler(uint32_t type, fault_context_t *context) { uint32_t FSR[9] = { SCB->HFSR, diff --git a/src/memcpy_dma.cpp b/src/memcpy_dma.cpp new file mode 100644 index 0000000..dedca9b --- /dev/null +++ b/src/memcpy_dma.cpp @@ -0,0 +1,38 @@ +/* + * llmemcpydma.cpp + * + * Created on: Nov 4, 2019 + * Author: abody + */ + +#include + +namespace f4ll { + +memcpy_dma::memcpy_dma(DMA_TypeDef *dma, uint32_t stream) + : dma_helper(dma, stream) +{ + LL_DMA_EnableIT_TC(dma, stream); +} + +void *memcpy_dma::copy(void *dst, void const *src, uint16_t length) +{ + LL_DMA_SetM2MSrcAddress(get_dma(), get_stream(), (uint32_t)src); + LL_DMA_SetM2MDstAddress(get_dma(), get_stream(), (uint32_t)dst); + LL_DMA_SetDataLength(get_dma(), get_stream(), (length + 3) / 4); + m_busy = 1; + LL_DMA_EnableStream(get_dma(), get_stream()); + while (m_busy) + ; + return dst; +} + +void memcpy_dma::dma_transfer_completed() +{ + if (*get_is_reg() & get_tc_mask()) { // DMA transfer complete + *get_ifc_reg() = get_tc_mask(); + LL_DMA_DisableStream(get_dma(), get_stream()); + m_busy = 0; + } +} +} /* namespace f4ll */ diff --git a/src/memcpydma.cpp b/src/memcpydma.cpp deleted file mode 100644 index 3bfb1b1..0000000 --- a/src/memcpydma.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* - * llmemcpydma.cpp - * - * Created on: Nov 4, 2019 - * Author: abody - */ - -#include "f4ll/memcpydma.h" - -namespace f4ll { - -MemcpyDma::MemcpyDma(DMA_TypeDef *dma, uint32_t stream) -: DmaHelper(dma, stream) -{ - LL_DMA_EnableIT_TC(dma, stream); -} - -void* MemcpyDma::Copy(void *dst, void const *src, uint16_t length) -{ - LL_DMA_SetM2MSrcAddress(GetDma(), GetStream(), (uint32_t)src); - LL_DMA_SetM2MDstAddress(GetDma(), GetStream(), (uint32_t)dst); - LL_DMA_SetDataLength(GetDma(), GetStream(), (length+3)/4 ); - m_busy = 1; - LL_DMA_EnableStream(GetDma(), GetStream()); - while(m_busy); - return dst; -} - -void MemcpyDma::DmaTransferCompleted() -{ - if(*GetIsReg() & GetTcMask()) { // DMA transfer complete - *GetIfcReg() = GetTcMask(); - LL_DMA_DisableStream(GetDma(), GetStream()); - m_busy = 0; - } -} -} /* namespace f4ll */ diff --git a/src/packet_usart.cpp b/src/packet_usart.cpp new file mode 100644 index 0000000..f56a0b6 --- /dev/null +++ b/src/packet_usart.cpp @@ -0,0 +1,212 @@ +/* + * ll_hsusart_impl.h + * + * Created on: Oct 29, 2019 + * Author: abody + */ +#include +#include + +namespace f4ll { + +template static inline T round_up_to_4(T input) +{ + return (input + 3) & (((T)-1) - 3); +} + +packet_usart::packet_usart(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t stream_rx, uint32_t stream_tx) + : usart_core(usart, dma, stream_rx, stream_tx) +{ + crc_handler::instance().attach_slot(m_crc_slot); + LL_USART_EnableIT_IDLE(usart); + LL_USART_EnableIT_ERROR(usart); +} + +void packet_usart::rx_processed(bool second) +{ + m_rx_buffers[second].busy = false; + m_rx_buffers[second].error = false; +} + +void packet_usart::set_callback(ihs_usart_callback *callback, uintptr_t callback_param) +{ + m_user_callback = callback; + m_user_callback_param = callback_param; +} + +void packet_usart::post_packet(uint8_t const *payload, uint8_t length, bool wait_for_crc_queue) +{ + uint16_t payload_length = round_up_to_4((uint16_t)length); + + build_header(m_tx_buffer.pkt, m_tx_serial_nr++, length); + if (payload) { + memcpy(m_tx_buffer.pkt.payload, payload, length); + } + m_tx_buffer.requested_length = sizeof(m_tx_buffer.pkt.header) + payload_length + sizeof(uint32_t); + m_tx_buffer.busy = true; + m_tx_buffer.error = false; + + crc_handler::instance().enqueue( + m_crc_slot, 0, &m_tx_buffer.pkt, sizeof(packet_header) + payload_length, nullptr, + reinterpret_cast(m_tx_buffer.pkt.payload + payload_length)); + + while (wait_for_crc_queue && crc_handler::instance().is_queued(m_crc_slot, 0)) + ; + + setup_transmit(&m_tx_buffer.pkt, m_tx_buffer.requested_length); + + ++m_stats.sent; +} + +void packet_usart::setup_receive() +{ + m_rx_buffers[m_rx_buffer_selector].requested_length = sizeof(m_rx_buffers[m_rx_buffer_selector].pkt); + usart_core::setup_receive(&m_rx_buffers[m_rx_buffer_selector], sizeof(m_rx_buffers[m_rx_buffer_selector].pkt)); +} + +////////////////////////////////////// +// UsartCore pure virtual functions // +////////////////////////////////////// + +void packet_usart::receiver_idle(void) +{ + uint16_t rcvdLen = + 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 (check_header(m_rx_buffers[m_rx_buffer_selector].pkt.header)) { + if (rcvdLen >= sizeof(packet_header) + round_up_to_4((uint16_t)m_rx_buffers[m_rx_buffer_selector].pkt.header.payload_length) + + sizeof(uint32_t)) { + LL_DMA_DisableStream(m_rx_dma.get_dma(), m_rx_dma.get_stream()); + } else { + ++m_stats.premature_payload; + } + } else { + m_rx_buffers[m_rx_buffer_selector].error = 1; + LL_DMA_DisableStream(m_rx_dma.get_dma(), m_rx_dma.get_stream()); + } + } else { + ++m_stats.premature_hdr; + } +} + +void packet_usart::transmission_complete(void) +{ + LL_USART_DisableDirectionTx(m_usart); // enforcing an idle frame + LL_USART_EnableDirectionTx(m_usart); + m_tx_buffer.busy = 0; +} + +void packet_usart::framing_error(void) {} + +void packet_usart::overrun(void) {} + +void packet_usart::rx_dma_transfer_complete(void) +{ + if (check_header(m_rx_buffers[m_rx_buffer_selector].pkt.header)) { + crc_handler::instance().enqueue( + m_crc_slot, 1, &m_rx_buffers[m_rx_buffer_selector].pkt, + sizeof(packet_header) + round_up_to_4((uint16_t)m_rx_buffers[m_rx_buffer_selector].pkt.header.payload_length), this, + m_rx_buffer_selector); + } else { + ++m_stats.hdr_error; + m_rx_buffers[m_rx_buffer_selector].error = true; + } + switch_rx_buffers(); +} + +void packet_usart::rx_dma_half_transfer(void) {} + +void packet_usart::rx_dma_error(dma_helper::dma_error_type reason) +{ + (void)reason; + + m_rx_buffers[m_rx_buffer_selector].error = 1; + ++m_stats.rx_dma_error; + switch_rx_buffers(); +} + +void packet_usart::tx_dma_transfer_complete(void) +{ + LL_USART_EnableIT_TC(m_usart); + LL_DMA_DisableStream(m_tx_dma.get_dma(), m_tx_dma.get_stream()); +} + +void packet_usart::tx_dma_half_transfer(void) {} + +void packet_usart::tx_dma_error(dma_helper::dma_error_type reason) +{ + (void)reason; + + m_tx_buffer.error = 1; + ++m_stats.tx_dma_error; +} + +/////////////////////// +// Private functions // +/////////////////////// + +void packet_usart::build_header(packet &packet, uint8_t serial_nr, uint8_t length) +{ + uint8_t hash = STARTMARKER; + + packet.header.start_byte = STARTMARKER; + packet.header.serial = serial_nr; + hash ^= serial_nr; + packet.header.payload_length = length; + hash ^= length; + packet.header.hash = hash; +} + +bool packet_usart::check_header(packet_header &header) +{ + return header.start_byte == STARTMARKER && (header.start_byte ^ header.serial ^ header.payload_length) == header.hash; +} + +void packet_usart::switch_rx_buffers(void) +{ + ++m_stats.rcvd; + m_rx_buffer_selector = !m_rx_buffer_selector; + + if (m_rx_buffers[m_rx_buffer_selector].busy) { + ++m_stats.overrun; + } + setup_receive(); +} + +/////////////////////////// +// crc_handler::ICallback // +/////////////////////////// + +void packet_usart::crc_succeeded(uintptr_t callback_param, uint32_t crc, uint8_t task) +{ + (void)task; + + Buffer &buf(m_rx_buffers[static_cast(callback_param)]); + + buf.busy = 1; + if (*(uint32_t *)(buf.pkt.payload + round_up_to_4((uint16_t)buf.pkt.header.payload_length)) != crc) { + buf.error = 1; + buf.error_info = crc; + ++m_stats.payload_errror; + } + if (m_user_callback) { + buf.busy = !m_user_callback->packet_received(this, m_user_callback_param, buf.pkt); + } +} + +void packet_usart::crc_failed(uintptr_t callback_param, uint32_t crc, uint8_t task) +{ + (void)crc; + (void)task; + + Buffer &buf(m_rx_buffers[static_cast(callback_param)]); + buf.busy = buf.error = true; + buf.error_info = 0; + ++m_stats.payload_errror; + if (m_user_callback) { + buf.busy = !m_user_callback->packet_received(this, m_user_callback_param, buf.pkt); + } +} + +} // namespace f4ll diff --git a/src/packetusart.cpp b/src/packetusart.cpp deleted file mode 100644 index b8141f1..0000000 --- a/src/packetusart.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/* - * ll_hsusart_impl.h - * - * Created on: Oct 29, 2019 - * Author: abody - */ -#include -#include "f4ll/packetusart.h" - -namespace f4ll { - -template static inline T RoundUpTo4(T input) -{ - return (input + 3) & (((T)-1) - 3); -} - - -PacketUsart::PacketUsart(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t streamRx, uint32_t streamTx) -: UsartCore(usart, dma, streamRx, streamTx) -{ - CrcHandler::Instance().AttachSlot(m_crcSlot); - LL_USART_EnableIT_IDLE(usart); - LL_USART_EnableIT_ERROR(usart); -} - - -void PacketUsart::RxProcessed(bool second) -{ - m_rxBuffers[second].busy = false; - m_rxBuffers[second].error = false; -} - - -void PacketUsart::SetCallback(IHsUsartCallback *callback, uintptr_t callbackParam) -{ - m_userCallback = callback; - m_userCallbackParam = callbackParam; -} - - -void PacketUsart::PostPacket(uint8_t const *payload, uint8_t length, bool waitForCrcQueue) -{ - uint16_t payloadLength = RoundUpTo4((uint16_t)length); - - BuildHeader(m_txBuffer.packet, m_txSerialNo++, length); - if(payload) - memcpy(m_txBuffer.packet.payload, payload, length); - m_txBuffer.requestedLength = sizeof(m_txBuffer.packet.header) + payloadLength + sizeof(uint32_t); - m_txBuffer.busy = true; - m_txBuffer.error = false; - - CrcHandler::Instance().Enqueue(m_crcSlot, 0, &m_txBuffer.packet, sizeof(PacketHeader) + payloadLength, - nullptr, reinterpret_cast(m_txBuffer.packet.payload + payloadLength)); - - while(waitForCrcQueue && CrcHandler::Instance().IsQueued(m_crcSlot, 0)); - - SetupTransmit(&m_txBuffer.packet, m_txBuffer.requestedLength); - - ++m_stats.sent; -} - - -void PacketUsart::SetupReceive() -{ - m_rxBuffers[m_rxBufferSelector].requestedLength = sizeof(m_rxBuffers[m_rxBufferSelector].packet); - UsartCore::SetupReceive(&m_rxBuffers[m_rxBufferSelector], sizeof(m_rxBuffers[m_rxBufferSelector].packet)); -} - - -////////////////////////////////////// -// UsartCore pure virtual functions // -////////////////////////////////////// - -void PacketUsart::ReceiverIdle(void) -{ - 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; - LL_DMA_DisableStream(m_rxDma.GetDma(), m_rxDma.GetStream()); - } - } else - ++m_stats.premature_hdr; -} - - -void PacketUsart::TransmissionComplete(void) -{ - LL_USART_DisableDirectionTx(m_usart); // enforcing an idle frame - LL_USART_EnableDirectionTx(m_usart); - m_txBuffer.busy = 0; -} - - -void PacketUsart::FramingError(void) {} - - -void PacketUsart::Overrun(void) {} - - -void PacketUsart::RxDmaTransferComplete(void) -{ - if(CheckHeader(m_rxBuffers[m_rxBufferSelector].packet.header)) - 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 PacketUsart::RxDmaHalfTransfer(void) -{ -} - - -void PacketUsart::RxDmaError(DmaHelper::DmaErrorType reason) -{ - m_rxBuffers[m_rxBufferSelector].error = 1; - ++m_stats.rxDmaError; - SwitchRxBuffers(); -} - -void PacketUsart::TxDmaTransferComplete(void) -{ - LL_USART_EnableIT_TC(m_usart); - LL_DMA_DisableStream(m_txDma.GetDma(), m_txDma.GetStream()); -} - - -void PacketUsart::TxDmaHalfTransfer(void) -{ -} - - -void PacketUsart::TxDmaError(DmaHelper::DmaErrorType reason) -{ - m_txBuffer.error = 1; - ++m_stats.txDmaError; -} - - -/////////////////////// -// Private functions // -/////////////////////// - -void PacketUsart::BuildHeader(Packet &packet, uint8_t serialNo, uint8_t length) -{ - uint8_t hash = STARTMARKER; - - packet.header.startByte = STARTMARKER; - packet.header.serial = serialNo; - hash ^= serialNo; - packet.header.payloadLength = length; - hash ^= length; - packet.header.hash = hash; -} - - -bool PacketUsart::CheckHeader(PacketHeader &header) -{ - return header.startByte == STARTMARKER && (header.startByte ^ header.serial ^ header.payloadLength) == header.hash; -} - - -void PacketUsart::SwitchRxBuffers(void) -{ - ++m_stats.rcvd; - m_rxBufferSelector = !m_rxBufferSelector; - - if(m_rxBuffers[m_rxBufferSelector].busy) - ++m_stats.overrun; - SetupReceive(); -} - -/////////////////////////// -// CrcHandler::ICallback // -/////////////////////////// - -void PacketUsart::CrcSucceeded(uintptr_t callbackParam, uint32_t crc, uint8_t task) -{ - Buffer &buf(m_rxBuffers[static_cast(callbackParam)]); - - buf.busy = 1; - if(*(uint32_t*) (buf.packet.payload + RoundUpTo4((uint16_t)buf.packet.header.payloadLength)) != crc) { - buf.error = 1; - buf.errorInfo = crc; - ++m_stats.payloadErrror; - } - if(m_userCallback) - buf.busy = !m_userCallback->PacketReceived(this, m_userCallbackParam, buf.packet); -} - - -void PacketUsart::CrcFailed(uintptr_t callbackParam, uint32_t crc, uint8_t task) -{ - Buffer &buf(m_rxBuffers[static_cast(callbackParam)]); - buf.busy = buf.error = true; - buf.errorInfo = 0; - ++m_stats.payloadErrror; - if(m_userCallback) - buf.busy = !m_userCallback->PacketReceived(this, m_userCallbackParam, buf.packet); -} - - -} // namespace f4ll diff --git a/src/str_util.cpp b/src/str_util.cpp new file mode 100644 index 0000000..7bc9bcb --- /dev/null +++ b/src/str_util.cpp @@ -0,0 +1,105 @@ +#include +#include + +////////////////////////////////////////////////////////////////////////////// +size_t strcpy_ex(char *dst, char const *src) +{ + size_t ret = 0; + do { + *dst++ = *src; + ++ret; + } while (*src++); + return ret - 1; +} + +////////////////////////////////////////////////////////////////////////////// +void strrev(char *first, char *last) +{ + char tmp; + while (last > first) { + tmp = *first; + *first++ = *last; + *last-- = tmp; + } +} + +////////////////////////////////////////////////////////////////////////////// +char tochr(const uint8_t in, const uint8_t upper) +{ + return in + ((in < 10) ? '0' : (upper ? 'A' : 'a') - 10); +} + +////////////////////////////////////////////////////////////////////////////// +size_t uitodec(char *buffer, uint32_t data) +{ + char *b2 = buffer; + if (!data) { + *b2++ = '0'; + *b2 = '\0'; + return 1; + } + + while (data) { + *b2++ = (data % 10) + '0'; + data /= 10; + } + size_t ret = b2 - buffer; + + *b2-- = 0; + + strrev(buffer, b2); + return ret; +} + +////////////////////////////////////////////////////////////////////////////// +size_t uitohex(char *buffer, uint32_t data, uint8_t chars) +{ + char *b2 = buffer; + size_t ret = 0; + + if (chars == 0xff || !chars) { + if (!data) { + *b2++ = '0'; + *b2 = '\0'; + return 1; + } + + while (data) { + uint8_t curval = data & 0x0f; + *b2++ = tochr(curval, 1); + data >>= 4; + } + ret = b2 - buffer; + + } else { + ret = chars; + for (uint8_t pos = 0; pos < (uint8_t)ret; ++pos) { + *b2++ = tochr(data & 0x0f, 1); + data >>= 4; + } + } + *b2-- = 0; + strrev(buffer, b2); + return ret; +} + +////////////////////////////////////////////////////////////////////////////// +size_t itodec(char *buffer, int data) +{ + if (data < 0) { + *buffer++ = '-'; + return uitodec(buffer, -data) + 1; + } + + return uitodec(buffer, data); +} + +////////////////////////////////////////////////////////////////////////////// +size_t itohex(char *buffer, int data) +{ + if (data < 0) { + *buffer++ = '-'; + return uitohex(buffer, -data, 0) + 1; + } + return uitohex(buffer, data, 0); +} diff --git a/src/strutil.cpp b/src/strutil.cpp deleted file mode 100644 index f7930be..0000000 --- a/src/strutil.cpp +++ /dev/null @@ -1,110 +0,0 @@ -#include -#include "f4ll/strutil.h" - -////////////////////////////////////////////////////////////////////////////// -size_t strcpy_ex(char *dst, char const *src) -{ - size_t ret = 0; - do { - *dst++ = *src; - ++ret; - } while(*src++); - return ret - 1; -} - -////////////////////////////////////////////////////////////////////////////// -void strrev(char *first, char *last) -{ - char tmp; - while(last > first) { - tmp = *first; - *first++ = *last; - *last-- = tmp; - } -} - -////////////////////////////////////////////////////////////////////////////// -char tochr(const uint8_t in, const uint8_t upper) -{ - return in + ((in < 10) ? '0' : (upper ? 'A' : 'a') - 10); -} - -////////////////////////////////////////////////////////////////////////////// -size_t uitodec(char* buffer, uint32_t data) -{ - char *b2 = buffer; - if(!data) { - *b2++ = '0'; - *b2 = '\0'; - return 1; - } - - while(data) { - *b2++ = (data % 10) + '0'; - data /= 10; - } - size_t ret = b2 - buffer; - - *b2-- = 0; - - strrev(buffer, b2); - return ret; -} - -////////////////////////////////////////////////////////////////////////////// -size_t uitohex(char* buffer, uint32_t data, uint8_t chars) -{ - char *b2 = buffer; - size_t ret = 0; - - if(chars == 0xff || !chars) - { - if(!data) { - *b2++ = '0'; - *b2 = '\0'; - return 1; - } - - while(data) { - uint8_t curval = data & 0x0f; - *b2++ = tochr(curval, 1); - data >>= 4; - } - ret = b2 - buffer; - - } - else - { - ret = chars; - for(uint8_t pos = 0; pos < (uint8_t)ret; ++pos) { - *b2++ = tochr(data & 0x0f, 1); - data >>= 4; - } - - } - *b2-- = 0; - strrev(buffer, b2); - return ret; -} - - -////////////////////////////////////////////////////////////////////////////// -size_t itodec(char* buffer, int data) -{ - if(data < 0) { - *buffer++ = '-'; - return uitodec(buffer, -data) + 1; - } - - return uitodec(buffer, data); -} - -////////////////////////////////////////////////////////////////////////////// -size_t itohex(char* buffer, int data) -{ - if(data < 0) { - *buffer++ = '-'; - return uitohex(buffer, -data, 0) + 1; - } - return uitohex(buffer, data, 0); -} diff --git a/src/usart_core.cpp b/src/usart_core.cpp new file mode 100644 index 0000000..c0051d6 --- /dev/null +++ b/src/usart_core.cpp @@ -0,0 +1,145 @@ +/* + * ll_dmadrivenusartcore.cpp + * + * Created on: Nov 4, 2019 + * Author: abody + */ + +#include + +namespace f4ll { + +usart_core::usart_core(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t streamRx, uint32_t streamTx) + : m_usart(usart), + m_rx_dma(dma, streamRx), + m_tx_dma(dma, streamTx) +{ + uint32_t status = usart->SR; + volatile uint32_t tmpreg = usart->DR; // clearing some of the error/status bits in the USART + (void)tmpreg; + (void)status; + + *m_tx_dma.get_ifc_reg() = + m_tx_dma.get_tc_mask() | m_rx_dma.get_ht_mask() | m_tx_dma.get_te_mask() | m_rx_dma.get_fe_mask() | m_rx_dma.get_dme_mask(); + *m_rx_dma.get_ifc_reg() = + m_rx_dma.get_tc_mask() | m_rx_dma.get_ht_mask() | m_rx_dma.get_te_mask() | m_rx_dma.get_fe_mask() | m_rx_dma.get_dme_mask(); + + LL_DMA_EnableIT_TC(dma, streamRx); + LL_DMA_EnableIT_TE(dma, streamRx); + LL_DMA_EnableIT_TC(dma, streamTx); + LL_DMA_EnableIT_TE(dma, streamTx); +} + +void usart_core::usart_isr() +{ + uint32_t status = m_usart->SR; + volatile uint32_t tmpreg = m_usart->DR; // clearing some of the error/status bits in the HW + (void)tmpreg; + + if (LL_USART_IsEnabledIT_TC(m_usart) && LL_USART_IsActiveFlag_TC(m_usart)) { // transmission complete + LL_USART_DisableIT_TC(m_usart); + transmission_complete(); + } + if (LL_USART_IsEnabledIT_IDLE(m_usart) && (status & USART_SR_IDLE)) { + receiver_idle(); + } + if (LL_USART_IsEnabledIT_ERROR(m_usart)) { + if (status & USART_SR_FE) { + framing_error(); + } + if (status & USART_SR_ORE) { + overrun(); + } + } +} + +void usart_core::rx_dma_isr() +{ + if (*m_rx_dma.get_is_reg() & m_rx_dma.get_tc_mask()) { + *m_rx_dma.get_ifc_reg() = m_rx_dma.get_tc_mask(); + if (m_rx_dma.is_enabled_it_tc()) { + rx_dma_transfer_complete(); + } + } + if (*m_rx_dma.get_is_reg() & m_rx_dma.get_ht_mask()) { + *m_rx_dma.get_ifc_reg() = m_rx_dma.get_ht_mask(); + if (m_rx_dma.is_enabled_it_ht()) { + rx_dma_half_transfer(); + } + } + if (*m_rx_dma.get_is_reg() & m_rx_dma.get_te_mask()) { + *m_rx_dma.get_ifc_reg() = m_rx_dma.get_te_mask(); + if (m_rx_dma.is_enabled_it_te()) { + rx_dma_error(dma_helper::dma_error_type::transfer); + } + } + if (*m_rx_dma.get_is_reg() & m_rx_dma.get_fe_mask()) { + *m_rx_dma.get_ifc_reg() = m_rx_dma.get_fe_mask(); + if (m_rx_dma.is_enabled_it_fe()) { + rx_dma_error(dma_helper::dma_error_type::fifo); + } + } + if (*m_rx_dma.get_is_reg() & m_rx_dma.get_dme_mask()) { + *m_rx_dma.get_ifc_reg() = m_rx_dma.get_dme_mask(); + if (m_rx_dma.is_enabled_it_dme()) { + rx_dma_error(dma_helper::dma_error_type::direct_mode); + } + } +} + +void usart_core::tx_dma_isr() +{ + if (*m_tx_dma.get_is_reg() & m_tx_dma.get_tc_mask()) { // DMA transfer complete + *m_tx_dma.get_ifc_reg() = m_tx_dma.get_tc_mask(); + if (m_tx_dma.is_enabled_it_tc()) { + tx_dma_transfer_complete(); + } + } + if (*m_tx_dma.get_is_reg() & m_tx_dma.get_ht_mask()) { + *m_tx_dma.get_ifc_reg() = m_tx_dma.get_ht_mask(); + if (m_tx_dma.is_enabled_it_ht()) { + tx_dma_half_transfer(); + } + } + if (*m_tx_dma.get_is_reg() & m_tx_dma.get_te_mask()) { + *m_tx_dma.get_ifc_reg() = m_tx_dma.get_te_mask(); + if (m_tx_dma.is_enabled_it_te()) { + tx_dma_error(dma_helper::dma_error_type::transfer); + } + } + if (*m_tx_dma.get_is_reg() & m_tx_dma.get_fe_mask()) { + *m_tx_dma.get_ifc_reg() = m_tx_dma.get_fe_mask(); + if (m_tx_dma.is_enabled_it_fe()) { + tx_dma_error(dma_helper::dma_error_type::fifo); + } + } + if (*m_tx_dma.get_is_reg() & m_tx_dma.get_dme_mask()) { + *m_tx_dma.get_ifc_reg() = m_tx_dma.get_dme_mask(); + if (m_tx_dma.is_enabled_it_dme()) { + tx_dma_error(dma_helper::dma_error_type::direct_mode); + } + } +} + +void usart_core::setup_transmit(void const *buffer, uint16_t length) +{ + LL_DMA_ConfigAddresses( + m_tx_dma.get_dma(), m_tx_dma.get_stream(), reinterpret_cast(buffer), LL_USART_DMA_GetRegAddr(m_usart), + LL_DMA_DIRECTION_MEMORY_TO_PERIPH); + LL_DMA_SetDataLength(m_tx_dma.get_dma(), m_tx_dma.get_stream(), length); + LL_USART_EnableDMAReq_TX(m_usart); + LL_DMA_EnableStream(m_tx_dma.get_dma(), m_tx_dma.get_stream()); +} + +void usart_core::setup_receive(void *buffer, uint16_t length) +{ + LL_DMA_ConfigAddresses( + m_rx_dma.get_dma(), m_rx_dma.get_stream(), LL_USART_DMA_GetRegAddr(m_usart), reinterpret_cast(buffer), + LL_DMA_DIRECTION_PERIPH_TO_MEMORY); + LL_DMA_SetDataLength(m_rx_dma.get_dma(), m_rx_dma.get_stream(), length); + LL_USART_EnableDMAReq_RX(m_usart); + LL_USART_ClearFlag_ORE(m_usart); + LL_DMA_EnableStream(m_rx_dma.get_dma(), m_rx_dma.get_stream()); +} + +} /* namespace f4ll */ diff --git a/src/usartcore.cpp b/src/usartcore.cpp deleted file mode 100644 index 27ffbb9..0000000 --- a/src/usartcore.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* - * ll_dmadrivenusartcore.cpp - * - * Created on: Nov 4, 2019 - * Author: abody - */ - -#include "f4ll/usartcore.h" - -namespace f4ll { - -UsartCore::UsartCore(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t streamRx, uint32_t streamTx) -: m_usart(usart) -, m_rxDma(dma, streamRx) -, m_txDma(dma, streamTx) -{ - uint32_t status = usart->SR; - volatile uint32_t tmpreg = usart->DR; // clearing some of the error/status bits in the USART - (void) tmpreg; - (void) status; - - *m_txDma.GetIfcReg() = - m_txDma.GetTcMask() | m_rxDma.GetHtMask() | m_txDma.GetTeMask() | m_rxDma.GetFeMask() | m_rxDma.GetDmeMask(); - *m_rxDma.GetIfcReg() = - m_rxDma.GetTcMask() | m_rxDma.GetHtMask() | m_rxDma.GetTeMask() | m_rxDma.GetFeMask() | m_rxDma.GetDmeMask(); - - LL_DMA_EnableIT_TC(dma, streamRx); - LL_DMA_EnableIT_TE(dma, streamRx); - LL_DMA_EnableIT_TC(dma, streamTx); - LL_DMA_EnableIT_TE(dma, streamTx); -} - - -void UsartCore::UsartIsr() -{ - uint32_t status = m_usart->SR; - volatile uint32_t tmpreg = m_usart->DR; // clearing some of the error/status bits in the HW - (void) tmpreg; - - if(LL_USART_IsEnabledIT_TC(m_usart) && LL_USART_IsActiveFlag_TC(m_usart)) { // transmission complete - LL_USART_DisableIT_TC(m_usart); - TransmissionComplete(); - } - if(LL_USART_IsEnabledIT_IDLE(m_usart) && (status & USART_SR_IDLE)) { - ReceiverIdle(); - } - if(LL_USART_IsEnabledIT_ERROR(m_usart)) { - if(status & USART_SR_FE) { - FramingError(); - } - if(status & USART_SR_ORE) { - Overrun(); - } - } -} - - -void UsartCore::RxDmaIsr() -{ - if(*m_rxDma.GetIsReg() & m_rxDma.GetTcMask()) { - *m_rxDma.GetIfcReg() = m_rxDma.GetTcMask(); - if(m_rxDma.IsEnabledIt_TC()) - RxDmaTransferComplete(); - } - if(*m_rxDma.GetIsReg() & m_rxDma.GetHtMask()) { - *m_rxDma.GetIfcReg() = m_rxDma.GetHtMask(); - if(m_rxDma.IsEnabledIt_HT()) - RxDmaHalfTransfer(); - } - if(*m_rxDma.GetIsReg() & m_rxDma.GetTeMask()) { - *m_rxDma.GetIfcReg() = m_rxDma.GetTeMask(); - if(m_rxDma.IsEnabledIt_TE()) - RxDmaError(DmaHelper::DmaErrorType::Transfer); - } - if(*m_rxDma.GetIsReg() & m_rxDma.GetFeMask()) { - *m_rxDma.GetIfcReg() = m_rxDma.GetFeMask(); - if(m_rxDma.IsEnabledIt_FE()) - RxDmaError(DmaHelper::DmaErrorType::Fifo); - } - if(*m_rxDma.GetIsReg() & m_rxDma.GetDmeMask()) { - *m_rxDma.GetIfcReg() = m_rxDma.GetDmeMask(); - if(m_rxDma.IsEnabledIt_DME()) - RxDmaError(DmaHelper::DmaErrorType::DirectMode); - } -} - - -void UsartCore::TxDmaIsr() -{ - if(*m_txDma.GetIsReg() & m_txDma.GetTcMask()) { // DMA transfer complete - *m_txDma.GetIfcReg() = m_txDma.GetTcMask(); - if(m_txDma.IsEnabledIt_TC()) - TxDmaTransferComplete(); - } - if(*m_txDma.GetIsReg() & m_txDma.GetHtMask()) { - *m_txDma.GetIfcReg() = m_txDma.GetHtMask(); - if(m_txDma.IsEnabledIt_HT()) - TxDmaHalfTransfer(); - } - if(*m_txDma.GetIsReg() & m_txDma.GetTeMask()) { - *m_txDma.GetIfcReg() = m_txDma.GetTeMask(); - if(m_txDma.IsEnabledIt_TE()) - TxDmaError(DmaHelper::DmaErrorType::Transfer); - } - if(*m_txDma.GetIsReg() & m_txDma.GetFeMask()) { - *m_txDma.GetIfcReg() = m_txDma.GetFeMask(); - if(m_txDma.IsEnabledIt_FE()) - TxDmaError(DmaHelper::DmaErrorType::Fifo); - } - if(*m_txDma.GetIsReg() & m_txDma.GetDmeMask()) { - *m_txDma.GetIfcReg() = m_txDma.GetDmeMask(); - if(m_txDma.IsEnabledIt_DME()) - TxDmaError(DmaHelper::DmaErrorType::DirectMode); - } -} - - -void UsartCore::SetupTransmit(void const *buffer, uint16_t length) -{ - LL_DMA_ConfigAddresses(m_txDma.GetDma(), m_txDma.GetStream(), reinterpret_cast(buffer), - LL_USART_DMA_GetRegAddr(m_usart), LL_DMA_DIRECTION_MEMORY_TO_PERIPH); - LL_DMA_SetDataLength(m_txDma.GetDma(), m_txDma.GetStream(), length); - LL_USART_EnableDMAReq_TX(m_usart); - LL_DMA_EnableStream(m_txDma.GetDma(), m_txDma.GetStream()); -} - - -void UsartCore::SetupReceive(void *buffer, uint16_t length) -{ - LL_DMA_ConfigAddresses(m_rxDma.GetDma(), m_rxDma.GetStream(), LL_USART_DMA_GetRegAddr(m_usart), - reinterpret_cast(buffer), LL_DMA_DIRECTION_PERIPH_TO_MEMORY); - LL_DMA_SetDataLength(m_rxDma.GetDma(), m_rxDma.GetStream(), length); - LL_USART_EnableDMAReq_RX(m_usart); - LL_USART_ClearFlag_ORE(m_usart); - LL_DMA_EnableStream(m_rxDma.GetDma(), m_rxDma.GetStream()); -} - -} /* namespace f4ll */