RISC-V/V203/usb/ch32v203/spiclass.cpp

115 lines
3.3 KiB
C++
Raw Normal View History

2024-11-08 20:56:19 +01:00
#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" {
2024-11-09 16:26:15 +01:00
//[[gnu::interrupt]] extern void DMA1_Channel2_IRQHandler();
[[gnu::interrupt]] extern void DMA1_Channel3_IRQHandler();
2024-11-08 20:56:19 +01:00
extern void * memcpy (void * dest, const void * src, size_t n);
};
2024-11-09 16:26:15 +01:00
void DMA1_Channel3_IRQHandler() { // transmit channel
if (pSpiInstance) pSpiInstance->drq();
2024-11-08 20:56:19 +01:00
}
2024-11-09 16:26:15 +01:00
static constexpr unsigned FM = 1u; // 10 MHz
2024-11-08 20:56:19 +01:00
static void InitPins () noexcept {
2024-11-09 16:26:15 +01:00
// PA4 - NSS, PA5 - SCK, PA6 - MISO, PA7 - MOSI
2024-11-08 20:56:19 +01:00
GPIOA.CFGLR.modify([](GPIOA_Type::CFGLR_DEF & r) -> uint32_t {
2024-11-09 16:26:15 +01:00
r.B.MODE4 = FM;
r.B.CNF4 = 2u; // alt push - pull
r.B.MODE5 = FM;
r.B.CNF5 = 2u; // alt push - pull
2024-11-08 20:56:19 +01:00
r.B.MODE6 = 0u; // input mode
r.B.CNF6 = 1u; // floating
2024-11-09 16:26:15 +01:00
r.B.MODE7 = FM;
r.B.CNF7 = 2u; // alt push - pull
2024-11-08 20:56:19 +01:00
return r.R;
});
// AFIO - default
}
2024-11-09 16:26:15 +01:00
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;
2024-11-08 20:56:19 +01:00
}
}
2024-11-09 16:26:15 +01:00
SpiClass::SpiClass() noexcept : total(0u), complete (true) {
2024-11-08 20:56:19 +01:00
pSpiInstance = this;
2024-11-09 16:26:15 +01:00
}
void SpiClass::Init() {
2024-11-08 20:56:19 +01:00
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;
});
2024-11-09 16:26:15 +01:00
RCC.AHBPCENR.B.DMA1EN = SET;
2024-11-08 20:56:19 +01:00
InitPins();
2024-11-09 16:26:15 +01:00
// Configure the peripheral data register address
DMA1.PADDR3.R = reinterpret_cast<size_t> (& SPI1.DATAR);
// Configure the memory address
DMA1.MADDR3.R = reinterpret_cast<size_t> (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;
});
2024-11-08 20:56:19 +01:00
SPI1.CTLR1.modify([](SPI1_Type::CTLR1_DEF & r) -> uint32_t {
r.B.CPHA = SET;
r.B.CPOL = SET;
r.B.MSTR = SET;
r.B.DFF = RESET; // 8 bit
r.B.SSM = SET;
r.B.SSI = SET;
r.B.LSBFIRST = RESET;
r.B.BR = FPCLK_64; // 4.5 MHz
return r.R;
});
SPI1.CTLR2.modify([](SPI1_Type::CTLR2_DEF & r) -> uint32_t {
r.B.SSOE = SET;
2024-11-09 16:26:15 +01:00
//r.B.RXNEIE = SET;
//r.B.TXEIE = SET;
r.B.TXDMAEN = SET;
2024-11-08 20:56:19 +01:00
return r.R;
});
2024-11-09 16:26:15 +01:00
NVIC.EnableIRQ(DMA1_Channel3_IRQn);
2024-11-08 20:56:19 +01:00
}
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);
2024-11-09 16:26:15 +01:00
DMA1.CNTR3.R = total;
DMA1.CFGR3.B.EN = SET;
SPI1.CTLR1.B.SPE = SET;
2024-11-08 20:56:19 +01:00
return true;
}