Skip to content

Commit

Permalink
Add support of SPI API for STM32H5 family (#324)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
JohnK1987 and Jan Kamidra authored Sep 8, 2024
1 parent d1dbb40 commit fa86c2b
Show file tree
Hide file tree
Showing 10 changed files with 206 additions and 27 deletions.
1 change: 1 addition & 0 deletions targets/TARGET_STM/TARGET_STM32H5/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ target_sources(mbed-stm32h5
gpio_irq_device.c
i2c_device.c
serial_device.c
spi_api.c
pwmout_device.c
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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
10 changes: 8 additions & 2 deletions targets/TARGET_STM/TARGET_STM32H5/clock_cfg/system_clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
14 changes: 0 additions & 14 deletions targets/TARGET_STM/TARGET_STM32H5/objects.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
79 changes: 79 additions & 0 deletions targets/TARGET_STM/TARGET_STM32H5/spi_api.c
Original file line number Diff line number Diff line change
@@ -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
30 changes: 30 additions & 0 deletions targets/TARGET_STM/TARGET_STM32H5/spi_device.h
Original file line number Diff line number Diff line change
@@ -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
61 changes: 61 additions & 0 deletions targets/TARGET_STM/TARGET_STM32H5/stm_dma_info.h
Original file line number Diff line number Diff line change
@@ -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
28 changes: 23 additions & 5 deletions targets/TARGET_STM/stm_spi_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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");
Expand All @@ -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");
Expand All @@ -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");
Expand All @@ -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");
}
Expand All @@ -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");
}
Expand All @@ -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");
}
Expand Down Expand Up @@ -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.
Expand Down
6 changes: 2 additions & 4 deletions targets/targets.json5
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down

0 comments on commit fa86c2b

Please sign in to comment.