stmhal: Extend SPI support to fully support all SPI devices on STM32F429.

This includes SPI4, SPI5 and SPI6.
This commit is contained in:
Tobias Badertscher 2015-12-08 15:41:47 +01:00 committed by Damien George
parent 130fde8130
commit c5d8ffef58
4 changed files with 162 additions and 12 deletions

View File

@ -1,3 +1,5 @@
#include STM32_HAL_H
#define MICROPY_HW_BOARD_NAME "F429I-DISCO" #define MICROPY_HW_BOARD_NAME "F429I-DISCO"
#define MICROPY_HW_MCU_NAME "STM32F429" #define MICROPY_HW_MCU_NAME "STM32F429"
@ -29,6 +31,32 @@
#define MICROPY_HW_I2C1_SCL (pin_A8) #define MICROPY_HW_I2C1_SCL (pin_A8)
#define MICROPY_HW_I2C1_SDA (pin_C9) #define MICROPY_HW_I2C1_SDA (pin_C9)
// SPI busses
//#define MICROPY_HW_SPI1_NSS (pin_A4)
//#define MICROPY_HW_SPI1_SCK (pin_A5)
//#define MICROPY_HW_SPI1_MISO (pin_A6)
//#define MICROPY_HW_SPI1_MOSI (pin_A7)
#if defined(USE_USB_HS_IN_FS)
// The HS USB uses B14 & B15 for D- and D+
#else
#define MICROPY_HW_SPI2_NSS (pin_B12)
#define MICROPY_HW_SPI2_SCK (pin_B13)
#define MICROPY_HW_SPI2_MISO (pin_B14)
#define MICROPY_HW_SPI2_MOSI (pin_B15)
#endif
//#define MICROPY_HW_SPI4_NSS (pin_E11)
//#define MICROPY_HW_SPI4_SCK (pin_E12)
//#define MICROPY_HW_SPI4_MISO (pin_E13)
//#define MICROPY_HW_SPI4_MOSI (pin_E14)
#define MICROPY_HW_SPI5_NSS (pin_F6)
#define MICROPY_HW_SPI5_SCK (pin_F7)
#define MICROPY_HW_SPI5_MISO (pin_F8)
#define MICROPY_HW_SPI5_MOSI (pin_F9)
//#define MICROPY_HW_SPI6_NSS (pin_G8)
//#define MICROPY_HW_SPI6_SCK (pin_G13)
//#define MICROPY_HW_SPI6_MISO (pin_G12)
//#define MICROPY_HW_SPI6_MOSI (pin_G14)
// USRSW is pulled low. Pressing the button makes the input go high. // USRSW is pulled low. Pressing the button makes the input go high.
#define MICROPY_HW_USRSW_PIN (pin_A0) #define MICROPY_HW_USRSW_PIN (pin_A0)
#define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) #define MICROPY_HW_USRSW_PULL (GPIO_NOPULL)

View File

@ -74,12 +74,30 @@
#define DMA_STREAM_SPI1_RX DMA2_Stream2 #define DMA_STREAM_SPI1_RX DMA2_Stream2
#define DMA_CHANNEL_SPI1_RX DMA_CHANNEL_3 #define DMA_CHANNEL_SPI1_RX DMA_CHANNEL_3
#define DMA_STREAM_SPI5_RX DMA2_Stream3
#define DMA_CHANNEL_SPI5_RX DMA_CHANNEL_2
#define DMA_STREAM_SDIO_RX DMA2_Stream3 #define DMA_STREAM_SDIO_RX DMA2_Stream3
#define DMA_CHANNEL_SDIO_RX DMA_CHANNEL_4 #define DMA_CHANNEL_SDIO_RX DMA_CHANNEL_4
#define DMA_STREAM_SPI4_RX DMA2_Stream3
#define DMA_CHANNEL_SPI4_RX DMA_CHANNEL_5
#define DMA_STREAM_SPI5_TX DMA2_Stream4
#define DMA_CHANNEL_SPI5_TX DMA_CHANNEL_2
#define DMA_STREAM_SPI4_TX DMA2_Stream4
#define DMA_CHANNEL_SPI4_TX DMA_CHANNEL_5
#define DMA_STREAM_SPI6_TX DMA2_Stream5
#define DMA_CHANNEL_SPI6_TX DMA_CHANNEL_1
#define DMA_STREAM_SPI1_TX DMA2_Stream5 #define DMA_STREAM_SPI1_TX DMA2_Stream5
#define DMA_CHANNEL_SPI1_TX DMA_CHANNEL_3 #define DMA_CHANNEL_SPI1_TX DMA_CHANNEL_3
#define DMA_STREAM_SPI6_RX DMA2_Stream6
#define DMA_CHANNEL_SPI6_RX DMA_CHANNEL_1
#define DMA_STREAM_SDIO_TX DMA2_Stream6 #define DMA_STREAM_SDIO_TX DMA2_Stream6
#define DMA_CHANNEL_SDIO_TX DMA_CHANNEL_4 #define DMA_CHANNEL_SDIO_TX DMA_CHANNEL_4

View File

@ -68,6 +68,12 @@
// SPI2_RX: DMA1_Stream3.CHANNEL_0 // SPI2_RX: DMA1_Stream3.CHANNEL_0
// SPI3_TX: DMA1_Stream5.CHANNEL_0 or DMA1_Stream7.CHANNEL_0 // SPI3_TX: DMA1_Stream5.CHANNEL_0 or DMA1_Stream7.CHANNEL_0
// SPI3_RX: DMA1_Stream0.CHANNEL_0 or DMA1_Stream2.CHANNEL_0 // SPI3_RX: DMA1_Stream0.CHANNEL_0 or DMA1_Stream2.CHANNEL_0
// SPI4_TX: DMA2_Stream4.CHANNEL_5 or DMA2_Stream1.CHANNEL_4
// SPI4_RX: DMA2_Stream3.CHANNEL_5 or DMA2_Stream0.CHANNEL_4
// SPI5_TX: DMA2_Stream4.CHANNEL_2 or DMA2_Stream6.CHANNEL_7
// SPI5_RX: DMA2_Stream3.CHANNEL_2 or DMA2_Stream5.CHANNEL_7
// SPI6_TX: DMA2_Stream5.CHANNEL_1
// SPI6_RX: DMA2_Stream6.CHANNEL_1
typedef struct _pyb_spi_obj_t { typedef struct _pyb_spi_obj_t {
mp_obj_base_t base; mp_obj_base_t base;
@ -87,6 +93,15 @@ SPI_HandleTypeDef SPIHandle2 = {.Instance = NULL};
#if defined(MICROPY_HW_SPI3_SCK) #if defined(MICROPY_HW_SPI3_SCK)
SPI_HandleTypeDef SPIHandle3 = {.Instance = NULL}; SPI_HandleTypeDef SPIHandle3 = {.Instance = NULL};
#endif #endif
#if defined(MICROPY_HW_SPI4_SCK)
SPI_HandleTypeDef SPIHandle4 = {.Instance = NULL};
#endif
#if defined(MICROPY_HW_SPI5_SCK)
SPI_HandleTypeDef SPIHandle5 = {.Instance = NULL};
#endif
#if defined(MICROPY_HW_SPI6_SCK)
SPI_HandleTypeDef SPIHandle6 = {.Instance = NULL};
#endif
STATIC const pyb_spi_obj_t pyb_spi_obj[] = { STATIC const pyb_spi_obj_t pyb_spi_obj[] = {
#if defined(MICROPY_HW_SPI1_SCK) #if defined(MICROPY_HW_SPI1_SCK)
@ -104,6 +119,21 @@ STATIC const pyb_spi_obj_t pyb_spi_obj[] = {
#else #else
{{&pyb_spi_type}, NULL, NULL, 0, NULL, 0}, {{&pyb_spi_type}, NULL, NULL, 0, NULL, 0},
#endif #endif
#if defined(MICROPY_HW_SPI4_SCK)
{{&pyb_spi_type}, &SPIHandle4, DMA_STREAM_SPI4_TX, DMA_CHANNEL_SPI4_TX, DMA_STREAM_SPI4_RX, DMA_CHANNEL_SPI4_RX},
#else
{{&pyb_spi_type}, NULL, NULL, 0, NULL, 0},
#endif
#if defined(MICROPY_HW_SPI5_SCK)
{{&pyb_spi_type}, &SPIHandle5, DMA_STREAM_SPI5_TX, DMA_CHANNEL_SPI5_TX, DMA_STREAM_SPI5_RX, DMA_CHANNEL_SPI5_RX},
#else
{{&pyb_spi_type}, NULL, NULL, 0, NULL, 0},
#endif
#if defined(MICROPY_HW_SPI6_SCK)
{{&pyb_spi_type}, &SPIHandle6, DMA_STREAM_SPI6_TX, DMA_CHANNEL_SPI6_TX, DMA_STREAM_SPI6_RX, DMA_CHANNEL_SPI6_RX},
#else
{{&pyb_spi_type}, NULL, NULL, 0, NULL, 0},
#endif
}; };
void spi_init0(void) { void spi_init0(void) {
@ -120,6 +150,18 @@ void spi_init0(void) {
memset(&SPIHandle3, 0, sizeof(SPI_HandleTypeDef)); memset(&SPIHandle3, 0, sizeof(SPI_HandleTypeDef));
SPIHandle3.Instance = SPI3; SPIHandle3.Instance = SPI3;
#endif #endif
#if defined(MICROPY_HW_SPI4_SCK)
memset(&SPIHandle4, 0, sizeof(SPI_HandleTypeDef));
SPIHandle4.Instance = SPI4;
#endif
#if defined(MICROPY_HW_SPI5_SCK)
memset(&SPIHandle5, 0, sizeof(SPI_HandleTypeDef));
SPIHandle5.Instance = SPI5;
#endif
#if defined(MICROPY_HW_SPI6_SCK)
memset(&SPIHandle6, 0, sizeof(SPI_HandleTypeDef));
SPIHandle6.Instance = SPI6;
#endif
} }
// TODO allow to take a list of pins to use // TODO allow to take a list of pins to use
@ -167,6 +209,39 @@ void spi_init(SPI_HandleTypeDef *spi, bool enable_nss_pin) {
// enable the SPI clock // enable the SPI clock
__SPI3_CLK_ENABLE(); __SPI3_CLK_ENABLE();
#endif #endif
#if defined(MICROPY_HW_SPI4_SCK)
} else if (spi->Instance == SPI4) {
self = &pyb_spi_obj[3];
pins[0] = &MICROPY_HW_SPI4_NSS;
pins[1] = &MICROPY_HW_SPI4_SCK;
pins[2] = &MICROPY_HW_SPI4_MISO;
pins[3] = &MICROPY_HW_SPI4_MOSI;
GPIO_InitStructure.Alternate = GPIO_AF5_SPI4;
// enable the SPI clock
__SPI4_CLK_ENABLE();
#endif
#if defined(MICROPY_HW_SPI5_SCK)
} else if (spi->Instance == SPI5) {
self = &pyb_spi_obj[4];
pins[0] = &MICROPY_HW_SPI5_NSS;
pins[1] = &MICROPY_HW_SPI5_SCK;
pins[2] = &MICROPY_HW_SPI5_MISO;
pins[3] = &MICROPY_HW_SPI5_MOSI;
GPIO_InitStructure.Alternate = GPIO_AF5_SPI5;
// enable the SPI clock
__SPI5_CLK_ENABLE();
#endif
#if defined(MICROPY_HW_SPI6_SCK)
} else if (spi->Instance == SPI6) {
self = &pyb_spi_obj[5];
pins[0] = &MICROPY_HW_SPI6_NSS;
pins[1] = &MICROPY_HW_SPI6_SCK;
pins[2] = &MICROPY_HW_SPI6_MISO;
pins[3] = &MICROPY_HW_SPI6_MOSI;
GPIO_InitStructure.Alternate = GPIO_AF5_SPI6;
// enable the SPI clock
__SPI6_CLK_ENABLE();
#endif
} else { } else {
// SPI does not exist for this board (shouldn't get here, should be checked by caller) // SPI does not exist for this board (shouldn't get here, should be checked by caller)
return; return;
@ -215,6 +290,24 @@ void spi_deinit(SPI_HandleTypeDef *spi) {
__SPI3_RELEASE_RESET(); __SPI3_RELEASE_RESET();
__SPI3_CLK_DISABLE(); __SPI3_CLK_DISABLE();
#endif #endif
#if defined(MICROPY_HW_SPI4_SCK)
} else if (spi->Instance == SPI4) {
__SPI4_FORCE_RESET();
__SPI4_RELEASE_RESET();
__SPI4_CLK_DISABLE();
#endif
#if defined(MICROPY_HW_SPI5_SCK)
} else if (spi->Instance == SPI5) {
__SPI5_FORCE_RESET();
__SPI5_RELEASE_RESET();
__SPI5_CLK_DISABLE();
#endif
#if defined(MICROPY_HW_SPI6_SCK)
} else if (spi->Instance == SPI6) {
__SPI6_FORCE_RESET();
__SPI6_RELEASE_RESET();
__SPI6_CLK_DISABLE();
#endif
} }
} }
@ -245,10 +338,18 @@ SPI_HandleTypeDef *spi_get_handle(mp_obj_t o) {
STATIC void pyb_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { STATIC void pyb_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_spi_obj_t *self = self_in; pyb_spi_obj_t *self = self_in;
uint spi_num; uint spi_num = 1; // default to SPI1
if (self->spi->Instance == SPI1) { spi_num = 1; } if (self->spi->Instance == SPI2) { spi_num = 2; }
else if (self->spi->Instance == SPI2) { spi_num = 2; } else if (self->spi->Instance == SPI3) { spi_num = 3; }
else { spi_num = 3; } #if defined(SPI4)
else if (self->spi->Instance == SPI4) { spi_num = 4; }
#endif
#if defined(SPI5)
else if (self->spi->Instance == SPI5) { spi_num = 5; }
#endif
#if defined(SPI6)
else if (self->spi->Instance == SPI6) { spi_num = 6; }
#endif
if (self->spi->State == HAL_SPI_STATE_RESET) { if (self->spi->State == HAL_SPI_STATE_RESET) {
mp_printf(print, "SPI(%u)", spi_num); mp_printf(print, "SPI(%u)", spi_num);
@ -256,12 +357,12 @@ STATIC void pyb_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ki
if (self->spi->Init.Mode == SPI_MODE_MASTER) { if (self->spi->Init.Mode == SPI_MODE_MASTER) {
// compute baudrate // compute baudrate
uint spi_clock; uint spi_clock;
if (self->spi->Instance == SPI1) { if (self->spi->Instance == SPI2 || self->spi->Instance == SPI3) {
// SPI1 is on APB2
spi_clock = HAL_RCC_GetPCLK2Freq();
} else {
// SPI2 and SPI3 are on APB1 // SPI2 and SPI3 are on APB1
spi_clock = HAL_RCC_GetPCLK1Freq(); spi_clock = HAL_RCC_GetPCLK1Freq();
} else {
// SPI1, SPI4, SPI5 and SPI6 are on APB2
spi_clock = HAL_RCC_GetPCLK2Freq();
} }
uint log_prescaler = (self->spi->Init.BaudRatePrescaler >> 3) + 1; uint log_prescaler = (self->spi->Init.BaudRatePrescaler >> 3) + 1;
uint baudrate = spi_clock >> log_prescaler; uint baudrate = spi_clock >> log_prescaler;
@ -311,12 +412,12 @@ STATIC mp_obj_t pyb_spi_init_helper(const pyb_spi_obj_t *self, mp_uint_t n_args,
if (br_prescale == 0xffffffff) { if (br_prescale == 0xffffffff) {
// prescaler not given, so select one that yields at most the requested baudrate // prescaler not given, so select one that yields at most the requested baudrate
mp_uint_t spi_clock; mp_uint_t spi_clock;
if (self->spi->Instance == SPI1) { if (self->spi->Instance == SPI2 || self->spi->Instance == SPI3) {
// SPI1 is on APB2
spi_clock = HAL_RCC_GetPCLK2Freq();
} else {
// SPI2 and SPI3 are on APB1 // SPI2 and SPI3 are on APB1
spi_clock = HAL_RCC_GetPCLK1Freq(); spi_clock = HAL_RCC_GetPCLK1Freq();
} else {
// SPI1, SPI4, SPI5 and SPI6 are on APB2
spi_clock = HAL_RCC_GetPCLK2Freq();
} }
br_prescale = spi_clock / args[1].u_int; br_prescale = spi_clock / args[1].u_int;
} }

View File

@ -27,6 +27,9 @@
extern SPI_HandleTypeDef SPIHandle1; extern SPI_HandleTypeDef SPIHandle1;
extern SPI_HandleTypeDef SPIHandle2; extern SPI_HandleTypeDef SPIHandle2;
extern SPI_HandleTypeDef SPIHandle3; extern SPI_HandleTypeDef SPIHandle3;
extern SPI_HandleTypeDef SPIHandle4;
extern SPI_HandleTypeDef SPIHandle5;
extern SPI_HandleTypeDef SPIHandle6;
extern const mp_obj_type_t pyb_spi_type; extern const mp_obj_type_t pyb_spi_type;
void spi_init0(void); void spi_init0(void);