#include "system.h" #include "spiclass.h" typedef __SIZE_TYPE__ size_t; enum SPICLK : uint32_t { FPCLK_2 = 0u, // 72 MHz FPCLK_4, // 72 MHz FPCLK_8, // 36 MHz FPCLK_16, // 18 MHz FPCLK_32, // 9 MHz FPCLK_64, // 4.5 MHz FPCLK_128, // 2.25 MHz FPCLK_256, // 1.125 MHz }; static SpiClass * pSpiInstance = nullptr; extern "C" { //[[gnu::interrupt]] extern void DMA1_Channel2_IRQHandler(); [[gnu::interrupt]] extern void DMA1_Channel3_IRQHandler(); extern void * memcpy (void * dest, const void * src, size_t n); }; void DMA1_Channel3_IRQHandler() { // transmit channel if (pSpiInstance) pSpiInstance->drq(); } static constexpr unsigned FM = 1u; // 10 MHz static void InitPins () noexcept { // PA4 - NSS, PA5 - SCK, PA6 - MISO, PA7 - MOSI GPIOA.CFGLR.modify([](GPIOA_Type::CFGLR_DEF & r) -> uint32_t { r.B.MODE4 = FM; r.B.CNF4 = 2u; // alt push - pull r.B.MODE5 = FM; r.B.CNF5 = 2u; // alt push - pull r.B.MODE6 = 0u; // input mode r.B.CNF6 = 1u; // floating r.B.MODE7 = FM; r.B.CNF7 = 2u; // alt push - pull return r.R; }); // AFIO - default } void SpiClass::drq() { DMA1_Type::INTFR_DEF state (DMA1.INTFR); if (state.B.TCIF3) { DMA1.INTFCR.B.CTCIF3 = SET; // clear complete = true; DMA1.CFGR3.B.EN = RESET; SPI1.CTLR1.B.SPE = RESET; } } SpiClass::SpiClass() noexcept : total(0u), complete (true) { pSpiInstance = this; } void SpiClass::Init() { RCC.APB2PCENR.modify([](RCC_Type::APB2PCENR_DEF & r) -> uint32_t { r.B.SPI1EN = SET; r.B.IOPAEN = SET; r.B.AFIOEN = SET; return r.R; }); RCC.AHBPCENR.B.DMA1EN = SET; InitPins(); // Configure the peripheral data register address DMA1.PADDR3.R = reinterpret_cast (& SPI1.DATAR); // Configure the memory address DMA1.MADDR3.R = reinterpret_cast (buffer); // Configure the number of DMA tranfer to be performs on DMA channel 1 // DMA1.CNTR3 .R = FULL_LEN; // Configure increment, size, interrupts and circular mode DMA1.CFGR3.modify([] (DMA1_Type::CFGR3_DEF & r) -> uint32_t { r.B.PL = 3u; // highest priority r.B.DIR = SET; // memory -> periferal r.B.MINC = SET; // memory increment r.B.MSIZE = 0u; // 8-bit r.B.PSIZE = 0u; // 8-bit //r.B.HTIE = SET; // INT Enable HALF r.B.TCIE = SET; // INT Enable FULL r.B.CIRC = RESET; // ! Circular MODE //Enable DMA Channel 1 //r.B.EN = SET; return r.R; }); SPI1.CTLR1.modify([](SPI1_Type::CTLR1_DEF & r) -> uint32_t { r.B.CPHA = RESET; r.B.CPOL = RESET; r.B.MSTR = SET; r.B.DFF = RESET; // 8 bit r.B.SSM = SET; r.B.SSI = SET; r.B.LSBFIRST = SET; r.B.BR = FPCLK_32; // 4.5 MHz return r.R; }); SPI1.CTLR2.modify([](SPI1_Type::CTLR2_DEF & r) -> uint32_t { r.B.SSOE = SET; //r.B.RXNEIE = SET; //r.B.TXEIE = SET; r.B.TXDMAEN = SET; return r.R; }); NVIC.EnableIRQ(DMA1_Channel3_IRQn); } bool SpiClass::send (const char * data, const unsigned int len) { if (!complete) return false; complete = false; total = len > SPIBUFLEN ? SPIBUFLEN : len; memcpy (buffer, data, total); DMA1.PADDR3.R = reinterpret_cast (& SPI1.DATAR); DMA1.MADDR3.R = reinterpret_cast (buffer); DMA1.CNTR3.R = total; DMA1.CFGR3.B.EN = SET; SPI1.CTLR1.B.SPE = SET; return true; }