#include "spi.h" #include "registers.h" #include "stm32f401xe.h" void spi_init(spi_t* spi, pin_t csn, SPI_TypeDef* peripheral, uint8_t idx) { spi->periph = peripheral; spi->idx = idx; spi->csn = csn; } void spi_master_configure_speed(spi_t *spi, uint8_t divider) { reg_write_bits(&spi->periph->CR1, divider << SPI_CR1_BR_Pos, SPI_CR1_BR_Msk); } void spi_master_configure(spi_t *spi, bool sw_nss, bool clock_polarity, bool clock_phase, spi_frame_orientation_t orientation, spi_frame_format_t format) { reg_write_bits(&spi->periph->CR1, (sw_nss << SPI_CR1_SSM_Pos) | (format << SPI_CR1_DFF_Pos) | (orientation << SPI_CR1_LSBFIRST_Pos) | (0 << SPI_CR1_BIDIMODE_Pos) | (1 << SPI_CR1_MSTR_Pos) | (clock_polarity << SPI_CR1_CPOL_Pos) | (clock_phase << SPI_CR1_CPHA_Pos), SPI_CR1_SSM_Msk | SPI_CR1_DFF_Msk | SPI_CR1_LSBFIRST_Msk | SPI_CR1_BIDIMODE_Msk | SPI_CR1_MSTR_Msk | SPI_CR1_CPOL_Msk | SPI_CR1_CPHA_Msk); spi->periph->CR2 |= SPI_CR2_SSOE | (1 << 3); } void spi_master_enable(spi_t *spi, bool enable) { reg_write_bits(&spi->periph->CR1, enable << SPI_CR1_SPE_Pos, SPI_CR1_SPE); } void spi_slave_configure(spi_t *spi, bool sw_nss, bool clock_polarity, bool clock_phase, spi_frame_orientation_t orientation, spi_frame_format_t format) { reg_write_bits(&spi->periph->CR1, (sw_nss << SPI_CR1_SSM_Pos) | (format << SPI_CR1_DFF_Pos) | (orientation << SPI_CR1_LSBFIRST_Pos) | (0 << SPI_CR1_BIDIMODE_Pos) | (0 << SPI_CR1_MSTR_Pos) | (clock_polarity << SPI_CR1_CPOL_Pos) | (clock_phase << SPI_CR1_CPHA_Pos), SPI_CR1_SSM_Msk | SPI_CR1_DFF_Msk | SPI_CR1_LSBFIRST_Msk | SPI_CR1_BIDIMODE_Msk | SPI_CR1_MSTR_Msk | SPI_CR1_CPOL_Msk | SPI_CR1_CPHA_Msk); } void spi_slave_enable(spi_t *spi, bool enable) { reg_write_bits(&spi->periph->CR1, enable << SPI_CR1_SPE_Pos, SPI_CR1_SPE); } uint16_t spi_transmit(spi_t *spi, uint16_t *data, uint16_t size) { pin_reset(&spi->csn); for (int16_t i = 0; i < size; i++) { while (!(spi->periph->SR & SPI_SR_TXE)); uint16_t word = *(data++); spi->periph->DR = word; } return size; } uint16_t spi_receive(spi_t *spi, uint16_t *buffer, uint16_t max_size) { uint16_t size = 0; while (size < max_size && (spi->periph->SR & SPI_SR_RXNE)) { *(buffer + (size++)) = (uint16_t)(spi->periph->DR & SPI_DR_DR_Msk); } return size; } void spi_pulse_csn(spi_t *spi) { pin_set(&spi->csn); /* pin_reset(&spi->csn); */ } bool spi_can_transmit(spi_t *spi) { return (spi->periph->SR & SPI_SR_TXE) != 0; } uint16_t spi_can_receive(spi_t *spi) { return ((spi->periph->SR & SPI_SR_RXNE) != 0) ? 1 : 0; } bool spi_enable_interrupt(spi_t *spi, bool tx, bool rx) { reg_write_bits(&spi->periph->CR2, (tx << SPI_CR2_TXEIE_Pos) | (rx << SPI_CR2_RXNEIE_Pos), SPI_CR2_TXEIE | SPI_CR2_RXNEIE); // TODO: proper irq by idx NVIC_SetPriority(SPI1_IRQn, 1); NVIC_EnableIRQ(SPI1_IRQn); }