almost fix SPI in F0 testboard

This commit is contained in:
Edward Emelianov 2021-07-06 23:33:53 +03:00
parent 83b3e56587
commit 3c452a6f19
8 changed files with 96 additions and 57 deletions

View File

@ -24,6 +24,9 @@
#include "adc.h"
#include "hardware.h"
#include "proto.h"
#include "spi.h"
#include "usart.h"
#include "usb.h"
void iwdg_setup(){
uint32_t tmout = 16000000;
@ -173,3 +176,44 @@ void hw_setup(){
adc_setup();
pwm_setup();
}
// USART & SPI both use common DMA interrupts, so put them together here
// SPI Rx use the same DMA channels as USART Tx, so they can't work together!
// USART1 Tx (channel 2) & SPI1 Tx (channel 3)
void dma1_channel2_3_isr(){
if(DMA1->ISR & DMA_ISR_TCIF2){ // Tx
DMA1->IFCR |= DMA_IFCR_CTCIF2; // clear TC flag
txrdy[0] = 1;
}
if(DMA1->ISR & DMA_ISR_TCIF3){ // transfer done
DMA1->IFCR |= DMA_IFCR_CTCIF3;
SPI_status[0] = SPI_READY;
USND("SPI1 tx done\n");
}
if(DMA1->ISR & DMA_ISR_TEIF2){ // receiver overflow
DMA1->IFCR |= DMA_IFCR_CTEIF2;
SPIoverfl[0] = 1;
}
}
// USART2 + USART3 Tx (channels 4 and 7) & SPI2 Tx (channel 5)
void dma1_channel4_5_isr(){
if(DMA1->ISR & DMA_ISR_TCIF4){ // Tx
DMA1->IFCR |= DMA_IFCR_CTCIF4; // clear TC flag
txrdy[1] = 1;
}
if(DMA1->ISR & DMA_ISR_TEIF4){
DMA1->IFCR |= DMA_IFCR_CTEIF4;
SPIoverfl[1] = 1;
}
if(DMA1->ISR & DMA_ISR_TCIF5){
DMA1->IFCR |= DMA_IFCR_CTCIF5;
SPI_status[1] = SPI_READY;
USND("SPI2 tx done\n");
}
#ifdef USART3
if(DMA1->ISR & DMA_ISR_TCIF7){ // Tx
DMA1->IFCR |= DMA_IFCR_CTCIF7; // clear TC flag
txrdy[2] = 1;
}
#endif
}

View File

@ -46,12 +46,10 @@ int main(void){
sysreset();
SysTick_Config(6000, 1);
hw_setup();
usart_setup();
RCC->CSR |= RCC_CSR_RMVF; // remove reset flags
USB_setup();
spi_setup();
iwdg_setup();
while (1){

Binary file not shown.

View File

@ -182,6 +182,7 @@ static inline char *DAC_chval(char *buf){
static inline void wrSPI(int SPIidx, char *buf){
uint16_t N = readNnumbers(buf);
if(N < 1){
*(uint8_t *)&(SPI1->DR) = 0xea;
USND("Enter at least 1 number (max: ");
USB_sendstr(u2str(LOCBUFFSZ)); USND(")\n");
return;
@ -234,7 +235,9 @@ const char *helpstring =
"pr - get data from SPI2\n"
"R - software reset\n"
"S - send short string over USB\n"
"s - setup SPI (and turn off USARTs)\n"
"Ux str - send string to USARTx (1..3)\n"
"u - setup USARTs (and turn off SPI)\n"
"T - MCU temperature\n"
"V - Vdd\n"
"W - test watchdog\n"
@ -314,9 +317,19 @@ const char *parse_cmd(char *buf){
USND("Test string for USB\n");
return "Short test sent";
break;
case 's':
USND("SPI are ON, USART are OFF\n");
usart_stop();
spi_setup();
break;
case 'T':
return u2str(getMCUtemp());
break;
case 'u':
USND("USART are ON, SPI are OFF\n");
spi_stop();
usart_setup();
break;
case 'V':
return u2str(getVdd());
break;

View File

@ -25,7 +25,7 @@
// buffers for DMA rx/tx
static uint8_t inbuff[SPInumber][SPIBUFSZ], outbuf[SPInumber][SPIBUFSZ];
static uint8_t overfl[SPInumber] = {0, 0};
volatile uint8_t SPIoverfl[SPInumber] = {0, 0};
spiStatus SPI_status[SPInumber] = {SPI_NOTREADY, SPI_NOTREADY};
static DMA_Channel_TypeDef * const rxDMA[SPInumber] = {DMA1_Channel2, DMA1_Channel4};
static DMA_Channel_TypeDef * const txDMA[SPInumber] = {DMA1_Channel3, DMA1_Channel5};
@ -46,6 +46,7 @@ static void spicommonsetup(uint8_t SPIidx, uint8_t master){
/* Peripheral to memory */
/* 8-bit transfer */
/* Overflow IR */
rxDMA[SPIidx]->CCR &= ~DMA_CCR_EN;
rxDMA[SPIidx]->CPAR = (uint32_t)&(SPI[SPIidx]->DR); /* (1) */
rxDMA[SPIidx]->CMAR = (uint32_t)inbuff[SPIidx]; /* (2) */
rxDMA[SPIidx]->CNDTR = SPIBUFSZ; /* (3) */
@ -57,6 +58,7 @@ static void spicommonsetup(uint8_t SPIidx, uint8_t master){
/* Memory to peripheral*/
/* 8-bit transfer */
/* Transfer complete IT */
txDMA[SPIidx]->CCR &= ~DMA_CCR_EN;
txDMA[SPIidx]->CPAR = (uint32_t)&(SPI[SPIidx]->DR); /* (5) */
txDMA[SPIidx]->CMAR = (uint32_t)outbuf[SPIidx]; /* (6) */
txDMA[SPIidx]->CCR |= DMA_CCR_MINC | DMA_CCR_TCIE | DMA_CCR_DIR; /* (7) */
@ -67,10 +69,12 @@ static void spicommonsetup(uint8_t SPIidx, uint8_t master){
NVIC_EnableIRQ(txDMAirqn[SPIidx]);
/* Configure SPI */
/* (1) Master selection, BR: Fpclk/256 CPOL and CPHA at zero (rising first edge) */
/* (1a) software slave management (SSI inactive) */
/* (2) TX and RX with DMA, 8-bit Rx fifo */
/* (3) Enable SPI1 */
SPI[SPIidx]->CR1 = master ? (SPI_CR1_MSTR | SPI_CR1_BR) : (SPI_CR1_BR); /* (1) */
SPI[SPIidx]->CR2 = SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN | SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0; /* (2) */
/* (3) Enable SPI */
if(master) SPI[SPIidx]->CR1 = SPI_CR1_MSTR | SPI_CR1_BR | SPI_CR1_SSM | SPI_CR1_SSI; /* (1) */
else SPI[SPIidx]->CR1 = SPI_CR1_SSM; // (1a)
SPI[SPIidx]->CR2 = SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN | SPI_CR2_FRXTH | SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0; /* (2) */
SPI[SPIidx]->CR1 |= SPI_CR1_SPE; /* (3) */
SPI_status[SPIidx] = SPI_READY;
SPI_prep_receive(SPIidx);
@ -90,36 +94,16 @@ void spi_setup(){
GPIOB->AFR[1] = (GPIOB->AFR[1] & ~(GPIO_AFRH_AFRH5 | GPIO_AFRH_AFRH6 | GPIO_AFRH_AFRH7)); /* (2) */
// enable clocking
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
RCC->APB1ENR |= RCC_APB1ENR_SPI2EN;
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
// SPI1 - master, SPI2 - slave
spicommonsetup(0, 1);
spicommonsetup(1, 0);
}
// SPI1 Tx (channel 3)
void dma1_channel2_3_isr(){
if(DMA1->ISR & DMA_ISR_TCIF3){ // transfer done
DMA1->IFCR |= DMA_IFCR_CTCIF3;
SPI_status[0] = SPI_READY;
USND("SPI1 tx done\n");
}
if(DMA1->ISR & DMA_ISR_TEIF2){ // receiver overflow
DMA1->IFCR |= DMA_IFCR_CTEIF2;
overfl[0] = 1;
}
}
// SPI2 Tx (channel 5)
void dma1_channel4_5_isr(){
if(DMA1->ISR & DMA_ISR_TCIF5){
DMA1->IFCR |= DMA_IFCR_CTCIF5;
SPI_status[1] = SPI_READY;
USND("SPI2 tx done\n");
}
if(DMA1->ISR & DMA_ISR_TEIF4){
DMA1->IFCR |= DMA_IFCR_CTEIF4;
overfl[1] = 1;
}
void spi_stop(){
RCC->APB1ENR &= ~RCC_APB1ENR_SPI2EN;
RCC->APB2ENR &= ~RCC_APB2ENR_SPI1EN;
}
/**
@ -132,11 +116,17 @@ void dma1_channel4_5_isr(){
uint8_t SPI_transmit(uint8_t N, const uint8_t *buf, uint8_t len){
if(!buf || !len || len > SPIBUFSZ || N >= SPInumber) return 1; // bad data format
if(SPI_status[N] != SPI_READY) return 2; // spi not ready to transmit data
int ctr = 0;
while(SPI[N]->SR & SPI_SR_FTLVL && ++ctr < 99999); // wait for transmission buffer empty
ctr = 0;
while(SPI[N]->SR & SPI_SR_BSY && ++ctr < 99999); // wait while busy
USND("SPI->SR="); USB_sendstr(uhex2str(SPI[N]->SR)); USND("\n");
txDMA[N]->CCR &=~ DMA_CCR_EN;
memcpy(outbuf[N], buf, len);
txDMA[N]->CNDTR = len;
SPI_status[N] = SPI_BUSY;
txDMA[N]->CMAR = (uint32_t)outbuf[N];
SPI_prep_receive(N);
SPI_status[N] = SPI_BUSY;
txDMA[N]->CCR |= DMA_CCR_EN;
return 0;
}
@ -145,9 +135,12 @@ uint8_t SPI_transmit(uint8_t N, const uint8_t *buf, uint8_t len){
uint8_t SPI_prep_receive(uint8_t N){
if(N >= SPInumber) return 1;
if(SPI_status[N] != SPI_READY) return 2; // still transmitting data
overfl[N] = 0;
SPIoverfl[N] = 0;
rxDMA[N]->CCR &= ~DMA_CCR_EN;
(void)SPI[N]->DR; // read DR and SR to clear OVR flag
(void)SPI[N]->SR;
rxDMA[N]->CNDTR = SPIBUFSZ;
rxDMA[N]->CMAR = (uint32_t)inbuff[N];
rxDMA[N]->CCR |= DMA_CCR_EN;
return 0;
}
@ -164,7 +157,7 @@ uint8_t SPI_getdata(uint8_t N, uint8_t *buf, uint8_t *maxlen){
if(N >= SPInumber) return 1;
if(SPI_status[N] != SPI_READY) return 2; // still transmitting data
rxDMA[N]->CCR &= ~DMA_CCR_EN;
overfl[N] = 0;
SPIoverfl[N] = 0;
uint8_t remain = rxDMA[N]->CNDTR;
if(maxlen){
if(buf && *maxlen) memcpy(buf, inbuff[N], *maxlen);
@ -179,7 +172,7 @@ uint8_t SPI_getdata(uint8_t N, uint8_t *buf, uint8_t *maxlen){
// should be called BEFORE SPI_prep_receive() or SPI_getdata()
uint8_t SPI_isoverflow(uint8_t N){
if(N >= SPInumber) return 1;
register uint8_t o = overfl[N];
overfl[N] = 0;
register uint8_t o = SPIoverfl[N];
SPIoverfl[N] = 0;
return o;
}

View File

@ -24,7 +24,7 @@
#define SPInumber (2)
#define SPIBUFSZ 4
#define SPIBUFSZ (32)
typedef enum{
SPI_NOTREADY,
@ -33,8 +33,10 @@ typedef enum{
} spiStatus;
extern spiStatus SPI_status[];
extern volatile uint8_t SPIoverfl[];
void spi_setup();
void spi_stop();
uint8_t SPI_transmit(uint8_t N, const uint8_t *buf, uint8_t len);
uint8_t SPI_prep_receive(uint8_t N);
uint8_t SPI_getdata(uint8_t N, uint8_t *buf, uint8_t *maxlen);

View File

@ -134,6 +134,7 @@ void usart_setup(){
// clock
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
#ifdef USART3
GPIOB->MODER = (GPIOB->MODER & ~(GPIO_MODER_MODER10 | GPIO_MODER_MODER11)) |
GPIO_MODER_MODER10_AF | GPIO_MODER_MODER11_AF;
@ -144,6 +145,7 @@ void usart_setup(){
for(int i = 0; i < USARTNUM; ++i){
USARTs[i]->ICR = 0xffffffff; // clear all flags
// USARTX Tx DMA
USARTDMA[i]->CCR &= ~DMA_CCR_EN;
USARTDMA[i]->CPAR = (uint32_t) &USARTs[i]->TDR; // periph
USARTDMA[i]->CCR |= DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE; // 8bit, mem++, mem->per, transcompl irq
// setup usarts
@ -168,6 +170,13 @@ void usart_setup(){
#endif
}
void usart_stop(){
RCC->APB2ENR &= ~RCC_APB2ENR_USART1EN;
RCC->APB1ENR &= ~RCC_APB1ENR_USART2EN;
#ifdef USART3
RCC->APB1ENR &= ~RCC_APB1ENR_USART3EN;
#endif
}
static void usart_IRQ(int usartno){
USART_TypeDef *USARTX = USARTs[usartno];
@ -221,7 +230,6 @@ void usart2_isr(){
usart_IRQ(1);
}
// work with USART3 only @ boards that have it
#ifdef USART3
void usart3_4_isr(){
@ -229,23 +237,3 @@ void usart3_4_isr(){
}
#endif
// USART1
void dma1_channel2_3_isr(){
if(DMA1->ISR & DMA_ISR_TCIF2){ // Tx
DMA1->IFCR |= DMA_IFCR_CTCIF2; // clear TC flag
txrdy[0] = 1;
}
}
// USART2 + USART3
void dma1_channel4_5_isr(){
if(DMA1->ISR & DMA_ISR_TCIF4){ // Tx
DMA1->IFCR |= DMA_IFCR_CTCIF4; // clear TC flag
txrdy[1] = 1;
}
#ifdef USART3
if(DMA1->ISR & DMA_ISR_TCIF7){ // Tx
DMA1->IFCR |= DMA_IFCR_CTCIF7; // clear TC flag
txrdy[2] = 1;
}
#endif
}

View File

@ -54,5 +54,6 @@ void usart_send(int usartno, const char *str);
void usart_sendn(int usartno, const char *str, uint32_t L);
void newline(int usartno);
void usart_putchar(int usartno, const char ch);
void usart_stop();
#endif // __USART_H__