hal/omv: Add SPI HAL.

This commit is contained in:
iabdalkader 2023-06-17 13:16:56 +02:00
parent 57842a7eb4
commit 28f808f54f
5 changed files with 564 additions and 18 deletions

79
src/omv/common/omv_spi.h Normal file
View File

@ -0,0 +1,79 @@
/*
* This file is part of the OpenMV project.
*
* Copyright (c) 2013-2023 Ibrahim Abdelkader <iabdalkader@openmv.io>
* Copyright (c) 2013-2023 Kwabena W. Agyeman <kwagyeman@openmv.io>
*
* This work is licensed under the MIT license, see the file LICENSE for details.
*
* SPI bus abstraction layer.
*/
#ifndef __OMV_SPI_H__
#define __OMV_SPI_H__
#include <stdint.h>
#include <stdbool.h>
#include "omv_portconfig.h"
// Config options are defined in ports so they can be used
// directly to initialize peripherals without remapping them.
typedef enum {
OMV_SPI_XFER_DMA = (1 << 0),
OMV_SPI_XFER_BLOCKING = (1 << 1),
OMV_SPI_XFER_NONBLOCK = (1 << 2),
OMV_SPI_XFER_CIRCULAR = (1 << 3),
OMV_SPI_XFER_FAILED = (1 << 4),
} omv_spi_xfer_flags_t;
typedef struct _omv_spi_config {
uint8_t id;
uint32_t baudrate;
uint8_t datasize;
uint32_t spi_mode;
uint32_t bus_mode;
uint32_t bit_order;
uint32_t clk_pol;
uint32_t clk_pha;
uint32_t nss_pol;
bool nss_enable;
bool dma_enable;
bool data_retained;
} omv_spi_config_t;
typedef struct _omv_spi omv_spi_t;
typedef void (*omv_spi_callback_t)(omv_spi_t *spi, void *data);
typedef struct _omv_spi_transfer {
void *txbuf;
void *rxbuf;
uint32_t size;
uint32_t timeout;
omv_spi_xfer_flags_t flags;
void *userdata;
omv_spi_callback_t callback;
} omv_spi_transfer_t;
typedef struct _omv_spi {
uint8_t id;
bool initialized;
bool dma_enabled;
omv_gpio_t cs; // For soft-NSS mode.
void *userdata;
omv_spi_callback_t callback;
uint32_t xfer_error;
omv_spi_xfer_flags_t xfer_flags;
#ifdef OMV_SPI_PORT_BITS
// Additional port-specific fields like device base pointer,
// dma handles, more I/Os etc... are included directly here,
// so that they can be accessible from this struct.
OMV_SPI_PORT_BITS
#endif
} omv_spi_t;
int omv_spi_init(omv_spi_t *spi, omv_spi_config_t *config);
// Default config: MASTER | FDX | 10MHz | 8 bits | MSB FIRST | NSS HARD | NSS/CPHA/CPOL LOW.
int omv_spi_default_config(omv_spi_config_t *config, uint32_t bus_id);
int omv_spi_deinit(omv_spi_t *spi);
int omv_spi_transfer_start(omv_spi_t *spi, omv_spi_transfer_t *xfer);
int omv_spi_transfer_abort(omv_spi_t *spi);
#endif // __OMV_SPI_H__

View File

@ -62,4 +62,31 @@ typedef const stm32_gpio_t *omv_gpio_t;
// IRQ handlers, if this I2C is enabled in Micropython, or defined and handled in stm32fxxx_hal_msp.c.
typedef I2C_HandleTypeDef *omv_i2c_dev_t;
#define OMV_SPI_MODE_SLAVE (SPI_MODE_SLAVE)
#define OMV_SPI_MODE_MASTER (SPI_MODE_MASTER)
#define OMV_SPI_LSB_FIRST (SPI_FIRSTBIT_LSB)
#define OMV_SPI_MSB_FIRST (SPI_FIRSTBIT_MSB)
#define OMV_SPI_BUS_TX (1 << 0)
#define OMV_SPI_BUS_RX (1 << 1)
#define OMV_SPI_BUS_TX_RX (OMV_SPI_BUS_TX | OMV_SPI_BUS_RX)
#define OMV_SPI_CPOL_LOW (SPI_POLARITY_LOW)
#define OMV_SPI_CPOL_HIGH (SPI_POLARITY_HIGH)
#define OMV_SPI_CPHA_1EDGE (SPI_PHASE_1EDGE)
#define OMV_SPI_CPHA_2EDGE (SPI_PHASE_2EDGE)
#define OMV_SPI_NSS_LOW (0)
#define OMV_SPI_NSS_HIGH (1)
#define OMV_SPI_PORT_BITS \
struct { \
IRQn_Type irqn; \
SPI_HandleTypeDef *descr; \
DMA_HandleTypeDef dma_descr_tx; \
DMA_HandleTypeDef dma_descr_rx; \
};
#endif // __OMV_PORTCONFIG_H__

View File

@ -569,6 +569,7 @@ UVC_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/ports/stm32/,\
dma_utils.o \
omv_gpio.o \
omv_i2c.o \
omv_spi.o \
)
UVC_OBJ += $(wildcard $(BUILD)/$(LEPTON_DIR)/src/*.o)

View File

@ -0,0 +1,400 @@
/*
* This file is part of the OpenMV project.
*
* Copyright (c) 2023 Ibrahim Abdelkader <iabdalkader@openmv.io>
* Copyright (c) 2023 Kwabena W. Agyeman <kwagyeman@openmv.io>
*
* This work is licensed under the MIT license, see the file LICENSE for details.
*
* OMV SPI port for stm32.
*/
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include STM32_HAL_H
#include "py/mphal.h"
#include "omv_boardconfig.h"
#include "irq.h"
#include "common.h"
#include "dma_utils.h"
#include "omv_spi.h"
// If an SPI handle is already defined in MicroPython, reuse that handle to allow
// MicroPython to process the SPI IRQ, otherwise define the IRQ handler and its handle.
#define DEFINE_SPI_INSTANCE(n) \
static SPI_HandleTypeDef SPIHandle##n; \
void SPI##n##_IRQHandler(void) { HAL_SPI_IRQHandler(&SPIHandle##n); }
#if defined(SPI1_ID) && defined(MICROPY_HW_SPI1_SCK)
extern SPI_HandleTypeDef SPIHandle1;
#elif defined(SPI1_ID)
DEFINE_SPI_INSTANCE(1)
#endif
#if defined(SPI2_ID) && defined(MICROPY_HW_SPI2_SCK)
extern SPI_HandleTypeDef SPIHandle2;
#elif defined(SPI2_ID)
DEFINE_SPI_INSTANCE(2)
#endif
#if defined(SPI3_ID) && defined(MICROPY_HW_SPI3_SCK)
extern SPI_HandleTypeDef SPIHandle3;
#elif defined(SPI3_ID)
DEFINE_SPI_INSTANCE(3)
#endif
#if defined(SPI4_ID) && defined(MICROPY_HW_SPI4_SCK)
extern SPI_HandleTypeDef SPIHandle4;
#elif defined(SPI4_ID)
DEFINE_SPI_INSTANCE(4)
#endif
#if defined(SPI5_ID) && defined(MICROPY_HW_SPI5_SCK)
extern SPI_HandleTypeDef SPIHandle5;
#elif defined(SPI5_ID)
DEFINE_SPI_INSTANCE(5)
#endif
#if defined(SPI6_ID) && defined(MICROPY_HW_SPI6_SCK)
extern SPI_HandleTypeDef SPIHandle6;
#elif defined(SPI6_ID)
DEFINE_SPI_INSTANCE(6)
#endif
#define INITIALIZE_SPI_DESCR(spi, spi_number) \
do { \
(spi)->id = spi_number; \
(spi)->irqn = SPI##spi_number##_IRQn; \
(spi)->cs = SPI##spi_number##_SSEL_PIN; \
(spi)->descr = &SPIHandle##spi_number; \
(spi)->descr->Instance = SPI##spi_number; \
(spi)->dma_descr_tx = (DMA_HandleTypeDef) \
{SPI##spi_number##_DMA_TX_CHANNEL, {DMA_REQUEST_SPI##spi_number##_TX}};\
(spi)->dma_descr_rx = (DMA_HandleTypeDef) \
{SPI##spi_number##_DMA_RX_CHANNEL, {DMA_REQUEST_SPI##spi_number##_RX}};\
} while(0)
static omv_spi_t *omv_spi_descr_all[6] = { NULL };
static uint32_t omv_spi_clocksource(SPI_TypeDef *spi) {
#if defined(MCU_SERIES_H7)
if (spi == SPI1 || spi == SPI2 || spi == SPI3) {
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI123);
} else if (spi == SPI4 || spi == SPI5) {
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI45);
} else {
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI6);
}
#else
if (spi == SPI2) {
// SPI2 is on APB1
return HAL_RCC_GetPCLK1Freq();
} else if (spi == SPI3) {
// SPI3 is on APB1
return HAL_RCC_GetPCLK1Freq();
} else {
// SPI1, SPI4, SPI5 and SPI6 are on APB2
return HAL_RCC_GetPCLK2Freq();
}
#endif
}
static int omv_spi_prescaler(SPI_TypeDef *spi, uint32_t baudrate)
{
const uint32_t prescalers[] = {
SPI_BAUDRATEPRESCALER_2,
SPI_BAUDRATEPRESCALER_4,
SPI_BAUDRATEPRESCALER_8,
SPI_BAUDRATEPRESCALER_16,
SPI_BAUDRATEPRESCALER_32,
SPI_BAUDRATEPRESCALER_64,
SPI_BAUDRATEPRESCALER_128,
SPI_BAUDRATEPRESCALER_256
};
uint32_t clksource = omv_spi_clocksource(spi);
for (size_t i = 0; i < OMV_ARRAY_SIZE(prescalers); i++) {
uint32_t target = clksource / ((2 << i));
if (target <= baudrate) {
return prescalers[i];
}
}
return SPI_BAUDRATEPRESCALER_256;
}
static void omv_spi_callback(SPI_HandleTypeDef *hspi)
{
omv_spi_t *spi = NULL;
if (0) {
#if defined(SPI1_ID)
} else if (hspi->Instance == SPI1) {
spi = omv_spi_descr_all[0];
#endif
#if defined(SPI2_ID)
} else if (hspi->Instance == SPI2) {
spi = omv_spi_descr_all[1];
#endif
#if defined(SPI3_ID)
} else if (hspi->Instance == SPI3) {
spi = omv_spi_descr_all[2];
#endif
#if defined(SPI4_ID)
} else if (hspi->Instance == SPI4) {
spi = omv_spi_descr_all[3];
#endif
#if defined(SPI5_ID)
} else if (hspi->Instance == SPI5) {
spi = omv_spi_descr_all[4];
#endif
#if defined(SPI6_ID)
} else if (hspi->Instance == SPI6) {
spi = omv_spi_descr_all[5];
#endif
}
if (spi == NULL) {
return;
}
if (hspi->ErrorCode != HAL_SPI_ERROR_NONE) {
spi->xfer_flags |= OMV_SPI_XFER_FAILED;
spi->xfer_error = hspi->ErrorCode;
omv_spi_transfer_abort(spi);
}
if (spi->callback) {
spi->callback(spi, spi->userdata);
}
}
int omv_spi_transfer_start(omv_spi_t *spi, omv_spi_transfer_t *xfer)
{
spi->callback = xfer->callback;
spi->userdata = xfer->userdata;
spi->xfer_error = 0;
spi->xfer_flags = xfer->flags;
if (spi->xfer_flags & OMV_SPI_XFER_BLOCKING) {
if (xfer->txbuf && xfer->rxbuf) {
if (HAL_SPI_TransmitReceive(spi->descr,
xfer->rxbuf, xfer->rxbuf, xfer->size, xfer->timeout) != HAL_OK) {
return -1;
}
} else if (xfer->txbuf) {
if (HAL_SPI_Transmit(spi->descr,
xfer->txbuf, xfer->size, xfer->timeout) != HAL_OK) {
return -1;
}
} else if (xfer->rxbuf) {
if (HAL_SPI_Receive(spi->descr,
xfer->rxbuf, xfer->size, xfer->timeout) != HAL_OK) {
return -1;
}
}
} else if (spi->xfer_flags & OMV_SPI_XFER_DMA) {
//HAL_NVIC_EnableIRQ(ISC_SPI_DMA_IRQn);
HAL_SPI_Receive_DMA(spi->descr, xfer->rxbuf, xfer->size);
} else {
return -1;
}
return 0;
}
int omv_spi_transfer_abort(omv_spi_t *spi)
{
HAL_NVIC_DisableIRQ(spi->irqn);
HAL_SPI_Abort(spi->descr);
return 0;
}
static int omv_spi_dma_init(omv_spi_t *spi, uint32_t direction)
{
DMA_HandleTypeDef *dma_descr;
if (direction == DMA_MEMORY_TO_PERIPH) {
dma_descr = &spi->dma_descr_tx;
} else {
dma_descr = &spi->dma_descr_rx;
}
// Configure the SPI DMA steam.
dma_descr->Init.Mode = DMA_CIRCULAR; // TODO FIX
dma_descr->Init.Priority = DMA_PRIORITY_HIGH;
dma_descr->Init.Direction = direction;
// When the DMA is configured in direct mode (the FIFO is disabled), the source and
// destination transfer widths are equal, and both defined by PSIZE (MSIZE is ignored).
// Additionally, burst transfers are not possible (MBURST and PBURST are both ignored).
dma_descr->Init.FIFOMode = DMA_FIFOMODE_DISABLE;
dma_descr->Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
// Note MBURST and PBURST are ignored.
dma_descr->Init.MemBurst = DMA_MBURST_INC4;
dma_descr->Init.PeriphBurst = DMA_PBURST_INC4;
dma_descr->Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
dma_descr->Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
dma_descr->Init.MemInc = DMA_MINC_ENABLE;
dma_descr->Init.PeriphInc = DMA_PINC_DISABLE;
// Initialize the DMA stream
HAL_DMA_DeInit(dma_descr);
if (HAL_DMA_Init(dma_descr) != HAL_OK) {
// Initialization Error
return -1;
}
// Link the DMA handle to SPI handle.
if (direction == DMA_MEMORY_TO_PERIPH) {
__HAL_LINKDMA(spi->descr, hdmatx, spi->dma_descr_tx);
} else {
__HAL_LINKDMA(spi->descr, hdmarx, spi->dma_descr_rx);
}
// Set the SPI handle used by the DMA channel's IRQ handler.
dma_utils_set_irq_descr(dma_descr->Instance, dma_descr);
// Get DMA channel's IRQ number.
uint8_t dma_irqn = dma_utils_channel_to_irqn(dma_descr->Instance);
// Configure and enable DMA IRQ channel.
NVIC_SetPriority(dma_irqn, IRQ_PRI_DMA21);
HAL_NVIC_EnableIRQ(dma_irqn);
return 0;
}
static int omv_spi_bus_init(omv_spi_t *spi, omv_spi_config_t *config)
{
SPI_HandleTypeDef *spi_descr = spi->descr;
spi_descr->Init.Mode = config->spi_mode;
spi_descr->Init.TIMode = SPI_TIMODE_DISABLE;
spi_descr->Init.NSS = (config->nss_enable == false) ? SPI_NSS_SOFT : SPI_NSS_HARD_OUTPUT;
spi_descr->Init.DataSize = (config->datasize == 8) ? SPI_DATASIZE_8BIT : SPI_DATASIZE_16BIT;
spi_descr->Init.FirstBit = config->bit_order;
spi_descr->Init.CLKPhase = config->clk_pha;
spi_descr->Init.CLKPolarity = config->clk_pol;
spi_descr->Init.BaudRatePrescaler = omv_spi_prescaler(spi_descr->Instance, config->baudrate);
#if defined(MCU_SERIES_F7) || defined(MCU_SERIES_H7)
spi_descr->Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
#if defined(MCU_SERIES_H7)
spi_descr->Init.NSSPolarity = (config->nss_pol == 0) ? SPI_NSS_POLARITY_LOW : SPI_NSS_POLARITY_HIGH;
spi_descr->Init.FifoThreshold = SPI_FIFO_THRESHOLD_04DATA;
spi_descr->Init.MasterKeepIOState = (config->data_retained == true) ?
SPI_MASTER_KEEP_IO_STATE_ENABLE : SPI_MASTER_KEEP_IO_STATE_ENABLE;
#endif
#endif
// Configure bus direction.
if (config->bus_mode == OMV_SPI_BUS_TX_RX) {
spi_descr->Init.Direction = SPI_DIRECTION_2LINES;
} else if (config->bus_mode == OMV_SPI_BUS_RX) {
spi_descr->Init.Direction = SPI_DIRECTION_2LINES_RXONLY;
} else {
#if defined(MCU_SERIES_H7)
spi_descr->Init.Direction = SPI_DIRECTION_2LINES_TXONLY;
#else
spi_descr->Init.Direction = SPI_DIRECTION_1LINE;
#endif
}
if (HAL_SPI_Init(spi_descr) != HAL_OK) {
HAL_SPI_DeInit(spi_descr);
return -1;
}
return 0;
}
int omv_spi_init(omv_spi_t *spi, omv_spi_config_t *config)
{
memset(spi, 0, sizeof(omv_spi_t));
if (0) {
#if defined(SPI1_ID)
} else if (config->id == 1) {
INITIALIZE_SPI_DESCR(spi, 1);
#endif
#if defined(SPI2_ID)
} else if (config->id == 2) {
INITIALIZE_SPI_DESCR(spi, 2);
#endif
#if defined(SPI3_ID)
} else if (config->id == 3) {
INITIALIZE_SPI_DESCR(spi, 3);
#endif
#if defined(SPI4_ID)
} else if (config->id == 4) {
INITIALIZE_SPI_DESCR(spi, 4);
#endif
#if defined(SPI5_ID)
} else if (config->id == 5) {
INITIALIZE_SPI_DESCR(spi, 5);
#endif
#if defined(SPI6_ID)
} else if (config->id == 6) {
INITIALIZE_SPI_DESCR(spi, 6);
#endif
} else {
return -1;
}
if (omv_spi_bus_init(spi, config) != 0) {
return -1;
}
if (config->dma_enable) {
if (config->bus_mode & OMV_SPI_BUS_TX) {
omv_spi_dma_init(spi, DMA_MEMORY_TO_PERIPH);
}
if (config->bus_mode & OMV_SPI_BUS_RX) {
omv_spi_dma_init(spi, DMA_PERIPH_TO_MEMORY);
}
// Configure and enable SPI IRQ channel.
NVIC_SetPriority(spi->irqn, IRQ_PRI_DCMI);// TODO use lower priority
HAL_NVIC_EnableIRQ(spi->irqn);
}
// Install TX/RX callbacks even if DMA mode is not enabled for non-blocking transfers.
if (config->bus_mode & OMV_SPI_BUS_TX) {
HAL_SPI_RegisterCallback(spi->descr, HAL_SPI_TX_COMPLETE_CB_ID, omv_spi_callback);
}
if (config->bus_mode & OMV_SPI_BUS_RX) {
HAL_SPI_RegisterCallback(spi->descr, HAL_SPI_RX_COMPLETE_CB_ID, omv_spi_callback);
}
spi->initialized = true;
spi->dma_enabled = config->dma_enable;
omv_spi_descr_all[config->id - 1] = spi;
return 0;
}
int omv_spi_deinit(omv_spi_t *spi)
{
if (spi && spi->initialized) {
spi->initialized = false;
omv_spi_descr_all[spi->id - 1] = NULL;
omv_spi_transfer_abort(spi);
if (spi->dma_enabled) {
// TODO: Deinit DMA
}
HAL_SPI_DeInit(spi->descr);
}
return 0;
}
int omv_spi_default_config(omv_spi_config_t *config, uint32_t bus_id)
{
config->id = bus_id;
config->baudrate = 10000000;
config->datasize = 8;
config->spi_mode = OMV_SPI_MODE_MASTER;
config->bus_mode = OMV_SPI_BUS_TX_RX;
config->bit_order = OMV_SPI_MSB_FIRST;
config->clk_pol = OMV_SPI_CPOL_LOW;
config->clk_pha = OMV_SPI_CPHA_1EDGE;
config->nss_pol = OMV_SPI_NSS_LOW;
config->nss_enable = true;
config->dma_enable = false;
config->data_retained = true;
return 0;
}

View File

@ -395,26 +395,65 @@ void HAL_DCMI_MspDeInit(DCMI_HandleTypeDef* hdcmi)
void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
{
#if defined(IMU_SPI)
if (hspi->Instance == IMU_SPI) {
IMU_SPI_CLK_ENABLE();
omv_gpio_config(IMU_SPI_SCLK_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_UP, OMV_GPIO_SPEED_HIGH, -1);
omv_gpio_config(IMU_SPI_MISO_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_UP, OMV_GPIO_SPEED_HIGH, -1);
omv_gpio_config(IMU_SPI_MOSI_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_UP, OMV_GPIO_SPEED_HIGH, -1);
omv_gpio_config(IMU_SPI_SSEL_PIN, OMV_GPIO_MODE_OUTPUT, OMV_GPIO_PULL_UP, OMV_GPIO_SPEED_HIGH, -1);
omv_gpio_write(IMU_SPI_SSEL_PIN, 1);
}
#endif
typedef struct {
omv_gpio_t sclk_pin;
omv_gpio_t miso_pin;
omv_gpio_t mosi_pin;
omv_gpio_t ssel_pin;
} spi_pins_t;
#if defined(ISC_SPI)
if (hspi->Instance == ISC_SPI) {
ISC_SPI_CLK_ENABLE();
omv_gpio_config(ISC_SPI_SCLK_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_UP, OMV_GPIO_SPEED_HIGH, -1);
omv_gpio_config(ISC_SPI_MISO_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_UP, OMV_GPIO_SPEED_HIGH, -1);
omv_gpio_config(ISC_SPI_MOSI_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_UP, OMV_GPIO_SPEED_HIGH, -1);
omv_gpio_config(ISC_SPI_SSEL_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_UP, OMV_GPIO_SPEED_HIGH, -1);
}
spi_pins_t spi_pins = { NULL, NULL, NULL, NULL };
if (0) {
#if defined(SPI1_ID)
} else if (hspi->Instance == SPI1) {
__HAL_RCC_SPI1_CLK_ENABLE();
spi_pins = (spi_pins_t) { SPI1_SCLK_PIN, SPI1_MISO_PIN, SPI1_MOSI_PIN, SPI1_SSEL_PIN };
#endif
#if defined(SPI2_ID)
} else if (hspi->Instance == SPI2) {
__HAL_RCC_SPI2_CLK_ENABLE();
spi_pins = (spi_pins_t) { SPI2_SCLK_PIN, SPI2_MISO_PIN, SPI2_MOSI_PIN, SPI2_SSEL_PIN };
#endif
#if defined(SPI3_ID)
} else if (hspi->Instance == SPI3) {
__HAL_RCC_SPI3_CLK_ENABLE();
spi_pins = (spi_pins_t) { SPI3_SCLK_PIN, SPI3_MISO_PIN, SPI3_MOSI_PIN, SPI3_SSEL_PIN };
#endif
#if defined(SPI4_ID)
} else if (hspi->Instance == SPI4) {
__HAL_RCC_SPI4_CLK_ENABLE();
spi_pins = (spi_pins_t) { SPI4_SCLK_PIN, SPI4_MISO_PIN, SPI4_MOSI_PIN, SPI4_SSEL_PIN };
#endif
#if defined(SPI5_ID)
} else if (hspi->Instance == SPI5) {
__HAL_RCC_SPI5_CLK_ENABLE();
spi_pins = (spi_pins_t) { SPI5_SCLK_PIN, SPI5_MISO_PIN, SPI5_MOSI_PIN, SPI5_SSEL_PIN };
#endif
#if defined(SPI6_ID)
} else if (hspi->Instance == SPI6) {
__HAL_RCC_SPI6_CLK_ENABLE();
spi_pins = (spi_pins_t) { SPI6_SCLK_PIN, SPI6_MISO_PIN, SPI6_MOSI_PIN, SPI6_SSEL_PIN };
#endif
} else {
return;
}
omv_gpio_config(spi_pins.sclk_pin, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_HIGH, -1);
omv_gpio_config(spi_pins.miso_pin, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_HIGH, -1);
omv_gpio_config(spi_pins.mosi_pin, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_HIGH, -1);
if (hspi->Init.NSS != SPI_NSS_SOFT) {
omv_gpio_config(spi_pins.ssel_pin, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_UP, OMV_GPIO_SPEED_HIGH, -1);
} else {
omv_gpio_config(spi_pins.ssel_pin, OMV_GPIO_MODE_OUTPUT, OMV_GPIO_PULL_UP, OMV_GPIO_SPEED_HIGH, -1);
#if defined(MCU_SERIES_H7)
if (hspi->Init.NSSPolarity == SPI_NSS_POLARITY_LOW) {
omv_gpio_write(spi_pins.ssel_pin, 1);
} else {
omv_gpio_write(spi_pins.ssel_pin, 0);
}
#endif
}
}
void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi)