Squashed commit of the following: commit 5f16309f629b9928d2134b85ae64af69bc3ebbcd Author: kuwoyuki <kuwoyuki@cock.li> Date: Sun Nov 24 22:55:15 2024 +0600 fix: Makefile, improve onewire retries commit 55496a3bda941b52ff349dc75c9c06eb5a37c07d Author: kuwoyuki <kuwoyuki@cock.li> Date: Mon Nov 18 00:41:18 2024 +0600 fix: make onewire validity less strict commit 3428a9bc9792508972ce3e7e4e35a64f047bca10 Author: kuwoyuki <kuwoyuki@cock.li> Date: Sun Nov 17 23:57:55 2024 +0600 chore: rm bins commit 1594e5ed430522b15466c8afa62ff7fb1b28947c Author: kuwoyuki <kuwoyuki@cock.li> Date: Sun Nov 17 23:32:01 2024 +0600 chore: unplatformiofy
132 lines
4.4 KiB
C
132 lines
4.4 KiB
C
#include "spi_dma.h"
|
|
|
|
#include "ch32v003fun.h"
|
|
#include "debug.h"
|
|
|
|
#define RX_Channel DMA1_Channel2
|
|
#define TX_Channel DMA1_Channel3
|
|
|
|
static const uint8_t tx_dummy_byte = 0xFF;
|
|
static uint8_t rx_dummy;
|
|
|
|
void spi_select(void) {
|
|
GPIOA->BCR = (1 << 4); // Set PA4 (CS) low
|
|
}
|
|
|
|
void spi_unselect(void) {
|
|
GPIOA->BSHR = (1 << 4); // Set PA4 (CS) high
|
|
}
|
|
|
|
// SPI DMA
|
|
void spidma_read_buffer(uint8_t* buf, uint16_t len) {
|
|
// tx
|
|
TX_Channel->MADDR = (uint32_t)&tx_dummy_byte;
|
|
TX_Channel->CNTR = len;
|
|
TX_Channel->CFGR &= ~DMA_MemoryInc_Enable;
|
|
// rx
|
|
RX_Channel->MADDR = (uint32_t)buf;
|
|
RX_Channel->CNTR = len;
|
|
RX_Channel->CFGR |= DMA_MemoryInc_Enable;
|
|
|
|
// enable
|
|
RX_Channel->CFGR |= DMA_CFGR1_EN;
|
|
TX_Channel->CFGR |= DMA_CFGR1_EN;
|
|
|
|
while (!(DMA1->INTFR & DMA1_FLAG_TC2) && !(DMA1->INTFR & DMA1_FLAG_TC3));
|
|
|
|
/**
|
|
* In transmission mode, when the DMA has written all the data to be
|
|
* transmitted (flag TCIF is set in the DMA_ISR register), the BSY flag can be
|
|
* monitored to ensure that the SPI communication is complete. This is
|
|
* required to avoid corrupting the last transmission before disabling the SPI
|
|
* or entering the Stop mode. The software must first wait until TXE=1 and
|
|
* then until BSY=0.
|
|
*/
|
|
while (!(SPI1->STATR & SPI_STATR_TXE));
|
|
while (SPI1->STATR & SPI_I2S_FLAG_BSY);
|
|
|
|
// clear intfr
|
|
DMA1->INTFCR |= DMA1_FLAG_TC2 | DMA1_FLAG_TC3;
|
|
|
|
RX_Channel->CFGR &= ~DMA_CFGR1_EN;
|
|
TX_Channel->CFGR &= ~DMA_CFGR1_EN;
|
|
}
|
|
|
|
void spidma_write_buffer(uint8_t* buf, uint16_t len) {
|
|
// tx
|
|
TX_Channel->MADDR = (uint32_t)buf;
|
|
TX_Channel->CNTR = len;
|
|
TX_Channel->CFGR |= DMA_MemoryInc_Enable;
|
|
// rx
|
|
RX_Channel->MADDR = (uint32_t)&rx_dummy;
|
|
RX_Channel->CNTR = len;
|
|
RX_Channel->CFGR &= ~DMA_MemoryInc_Enable;
|
|
|
|
// enable
|
|
TX_Channel->CFGR |= DMA_CFGR1_EN;
|
|
RX_Channel->CFGR |= DMA_CFGR1_EN;
|
|
|
|
while (!(DMA1->INTFR & DMA1_FLAG_TC2) && !(DMA1->INTFR & DMA1_FLAG_TC3));
|
|
|
|
// wait for SPI to complete: TXE = 1, then BSY = 0
|
|
while (!(SPI1->STATR & SPI_STATR_TXE));
|
|
while (SPI1->STATR & SPI_I2S_FLAG_BSY);
|
|
|
|
// clear intfr
|
|
DMA1->INTFCR |= DMA1_FLAG_TC2 | DMA1_FLAG_TC3;
|
|
|
|
RX_Channel->CFGR &= ~DMA_CFGR1_EN;
|
|
TX_Channel->CFGR &= ~DMA_CFGR1_EN;
|
|
}
|
|
|
|
void spidma_init(void) {
|
|
// Enable clock for GPIOA and SPI1
|
|
RCC->APB2PCENR |= RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1;
|
|
// Enable clock for DMA1
|
|
RCC->AHBPCENR |= RCC_AHBPeriph_DMA1;
|
|
|
|
// SPI1 Pin Configuration
|
|
// CS on PA4, 10MHz Output, push-pull
|
|
GPIOA->CFGLR &= ~(0xf << (4 * 4));
|
|
GPIOA->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP) << (4 * 4);
|
|
// SCK on PA5, 10MHz Output, alt func, push-pull
|
|
GPIOA->CFGLR &= ~(0xf << (4 * 5));
|
|
GPIOA->CFGLR |= (GPIO_Speed_50MHz | GPIO_CNF_OUT_PP_AF) << (4 * 5);
|
|
// MISO on PA6, 10MHz input, floating
|
|
GPIOA->CFGLR &= ~(0xf << (4 * 6));
|
|
GPIOA->CFGLR |= (GPIO_CNF_IN_FLOATING) << (4 * 6);
|
|
// MOSI on PA7, 10MHz Output, alt func, push-pull
|
|
GPIOA->CFGLR &= ~(0xf << (4 * 7));
|
|
GPIOA->CFGLR |= (GPIO_Speed_50MHz | GPIO_CNF_OUT_PP_AF) << (4 * 7);
|
|
|
|
// Reset and Configure SPI1
|
|
SPI1->CTLR1 = 0; // Clear CTLR1 initially
|
|
|
|
SPI1->CTLR1 = SPI_Mode_Master | // Master mode
|
|
SPI_Direction_2Lines_FullDuplex | // Full duplex
|
|
SPI_DataSize_8b | // 8-bit data frame format
|
|
SPI_CPHA_1Edge | // Clock polarity
|
|
SPI_CPOL_Low | // Clock phase
|
|
SPI_BaudRatePrescaler_64 | // Baud rate prescaler
|
|
SPI_NSS_Soft; // Software NSS management
|
|
|
|
// Enable TX and RX DMA
|
|
SPI1->CTLR2 = SPI_CTLR2_TXDMAEN | SPI_CTLR2_RXDMAEN;
|
|
|
|
SPI1->I2SCFGR &= SPI_Mode_Select; // Disable I2S mode
|
|
SPI1->CTLR1 |= SPI_CTLR1_SPE; // Enable SPI
|
|
|
|
// DMA setup
|
|
TX_Channel->PADDR = (uint32_t)&SPI1->DATAR; // TX Channel
|
|
TX_Channel->CFGR = DMA_M2M_Disable | DMA_Priority_VeryHigh |
|
|
DMA_MemoryDataSize_Byte | DMA_PeripheralDataSize_Byte |
|
|
DMA_MemoryInc_Enable | DMA_PeripheralInc_Disable |
|
|
DMA_Mode_Normal | DMA_DIR_PeripheralDST;
|
|
|
|
RX_Channel->PADDR = (uint32_t)&SPI1->DATAR; // RX Channel
|
|
RX_Channel->CFGR = DMA_M2M_Disable | DMA_Priority_VeryHigh |
|
|
DMA_MemoryDataSize_Byte | DMA_PeripheralDataSize_Byte |
|
|
DMA_MemoryInc_Enable | DMA_PeripheralInc_Disable |
|
|
DMA_Mode_Normal | DMA_DIR_PeripheralSRC;
|
|
}
|