added spi_get_baudrate() + some consistency changes (#395)

* added spi_get_baudrate()
This commit is contained in:
Rene 2021-06-01 18:12:15 +02:00 committed by GitHub
parent c573775f86
commit 42cbdcb13a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 38 additions and 15 deletions

View File

@ -132,13 +132,23 @@ void spi_deinit(spi_inst_t *spi);
*/ */
uint spi_set_baudrate(spi_inst_t *spi, uint baudrate); 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 /*! \brief Convert SPI instance to hardware instance number
* \ingroup hardware_spi * \ingroup hardware_spi
* *
* \param spi SPI instance * \param spi SPI instance
* \return Number of SPI, 0 or 1. * \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); invalid_params_if(SPI, spi != spi0 && spi != spi1);
return spi == spi1 ? 1 : 0; 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; 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 /*! \brief Configure SPI
* \ingroup hardware_spi * \ingroup hardware_spi
* *
@ -197,27 +212,30 @@ static inline void spi_set_slave(spi_inst_t *spi, bool slave) {
* \ingroup hardware_spi * \ingroup hardware_spi
* *
* \param spi SPI instance specifier, either \ref spi0 or \ref spi1 * \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 * \return false if no space is available to write. True 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.
*/ */
static inline size_t spi_is_writable(spi_inst_t *spi) { static inline bool spi_is_writable(const spi_inst_t *spi) {
// PL022 doesn't expose levels directly, so return values are only 0 or 1 return (spi_get_const_hw(spi)->sr & SPI_SSPSR_TNF_BITS);
return (spi_get_hw(spi)->sr & SPI_SSPSR_TNF_BITS) >> SPI_SSPSR_TNF_LSB;
} }
/*! \brief Check whether a read can be done on SPI device /*! \brief Check whether a read can be done on SPI device
* \ingroup hardware_spi * \ingroup hardware_spi
* *
* \param spi SPI instance specifier, either \ref spi0 or \ref spi1 * \param spi SPI instance specifier, either \ref spi0 or \ref spi1
* \return Non-zero if a read is possible i.e. data is present * \return true 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.
*/ */
static inline size_t spi_is_readable(spi_inst_t *spi) { static inline bool spi_is_readable(const spi_inst_t *spi) {
return (spi_get_hw(spi)->sr & SPI_SSPSR_RNE_BITS) >> SPI_SSPSR_RNE_LSB; 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 /*! \brief Write/Read to/from an SPI device

View File

@ -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); spi_set_format(spi, 8, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST);
// Always enable DREQ signals -- harmless if DMA is not listening // 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); 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 // Finally enable the SPI
hw_set_bits(&spi_get_hw(spi)->cr1, SPI_SSPCR1_SSE_BITS); 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); 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. // 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) // 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) { int __not_in_flash_func(spi_write_read_blocking)(spi_inst_t *spi, const uint8_t *src, uint8_t *dst, size_t len) {