Add support of SPI API for STM32H5 family (#324)

* fix PWM pin map in context of Timer change

* Note about DAC on Nucleo-H503RB

* Add ADC and DAC for STM32H5

* Copyright fix

* Add I2C for STM32H5

* fix I2C related code

* ADC/DAC fix

* Enable I2C API

* Copyright fix

* Add SPI for STM32H5

* Modification of stm spi API for h5 family

* fix I2C device

* fix I2C ASYNCH macro

* fix revert back the stop variable position

* Fix clock for SPI

* fix some details

* Rename startup_stm32h563xx.s to startup_stm32h563xx.S

* Rename startup_stm32h503xx.s to startup_stm32h503xx.S

---------

Co-authored-by: Jan Kamidra <odiin@windowslive.com>
pull/15530/head
JohnK1987 2024-09-08 21:58:45 +02:00 committed by GitHub
parent d1dbb405c8
commit fa86c2b73c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 206 additions and 27 deletions

View File

@ -15,6 +15,7 @@ target_sources(mbed-stm32h5
gpio_irq_device.c
i2c_device.c
serial_device.c
spi_api.c
pwmout_device.c
)

View File

@ -541,4 +541,4 @@ g_pfnVectors:
.thumb_set I3C2_ER_IRQHandler,Default_Handler
.weak COMP1_IRQHandler
.thumb_set COMP1_IRQHandler,Default_Handler
.thumb_set COMP1_IRQHandler,Default_Handler

View File

@ -688,4 +688,4 @@ g_pfnVectors:
.thumb_set LPTIM5_IRQHandler,Default_Handler
.weak LPTIM6_IRQHandler
.thumb_set LPTIM6_IRQHandler,Default_Handler
.thumb_set LPTIM6_IRQHandler,Default_Handler

View File

@ -123,7 +123,10 @@ else // Divisible by 5MHz
RCC_OscInitStruct.PLL.PLLSource = RCC_PLL1_SOURCE_HSE;
RCC_OscInitStruct.PLL.PLLP = 2;
RCC_OscInitStruct.PLL.PLLQ = 2;
// Most of the SPI busses are clocked off of PLL1Q, and the max usable frequency for SPI is about
// ~50MHz. Plus, SPI has only limited, power-of-2 prescaler options so a high input clock really hurts
// its clock resolution. So, give it a much lower input clock.
RCC_OscInitStruct.PLL.PLLQ = 10; // output freq = 50MHz
RCC_OscInitStruct.PLL.PLLR = 2;
RCC_OscInitStruct.PLL.PLLFRACN = 0;
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1_VCORANGE_WIDE;
@ -189,7 +192,10 @@ uint8_t SetSysClock_PLL_HSI(void)
RCC_OscInitStruct.PLL.PLLM = 4;
RCC_OscInitStruct.PLL.PLLN = 31;
RCC_OscInitStruct.PLL.PLLP = 2;
RCC_OscInitStruct.PLL.PLLQ = 2;
// Most of the SPI busses are clocked off of PLL1Q, and the max usable frequency for SPI is about
// ~50MHz. Plus, SPI has only limited, power-of-2 prescaler options so a high input clock really hurts
// its clock resolution. So, give it a much lower input clock.
RCC_OscInitStruct.PLL.PLLQ = 10; // output freq = 50MHz
RCC_OscInitStruct.PLL.PLLR = 2;
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1_VCIRANGE_3;
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1_VCORANGE_WIDE;

View File

@ -51,20 +51,6 @@ struct trng_s {
RNG_HandleTypeDef handle;
};
struct spi_s {
SPI_HandleTypeDef handle;
IRQn_Type spiIRQ;
SPIName spi;
PinName pin_miso;
PinName pin_mosi;
PinName pin_sclk;
PinName pin_ssel;
#if DEVICE_SPI_ASYNCH
uint32_t event;
uint8_t transfer_type;
#endif
};
struct serial_s {
UARTName uart;
int index; // Used by irq

View File

@ -0,0 +1,79 @@
/* mbed Microcontroller Library
* SPDX-License-Identifier: BSD-3-Clause
******************************************************************************
*
* Copyright (c) 2015-2024 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
#include "mbed_assert.h"
#include "mbed_error.h"
#include "spi_api.h"
#if DEVICE_SPI
#include "cmsis.h"
#include "pinmap.h"
#include "PeripheralPins.h"
#include "mbed_error.h"
#include "spi_device.h"
#if DEVICE_SPI_ASYNCH
#define SPI_S(obj) (( struct spi_s *)(&(obj->spi)))
#else
#define SPI_S(obj) (( struct spi_s *)(obj))
#endif
/*
* Only the frequency is managed in the family specific part
* the rest of SPI management is common to all STM32 families
*/
int spi_get_clock_freq(spi_t *obj)
{
struct spi_s *spiobj = SPI_S(obj);
int spi_hz = 0;
/* Get source clock depending on SPI instance */
switch ((int)spiobj->spi) {
case SPI_1:
spi_hz = LL_RCC_GetSPIClockFreq(LL_RCC_SPI1_CLKSOURCE);
break;
case SPI_2:
spi_hz = LL_RCC_GetSPIClockFreq(LL_RCC_SPI2_CLKSOURCE);
break;
case SPI_3:
spi_hz = LL_RCC_GetSPIClockFreq(LL_RCC_SPI3_CLKSOURCE);
break;
#if defined(SPI4)
case SPI_4:
spi_hz = LL_RCC_GetSPIClockFreq(LL_RCC_SPI4_CLKSOURCE);
break;
#endif
#if defined(SPI5)
case SPI_5:
spi_hz = LL_RCC_GetSPIClockFreq(LL_RCC_SPI5_CLKSOURCE);
break;
#endif
#if defined(SPI6)
case SPI_6:
spi_hz = LL_RCC_GetSPIClockFreq(LL_RCC_SPI6_CLKSOURCE);
break;
#endif
default:
error("CLK: SPI instance not set");
break;
}
if (spi_hz == LL_RCC_PERIPH_FREQUENCY_NO) {
error("spi_hz not found\n");
}
return spi_hz;
}
#endif

View File

@ -0,0 +1,30 @@
/* mbed Microcontroller Library
* SPDX-License-Identifier: BSD-3-Clause
******************************************************************************
*
* Copyright (c) 2015-2024 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
#ifndef MBED_SPI_DEVICE_H
#define MBED_SPI_DEVICE_H
#include "stm32h5xx_ll_rcc.h"
#include "stm32h5xx_ll_spi.h"
#define SPI_IP_VERSION_V2
// Defines the word legnth capability of the device where Nth bit allows for N window size
#define STM32_SPI_CAPABILITY_WORD_LENGTH (0xFFFFFFF8)
// We have DMA support
#define STM32_SPI_CAPABILITY_DMA 1
#endif

View File

@ -0,0 +1,61 @@
/* mbed Microcontroller Library
* Copyright (c) 2016-2024 STMicroelectronics
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_OS_STM_DMA_INFO_H
#define MBED_OS_STM_DMA_INFO_H
#include "cmsis.h"
#include "stm_dma_utils.h"
// STM32h5 devices.
// On this device, the DMA channels may be chosen arbitrarily.
/// Mapping from SPI index to DMA link info for Tx
static const DMALinkInfo SPITxDMALinks[] = {
{1, 0, GPDMA1_REQUEST_SPI1_TX},
{1, 2, GPDMA1_REQUEST_SPI2_TX},
{1, 4, GPDMA1_REQUEST_SPI3_TX}
#if defined (SPI4)
,{1, 6, GPDMA1_REQUEST_SPI4_TX}
#endif
#if defined (SPI5)
,{2, 0, GPDMA1_REQUEST_SPI5_TX}
#endif
#if defined (SPI6)
,{2, 2, GPDMA1_REQUEST_SPI6_TX}
#endif
};
/// Mapping from SPI index to DMA link info for Rx
static const DMALinkInfo SPIRxDMALinks[] = {
{1, 1, GPDMA1_REQUEST_SPI1_RX},
{1, 3, GPDMA1_REQUEST_SPI2_RX},
{1, 5, GPDMA1_REQUEST_SPI3_TX}
#if defined (SPI4)
,{1, 7, GPDMA1_REQUEST_SPI4_RX}
#endif
#if defined (SPI5)
,{2, 1, GPDMA1_REQUEST_SPI5_RX}
#endif
#if defined (SPI6)
,{2, 3, GPDMA1_REQUEST_SPI6_RX}
#endif
};
#endif //MBED_OS_STM_DMA_INFO_H

View File

@ -76,7 +76,7 @@
#define TIMEOUT_1_BYTE 10
#if defined(SPI_FLAG_FRLVL) // STM32F0 STM32F3 STM32F7 STM32L4
#if defined(STM32U5)
#if defined(STM32U5) || defined(STM32H5)
extern HAL_StatusTypeDef HAL_SPIEx_FlushRxFifo(const SPI_HandleTypeDef *hspi);
#else
extern HAL_StatusTypeDef HAL_SPIEx_FlushRxFifo(SPI_HandleTypeDef *hspi);
@ -291,8 +291,10 @@ static void _spi_init_direct(spi_t *obj, const spi_pinmap_t *pinmap)
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SPI1;
#if defined (RCC_SPI123CLKSOURCE_PLL)
PeriphClkInit.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL;
#elif defined (RCC_SPI1CLKSOURCE_SYSCLK)
PeriphClkInit.Spi1ClockSelection = RCC_SPI1CLKSOURCE_SYSCLK;
#else
PeriphClkInit.Spi1ClockSelection = RCC_SPI1CLKSOURCE_SYSCLK;
PeriphClkInit.Spi1ClockSelection = RCC_SPI1CLKSOURCE_PLL1Q;
#endif
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
error("HAL_RCCEx_PeriphCLKConfig\n");
@ -314,8 +316,10 @@ static void _spi_init_direct(spi_t *obj, const spi_pinmap_t *pinmap)
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SPI2;
#if defined (RCC_SPI123CLKSOURCE_PLL)
PeriphClkInit.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL;
#else
#elif defined (RCC_SPI2CLKSOURCE_SYSCLK)
PeriphClkInit.Spi2ClockSelection = RCC_SPI2CLKSOURCE_SYSCLK;
#else
PeriphClkInit.Spi2ClockSelection = RCC_SPI2CLKSOURCE_PLL1Q;
#endif
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
error("HAL_RCCEx_PeriphCLKConfig\n");
@ -337,8 +341,10 @@ static void _spi_init_direct(spi_t *obj, const spi_pinmap_t *pinmap)
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SPI3;
#if defined (RCC_SPI123CLKSOURCE_PLL)
PeriphClkInit.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL;
#else
#elif defined (RCC_SPI2CLKSOURCE_SYSCLK)
PeriphClkInit.Spi3ClockSelection = RCC_SPI3CLKSOURCE_SYSCLK;
#else
PeriphClkInit.Spi3ClockSelection = RCC_SPI3CLKSOURCE_PLL1Q;
#endif
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
error("HAL_RCCEx_PeriphCLKConfig\n");
@ -358,7 +364,11 @@ static void _spi_init_direct(spi_t *obj, const spi_pinmap_t *pinmap)
if (spiobj->spi == SPI_4) {
#if defined(SPI_IP_VERSION_V2)
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SPI4;
#if defined RCC_SPI45CLKSOURCE_PCLK1
PeriphClkInit.Spi45ClockSelection = RCC_SPI45CLKSOURCE_PCLK1;
#else
PeriphClkInit.Spi4ClockSelection = RCC_SPI4CLKSOURCE_PCLK2;
#endif
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
error("HAL_RCCEx_PeriphCLKConfig\n");
}
@ -377,7 +387,11 @@ static void _spi_init_direct(spi_t *obj, const spi_pinmap_t *pinmap)
if (spiobj->spi == SPI_5) {
#if defined(SPI_IP_VERSION_V2)
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SPI5;
#if defined RCC_SPI45CLKSOURCE_PCLK1
PeriphClkInit.Spi45ClockSelection = RCC_SPI45CLKSOURCE_PCLK1;
#else
PeriphClkInit.Spi5ClockSelection = RCC_SPI5CLKSOURCE_PCLK3;
#endif
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
error("HAL_RCCEx_PeriphCLKConfig\n");
}
@ -396,7 +410,11 @@ static void _spi_init_direct(spi_t *obj, const spi_pinmap_t *pinmap)
if (spiobj->spi == SPI_6) {
#if defined(SPI_IP_VERSION_V2)
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SPI6;
#if defined RCC_SPI6CLKSOURCE_PCLK4
PeriphClkInit.Spi6ClockSelection = RCC_SPI6CLKSOURCE_PCLK4;
#else
PeriphClkInit.Spi6ClockSelection = RCC_SPI6CLKSOURCE_PCLK2;
#endif
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
error("HAL_RCCEx_PeriphCLKConfig\n");
}
@ -508,7 +526,7 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel
SPI_INIT_DIRECT(obj, &explicit_spi_pinmap);
}
#ifdef STM32_SPI_CAPABILITY_DMA
#if STM32_SPI_CAPABILITY_DMA
/**
* Initialize the DMA for an SPI object in the Tx direction.

View File

@ -3093,16 +3093,14 @@
],
"device_has_add": [
"MPU",
"ANALOGOUT"
"ANALOGOUT",
"SPI_32BIT_WORDS"
],
"device_has_remove": [
"FLASH",
"LPTICKER",
"CAN",
"SERIAL_FC",
"SPI",
"SPISLAVE",
"SPI_ASYNCH",
"WATCHDOG",
"ETHERNET",
"EMAC"