round SPI freq down; check max freq

This commit is contained in:
Dan Halbert 2018-10-02 21:06:40 -04:00
parent aa95526428
commit 21d331c8cc
2 changed files with 30 additions and 26 deletions

View File

@ -65,27 +65,27 @@ void spi_reset(void) {
} }
} }
// Convert frequency to clock-speed-dependent value. Choose the nearest value, lower or higher. // Convert frequency to clock-speed-dependent value. Choose the next lower baudrate if in between
// available baudrates.
static nrf_spim_frequency_t baudrate_to_spim_frequency(const uint32_t baudrate) { static nrf_spim_frequency_t baudrate_to_spim_frequency(const uint32_t baudrate) {
// Round requested baudrate to nearest available baudrate.
static const struct { static const struct {
const uint32_t boundary; const uint32_t boundary;
nrf_spim_frequency_t spim_frequency; nrf_spim_frequency_t spim_frequency;
} baudrate_map[] = { } baudrate_map[] = {
#ifdef SPIM_FREQUENCY_FREQUENCY_M32 #ifdef SPIM_FREQUENCY_FREQUENCY_M32
{ (16000000 + 32000000) / 2, NRF_SPIM_FREQ_32M }, { 32000000, NRF_SPIM_FREQ_32M },
#endif #endif
#ifdef SPIM_FREQUENCY_FREQUENCY_M16 #ifdef SPIM_FREQUENCY_FREQUENCY_M16
{ ( 8000000 + 16000000) / 2, NRF_SPIM_FREQ_16M }, { 16000000, NRF_SPIM_FREQ_16M },
#endif #endif
{ ( 4000000 + 8000000) / 2, NRF_SPIM_FREQ_8M }, { 8000000, NRF_SPIM_FREQ_8M },
{ ( 2000000 + 4000000) / 2, NRF_SPIM_FREQ_4M }, { 4000000, NRF_SPIM_FREQ_4M },
{ ( 1000000 + 2000000) / 2, NRF_SPIM_FREQ_2M }, { 2000000, NRF_SPIM_FREQ_2M },
{ ( 500000 + 1000000) / 2, NRF_SPIM_FREQ_1M }, { 1000000, NRF_SPIM_FREQ_1M },
{ ( 250000 + 500000) / 2, NRF_SPIM_FREQ_500K }, { 500000, NRF_SPIM_FREQ_500K },
{ ( 125000 + 250000) / 2, NRF_SPIM_FREQ_250K }, { 250000, NRF_SPIM_FREQ_250K },
{ 0, NRF_SPIM_FREQ_125K }, { 0, NRF_SPIM_FREQ_125K },
}; };
size_t i = 0; size_t i = 0;
@ -97,7 +97,7 @@ static nrf_spim_frequency_t baudrate_to_spim_frequency(const uint32_t baudrate)
} }
i++; i++;
} while (boundary != 0); } while (boundary != 0);
// Will get here only if baudrate == 0. // Should not get here.
return 0; return 0;
} }
@ -168,22 +168,26 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
} }
bool common_hal_busio_spi_configure(busio_spi_obj_t *self, uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t bits) { bool common_hal_busio_spi_configure(busio_spi_obj_t *self, uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t bits) {
// nrf52 does not support 16 bit // nrf52 does not support 16 bit
if (bits != 8) if (bits != 8) {
return false; return false;
}
nrf_spim_frequency_set(self->spim_peripheral->spim.p_reg, baudrate_to_spim_frequency(baudrate)); // Set desired frequency, rounding down, and don't go above available frequency for this SPIM.
nrf_spim_frequency_set(self->spim_peripheral->spim.p_reg,
baudrate_to_spim_frequency(MIN(baudrate,
self->spim_peripheral->max_frequency_MHz * 1000000)));
nrf_spim_mode_t mode = NRF_SPIM_MODE_0; nrf_spim_mode_t mode = NRF_SPIM_MODE_0;
if (polarity) { if (polarity) {
mode = (phase) ? NRF_SPIM_MODE_3 : NRF_SPIM_MODE_2; mode = (phase) ? NRF_SPIM_MODE_3 : NRF_SPIM_MODE_2;
} else { } else {
mode = (phase) ? NRF_SPIM_MODE_1 : NRF_SPIM_MODE_0; mode = (phase) ? NRF_SPIM_MODE_1 : NRF_SPIM_MODE_0;
} }
nrf_spim_configure(self->spim_peripheral->spim.p_reg, mode, NRF_SPIM_BIT_ORDER_MSB_FIRST); nrf_spim_configure(self->spim_peripheral->spim.p_reg, mode, NRF_SPIM_BIT_ORDER_MSB_FIRST);
return true; return true;
} }
bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) { bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) {

View File

@ -136,7 +136,7 @@ static void check_lock(busio_spi_obj_t *self) {
//| .. method:: SPI.configure(\*, baudrate=100000, polarity=0, phase=0, bits=8) //| .. method:: SPI.configure(\*, baudrate=100000, polarity=0, phase=0, bits=8)
//| //|
//| Configures the SPI bus. Only valid when locked. //| Configures the SPI bus. The SPI object must be locked.
//| //|
//| :param int baudrate: the desired clock rate in Hertz. The actual clock rate may be higher or lower //| :param int baudrate: the desired clock rate in Hertz. The actual clock rate may be higher or lower
//| due to the granularity of available clock settings. //| due to the granularity of available clock settings.
@ -154,8 +154,8 @@ static void check_lock(busio_spi_obj_t *self) {
//| and 8MHz. On the nRF52840, 16MHz and 32MHz are also available, but only on the first //| and 8MHz. On the nRF52840, 16MHz and 32MHz are also available, but only on the first
//| `busio.SPI` object you create. Two more ``busio.SPI`` objects can be created, but they are restricted //| `busio.SPI` object you create. Two more ``busio.SPI`` objects can be created, but they are restricted
//| to 8MHz maximum. This is a hardware restriction: there is only one high-speed SPI peripheral. //| to 8MHz maximum. This is a hardware restriction: there is only one high-speed SPI peripheral.
//| If you pick a a baudrate other than one of these, the nearest available //| If you pick a a baudrate other than one of these, the nearest lower
//| baudrate will be chosen. //| baudrate will be chosen, with a minimum of 125kHz.
STATIC mp_obj_t busio_spi_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { STATIC mp_obj_t busio_spi_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits }; enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits };
static const mp_arg_t allowed_args[] = { static const mp_arg_t allowed_args[] = {