diff --git a/src/rp2_common/hardware_spi/include/hardware/spi.h b/src/rp2_common/hardware_spi/include/hardware/spi.h index f0d89c1..b766f74 100644 --- a/src/rp2_common/hardware_spi/include/hardware/spi.h +++ b/src/rp2_common/hardware_spi/include/hardware/spi.h @@ -132,13 +132,23 @@ void spi_deinit(spi_inst_t *spi); */ uint spi_set_baudrate(spi_inst_t *spi, uint baudrate); +/*! \brief Get SPI baudrate + * \ingroup hardware_spi + * + * Get SPI baudrate which was set by \see spi_set_baudrate + * + * \param spi SPI instance specifier, either \ref spi0 or \ref spi1 + * \return The actual baudrate set + */ +uint spi_get_baudrate(const spi_inst_t *spi); + /*! \brief Convert SPI instance to hardware instance number * \ingroup hardware_spi * * \param spi SPI instance * \return Number of SPI, 0 or 1. */ -static inline uint spi_get_index(spi_inst_t *spi) { +static inline uint spi_get_index(const spi_inst_t *spi) { invalid_params_if(SPI, spi != spi0 && spi != spi1); return spi == spi1 ? 1 : 0; } @@ -148,6 +158,11 @@ static inline spi_hw_t *spi_get_hw(spi_inst_t *spi) { return (spi_hw_t *)spi; } +static inline const spi_hw_t *spi_get_const_hw(const spi_inst_t *spi) { + spi_get_index(spi); // check it is a hw spi + return (const spi_hw_t *)spi; +} + /*! \brief Configure SPI * \ingroup hardware_spi * @@ -197,27 +212,30 @@ static inline void spi_set_slave(spi_inst_t *spi, bool slave) { * \ingroup hardware_spi * * \param spi SPI instance specifier, either \ref spi0 or \ref spi1 - * \return 0 if no space is available to write. Non-zero if a write is possible - * - * \note Although the controllers each have a 8 deep TX FIFO, the current HW implementation can only return 0 or 1 - * rather than the space available. + * \return false if no space is available to write. True if a write is possible */ -static inline size_t spi_is_writable(spi_inst_t *spi) { - // PL022 doesn't expose levels directly, so return values are only 0 or 1 - return (spi_get_hw(spi)->sr & SPI_SSPSR_TNF_BITS) >> SPI_SSPSR_TNF_LSB; +static inline bool spi_is_writable(const spi_inst_t *spi) { + return (spi_get_const_hw(spi)->sr & SPI_SSPSR_TNF_BITS); } /*! \brief Check whether a read can be done on SPI device * \ingroup hardware_spi * * \param spi SPI instance specifier, either \ref spi0 or \ref spi1 - * \return Non-zero if a read is possible i.e. data is present - * - * \note Although the controllers each have a 8 deep RX FIFO, the current HW implementation can only return 0 or 1 - * rather than the data available. + * \return true if a read is possible i.e. data is present */ -static inline size_t spi_is_readable(spi_inst_t *spi) { - return (spi_get_hw(spi)->sr & SPI_SSPSR_RNE_BITS) >> SPI_SSPSR_RNE_LSB; +static inline bool spi_is_readable(const spi_inst_t *spi) { + return (spi_get_const_hw(spi)->sr & SPI_SSPSR_RNE_BITS); +} + +/*! \brief Check whether SPI is busy + * \ingroup hardware_spi + * + * \param spi SPI instance specifier, either \ref spi0 or \ref spi1 + * \return true if SPI is busy + */ +static inline bool spi_is_busy(const spi_inst_t *spi) { + return (spi_get_const_hw(spi)->sr & SPI_SSPSR_BSY_BITS); } /*! \brief Write/Read to/from an SPI device diff --git a/src/rp2_common/hardware_spi/spi.c b/src/rp2_common/hardware_spi/spi.c index e74aca7..880b534 100644 --- a/src/rp2_common/hardware_spi/spi.c +++ b/src/rp2_common/hardware_spi/spi.c @@ -26,7 +26,6 @@ uint spi_init(spi_inst_t *spi, uint baudrate) { spi_set_format(spi, 8, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST); // Always enable DREQ signals -- harmless if DMA is not listening hw_set_bits(&spi_get_hw(spi)->dmacr, SPI_SSPDMACR_TXDMAE_BITS | SPI_SSPDMACR_RXDMAE_BITS); - spi_set_format(spi, 8, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST); // Finally enable the SPI hw_set_bits(&spi_get_hw(spi)->cr1, SPI_SSPCR1_SSE_BITS); @@ -66,6 +65,12 @@ uint spi_set_baudrate(spi_inst_t *spi, uint baudrate) { return freq_in / (prescale * postdiv); } +uint spi_get_baudrate(const spi_inst_t *spi) { + uint prescale = spi_get_const_hw(spi)->cpsr; + uint postdiv = ((spi_get_const_hw(spi)->cr0 & SPI_SSPCR0_SCR_BITS) >> SPI_SSPCR0_SCR_LSB) + 1; + return clock_get_hz(clk_peri) / (prescale * postdiv); +} + // Write len bytes from src to SPI. Simultaneously read len bytes from SPI to dst. // Note this function is guaranteed to exit in a known amount of time (bits sent * time per bit) int __not_in_flash_func(spi_write_read_blocking)(spi_inst_t *spi, const uint8_t *src, uint8_t *dst, size_t len) {