Skip to content

Commit e550b02

Browse files
committed
atmel-samd: Correct computation of SPI baud rate.
all: Add .frequency read-only property for busio.SPI to return actual frequency. Fix esp8266/posix_helpers.c, which was not up to date for the new long-lived/short-lived heap allocation scheme.
1 parent a1e279a commit e550b02

File tree

9 files changed

+54
-20
lines changed

9 files changed

+54
-20
lines changed

ports/atmel-samd/common-hal/busio/SPI.c

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
122122

123123
// Always start at 250khz which is what SD cards need. They are sensitive to
124124
// SPI bus noise before they are put into SPI mode.
125-
uint8_t baud_value = samd_peripherals_baudrate_to_baud_reg_value(250000);
126-
if (baud_value == 0) {
127-
mp_raise_RuntimeError("SPI initial baudrate out of range.");
128-
}
125+
uint8_t baud_value = samd_peripherals_spi_baudrate_to_baud_reg_value(250000);
129126
if (spi_m_sync_set_baudrate(&self->spi_desc, baud_value) != ERR_NONE) {
130127
// spi_m_sync_set_baudrate does not check for validity, just whether the device is
131128
// busy or not
@@ -179,10 +176,7 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
179176

180177
bool common_hal_busio_spi_configure(busio_spi_obj_t *self,
181178
uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t bits) {
182-
uint8_t baud_reg_value = samd_peripherals_baudrate_to_baud_reg_value(baudrate);
183-
if (baud_reg_value == 0) {
184-
mp_raise_ValueError("baudrate out of range");
185-
}
179+
uint8_t baud_reg_value = samd_peripherals_spi_baudrate_to_baud_reg_value(baudrate);
186180

187181
void * hw = self->spi_desc.dev.prvt;
188182
// 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
279273
// }
280274
return status >= 0; // Status is number of chars read or an error code < 0.
281275
}
276+
277+
uint32_t common_hal_busio_spi_get_frequency(busio_spi_obj_t* self) {
278+
return samd_peripherals_spi_baud_reg_value_to_baudrate(hri_sercomspi_read_BAUD_reg(self->spi_desc.dev.prvt));
279+
}

ports/atmel-samd/peripherals.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,15 @@
3131
// Routines that are the same across all samd variants.
3232

3333

34-
// Convert frequency to clock-speed-dependent value. Return 0 if out of range.
35-
uint8_t samd_peripherals_baudrate_to_baud_reg_value(const uint32_t baudrate) {
34+
// Convert frequency to clock-speed-dependent value. Return 255 if > 255.
35+
uint8_t samd_peripherals_spi_baudrate_to_baud_reg_value(const uint32_t baudrate) {
3636
uint32_t baud_reg_value = (uint32_t) (((float) PROTOTYPE_SERCOM_SPI_M_SYNC_CLOCK_FREQUENCY /
37-
(2 * baudrate)) + 0.5f);
38-
if (baud_reg_value > 0xff) {
39-
return 0;
40-
}
41-
return (uint8_t) baud_reg_value;
37+
(2 * baudrate)) - 0.5f);
38+
return (uint8_t) (baud_reg_value > 255 ? 255 : baud_reg_value);
39+
}
40+
41+
// Convert BAUD reg value back to a frequency.
42+
uint32_t samd_peripherals_spi_baud_reg_value_to_baudrate(const uint8_t baud_reg_value) {
43+
return PROTOTYPE_SERCOM_SPI_M_SYNC_CLOCK_FREQUENCY / (2 * (baud_reg_value + 1));
4244
}
4345

ports/atmel-samd/peripherals.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@
3232
#include "mpconfigport.h"
3333

3434
// Routines common across chip families.
35-
uint8_t samd_peripherals_baudrate_to_baud_reg_value(const uint32_t baudrate);
35+
uint8_t samd_peripherals_spi_baudrate_to_baud_reg_value(const uint32_t baudrate);
36+
uint32_t samd_peripherals_spi_baud_reg_value_to_baudrate(const uint8_t baud_reg_value);
3637

3738
#ifdef SAMD21
3839
#include "samd21_peripherals.h"

ports/atmel-samd/spi_flash.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ void spi_flash_init(void) {
280280
hri_sercomspi_write_CTRLA_DOPO_bf(SPI_FLASH_SERCOM, SPI_FLASH_DOPO);
281281
hri_sercomspi_write_CTRLA_DIPO_bf(SPI_FLASH_SERCOM, SPI_FLASH_DIPO);
282282

283-
spi_m_sync_set_baudrate(&spi_flash_desc, samd_peripherals_baudrate_to_baud_reg_value(SPI_FLASH_BAUDRATE));
283+
spi_m_sync_set_baudrate(&spi_flash_desc, samd_peripherals_spi_baudrate_to_baud_reg_value(SPI_FLASH_BAUDRATE));
284284

285285
gpio_set_pin_direction(SPI_FLASH_CS_PIN, GPIO_DIRECTION_OUT);
286286
// There's already a pull-up on the board.

ports/esp8266/common-hal/busio/SPI.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
6767
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);
6868

6969
spi_clock(HSPI, SPI_CLK_PREDIV, SPI_CLK_CNTDIV);
70+
self->frequency = SPI_CLK_FREQ;
7071
spi_tx_byte_order(HSPI, SPI_BYTE_ORDER_HIGH_TO_LOW);
7172
spi_rx_byte_order(HSPI, SPI_BYTE_ORDER_HIGH_TO_LOW);
7273

@@ -107,6 +108,7 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self,
107108
// Special case for full speed.
108109
spi_init_gpio(HSPI, SPI_CLK_80MHZ_NODIV);
109110
spi_clock(HSPI, 0, 0);
111+
self->frequency = 80000000L;
110112
} else if (baudrate > 40000000L) {
111113
return false;
112114
} else {
@@ -118,6 +120,7 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self,
118120
}
119121
spi_init_gpio(HSPI, SPI_CLK_USE_DIV);
120122
spi_clock(HSPI, prediv, cntdiv);
123+
self->frequency = 80000000L / (prediv * cntdiv);
121124
}
122125
spi_mode(HSPI, phase, polarity);
123126
return true;
@@ -205,3 +208,7 @@ bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uin
205208
return true;
206209

207210
}
211+
212+
uint32_t common_hal_busio_spi_get_frequency(busio_spi_obj_t* self) {
213+
return self->frequency;
214+
}

ports/esp8266/common-hal/busio/SPI.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
typedef struct {
3535
mp_obj_base_t base;
36+
uint32_t frequency;
3637
bool locked;
3738
bool deinited;
3839
} busio_spi_obj_t;

ports/esp8266/posix_helpers.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
// Functions for external libs like axTLS, BerkeleyDB, etc.
3434

3535
void *malloc(size_t size) {
36-
void *p = gc_alloc(size, false);
36+
void *p = gc_alloc(size, false, false);
3737
if (p == NULL) {
3838
// POSIX requires ENOMEM to be set in case of error
3939
errno = ENOMEM;

shared-bindings/busio/SPI.c

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
#include "lib/utils/buffer_helper.h"
3737
#include "lib/utils/context_manager_helpers.h"
3838
#include "py/mperrno.h"
39-
#include "py/nlr.h"
39+
#include "py/objproperty.h"
4040
#include "py/runtime.h"
4141

4242
//| .. currentmodule:: busio
@@ -137,7 +137,9 @@ static void check_lock(busio_spi_obj_t *self) {
137137
//|
138138
//| Configures the SPI bus. Only valid when locked.
139139
//|
140-
//| :param int baudrate: the clock rate in Hertz
140+
//| :param int baudrate: the desired clock rate in Hertz. The actual clock rate may be higher or lower
141+
//| due to the granularity of available clock settings.
142+
//| Check the `frequency` attribute for the actual clock rate.
141143
//| :param int polarity: the base state of the clock line (0 or 1)
142144
//| :param int phase: the edge of the clock that data is captured. First (0)
143145
//| or second (1). Rising or falling depends on clock polarity.
@@ -350,6 +352,25 @@ STATIC mp_obj_t busio_spi_write_readinto(size_t n_args, const mp_obj_t *pos_args
350352
}
351353
MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_write_readinto_obj, 2, busio_spi_write_readinto);
352354

355+
//| .. attribute:: frequency
356+
//|
357+
//| The actual SPI bus frequency. This may not match the frequency requested
358+
//| due to internal limitations.
359+
//|
360+
STATIC mp_obj_t busio_spi_obj_get_frequency(mp_obj_t self_in) {
361+
busio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
362+
raise_error_if_deinited(common_hal_busio_spi_deinited(self));
363+
return MP_OBJ_NEW_SMALL_INT(common_hal_busio_spi_get_frequency(self));
364+
}
365+
MP_DEFINE_CONST_FUN_OBJ_1(busio_spi_get_frequency_obj, busio_spi_obj_get_frequency);
366+
367+
const mp_obj_property_t busio_spi_frequency_obj = {
368+
.base.type = &mp_type_property,
369+
.proxy = {(mp_obj_t)&busio_spi_get_frequency_obj,
370+
(mp_obj_t)&mp_const_none_obj,
371+
(mp_obj_t)&mp_const_none_obj},
372+
};
373+
353374
STATIC const mp_rom_map_elem_t busio_spi_locals_dict_table[] = {
354375
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&busio_spi_deinit_obj) },
355376
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
@@ -362,6 +383,7 @@ STATIC const mp_rom_map_elem_t busio_spi_locals_dict_table[] = {
362383
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&busio_spi_readinto_obj) },
363384
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&busio_spi_write_obj) },
364385
{ MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&busio_spi_write_readinto_obj) },
386+
{ MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&busio_spi_frequency_obj) }
365387
};
366388
STATIC MP_DEFINE_CONST_DICT(busio_spi_locals_dict, busio_spi_locals_dict_table);
367389

shared-bindings/busio/SPI.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,7 @@ extern bool common_hal_busio_spi_read(busio_spi_obj_t *self, uint8_t *data, size
5858
// Reads and write len bytes simultaneously.
5959
extern bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uint8_t *data_in, size_t len);
6060

61+
// Return actual SPI bus frequency.
62+
uint32_t common_hal_busio_spi_get_frequency(busio_spi_obj_t* self);
63+
6164
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSIO_SPI_H

0 commit comments

Comments
 (0)