You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
KED/ked/csl/stm32f042/Src/imp_spi.c

147 lines
3.3 KiB

#include "spi.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);
}