Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 31 additions & 13 deletions src/rp2_common/hardware_spi/include/hardware/spi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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
*
Expand Down Expand Up @@ -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
* \return true if a read is possible i.e. data is present
*/
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
*
* \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.
* \param spi SPI instance specifier, either \ref spi0 or \ref spi1
* \return true if SPI is busy
*/
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_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
Expand Down
7 changes: 6 additions & 1 deletion src/rp2_common/hardware_spi/spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down