/* * ll_crchandler.h * * Created on: Oct 26, 2019 * Author: compi */ #ifndef LL_CRCHANDLER_H_ #define LL_CRCHANDLER_H_ #include #include #include "ll_dmahelper.h" #include "singleton.h" extern "C" void _HandleCrcDmaIrq(void); namespace f4ll { class LL_CrcHandler : public Singleton { friend class Singleton; public: struct ICallback { virtual void CrcSucceeded(uintptr_t callbackParam, uint32_t crc, int prio) = 0; virtual void CrcFailed(uintptr_t callbackParam, uint32_t crc, int prio) = 0; }; class Slot { friend class LL_CrcHandler; public: struct CrcTask { void const * volatile m_address; // changed to nullptr when execution starts uint16_t volatile m_wordCount; LL_CrcHandler::ICallback *m_callback; uintptr_t m_callbackParam; }; private: Slot *m_next = nullptr; uint8_t m_taskCount; CrcTask m_tasks[1]; protected: Slot(unsigned int taskCount) : m_taskCount(taskCount) {} Slot() = delete; Slot(Slot const &other) = delete; }; // DON't try this at home! we "extend" LL_CrcHandler::m_tasks this way template class TSlot : public Slot { public: TSlot() : Slot(n) {} private: TSlot::CrcTask _m_tasks[n-1]; }; void AttachSlot(Slot &slot); bool Enqueue(Slot &slot, uint8_t prio, void const *address, uint16_t len, ICallback *cb, uintptr_t cbParam); uint32_t Compute(Slot &slot, uint8_t prio, void const *address, uint16_t len); bool IsActive(Slot &slot, uint8_t prio) const; bool IsQueued(Slot &slot, uint8_t prio) const; bool IsRunning(Slot &slot, uint8_t prio) const; private: LL_CrcHandler(DMA_TypeDef *dma, uint32_t stream); friend void ::_HandleCrcDmaIrq(void); void DmaTransferCompleted(void); void StartNextTask(void); void WaitResults(Slot &slot, uint8_t prio) const; LL_DmaHelper m_dma; Slot * volatile m_firstSlot = nullptr; Slot * volatile m_activeSlot = nullptr; int volatile m_activePrio; }; } // namespace f4ll #endif /* LL_CRCHANDLER_H_ */