Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@

if("NUCLEO_H563ZI" IN_LIST MBED_TARGET_LABELS)
add_subdirectory(TARGET_NUCLEO_H563ZI)
endif()
endif()
if("DISCO_H573I" IN_LIST MBED_TARGET_LABELS)
add_subdirectory(TARGET_DISCO_H573I)
endif()
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Copyright (c) 2025 Jamie Smith
# SPDX-License-Identifier: Apache-2.0

target_sources(mbed-emac
PRIVATE
stm32h5_eth_init.c
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/* mbed Microcontroller Library
* Copyright (c) 2025, STMicroelectronics
* All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "stm32h5xx_hal.h"
#include "platform/mbed_critical.h"
#include "PinNames.h"

/**
* Override HAL Eth Init function.
*
* Note: This was copied from HAL_ETH_MspInit() in a project for the DISCO-H573I in STM32CubeIDE
*/
void EthInitPinmappings(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};

/* Peripheral clock enable */
__HAL_RCC_ETH_CLK_ENABLE();
__HAL_RCC_ETHTX_CLK_ENABLE();
__HAL_RCC_ETHRX_CLK_ENABLE();

__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
/**ETH GPIO Configuration
PC1 ------> ETH_MDC
PA1 ------> ETH_REF_CLK
PA2 ------> ETH_MDIO
PA7 ------> ETH_CRS_DV
PC4 ------> ETH_RXD0
PC5 ------> ETH_RXD1
PG12 ------> ETH_TXD1
PG11 ------> ETH_TX_EN
PG13 ------> ETH_TXD0
*/
GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
}

/**
* Override HAL Eth DeInit function
*/
void EthDeinitPinmappings()
{
/* Peripheral clock disable */
__HAL_RCC_ETH_CLK_DISABLE();
__HAL_RCC_ETHTX_CLK_DISABLE();
__HAL_RCC_ETHRX_CLK_DISABLE();

/**ETH GPIO Configuration
PC1 ------> ETH_MDC
PA1 ------> ETH_REF_CLK
PA2 ------> ETH_MDIO
PA7 ------> ETH_CRS_DV
PC4 ------> ETH_RXD0
PC5 ------> ETH_RXD1
PB15 ------> ETH_TXD1
PG11 ------> ETH_TX_EN
PG13 ------> ETH_TXD0
*/
HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5);

HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_7);

HAL_GPIO_DeInit(GPIOG, GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13);
}

// Get Ethernet PHY reset pin
PinName EthGetPhyResetPin(void)
{
return NC; // Not connected on this board
}
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,9 @@ class OSPIFBlockDevice : public mbed::BlockDevice {
// Enable Quad mode if supported (1-1-4, 1-4-4, 4-4-4 bus modes)
int _sfdp_set_quad_enabled(uint8_t *basic_param_table_ptr);

// Perform soft reset if supported - returns error if soft reset is not supported
int _soft_reset();

// Enable QPI mode (4-4-4)
int _sfdp_set_qpi_enabled(uint8_t *basic_param_table_ptr);

Expand All @@ -405,6 +408,12 @@ class OSPIFBlockDevice : public mbed::BlockDevice {
OSPIF_BP_CLEAR_SR, // Clear protection bits in status register 1
};

enum ospif_soft_reset_mode {
OSPIF_SOFT_RESET_UNSUPPORTED = 0, // Soft reset not supported
OSPIF_DIRECT_SOFT_RESET, // Direct soft reset mode
OSPIF_ENABLE_AND_SOFT_RESET // Enable and soft reset mode
};

// OSPI Driver Object
mbed::OSPI _ospi;

Expand Down Expand Up @@ -463,6 +472,9 @@ class OSPIFBlockDevice : public mbed::BlockDevice {

uint32_t _init_ref_count;
bool _is_initialized;

ospif_soft_reset_mode _soft_reset_mode; // Soft Reset mode

#ifdef MX_FLASH_SUPPORT_RWW
enum wait_flag {
NOT_STARTED, // no wait is started
Expand Down
115 changes: 53 additions & 62 deletions storage/blockdevice/COMPONENT_OSPIF/source/OSPIFBlockDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,8 @@ OSPIFBlockDevice::OSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinNam
int clock_mode, int freq)
: _ospi(io0, io1, io2, io3, io4, io5, io6, io7, sclk, csel, dqs, clock_mode), _csel(csel), _freq(freq),
_init_ref_count(0),
_is_initialized(false)
_is_initialized(false),
_soft_reset_mode(OSPIF_SOFT_RESET_UNSUPPORTED)
{
_unique_device_status = add_new_csel_instance(csel);

Expand Down Expand Up @@ -389,14 +390,7 @@ int OSPIFBlockDevice::deinit()
_wait_flag = NOT_STARTED;
#endif

change_mode(OSPIF_OPI_MODE_SPI);

// Disable Device for Writing
ospi_status_t status = _ospi_send_general_command(OSPIF_INST_WRDI, OSPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0);
if (status != OSPI_STATUS_OK) {
tr_error("Write Disable failed");
result = OSPIF_BD_ERROR_DEVICE_ERROR;
}
result = _soft_reset();

_is_initialized = false;

Expand Down Expand Up @@ -746,10 +740,6 @@ int OSPIFBlockDevice::change_mode(int mode)
tr_error(" Writing Config Register2 Failed");
return -1;
}

// Configure BUS Mode to 1_1_1
_ospi.configure_format(OSPI_CFG_BUS_SINGLE, OSPI_CFG_INST_SIZE_8, OSPI_CFG_BUS_SINGLE, OSPI_CFG_ADDR_SIZE_32,
OSPI_CFG_BUS_SINGLE, 0, OSPI_CFG_BUS_SINGLE, 0);
}

_ospi.configure_format(OSPI_CFG_BUS_SINGLE, OSPI_CFG_INST_SIZE_8, OSPI_CFG_BUS_SINGLE, OSPI_CFG_ADDR_SIZE_32,
Expand Down Expand Up @@ -793,15 +783,11 @@ int OSPIFBlockDevice::change_mode(int mode)

if (OSPI_STATUS_OK == _ospi_send_general_command(OSPIF_INST_WRCR2, OSPIF_CR2_OPI_EN_ADDR, &config_reg2,
1, NULL, 0)) {
tr_debug("OPI mode enable - Writing Config Register2 Success: value = 0x%x", config_reg2);
tr_debug("OPI mode disable - Writing Config Register2 Success: value = 0x%x", config_reg2);
} else {
tr_error("OPI mode enable - Writing Config Register2 failed");
tr_error("OPI mode disable - Writing Config Register2 failed");
return -1;
}

// Configure BUS Mode to 1_1_1
_ospi.configure_format(OSPI_CFG_BUS_SINGLE, OSPI_CFG_INST_SIZE_8, OSPI_CFG_BUS_SINGLE, OSPI_CFG_ADDR_SIZE_32,
OSPI_CFG_BUS_SINGLE, 0, OSPI_CFG_BUS_SINGLE, 0);
}

_ospi.configure_format(OSPI_CFG_BUS_SINGLE, OSPI_CFG_INST_SIZE_8, OSPI_CFG_BUS_SINGLE, OSPI_CFG_ADDR_SIZE_32,
Expand Down Expand Up @@ -834,32 +820,8 @@ int OSPIFBlockDevice::change_mode(int mode)
_ospi.configure_format(_inst_width, _inst_size, _address_width, _address_size, OSPI_CFG_BUS_SINGLE,
0, _data_width, 0);
} else if (mode == OSPIF_OPI_MODE_SPI) {
// Write new Status Register Setup
if (_set_write_enable() != 0) {
tr_error("Write Enabe failed");
return -1;
}

config_reg2 = 0x00;

if (OSPI_STATUS_OK == _ospi_send_general_command(OSPIF_INST_WRCR2, OSPIF_CR2_OPI_EN_ADDR, &config_reg2,
1, NULL, 0)) {
tr_debug("OPI mode enable - Writing Config Register2 Success: value = 0x%x", config_reg2);
} else {
tr_error("OPI mode enable - Writing Config Register2 failed");
return -1;
}
_read_instruction = OSPIF_INST_READ_4B;
_dummy_cycles = 0;

_inst_width = OSPI_CFG_BUS_SINGLE;
_inst_size = OSPI_CFG_INST_SIZE_8;
_address_width = OSPI_CFG_BUS_SINGLE;
_address_size = OSPI_CFG_ADDR_SIZE_32;
_data_width = OSPI_CFG_BUS_SINGLE;

_ospi.configure_format(_inst_width, _inst_size, _address_width, _address_size, OSPI_CFG_BUS_SINGLE,
0, _data_width, _dummy_cycles);
// Perform a soft reset to switch to SPI mode as suggested by Copilot
status = _soft_reset();
}
return status;
}
Expand Down Expand Up @@ -1364,8 +1326,6 @@ int OSPIFBlockDevice::_sfdp_detect_and_enable_4byte_addressing(uint8_t *basic_pa

int OSPIFBlockDevice::_sfdp_detect_reset_protocol_and_reset(uint8_t *basic_param_table_ptr)
{
int status = OSPIF_BD_ERROR_OK;

#if RESET_SEQUENCE_FROM_SFDP
uint8_t examined_byte = basic_param_table_ptr[OSPIF_BASIC_PARAM_TABLE_SOFT_RESET_BYTE];

Expand All @@ -1374,38 +1334,69 @@ int OSPIFBlockDevice::_sfdp_detect_reset_protocol_and_reset(uint8_t *basic_param
#endif

#if !MBED_CONF_OSPIF_ENABLE_AND_RESET // i.e. direct reset, or determined from SFDP
// Issue instruction 0xF0 to reset the device
ospi_status_t ospi_status = _ospi_send_general_command(0xF0, OSPI_NO_ADDRESS_COMMAND, // Send reset instruction
NULL, 0, NULL, 0);
status = (ospi_status == OSPI_STATUS_OK) ? OSPIF_BD_ERROR_OK : OSPIF_BD_ERROR_PARSING_FAILED;
_soft_reset_mode = OSPIF_DIRECT_SOFT_RESET;
#endif

#if RESET_SEQUENCE_FROM_SFDP
} else if (examined_byte & SOFT_RESET_ENABLE_AND_RESET_INST_BITMASK) {
#endif

#if !MBED_CONF_OSPIF_DIRECT_RESET // i.e. enable and reset, or determined from SFDP
// Issue instruction 66h to enable resets on the device
// Then issue instruction 99h to reset the device
ospi_status_t ospi_status = _ospi_send_general_command(0x66, OSPI_NO_ADDRESS_COMMAND, // Send reset enable instruction
NULL, 0, NULL, 0);
if (ospi_status == OSPI_STATUS_OK) {
ospi_status = _ospi_send_general_command(0x99, OSPI_NO_ADDRESS_COMMAND, // Send reset instruction
NULL, 0, NULL, 0);
}
status = (ospi_status == OSPI_STATUS_OK) ? OSPIF_BD_ERROR_OK : OSPIF_BD_ERROR_PARSING_FAILED;
_soft_reset_mode = OSPIF_ENABLE_AND_SOFT_RESET;
#endif

#if RESET_SEQUENCE_FROM_SFDP
} else {
// Soft reset either is not supported or requires direct control over data lines
tr_error("Failed to determine soft reset sequence. If your device has a legacy SFDP table, please manually set enable-and-reset or direct-reset.");

status = OSPIF_BD_ERROR_PARSING_FAILED;
_soft_reset_mode = OSPIF_SOFT_RESET_UNSUPPORTED;
}
#endif

return _soft_reset();
}

int OSPIFBlockDevice::_soft_reset()
{
int status = OSPIF_BD_ERROR_OK;
ospi_status_t ospi_status = OSPI_STATUS_OK;

switch (_soft_reset_mode) {
case OSPIF_SOFT_RESET_UNSUPPORTED:
status = OSPIF_BD_ERROR_PARSING_FAILED;
break;
case OSPIF_DIRECT_SOFT_RESET:
// Issue instruction 0xF0 to reset the device
ospi_status = _ospi_send_general_command(0xF0, OSPI_NO_ADDRESS_COMMAND, // Send reset instruction
NULL, 0, NULL, 0);
status = (ospi_status == OSPI_STATUS_OK) ? OSPIF_BD_ERROR_OK : OSPIF_BD_ERROR_PARSING_FAILED;
break;
case OSPIF_ENABLE_AND_SOFT_RESET:
// Issue instruction 66h to enable resets on the device
// Then issue instruction 99h to reset the device
ospi_status = _ospi_send_general_command(0x66, OSPI_NO_ADDRESS_COMMAND, // Send reset enable instruction
NULL, 0, NULL, 0);
if (ospi_status == OSPI_STATUS_OK) {
ospi_status = _ospi_send_general_command(0x99, OSPI_NO_ADDRESS_COMMAND, // Send reset instruction
NULL, 0, NULL, 0);
}
status = (ospi_status == OSPI_STATUS_OK) ? OSPIF_BD_ERROR_OK : OSPIF_BD_ERROR_PARSING_FAILED;
break;
}
if (status == OSPIF_BD_ERROR_OK) {
// Set SPI format after soft reset
_read_instruction = OSPIF_INST_READ_4B;
_dummy_cycles = 0;

_inst_width = OSPI_CFG_BUS_SINGLE;
_inst_size = OSPI_CFG_INST_SIZE_8;
_address_width = OSPI_CFG_BUS_SINGLE;
_address_size = OSPI_CFG_ADDR_SIZE_32;
_data_width = OSPI_CFG_BUS_SINGLE;

_ospi.configure_format(_inst_width, _inst_size, _address_width, _address_size, OSPI_CFG_BUS_SINGLE,
0, _data_width, _dummy_cycles);

if (false == _is_mem_ready()) {
tr_error("Device not ready, reset failed");
status = OSPIF_BD_ERROR_READY_FAILED;
Expand Down
4 changes: 4 additions & 0 deletions targets/TARGET_STM/TARGET_STM32H5/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
add_subdirectory(STM32Cube_FW EXCLUDE_FROM_ALL)
add_subdirectory(TARGET_STM32H503xB EXCLUDE_FROM_ALL)
add_subdirectory(TARGET_STM32H563xI EXCLUDE_FROM_ALL)
add_subdirectory(TARGET_STM32H573xI EXCLUDE_FROM_ALL)

add_library(mbed-stm32h5 INTERFACE)

Expand All @@ -27,3 +28,6 @@ target_include_directories(mbed-stm32h5
)

target_link_libraries(mbed-stm32h5 INTERFACE mbed-stm mbed-stm32h5cube-fw)

# Add linker scripts
add_subdirectory(linker_scripts)
6 changes: 6 additions & 0 deletions targets/TARGET_STM/TARGET_STM32H5/PeripheralNames.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,12 @@ typedef enum {
#endif
} CANName;

#if defined OCTOSPI1_R_BASE
typedef enum {
QSPI_1 = (int)OCTOSPI1_R_BASE,
} QSPIName;
#endif

#if defined OCTOSPI1_R_BASE
typedef enum {
OSPI_1 = (int)OCTOSPI1_R_BASE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,4 @@ target_include_directories(mbed-stm32h503xb
.
)

mbed_set_linker_script(mbed-stm32h503xb ${CMAKE_CURRENT_SOURCE_DIR}/${LINKER_FILE})

target_link_libraries(mbed-stm32h503xb INTERFACE mbed-stm32h5)
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,4 @@ target_include_directories(mbed-stm32h563xi
.
)

mbed_set_linker_script(mbed-stm32h563xi ${CMAKE_CURRENT_SOURCE_DIR}/${LINKER_FILE})

target_link_libraries(mbed-stm32h563xi INTERFACE mbed-stm32h5)
Loading
Loading