Improve SPI set-up: Don't change the config whilst it is enabled (#1227)

Co-authored-by: David Thacher <davidethacher@gmail.com>
This commit is contained in:
Graham Sanderson 2023-02-10 19:02:46 -06:00 committed by GitHub
parent 6d336e04be
commit 0121007c85
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 23 additions and 0 deletions

View file

@ -180,6 +180,11 @@ static inline void spi_set_format(spi_inst_t *spi, uint data_bits, spi_cpol_t cp
invalid_params_if(SPI, order != SPI_MSB_FIRST);
invalid_params_if(SPI, cpol != SPI_CPOL_0 && cpol != SPI_CPOL_1);
invalid_params_if(SPI, cpha != SPI_CPHA_0 && cpha != SPI_CPHA_1);
// Disable the SPI
uint32_t enable_mask = spi_get_hw(spi)->cr1 & SPI_SSPCR1_SSE_BITS;
hw_clear_bits(&spi_get_hw(spi)->cr1, SPI_SSPCR1_SSE_BITS);
hw_write_masked(&spi_get_hw(spi)->cr0,
((uint)(data_bits - 1)) << SPI_SSPCR0_DSS_LSB |
((uint)cpol) << SPI_SSPCR0_SPO_LSB |
@ -187,6 +192,9 @@ static inline void spi_set_format(spi_inst_t *spi, uint data_bits, spi_cpol_t cp
SPI_SSPCR0_DSS_BITS |
SPI_SSPCR0_SPO_BITS |
SPI_SSPCR0_SPH_BITS);
// Re-enable the SPI
hw_set_bits(&spi_get_hw(spi)->cr1, enable_mask);
}
/*! \brief Set SPI master/slave
@ -199,10 +207,17 @@ static inline void spi_set_format(spi_inst_t *spi, uint data_bits, spi_cpol_t cp
* \param slave true to set SPI device as a slave device, false for master.
*/
static inline void spi_set_slave(spi_inst_t *spi, bool slave) {
// Disable the SPI
uint32_t enable_mask = spi_get_hw(spi)->cr1 & SPI_SSPCR1_SSE_BITS;
hw_clear_bits(&spi_get_hw(spi)->cr1, SPI_SSPCR1_SSE_BITS);
if (slave)
hw_set_bits(&spi_get_hw(spi)->cr1, SPI_SSPCR1_MS_BITS);
else
hw_clear_bits(&spi_get_hw(spi)->cr1, SPI_SSPCR1_MS_BITS);
// Re-enable the SPI
hw_set_bits(&spi_get_hw(spi)->cr1, enable_mask);
}
// ----------------------------------------------------------------------------

View file

@ -29,6 +29,7 @@ uint spi_init(spi_inst_t *spi, uint baudrate) {
// Finally enable the SPI
hw_set_bits(&spi_get_hw(spi)->cr1, SPI_SSPCR1_SSE_BITS);
return baud;
}
@ -43,6 +44,10 @@ uint spi_set_baudrate(spi_inst_t *spi, uint baudrate) {
uint prescale, postdiv;
invalid_params_if(SPI, baudrate > freq_in);
// Disable the SPI
uint32_t enable_mask = spi_get_hw(spi)->cr1 & SPI_SSPCR1_SSE_BITS;
hw_clear_bits(&spi_get_hw(spi)->cr1, SPI_SSPCR1_SSE_BITS);
// Find smallest prescale value which puts output frequency in range of
// post-divide. Prescale is an even number from 2 to 254 inclusive.
for (prescale = 2; prescale <= 254; prescale += 2) {
@ -61,6 +66,9 @@ uint spi_set_baudrate(spi_inst_t *spi, uint baudrate) {
spi_get_hw(spi)->cpsr = prescale;
hw_write_masked(&spi_get_hw(spi)->cr0, (postdiv - 1) << SPI_SSPCR0_SCR_LSB, SPI_SSPCR0_SCR_BITS);
// Re-enable the SPI
hw_set_bits(&spi_get_hw(spi)->cr1, enable_mask);
// Return the frequency we were able to achieve
return freq_in / (prescale * postdiv);
}