diff --git a/F0-nolib/F0_testbrd/hardware.c b/F0-nolib/F0_testbrd/hardware.c index f9a0fa2..63d06e0 100644 --- a/F0-nolib/F0_testbrd/hardware.c +++ b/F0-nolib/F0_testbrd/hardware.c @@ -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 +} diff --git a/F0-nolib/F0_testbrd/main.c b/F0-nolib/F0_testbrd/main.c index ded79c5..135a6f2 100644 --- a/F0-nolib/F0_testbrd/main.c +++ b/F0-nolib/F0_testbrd/main.c @@ -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){ diff --git a/F0-nolib/F0_testbrd/pl2303.bin b/F0-nolib/F0_testbrd/pl2303.bin index d270bdf..a18e5ff 100755 Binary files a/F0-nolib/F0_testbrd/pl2303.bin and b/F0-nolib/F0_testbrd/pl2303.bin differ diff --git a/F0-nolib/F0_testbrd/proto.c b/F0-nolib/F0_testbrd/proto.c index f0f88af..9c7ff48 100644 --- a/F0-nolib/F0_testbrd/proto.c +++ b/F0-nolib/F0_testbrd/proto.c @@ -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; diff --git a/F0-nolib/F0_testbrd/spi.c b/F0-nolib/F0_testbrd/spi.c index bbfd3f5..a5a4a8b 100644 --- a/F0-nolib/F0_testbrd/spi.c +++ b/F0-nolib/F0_testbrd/spi.c @@ -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; } diff --git a/F0-nolib/F0_testbrd/spi.h b/F0-nolib/F0_testbrd/spi.h index 208a739..1c7f99d 100644 --- a/F0-nolib/F0_testbrd/spi.h +++ b/F0-nolib/F0_testbrd/spi.h @@ -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); diff --git a/F0-nolib/F0_testbrd/usart.c b/F0-nolib/F0_testbrd/usart.c index 7a85866..34a207f 100644 --- a/F0-nolib/F0_testbrd/usart.c +++ b/F0-nolib/F0_testbrd/usart.c @@ -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 -} diff --git a/F0-nolib/F0_testbrd/usart.h b/F0-nolib/F0_testbrd/usart.h index 32e758f..40cf0ca 100644 --- a/F0-nolib/F0_testbrd/usart.h +++ b/F0-nolib/F0_testbrd/usart.h @@ -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__