summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ports/atmel-samd/common-hal/busio/SPI.c14
-rw-r--r--ports/atmel-samd/peripherals.c16
-rw-r--r--ports/atmel-samd/peripherals.h3
-rw-r--r--ports/atmel-samd/spi_flash.c2
-rw-r--r--ports/esp8266/common-hal/busio/SPI.c7
-rw-r--r--ports/esp8266/common-hal/busio/SPI.h1
-rw-r--r--ports/esp8266/posix_helpers.c2
-rw-r--r--ports/nrf/common-hal/busio/SPI.c20
-rw-r--r--shared-bindings/busio/SPI.c29
-rw-r--r--shared-bindings/busio/SPI.h3
10 files changed, 77 insertions, 20 deletions
diff --git a/ports/atmel-samd/common-hal/busio/SPI.c b/ports/atmel-samd/common-hal/busio/SPI.c
index 4414d7ca9..ca98d1d2f 100644
--- a/ports/atmel-samd/common-hal/busio/SPI.c
+++ b/ports/atmel-samd/common-hal/busio/SPI.c
@@ -122,10 +122,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
// Always start at 250khz which is what SD cards need. They are sensitive to
// SPI bus noise before they are put into SPI mode.
- uint8_t baud_value = samd_peripherals_baudrate_to_baud_reg_value(250000);
- if (baud_value == 0) {
- mp_raise_RuntimeError("SPI initial baudrate out of range.");
- }
+ uint8_t baud_value = samd_peripherals_spi_baudrate_to_baud_reg_value(250000);
if (spi_m_sync_set_baudrate(&self->spi_desc, baud_value) != ERR_NONE) {
// spi_m_sync_set_baudrate does not check for validity, just whether the device is
// busy or not
@@ -179,10 +176,7 @@ 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) {
- uint8_t baud_reg_value = samd_peripherals_baudrate_to_baud_reg_value(baudrate);
- if (baud_reg_value == 0) {
- mp_raise_ValueError("baudrate out of range");
- }
+ uint8_t baud_reg_value = samd_peripherals_spi_baudrate_to_baud_reg_value(baudrate);
void * hw = self->spi_desc.dev.prvt;
// If the settings are already what we want then don't reset them.
@@ -279,3 +273,7 @@ bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uin
// }
return status >= 0; // Status is number of chars read or an error code < 0.
}
+
+uint32_t common_hal_busio_spi_get_frequency(busio_spi_obj_t* self) {
+ return samd_peripherals_spi_baud_reg_value_to_baudrate(hri_sercomspi_read_BAUD_reg(self->spi_desc.dev.prvt));
+}
diff --git a/ports/atmel-samd/peripherals.c b/ports/atmel-samd/peripherals.c
index 6de813cca..0c7f1dc63 100644
--- a/ports/atmel-samd/peripherals.c
+++ b/ports/atmel-samd/peripherals.c
@@ -31,13 +31,15 @@
// Routines that are the same across all samd variants.
-// Convert frequency to clock-speed-dependent value. Return 0 if out of range.
-uint8_t samd_peripherals_baudrate_to_baud_reg_value(const uint32_t baudrate) {
+// Convert frequency to clock-speed-dependent value. Return 255 if > 255.
+uint8_t samd_peripherals_spi_baudrate_to_baud_reg_value(const uint32_t baudrate) {
uint32_t baud_reg_value = (uint32_t) (((float) PROTOTYPE_SERCOM_SPI_M_SYNC_CLOCK_FREQUENCY /
- (2 * baudrate)) + 0.5f);
- if (baud_reg_value > 0xff) {
- return 0;
- }
- return (uint8_t) baud_reg_value;
+ (2 * baudrate)) - 0.5f);
+ return (uint8_t) (baud_reg_value > 255 ? 255 : baud_reg_value);
+}
+
+// Convert BAUD reg value back to a frequency.
+uint32_t samd_peripherals_spi_baud_reg_value_to_baudrate(const uint8_t baud_reg_value) {
+ return PROTOTYPE_SERCOM_SPI_M_SYNC_CLOCK_FREQUENCY / (2 * (baud_reg_value + 1));
}
diff --git a/ports/atmel-samd/peripherals.h b/ports/atmel-samd/peripherals.h
index 95bc1ec53..bb01bc1ac 100644
--- a/ports/atmel-samd/peripherals.h
+++ b/ports/atmel-samd/peripherals.h
@@ -32,7 +32,8 @@
#include "mpconfigport.h"
// Routines common across chip families.
-uint8_t samd_peripherals_baudrate_to_baud_reg_value(const uint32_t baudrate);
+uint8_t samd_peripherals_spi_baudrate_to_baud_reg_value(const uint32_t baudrate);
+uint32_t samd_peripherals_spi_baud_reg_value_to_baudrate(const uint8_t baud_reg_value);
#ifdef SAMD21
#include "samd21_peripherals.h"
diff --git a/ports/atmel-samd/spi_flash.c b/ports/atmel-samd/spi_flash.c
index 1070481ea..55a00dcba 100644
--- a/ports/atmel-samd/spi_flash.c
+++ b/ports/atmel-samd/spi_flash.c
@@ -280,7 +280,7 @@ void spi_flash_init(void) {
hri_sercomspi_write_CTRLA_DOPO_bf(SPI_FLASH_SERCOM, SPI_FLASH_DOPO);
hri_sercomspi_write_CTRLA_DIPO_bf(SPI_FLASH_SERCOM, SPI_FLASH_DIPO);
- spi_m_sync_set_baudrate(&spi_flash_desc, samd_peripherals_baudrate_to_baud_reg_value(SPI_FLASH_BAUDRATE));
+ spi_m_sync_set_baudrate(&spi_flash_desc, samd_peripherals_spi_baudrate_to_baud_reg_value(SPI_FLASH_BAUDRATE));
gpio_set_pin_direction(SPI_FLASH_CS_PIN, GPIO_DIRECTION_OUT);
// There's already a pull-up on the board.
diff --git a/ports/esp8266/common-hal/busio/SPI.c b/ports/esp8266/common-hal/busio/SPI.c
index aa2b3a354..b862c1da7 100644
--- a/ports/esp8266/common-hal/busio/SPI.c
+++ b/ports/esp8266/common-hal/busio/SPI.c
@@ -67,6 +67,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);
spi_clock(HSPI, SPI_CLK_PREDIV, SPI_CLK_CNTDIV);
+ self->frequency = SPI_CLK_FREQ;
spi_tx_byte_order(HSPI, SPI_BYTE_ORDER_HIGH_TO_LOW);
spi_rx_byte_order(HSPI, SPI_BYTE_ORDER_HIGH_TO_LOW);
@@ -107,6 +108,7 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self,
// Special case for full speed.
spi_init_gpio(HSPI, SPI_CLK_80MHZ_NODIV);
spi_clock(HSPI, 0, 0);
+ self->frequency = 80000000L;
} else if (baudrate > 40000000L) {
return false;
} else {
@@ -118,6 +120,7 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self,
}
spi_init_gpio(HSPI, SPI_CLK_USE_DIV);
spi_clock(HSPI, prediv, cntdiv);
+ self->frequency = 80000000L / (prediv * cntdiv);
}
spi_mode(HSPI, phase, polarity);
return true;
@@ -205,3 +208,7 @@ bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uin
return true;
}
+
+uint32_t common_hal_busio_spi_get_frequency(busio_spi_obj_t* self) {
+ return self->frequency;
+}
diff --git a/ports/esp8266/common-hal/busio/SPI.h b/ports/esp8266/common-hal/busio/SPI.h
index 24822ca3c..ba9a5268e 100644
--- a/ports/esp8266/common-hal/busio/SPI.h
+++ b/ports/esp8266/common-hal/busio/SPI.h
@@ -33,6 +33,7 @@
typedef struct {
mp_obj_base_t base;
+ uint32_t frequency;
bool locked;
bool deinited;
} busio_spi_obj_t;
diff --git a/ports/esp8266/posix_helpers.c b/ports/esp8266/posix_helpers.c
index 1fc677c5c..1c20c8b0b 100644
--- a/ports/esp8266/posix_helpers.c
+++ b/ports/esp8266/posix_helpers.c
@@ -33,7 +33,7 @@
// Functions for external libs like axTLS, BerkeleyDB, etc.
void *malloc(size_t size) {
- void *p = gc_alloc(size, false);
+ void *p = gc_alloc(size, false, false);
if (p == NULL) {
// POSIX requires ENOMEM to be set in case of error
errno = ENOMEM;
diff --git a/ports/nrf/common-hal/busio/SPI.c b/ports/nrf/common-hal/busio/SPI.c
index 4bb448a0c..32ebbf53a 100644
--- a/ports/nrf/common-hal/busio/SPI.c
+++ b/ports/nrf/common-hal/busio/SPI.c
@@ -184,3 +184,23 @@ bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uin
return true;
}
+uint32_t common_hal_busio_spi_get_frequency(busio_spi_obj_t* self) {
+ switch (self->spi->FREQUENCY) {
+ case SPI_FREQUENCY_FREQUENCY_K125:
+ return 125000;
+ case SPI_FREQUENCY_FREQUENCY_K250:
+ return 250000;
+ case SPI_FREQUENCY_FREQUENCY_K500:
+ return 500000;
+ case SPI_FREQUENCY_FREQUENCY_M1:
+ return 1000000;
+ case SPI_FREQUENCY_FREQUENCY_M2:
+ return 2000000;
+ case SPI_FREQUENCY_FREQUENCY_M4:
+ return 4000000;
+ case SPI_FREQUENCY_FREQUENCY_M8:
+ return 8000000;
+ default:
+ return 0;
+ }
+}
diff --git a/shared-bindings/busio/SPI.c b/shared-bindings/busio/SPI.c
index c4c139105..c2889bb12 100644
--- a/shared-bindings/busio/SPI.c
+++ b/shared-bindings/busio/SPI.c
@@ -36,7 +36,7 @@
#include "lib/utils/buffer_helper.h"
#include "lib/utils/context_manager_helpers.h"
#include "py/mperrno.h"
-#include "py/nlr.h"
+#include "py/objproperty.h"
#include "py/runtime.h"
//| .. currentmodule:: busio
@@ -137,7 +137,12 @@ static void check_lock(busio_spi_obj_t *self) {
//|
//| Configures the SPI bus. Only valid when locked.
//|
-//| :param int baudrate: the clock rate in Hertz
+//| :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.
+//| Check the `frequency` attribute for the actual clock rate.
+//| **Note:** on the SAMD21, it is possible to set the baud rate to 24 MHz, but that
+//| speed is not guaranteed to work. 12 MHz is the next available lower speed, and is
+//| within spec for the SAMD21.
//| :param int polarity: the base state of the clock line (0 or 1)
//| :param int phase: the edge of the clock that data is captured. First (0)
//| or second (1). Rising or falling depends on clock polarity.
@@ -350,6 +355,25 @@ STATIC mp_obj_t busio_spi_write_readinto(size_t n_args, const mp_obj_t *pos_args
}
MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_write_readinto_obj, 2, busio_spi_write_readinto);
+//| .. attribute:: frequency
+//|
+//| The actual SPI bus frequency. This may not match the frequency requested
+//| due to internal limitations.
+//|
+STATIC mp_obj_t busio_spi_obj_get_frequency(mp_obj_t self_in) {
+ busio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ raise_error_if_deinited(common_hal_busio_spi_deinited(self));
+ return MP_OBJ_NEW_SMALL_INT(common_hal_busio_spi_get_frequency(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(busio_spi_get_frequency_obj, busio_spi_obj_get_frequency);
+
+const mp_obj_property_t busio_spi_frequency_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&busio_spi_get_frequency_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
STATIC const mp_rom_map_elem_t busio_spi_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&busio_spi_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
@@ -362,6 +386,7 @@ STATIC const mp_rom_map_elem_t busio_spi_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&busio_spi_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&busio_spi_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&busio_spi_write_readinto_obj) },
+ { MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&busio_spi_frequency_obj) }
};
STATIC MP_DEFINE_CONST_DICT(busio_spi_locals_dict, busio_spi_locals_dict_table);
diff --git a/shared-bindings/busio/SPI.h b/shared-bindings/busio/SPI.h
index b6e5c9b1b..555f32c92 100644
--- a/shared-bindings/busio/SPI.h
+++ b/shared-bindings/busio/SPI.h
@@ -58,4 +58,7 @@ extern bool common_hal_busio_spi_read(busio_spi_obj_t *self, uint8_t *data, size
// Reads and write len bytes simultaneously.
extern bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uint8_t *data_in, size_t len);
+// Return actual SPI bus frequency.
+uint32_t common_hal_busio_spi_get_frequency(busio_spi_obj_t* self);
+
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSIO_SPI_H