#include "spi.h" #include "hardwareDescription.h" #include "hwd_spi.h" #include "interrupt.h" #define SPI_BASE ((SPI_TypeDef *)spiBase_Addr_List[spi_hw_ch]) void spiReset(spiCH_t spi_hw_ch) { if(spiBus_No[spi_hw_ch] == 1) { RCC->APB1RSTR |= (1 << spiBus_Rst_bitPos[spi_hw_ch]); RCC->APB1RSTR &= ~(1 << spiBus_Rst_bitPos[spi_hw_ch]); return; } RCC->APB2RSTR |= (1 << spiBus_Rst_bitPos[spi_hw_ch]); RCC->APB2RSTR &= ~(1 << spiBus_Rst_bitPos[spi_hw_ch]); } void spiEnableBus(spiCH_t spi_hw_ch) { if(spiBus_No[spi_hw_ch] == 1) { RCC->APB1ENR |= (1 << spiBus_En_bitPos[spi_hw_ch]); return; } RCC->APB2ENR |= (1 << spiBus_En_bitPos[spi_hw_ch]); } void spiEnable(spiCH_t spi_hw_ch) { SPI_BASE->CR1 |= SPI_CR1_SPE; } void spiDissable(spiCH_t spi_hw_ch) { // TODO: implement p.768 procedure for dissabling //while(SPI_BASE->SR SPI_BASE->CR1 &= ~SPI_CR1_SPE; } void spiSetMode(spiCH_t spi_hw_ch, spi_mode_t mode) { SPI_BASE->CR1 &= ~(mode << SPI_CR1_MSTR_Pos); SPI_BASE->CR1 |= mode << SPI_CR1_MSTR_Pos; // TODO: find out if this is the correct place to set the SSOE bit SPI_BASE->CR2 &= ~SPI_CR2_SSOE; if(mode == SPI_MASTER) { SPI_BASE->CR2 |= SPI_CR2_SSOE; } } void spiSetPolarity(spiCH_t spi_hw_ch, spi_clkPol_t clkPol) { // reset SPI_BASE->CR1 &= ~SPI_CR1_CPOL; // set SPI_BASE->CR1 |= clkPol << SPI_CR1_CPOL_Pos; } void spiSetPhase(spiCH_t spi_hw_ch, spi_phase_t phase) { // reset SPI_BASE->CR1 &= ~(phase << SPI_CR1_CPHA_Pos); // set SPI_BASE->CR1 |= phase << SPI_CR1_CPHA_Pos; } void spiSetBitFrameLength(spiCH_t spi_hw_ch, spi_framel_t framel) { SPI_BASE->CR2 &= ~(SPI_CR2_FRXTH | SPI_CR2_DS); // using p.974 as example if(framel == SPI_FRAME_LENGTH_8BIT) { // set FIFO reception threshold to 8 bit SPI_BASE->CR2 |= SPI_CR2_FRXTH; // set transfer lwnght to 8 bit SPI_BASE->CR2 |= SPI_CR2_DS_0 | SPI_CR2_DS_1 | SPI_CR2_DS_2; return; } SPI_BASE->CR2 |= SPI_CR2_DS; } void spiSetFrameFormat(spiCH_t spi_hw_ch, spi_framef_t framef) { // reset SPI_BASE->CR1 &= ~SPI_CR1_LSBFIRST; // set SPI_BASE->CR1 |= framef << SPI_CR1_LSBFIRST_Pos; } spi_framef_t spiGetFrameFormat(spiCH_t spi_hw_ch) { return (spi_framef_t)(SPI_BASE->CR1 & SPI_CR1_LSBFIRST) >> SPI_CR1_LSBFIRST_Pos; } void spiSetClockPrescaler(spiCH_t spi_hw_ch, uint32_t clkDiv) { // reset SPI_BASE->CR1 &= ~SPI_CR1_BR; // set SPI_BASE->CR1 |= (clkDiv << SPI_CR1_BR_Pos) & SPI_CR1_BR; } void spiSetComMode(spiCH_t spi_hw_ch, spi_comMode_t comMode) { // reset SPI_BASE->CR1 &= ~SPI_CR1_RXONLY; // set SPI_BASE->CR1 |= comMode << SPI_CR1_RXONLY_Pos; } void spiSetSoftwareSlaveManagement(spiCH_t spi_hw_ch, uint8_t logic) { SPI_BASE->CR1 &= ~SPI_CR1_SSM; if(logic){ SPI_BASE->CR1 |= SPI_CR1_SSM; } } void spiSetInternalSlaveSelect(spiCH_t spi_hw_ch, uint8_t logic) { SPI_BASE->CR1 &= ~SPI_CR1_SSI; if(logic) { SPI_BASE->CR1 |= SPI_CR1_SSI; } } uint8_t spiTrx8BitPolling(spiCH_t spi_hw_ch, uint8_t tx_data) { // wait for BSY bit to Reset -> This will indicate that SPI is not busy in communication while (SPI_BASE->SR & SPI_SR_BSY); // from example code p.975 f // this masking must be done. otherwise 16bits frame will be used *(uint8_t*)&(SPI_BASE->DR) = tx_data; // Wait for RXNE to set -> This will indicate that the Rx buffer is not empty while (!(SPI_BASE->SR &SPI_SR_RXNE)); // TODO: test read! return *(uint8_t*)&(SPI_BASE->DR); } // Interrupt Service Routines void SPI1_IRQHandle() { //HANDLE_INT_FLAG(SPI1->SR, ); } void SPI2_IRQHandle() { }