Skip to content

Commit 4bc0936

Browse files
authored
Merge branch 'master' into stm32-temperature-us
2 parents 42ceb97 + fb8fbbf commit 4bc0936

File tree

27 files changed

+2053
-31
lines changed

27 files changed

+2053
-31
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ jobs:
219219
- "stm32f411ce_blackpill"
220220
- "stm32f411ve_discovery"
221221
- "stm32f412zg_discovery"
222+
- "stm32f4_discovery"
222223
- "stringcar_m0_express"
223224
- "teensy40"
224225
- "teknikio_bluebird"

ports/nrf/boards/common.template.ld

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ MEMORY
2222
/* SoftDevice 6.1.0 with 5 connections and various increases takes just under 64kiB.
2323
/* To measure the minimum required amount of memory for given configuration, set this number
2424
high enough to work and then check the mutation of the value done by sd_ble_enable. */
25-
RAM (xrw) : ORIGIN = 0x20000000 + 64K, LENGTH = 256K - 64K
25+
SPIM3_RAM (rw) : ORIGIN = 0x20000000 + 64K, LENGTH = 8K
26+
RAM (xrw) : ORIGIN = 0x20000000 + 64K + 8K, LENGTH = 256K - 64K -8K
27+
2628
}
2729

2830
/* produce a link error if there is not this amount of RAM available */
@@ -37,6 +39,10 @@ _estack = ORIGIN(RAM) + LENGTH(RAM);
3739
_ram_end = ORIGIN(RAM) + LENGTH(RAM);
3840
_heap_end = 0x20020000; /* tunable */
3941

42+
/* nrf52840 SPIM3 needs its own area to work around hardware problems. Nothing else may use this space. */
43+
_spim3_ram = ORIGIN(SPIM3_RAM);
44+
_spim3_ram_end = ORIGIN(SPIM3_RAM) + LENGTH(RAM);
45+
4046
/* define output sections */
4147
SECTIONS
4248
{

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

Lines changed: 55 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,47 +22,55 @@
2222
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2323
*/
2424

25+
#include <string.h>
26+
2527
#include "shared-bindings/busio/SPI.h"
2628
#include "py/mperrno.h"
2729
#include "py/runtime.h"
2830

2931
#include "nrfx_spim.h"
3032
#include "nrf_gpio.h"
3133

34+
// These are in order from ighest available frequency to lowest (32MHz first, then 8MHz).
3235
STATIC spim_peripheral_t spim_peripherals[] = {
3336
#if NRFX_CHECK(NRFX_SPIM3_ENABLED)
3437
// SPIM3 exists only on nRF52840 and supports 32MHz max. All other SPIM's are only 8MHz max.
3538
// Allocate SPIM3 first.
3639
{ .spim = NRFX_SPIM_INSTANCE(3),
37-
.max_frequency_MHz = 32,
40+
.max_frequency = 32000000,
3841
.max_xfer_size = SPIM3_EASYDMA_MAXCNT_SIZE,
3942
},
4043
#endif
4144
#if NRFX_CHECK(NRFX_SPIM2_ENABLED)
4245
// SPIM2 is not shared with a TWIM, so allocate before the shared ones.
4346
{ .spim = NRFX_SPIM_INSTANCE(2),
44-
.max_frequency_MHz = 8,
47+
.max_frequency = 8000000,
4548
.max_xfer_size = SPIM2_EASYDMA_MAXCNT_SIZE,
4649
},
4750
#endif
4851
#if NRFX_CHECK(NRFX_SPIM1_ENABLED)
4952
// SPIM1 and TWIM1 share an address.
5053
{ .spim = NRFX_SPIM_INSTANCE(1),
51-
.max_frequency_MHz = 8,
54+
.max_frequency = 8000000,
5255
.max_xfer_size = SPIM1_EASYDMA_MAXCNT_SIZE,
5356
},
5457
#endif
5558
#if NRFX_CHECK(NRFX_SPIM0_ENABLED)
5659
// SPIM0 and TWIM0 share an address.
5760
{ .spim = NRFX_SPIM_INSTANCE(0),
58-
.max_frequency_MHz = 8,
61+
.max_frequency = 8000000,
5962
.max_xfer_size = SPIM0_EASYDMA_MAXCNT_SIZE,
6063
},
6164
#endif
6265
};
6366

6467
STATIC bool never_reset[MP_ARRAY_SIZE(spim_peripherals)];
6568

69+
// Separate RAM area for SPIM3 transmit buffer to avoid SPIM3 hardware errata.
70+
// https://infocenter.nordicsemi.com/index.jsp?topic=%2Ferrata_nRF52840_Rev2%2FERR%2FnRF52840%2FRev2%2Flatest%2Fanomaly_840_198.html
71+
extern uint32_t _spim3_ram;
72+
STATIC uint8_t *spim3_transmit_buffer = (uint8_t *) &_spim3_ram;
73+
6674
void spi_reset(void) {
6775
for (size_t i = 0 ; i < MP_ARRAY_SIZE(spim_peripherals); i++) {
6876
if (never_reset[i]) {
@@ -122,7 +130,7 @@ static nrf_spim_frequency_t baudrate_to_spim_frequency(const uint32_t baudrate)
122130
}
123131

124132
void common_hal_busio_spi_construct(busio_spi_obj_t *self, const mcu_pin_obj_t * clock, const mcu_pin_obj_t * mosi, const mcu_pin_obj_t * miso) {
125-
// Find a free instance.
133+
// Find a free instance, with most desirable (highest freq and not shared) allocated first.
126134
self->spim_peripheral = NULL;
127135
for (size_t i = 0 ; i < MP_ARRAY_SIZE(spim_peripherals); i++) {
128136
if ((spim_peripherals[i].spim.p_reg->ENABLE & SPIM_ENABLE_ENABLE_Msk) == 0) {
@@ -137,7 +145,8 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, const mcu_pin_obj_t *
137145

138146
nrfx_spim_config_t config = NRFX_SPIM_DEFAULT_CONFIG(NRFX_SPIM_PIN_NOT_USED, NRFX_SPIM_PIN_NOT_USED,
139147
NRFX_SPIM_PIN_NOT_USED, NRFX_SPIM_PIN_NOT_USED);
140-
config.frequency = NRF_SPIM_FREQ_8M;
148+
149+
config.frequency = baudrate_to_spim_frequency(self->spim_peripheral->max_frequency);
141150

142151
config.sck_pin = clock->number;
143152
self->clock_pin_number = clock->number;
@@ -189,8 +198,7 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self, uint32_t baudrate, ui
189198

190199
// Set desired frequency, rounding down, and don't go above available frequency for this SPIM.
191200
nrf_spim_frequency_set(self->spim_peripheral->spim.p_reg,
192-
baudrate_to_spim_frequency(MIN(baudrate,
193-
self->spim_peripheral->max_frequency_MHz * 1000000)));
201+
baudrate_to_spim_frequency(MIN(baudrate, self->spim_peripheral->max_frequency)));
194202

195203
nrf_spim_mode_t mode = NRF_SPIM_MODE_0;
196204
if (polarity) {
@@ -224,21 +232,36 @@ void common_hal_busio_spi_unlock(busio_spi_obj_t *self) {
224232
}
225233

226234
bool common_hal_busio_spi_write(busio_spi_obj_t *self, const uint8_t *data, size_t len) {
227-
if (len == 0)
235+
if (len == 0) {
228236
return true;
237+
}
238+
239+
const bool is_spim3 = self->spim_peripheral->spim.p_reg == NRF_SPIM3;
229240

230241
const uint32_t max_xfer_size = self->spim_peripheral->max_xfer_size;
231242
const uint32_t parts = len / max_xfer_size;
232243
const uint32_t remainder = len % max_xfer_size;
233244

234245
for (uint32_t i = 0; i < parts; ++i) {
235-
const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_TX(data + i * max_xfer_size, max_xfer_size);
246+
uint8_t *start = (uint8_t *) (data + i * max_xfer_size);
247+
if (is_spim3) {
248+
// If SPIM3, copy into unused RAM block, and do DMA from there.
249+
memcpy(spim3_transmit_buffer, start, max_xfer_size);
250+
start = spim3_transmit_buffer;
251+
}
252+
const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_TX(start, max_xfer_size);
236253
if (nrfx_spim_xfer(&self->spim_peripheral->spim, &xfer, 0) != NRFX_SUCCESS)
237254
return false;
238255
}
239256

240257
if (remainder > 0) {
241-
const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_TX(data + parts * max_xfer_size, remainder);
258+
uint8_t *start = (uint8_t *) (data + parts * max_xfer_size);
259+
if (is_spim3) {
260+
// If SPIM3, copy into unused RAM block, and do DMA from there.
261+
memcpy(spim3_transmit_buffer, start, remainder);
262+
start = spim3_transmit_buffer;
263+
}
264+
const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_TX(start, remainder);
242265
if (nrfx_spim_xfer(&self->spim_peripheral->spim, &xfer, 0) != NRFX_SUCCESS)
243266
return false;
244267
}
@@ -247,8 +270,9 @@ bool common_hal_busio_spi_write(busio_spi_obj_t *self, const uint8_t *data, size
247270
}
248271

249272
bool common_hal_busio_spi_read(busio_spi_obj_t *self, uint8_t *data, size_t len, uint8_t write_value) {
250-
if (len == 0)
273+
if (len == 0) {
251274
return true;
275+
}
252276

253277
const uint32_t max_xfer_size = self->spim_peripheral->max_xfer_size;
254278
const uint32_t parts = len / max_xfer_size;
@@ -270,23 +294,37 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self, uint8_t *data, size_t len,
270294
}
271295

272296
bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uint8_t *data_in, size_t len) {
273-
if (len == 0)
297+
if (len == 0) {
274298
return true;
299+
}
275300

301+
const bool is_spim3 = self->spim_peripheral->spim.p_reg == NRF_SPIM3;
276302

277303
const uint32_t max_xfer_size = self->spim_peripheral->max_xfer_size;
278304
const uint32_t parts = len / max_xfer_size;
279305
const uint32_t remainder = len % max_xfer_size;
280306

281307
for (uint32_t i = 0; i < parts; ++i) {
282-
const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_SINGLE_XFER(data_out + i * max_xfer_size, max_xfer_size,
308+
uint8_t *out_start = (uint8_t *) (data_out + i * max_xfer_size);
309+
if (is_spim3) {
310+
// If SPIM3, copy into unused RAM block, and do DMA from there.
311+
memcpy(spim3_transmit_buffer, out_start, max_xfer_size);
312+
out_start = spim3_transmit_buffer;
313+
}
314+
const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_SINGLE_XFER(out_start, max_xfer_size,
283315
data_in + i * max_xfer_size, max_xfer_size);
284316
if (nrfx_spim_xfer(&self->spim_peripheral->spim, &xfer, 0) != NRFX_SUCCESS)
285317
return false;
286318
}
287319

288320
if (remainder > 0) {
289-
const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_SINGLE_XFER(data_out + parts * max_xfer_size, remainder,
321+
uint8_t *out_start = (uint8_t *) (data_out + parts * max_xfer_size);
322+
if (is_spim3) {
323+
// If SPIM3, copy into unused RAM block, and do DMA from there.
324+
memcpy(spim3_transmit_buffer, out_start, remainder);
325+
out_start = spim3_transmit_buffer;
326+
}
327+
const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_SINGLE_XFER(out_start, remainder,
290328
data_in + parts * max_xfer_size, remainder);
291329
if (nrfx_spim_xfer(&self->spim_peripheral->spim, &xfer, 0) != NRFX_SUCCESS)
292330
return false;
@@ -325,9 +363,9 @@ uint32_t common_hal_busio_spi_get_frequency(busio_spi_obj_t* self) {
325363
}
326364

327365
uint8_t common_hal_busio_spi_get_phase(busio_spi_obj_t* self) {
328-
return 0;
366+
return (self->spim_peripheral->spim.p_reg->CONFIG & SPIM_CONFIG_CPHA_Msk) >> SPIM_CONFIG_CPHA_Pos;
329367
}
330368

331369
uint8_t common_hal_busio_spi_get_polarity(busio_spi_obj_t* self) {
332-
return 0;
370+
return (self->spim_peripheral->spim.p_reg->CONFIG & SPIM_CONFIG_CPOL_Msk) >> SPIM_CONFIG_CPOL_Pos;
333371
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
typedef struct {
3434
nrfx_spim_t spim;
35-
uint8_t max_frequency_MHz;
35+
uint32_t max_frequency;
3636
uint8_t max_xfer_size;
3737
} spim_peripheral_t;
3838

ports/nrf/nrfx_config.h

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,9 @@
2626

2727
// CIRCUITPY_NRF_NUM_I2C is 1 or 2 to choose how many I2C (TWIM) peripherals
2828
// to provide.
29-
// This can go away once we have SPIM3 working: then we can have two
30-
// I2C and two SPI.
29+
// With SPIM3 working we can have two I2C and two SPI.
3130
#ifndef CIRCUITPY_NRF_NUM_I2C
32-
#define CIRCUITPY_NRF_NUM_I2C 1
31+
#define CIRCUITPY_NRF_NUM_I2C 2
3332
#endif
3433

3534
#if CIRCUITPY_NRF_NUM_I2C != 1 && CIRCUITPY_NRF_NUM_I2C != 2
@@ -42,13 +41,12 @@
4241
#define NRFX_SPIM1_ENABLED 1
4342
#endif
4443
#define NRFX_SPIM2_ENABLED 1
45-
// DON'T ENABLE SPIM3 DUE TO ANOMALY WORKAROUND FAILURE (SEE ABOVE).
46-
// #ifdef NRF52840_XXAA
47-
// #define NRFX_SPIM_EXTENDED_ENABLED 1
48-
// #define NRFX_SPIM3_ENABLED 1
49-
// #else
50-
// #define NRFX_SPIM3_ENABLED 0
51-
// #endif
44+
#ifdef NRF52840_XXAA
45+
#define NRFX_SPIM_EXTENDED_ENABLED 1
46+
#define NRFX_SPIM3_ENABLED 1
47+
#else
48+
#define NRFX_SPIM3_ENABLED 0
49+
#endif
5250

5351

5452
#define NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY 7

ports/stm32f4/boards/STM32F407_fs.ld

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
GNU linker script for STM32F405 via Micropython
3+
*/
4+
5+
/* Specify the memory areas */
6+
MEMORY
7+
{
8+
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K /* entire flash */
9+
FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 16K /* sector 0 */
10+
FLASH_FS (rx) : ORIGIN = 0x08004000, LENGTH = 48K /* sectors 1,2,3 are 16K */
11+
FLASH_TEXT (rx) : ORIGIN = 0x08010000, LENGTH = 960K /* sector 4 is 64K, sectors 5,6,7 are 128K */
12+
CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K
13+
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
14+
}
15+
16+
/* produce a link error if there is not this amount of RAM for these sections */
17+
_minimum_stack_size = 2K;
18+
_minimum_heap_size = 16K;
19+
20+
/* Define tho top end of the stack. The stack is full descending so begins just
21+
above last byte of RAM. Note that EABI requires the stack to be 8-byte
22+
aligned for a call. */
23+
_estack = ORIGIN(RAM) + LENGTH(RAM);
24+
25+
/* RAM extents for the garbage collector */
26+
_ram_start = ORIGIN(RAM);
27+
_ram_end = ORIGIN(RAM) + LENGTH(RAM);
28+
29+
ENTRY(Reset_Handler)
30+
31+
/* define output sections */
32+
SECTIONS
33+
{
34+
/* The startup code goes first into FLASH */
35+
.isr_vector :
36+
{
37+
. = ALIGN(4);
38+
KEEP(*(.isr_vector)) /* Startup code */
39+
40+
/* This first flash block is 16K annd the isr vectors only take up
41+
about 400 bytes. Micropython pads this with files, but this didn't
42+
work with the size of Circuitpython's ff object. */
43+
44+
. = ALIGN(4);
45+
} >FLASH_ISR
46+
47+
/* The program code and other data goes into FLASH */
48+
.text :
49+
{
50+
. = ALIGN(4);
51+
*(.text*) /* .text* sections (code) */
52+
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
53+
/* *(.glue_7) */ /* glue arm to thumb code */
54+
/* *(.glue_7t) */ /* glue thumb to arm code */
55+
56+
. = ALIGN(4);
57+
_etext = .; /* define a global symbol at end of code */
58+
} >FLASH_TEXT
59+
60+
/* used by the startup to initialize data */
61+
_sidata = LOADADDR(.data);
62+
63+
/* This is the initialized data section
64+
The program executes knowing that the data is in the RAM
65+
but the loader puts the initial values in the FLASH (inidata).
66+
It is one task of the startup to copy the initial values from FLASH to RAM. */
67+
.data :
68+
{
69+
. = ALIGN(4);
70+
_sdata = .; /* create a global symbol at data start; used by startup code in order to initialise the .data section in RAM */
71+
*(.data*) /* .data* sections */
72+
73+
. = ALIGN(4);
74+
_edata = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */
75+
} >RAM AT> FLASH_TEXT
76+
77+
/* Uninitialized data section */
78+
.bss :
79+
{
80+
. = ALIGN(4);
81+
_sbss = .; /* define a global symbol at bss start; used by startup code */
82+
*(.bss*)
83+
*(COMMON)
84+
85+
. = ALIGN(4);
86+
_ebss = .; /* define a global symbol at bss end; used by startup code and GC */
87+
} >RAM
88+
89+
/* this is to define the start of the heap, and make sure we have a minimum size */
90+
.heap :
91+
{
92+
. = ALIGN(4);
93+
. = . + _minimum_heap_size;
94+
. = ALIGN(4);
95+
} >RAM
96+
97+
/* this just checks there is enough RAM for the stack */
98+
.stack :
99+
{
100+
. = ALIGN(4);
101+
. = . + _minimum_stack_size;
102+
. = ALIGN(4);
103+
} >RAM
104+
105+
.ARM.attributes 0 : { *(.ARM.attributes) }
106+
}
107+
108+

ports/stm32f4/boards/feather_stm32f405_express/mpconfigboard.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434

3535
#define MICROPY_HW_NEOPIXEL (&pin_PC00)
3636

37+
#define BOARD_OSC_DIV 12
38+
3739
// On-board flash
3840
#define SPI_FLASH_MOSI_PIN (&pin_PB05)
3941
#define SPI_FLASH_MISO_PIN (&pin_PB04)

ports/stm32f4/boards/pyboard_v11/mpconfigboard.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#define FLASH_SIZE (0x100000)
3333
#define FLASH_PAGE_SIZE (0x4000)
3434

35+
#define BOARD_OSC_DIV 12
3536

3637
#define DEFAULT_I2C_BUS_SCL (&pin_PB06)
3738
#define DEFAULT_I2C_BUS_SDA (&pin_PB07)

0 commit comments

Comments
 (0)