diff --git a/src/shared/BusTemplate.h b/src/shared/BusTemplate.h index 482c8812e552471302881d78c9fdbb96e329e7bc..47e6df14ae9b44fbb6a8ecf0964bce6087184e19 100644 --- a/src/shared/BusTemplate.h +++ b/src/shared/BusTemplate.h @@ -91,6 +91,8 @@ private: } BusSPI() { + //FIXME: this code is duplicated here and in the DMA driver, + //and both of them initialize SPI1 GpioMosi::mode(Mode::ALTERNATE); GpioMosi::alternateFunction(GetAlternativeFunctionNumber(N)); GpioMiso::mode(Mode::ALTERNATE); @@ -99,13 +101,21 @@ private: GpioSclk::alternateFunction(GetAlternativeFunctionNumber(N)); usleep(CS_DELAY); enableSPIBus(getSPIAddr(N)); - getSPIAddr(N)->CR1 = SPI_CR1_SSM - | SPI_CR1_SSI - | SPI_CR1_MSTR - // | SPI_CR1_BR_0 - // | SPI_CR1_BR_1 - | SPI_CR1_BR_2 - | SPI_CR1_SPE; + if(getSPIAddr(N) == SPI1) + { + getSPIAddr(N)->CR1 = SPI_CR1_SSM //Software cs + | SPI_CR1_SSI //Hardware cs internally tied high + | SPI_CR1_MSTR //Master mode + | SPI_CR1_BR_1 + | SPI_CR1_BR_2 // SPI FREQ=90MHz / 128 = 703KHz + | SPI_CR1_SPE; //SPI enabled + } else { + getSPIAddr(N)->CR1 = SPI_CR1_SSM //Software cs + | SPI_CR1_SSI //Hardware cs internally tied high + | SPI_CR1_MSTR //Master mode + | SPI_CR1_BR_2 // SPI clock divided by 32 + | SPI_CR1_SPE; //SPI enabled + } } inline static constexpr int GetAlternativeFunctionNumber(int n_spi) { @@ -118,6 +128,9 @@ private: } static inline void enableSPIBus(SPI_TypeDef* spi) { + //Interrupts are disabled to prevent bugs if more than one threads does + //a read-modify-write to RCC registers at the same time + FastInterruptDisableLock dLock; if(spi == SPI1) RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; else if(spi == SPI2) diff --git a/src/shared/DMA/DMA.cpp b/src/shared/DMA/DMA.cpp index 7e53eab192419f74cd997535d37744a6f9a210fe..2f14f41d1bc0b4aa0d19225620e28b38abb051cf 100644 --- a/src/shared/DMA/DMA.cpp +++ b/src/shared/DMA/DMA.cpp @@ -31,6 +31,11 @@ typedef Gpio<GPIOA_BASE,5> sck; typedef Gpio<GPIOA_BASE,6> miso; typedef Gpio<GPIOA_BASE,7> mosi; +static Thread *waiting = nullptr; +static vector<SPIRequest> *requestVector = nullptr; +static size_t requestIndex = 0; +static bool error = false; + /** * DMA RX end of transfer */ @@ -41,11 +46,6 @@ void __attribute__((naked)) DMA2_Stream0_IRQHandler() restoreContext(); } -static Thread *waiting = nullptr; -static vector<SPIRequest> *requestVector = nullptr; -static size_t requestIndex = 0; -static bool error = false; - /** * DMA RX end of transfer actual implementation */ @@ -55,6 +55,7 @@ void __attribute__((used)) SPI1rxDmaHandlerImpl() error = true; if(DMA2->HISR & (DMA_HISR_TEIF5 | DMA_HISR_DMEIF5)) error = true; + DMA2->LIFCR = DMA_LIFCR_CTCIF0 | DMA_LIFCR_CTEIF0 | DMA_LIFCR_CDMEIF0; @@ -131,6 +132,8 @@ SPIDriver::SPIDriver() { pthread_mutex_init(&mutex,0); { + //Interrupts are disabled to prevent bugs if more than one threads does + //a read-modify-write to RCC or GPIO->MODER registers at the same time FastInterruptDisableLock dLock; mosi::mode(Mode::ALTERNATE); mosi::alternateFunction(5); @@ -141,14 +144,24 @@ SPIDriver::SPIDriver() RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN; RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; + + /* + * Table of the maximum speed of each sensor, used to set SPI speed + * LSM9DS0 IMU SPI <10MHz + * MPU9250 IMU SPI < 1MHz + * MAX21105 IMU SPI <10MHz + * FXAS21002 gyro SPI < 2MHz + * MS5803 baro SPI <20MHz + * LPS331 baro SPI FIXME: unknown! + * MAX31856 thermocouple SPI < 5MHz + */ disableDMA(); SPI1->CR1 = SPI_CR1_SSM //Software cs | SPI_CR1_SSI //Hardware cs internally tied high | SPI_CR1_MSTR //Master mode -// | SPI_CR1_BR_0 -// | SPI_CR1_BR_1 //Less than 10MHz - | SPI_CR1_BR_2 // fClock / 32 + | SPI_CR1_BR_1 + | SPI_CR1_BR_2 // SPI FREQ=90MHz / 128 = 703KHz | SPI_CR1_SPE; //SPI enabled NVIC_SetPriority(DMA2_Stream0_IRQn,10);//Low priority for DMA NVIC_EnableIRQ(DMA2_Stream0_IRQn); @@ -190,11 +203,17 @@ void SPIRequest::IRQbeginTransaction() | DMA_SxCR_TEIE //Interrupt on transfer error | DMA_SxCR_DMEIE //Interrupt on direct mode error | DMA_SxCR_EN; //Start DMA - // FIXME: handle DMA_SxCR_TEIE } void SPIRequest::IRQendTransaction() { chipSelect.high(); - delayUs(10); //FIXME: properly size the delay + /* + * NOTE: this code has no explicit delays and relies on the code execution + * timings to add the requred minimum delays between data CS toggling. + * When running at 180MHz with data in external RAM, the delay are as follow + * From last clock pulse till CS high : ~1.5us + * From CS high to CS low : ~2 us + * From CS low to first clock pulse : ~3.5us + */ }