From cbfb21ea4779b5407a707b9be0d2440756b216d4 Mon Sep 17 00:00:00 2001 From: wdx04 <25487439@qq.com> Date: Mon, 14 Jul 2025 14:34:09 +0800 Subject: [PATCH 1/6] support CAN FD for STM32 L5,G0,G4,H5,H7 and U5 --- drivers/include/drivers/CAN.h | 34 +- .../include/drivers/interfaces/InterfaceCAN.h | 101 +++++ drivers/source/CAN.cpp | 41 ++- targets/TARGET_STM/TARGET_STM32G0/objects.h | 9 + targets/TARGET_STM/TARGET_STM32G4/objects.h | 1 + targets/TARGET_STM/TARGET_STM32H5/objects.h | 1 + targets/TARGET_STM/TARGET_STM32H7/objects.h | 1 + targets/TARGET_STM/TARGET_STM32L5/objects.h | 1 + targets/TARGET_STM/TARGET_STM32U5/objects.h | 1 + targets/TARGET_STM/can_api.c | 347 ++++++++++++++++-- targets/targets.json5 | 9 +- 11 files changed, 506 insertions(+), 40 deletions(-) diff --git a/drivers/include/drivers/CAN.h b/drivers/include/drivers/CAN.h index e5c539bd58e..c18019275a8 100644 --- a/drivers/include/drivers/CAN.h +++ b/drivers/include/drivers/CAN.h @@ -94,8 +94,9 @@ class CAN * @param rd the read pin * @param td the transmit pin * @param hz the bus frequency in hertz + * @param data_hz the data frequency in hertz(CAN FD only) */ - CAN(PinName rd, PinName td, int hz); + CAN(PinName rd, PinName td, int hz, int data_hz = 0); /** Initialize CAN interface * @@ -108,8 +109,9 @@ class CAN * * @param pinmap reference to structure which holds static pinmap * @param hz the bus frequency in hertz + * @param data_hz the data frequency in hertz(CAN FD only) */ - CAN(const can_pinmap_t &pinmap, int hz); + CAN(const can_pinmap_t &pinmap, int hz, int data_hz = 0); CAN(const can_pinmap_t &&, int) = delete; // prevent passing of temporary objects virtual ~CAN(); @@ -117,12 +119,13 @@ class CAN /** Set the frequency of the CAN interface * * @param hz The bus frequency in hertz + * @param data_hz the data frequency in hertz(CAN FD only) * * @returns * 1 if successful, * 0 otherwise */ - int frequency(int hz); + int frequency(int hz, int data_hz = 0); /** Write a CANMessage to the bus. * @@ -145,6 +148,31 @@ class CAN */ int read(CANMessage &msg, int handle = 0); +#ifdef DEVICE_CAN_FD + + /** Write a CANFDMessage to the bus. + * + * @param msg The CANFDMessage to write. + * + * @returns + * 0 if write failed, + * 1 if write was successful + */ + int write(CANFDMessage msg); + + /** Read a CANFDMessage from the bus. + * + * @param msg A CANFDMessage to read to. + * @param handle message filter handle (0 for any message) + * + * @returns + * 0 if no message arrived, + * 1 if message arrived + */ + int read(CANFDMessage &msg, int handle = 0); + +#endif + /** Reset CAN interface. * * To use after error overflow. diff --git a/drivers/include/drivers/interfaces/InterfaceCAN.h b/drivers/include/drivers/interfaces/InterfaceCAN.h index 5fad158112c..1aa7045083a 100644 --- a/drivers/include/drivers/interfaces/InterfaceCAN.h +++ b/drivers/include/drivers/interfaces/InterfaceCAN.h @@ -140,6 +140,107 @@ class CANMessage : public CAN_Message { } }; +#ifdef DEVICE_CAN_FD + +/** CANFDMessage class + * + * @note Synchronization level: Thread safe + */ +class CANFDMessage : public CANFD_Message { + +public: + /** Creates empty CANFD message. + */ + CANFDMessage() : CANFD_Message() + { + len = 64U; + type = CANData; + format = CANStandard; + id = 0U; + memset(data, 0, 64); + } + + /** Creates CANFD message with specific content. + * + * @param _id Message ID + * @param _data Mesaage Data + * @param _len Message Data length + * @param _type Type of Data: Use enum CANType for valid parameter values + * @param _format Data Format: Use enum CANFormat for valid parameter values + */ + CANFDMessage(unsigned int _id, const unsigned char *_data, unsigned char _len = 64, CANType _type = CANData, CANFormat _format = CANStandard) + { + len = (_len > 64) ? 64 : _len; + type = _type; + format = _format; + id = _id; + memcpy(data, _data, len); + } + + + /** Creates CANFD message with specific content. + * + * @param _id Message ID + * @param _data Mesaage Data + * @param _len Message Data length + * @param _type Type of Data: Use enum CANType for valid parameter values + * @param _format Data Format: Use enum CANFormat for valid parameter values + */ + CANFDMessage(unsigned int _id, const char *_data, unsigned char _len = 64, CANType _type = CANData, CANFormat _format = CANStandard) + { + len = (_len > 64) ? 64 : _len; + type = _type; + format = _format; + id = _id; + memcpy(data, _data, len); + } + + /** Creates CANFD remote message. + * + * @param _id Message ID + * @param _format Data Format: Use enum CANType for valid parameter values + */ + CANFDMessage(unsigned int _id, CANFormat _format = CANStandard) + { + len = 0; + type = CANRemote; + format = _format; + id = _id; + memset(data, 0, 64); + } + + /** + * "Deep" comparison operator (ie: compare value of each data member) + */ + bool operator ==(const CANFDMessage &b) const + { + if (id != b.id) { + return false; + } + if (len != b.len) { + return false; + } + if (format != b.format) { + return false; + } + if (type != b.type) { + return false; + } + if (memcmp(data, b.data, len) != 0) { + return false; + } + + return true; + } + + bool operator !=(const CANFDMessage &b) const + { + return !(*this == b); + } +}; + +#endif + /** @}*/ namespace interface { diff --git a/drivers/source/CAN.cpp b/drivers/source/CAN.cpp index 07ea344d024..9f361e689bb 100644 --- a/drivers/source/CAN.cpp +++ b/drivers/source/CAN.cpp @@ -30,10 +30,14 @@ CAN::CAN(PinName rd, PinName td) : _can(), _irq() can_irq_init(&_can, (&CAN::_irq_handler), reinterpret_cast(this)); } -CAN::CAN(PinName rd, PinName td, int hz) : _can(), _irq() +CAN::CAN(PinName rd, PinName td, int hz, int data_hz) : _can(), _irq() { // No lock needed in constructor +#ifdef DEVICE_CAN_FD + canfd_init_freq(&_can, rd, td, hz, data_hz); +#else can_init_freq(&_can, rd, td, hz); +#endif can_irq_init(&_can, (&CAN::_irq_handler), reinterpret_cast(this)); } @@ -44,10 +48,14 @@ CAN::CAN(const can_pinmap_t &pinmap) : _can(), _irq() can_irq_init(&_can, (&CAN::_irq_handler), reinterpret_cast(this)); } -CAN::CAN(const can_pinmap_t &pinmap, int hz) : _can(), _irq() +CAN::CAN(const can_pinmap_t &pinmap, int hz, int data_hz) : _can(), _irq() { // No lock needed in constructor +#ifdef DEVICE_CAN_FD + canfd_init_freq_direct(&_can, &pinmap, hz, data_hz); +#else can_init_freq_direct(&_can, &pinmap, hz); +#endif can_irq_init(&_can, (&CAN::_irq_handler), reinterpret_cast(this)); } @@ -63,10 +71,14 @@ CAN::~CAN() can_free(&_can); } -int CAN::frequency(int f) +int CAN::frequency(int f, int data_f) { lock(); +#ifdef DEVICE_CAN_FD + int ret = canfd_frequency(&_can, f, data_f); +#else int ret = can_frequency(&_can, f); +#endif unlock(); return ret; } @@ -90,6 +102,29 @@ int CAN::read(CANMessage &msg, int handle) return ret; } +#ifdef DEVICE_CAN_FD + +int CAN::write(CANFDMessage msg) +{ + lock(); + int ret = canfd_write(&_can, msg, 0); + unlock(); + return ret; +} + +int CAN::read(CANFDMessage &msg, int handle) +{ + lock(); + int ret = canfd_read(&_can, &msg, handle); + if (msg.len > 64) { + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER_CAN, MBED_ERROR_CODE_READ_FAILED), "Read tried to write more than 64 bytes"); + } + unlock(); + return ret; +} + +#endif + void CAN::reset() { lock(); diff --git a/targets/TARGET_STM/TARGET_STM32G0/objects.h b/targets/TARGET_STM/TARGET_STM32G0/objects.h index 227932cfe44..fc89aff35c5 100644 --- a/targets/TARGET_STM/TARGET_STM32G0/objects.h +++ b/targets/TARGET_STM/TARGET_STM32G0/objects.h @@ -75,6 +75,15 @@ struct analogin_s { uint8_t channel; }; +#if DEVICE_CAN +struct can_s { + FDCAN_HandleTypeDef CanHandle; + int index; + int hz; + int data_hz; +}; +#endif + #include "gpio_object.h" #if DEVICE_ANALOGOUT diff --git a/targets/TARGET_STM/TARGET_STM32G4/objects.h b/targets/TARGET_STM/TARGET_STM32G4/objects.h index f70dd1a8f77..3fbd97297ff 100644 --- a/targets/TARGET_STM/TARGET_STM32G4/objects.h +++ b/targets/TARGET_STM/TARGET_STM32G4/objects.h @@ -88,6 +88,7 @@ struct can_s { FDCAN_HandleTypeDef CanHandle; int index; int hz; + int data_hz; }; #endif diff --git a/targets/TARGET_STM/TARGET_STM32H5/objects.h b/targets/TARGET_STM/TARGET_STM32H5/objects.h index 007a43f1a5e..881d4d5fe4a 100644 --- a/targets/TARGET_STM/TARGET_STM32H5/objects.h +++ b/targets/TARGET_STM/TARGET_STM32H5/objects.h @@ -133,6 +133,7 @@ struct can_s { FDCAN_HandleTypeDef CanHandle; int index; int hz; + int data_hz; }; #endif diff --git a/targets/TARGET_STM/TARGET_STM32H7/objects.h b/targets/TARGET_STM/TARGET_STM32H7/objects.h index b29885e16c1..880074678e1 100644 --- a/targets/TARGET_STM/TARGET_STM32H7/objects.h +++ b/targets/TARGET_STM/TARGET_STM32H7/objects.h @@ -177,6 +177,7 @@ struct can_s { FDCAN_HandleTypeDef CanHandle; int index; int hz; + int data_hz; }; #endif diff --git a/targets/TARGET_STM/TARGET_STM32L5/objects.h b/targets/TARGET_STM/TARGET_STM32L5/objects.h index 72127a375ac..f4c0e5bf79c 100644 --- a/targets/TARGET_STM/TARGET_STM32L5/objects.h +++ b/targets/TARGET_STM/TARGET_STM32L5/objects.h @@ -106,6 +106,7 @@ struct can_s { FDCAN_HandleTypeDef CanHandle; int index; int hz; + int data_hz; }; #endif diff --git a/targets/TARGET_STM/TARGET_STM32U5/objects.h b/targets/TARGET_STM/TARGET_STM32U5/objects.h index 1d655949b1a..c6dc11449bc 100644 --- a/targets/TARGET_STM/TARGET_STM32U5/objects.h +++ b/targets/TARGET_STM/TARGET_STM32U5/objects.h @@ -106,6 +106,7 @@ struct can_s { FDCAN_HandleTypeDef CanHandle; int index; int hz; + int data_hz; }; #endif diff --git a/targets/TARGET_STM/can_api.c b/targets/TARGET_STM/can_api.c index fda4f5057fd..dd82c86a8f4 100644 --- a/targets/TARGET_STM/can_api.c +++ b/targets/TARGET_STM/can_api.c @@ -45,6 +45,17 @@ int can_internal_init(can_t *obj) error("HAL_FDCAN_Init error\n"); } + if(obj->data_hz > obj->hz) + { + uint32_t tx_delay = obj->CanHandle.Init.DataPrescaler * (obj->CanHandle.Init.DataTimeSeg1 + obj->CanHandle.Init.DataTimeSeg2 + 1) / 4; + if(tx_delay > 0x7FU) + { + tx_delay = 0x7FU; + } + HAL_FDCAN_ConfigTxDelayCompensation(&obj->CanHandle, tx_delay, 0); + HAL_FDCAN_EnableTxDelayCompensation(&obj->CanHandle); + } + if (can_filter(obj, 0, 0, CANStandard, 0) == 0) { error("can_filter error\n"); } @@ -65,11 +76,11 @@ int can_internal_init(can_t *obj) } #if STATIC_PINMAP_READY -#define CAN_INIT_FREQ_DIRECT can_init_freq_direct -void can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz) +#define CANFD_INIT_FREQ_DIRECT canfd_init_freq_direct +void canfd_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz) #else -#define CAN_INIT_FREQ_DIRECT _can_init_freq_direct -static void _can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz) +#define CANFD_INIT_FREQ_DIRECT _canfd_init_freq_direct +static void _canfd_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz, int data_hz) #endif { MBED_ASSERT((int)pinmap->peripheral != NC); @@ -100,6 +111,7 @@ static void _can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz /* Store frequency to be restored in case of reset */ obj->hz = hz; + obj->data_hz = data_hz; // Select PLL1Q as source of FDCAN clock RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit; @@ -135,16 +147,16 @@ static void _can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz obj->CanHandle.Instance = (FDCAN_GlobalTypeDef *)pinmap->peripheral; /* Bit time parameter - ex with 100 kHz requested frequency hz - fdcan_ker_ck | 10 MHz | 10 MHz + ex with 5.0 MHz requested frequency hz + fdcan_ker_ck | 160 MHz | 160 MHz Prescaler | 1 | 1 - Time_quantum (tq) | 100 ns | 100 ns - Bit_rate | 0.1 MBit/s | - Bit_length | 10 µs = 100 tq | = 10 000 000 / + Time_quantum (tq) | 6.25 ns | 6.25 ns + Bit_rate | 5.0 MBit/s | + Bit_length | 200 ns = 32 tq | = 160 000 000 / Synchronization_segment | 1 tq | 1 tq - Phase_segment_1 | 69 tq | = * 0.75 - Phase_segment_2 | 30 tq | = - 1 - - Synchronization_Jump_width | 30 tq | = + Phase_segment_1 | 22 tq | = * 0.7 + Phase_segment_2 | 9 tq | = - 1 - + Synchronization_Jump_width | 9 tq | = */ // !Attention Not all bitrates can be covered with all fdcan-core-clk values. When a clk @@ -165,6 +177,7 @@ static void _can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz #endif uint32_t nominalPrescaler = 1; + uint32_t dataPrescaler = 1; // !When the sample point should be lower than 50%, this must be changed to // !IS_FDCAN_NOMINAL_TSEG2(ntq/nominalPrescaler), since // NTSEG2 and SJW max values are lower. For now the sample point is fix @75% @@ -175,8 +188,36 @@ static void _can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz } } ntq = ntq / nominalPrescaler; + uint32_t ntq_data = ntq; - obj->CanHandle.Init.FrameFormat = FDCAN_FRAME_CLASSIC; + if(data_hz == 0) + { + obj->CanHandle.Init.FrameFormat = FDCAN_FRAME_CLASSIC; + dataPrescaler = nominalPrescaler; + } + else if(data_hz == hz) + { + obj->CanHandle.Init.FrameFormat = FDCAN_FRAME_FD_NO_BRS; + dataPrescaler = nominalPrescaler; + } + else + { + obj->CanHandle.Init.FrameFormat = FDCAN_FRAME_FD_BRS; +#if (defined TARGET_STM32H7) + ntq_data = pll1_clocks.PLL1_Q_Frequency / (uint32_t)data_hz; +#elif (defined RCC_PERIPHCLK_FDCAN1) + ntq_data = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN1) / (uint32_t)data_hz; +#else + ntq_data = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN) / (uint32_t)data_hz; +#endif + while (!IS_FDCAN_DATA_TSEG1(ntq_data / dataPrescaler)) { + dataPrescaler ++; + if (!IS_FDCAN_DATA_PRESCALER(dataPrescaler)) { + error("Could not determine good dataPrescaler. Bad clock value\n"); + } + } + ntq_data = ntq_data / dataPrescaler; + } obj->CanHandle.Init.Mode = FDCAN_MODE_NORMAL; obj->CanHandle.Init.AutoRetransmission = ENABLE; obj->CanHandle.Init.TransmitPause = DISABLE; @@ -185,13 +226,13 @@ static void _can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz obj->CanHandle.Init.NominalTimeSeg1 = ntq * 0.75; // Phase_segment_1 obj->CanHandle.Init.NominalTimeSeg2 = ntq - 1 - obj->CanHandle.Init.NominalTimeSeg1; // Phase_segment_2 obj->CanHandle.Init.NominalSyncJumpWidth = obj->CanHandle.Init.NominalTimeSeg2; // Synchronization_Jump_width - obj->CanHandle.Init.DataPrescaler = 0x1; // Not used - only in FDCAN - obj->CanHandle.Init.DataSyncJumpWidth = 0x1; // Not used - only in FDCAN - obj->CanHandle.Init.DataTimeSeg1 = 0x1; // Not used - only in FDCAN - obj->CanHandle.Init.DataTimeSeg2 = 0x1; // Not used - only in FDCAN + obj->CanHandle.Init.DataPrescaler = dataPrescaler; + obj->CanHandle.Init.DataTimeSeg1 = ntq_data * 0.7; + obj->CanHandle.Init.DataTimeSeg2 = ntq_data - 1 - obj->CanHandle.Init.DataTimeSeg1; + obj->CanHandle.Init.DataSyncJumpWidth = obj->CanHandle.Init.DataTimeSeg2; #ifdef TARGET_STM32H7 - /* Message RAM offset is only supported in STM32H7 platforms of supported FDCAN platforms - * Total RAM size is 2560 words, each FDCAN object allocates approx 300 words, so offset each by + /* Message RAM offset is only supported in STM32H7 platforms of supported FDCAN platforms + * Total RAM size is 2560 words, each FDCAN object allocates approx 300 words, so offset each by * 512 to make sure RAM sections don't overlap if using multiple FDCAN instances on one chip */ obj->CanHandle.Init.MessageRAMOffset = obj->index * 512; @@ -202,37 +243,67 @@ static void _can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz obj->CanHandle.Init.StdFiltersNbr = 128; // to be aligned with the handle parameter in can_filter obj->CanHandle.Init.ExtFiltersNbr = 64; // to be aligned with the handle parameter in can_filter #else - /* The number of Standard and Extended ID filters are initialized to the maximum possile extent + /* The number of Standard and Extended ID filters are initialized to the maximum possile extent * for STM32G0x1, STM32G4 and STM32L5 platforms */ obj->CanHandle.Init.StdFiltersNbr = 28; // to be aligned with the handle parameter in can_filter obj->CanHandle.Init.ExtFiltersNbr = 8; // to be aligned with the handle parameter in can_filter #endif #ifdef TARGET_STM32H7 - obj->CanHandle.Init.RxFifo0ElmtsNbr = 8; - obj->CanHandle.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8; - obj->CanHandle.Init.RxFifo1ElmtsNbr = 0; - obj->CanHandle.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8; - obj->CanHandle.Init.RxBuffersNbr = 0; - obj->CanHandle.Init.RxBufferSize = FDCAN_DATA_BYTES_8; + if(obj->CanHandle.Init.FrameFormat == FDCAN_FRAME_CLASSIC) + { + obj->CanHandle.Init.RxFifo0ElmtsNbr = 8; + obj->CanHandle.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8; + obj->CanHandle.Init.RxFifo1ElmtsNbr = 0; + obj->CanHandle.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8; + obj->CanHandle.Init.RxBuffersNbr = 0; + obj->CanHandle.Init.RxBufferSize = FDCAN_DATA_BYTES_8; + } + else + { + obj->CanHandle.Init.RxFifo0ElmtsNbr = 8; + obj->CanHandle.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_64; + obj->CanHandle.Init.RxFifo1ElmtsNbr = 0; + obj->CanHandle.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_64; + obj->CanHandle.Init.RxBuffersNbr = 0; + obj->CanHandle.Init.RxBufferSize = FDCAN_DATA_BYTES_64; + } obj->CanHandle.Init.TxEventsNbr = 3; obj->CanHandle.Init.TxBuffersNbr = 0; obj->CanHandle.Init.TxFifoQueueElmtsNbr = 3; #endif obj->CanHandle.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; #ifdef TARGET_STM32H7 - obj->CanHandle.Init.TxElmtSize = FDCAN_DATA_BYTES_8; + if(obj->CanHandle.Init.FrameFormat == FDCAN_FRAME_CLASSIC) + { + obj->CanHandle.Init.TxElmtSize = FDCAN_DATA_BYTES_8; + } + else + { + obj->CanHandle.Init.TxElmtSize = FDCAN_DATA_BYTES_64; + } #endif can_internal_init(obj); } +#if STATIC_PINMAP_READY +#define CAN_INIT_FREQ_DIRECT can_init_freq_direct +void can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz) +#else +#define CAN_INIT_FREQ_DIRECT _can_init_freq_direct +static void _can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz) +#endif +{ + CANFD_INIT_FREQ_DIRECT(obj, pinmap, hz, 0); +} + void can_init_direct(can_t *obj, const can_pinmap_t *pinmap) { /* default frequency is 100 kHz */ CAN_INIT_FREQ_DIRECT(obj, pinmap, 100000); } -void can_init_freq(can_t *obj, PinName rd, PinName td, int hz) +void canfd_init_freq(can_t *obj, PinName rd, PinName td, int hz, int data_hz) { CANName can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD); CANName can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TD); @@ -243,7 +314,12 @@ void can_init_freq(can_t *obj, PinName rd, PinName td, int hz) const can_pinmap_t static_pinmap = {peripheral, rd, function_rd, td, function_td}; - CAN_INIT_FREQ_DIRECT(obj, &static_pinmap, hz); + CANFD_INIT_FREQ_DIRECT(obj, &static_pinmap, hz, data_hz); +} + +void can_init_freq(can_t *obj, PinName rd, PinName td, int hz) +{ + canfd_init_freq(obj, rd, td, hz, 0); } void can_init(can_t *obj, PinName rd, PinName td) @@ -261,13 +337,29 @@ void can_irq_free(can_t *obj) { CANName can = (CANName)obj->CanHandle.Instance; if (can == CAN_1) { +#if defined(TARGET_STM32G0) + if(can_irq_contexts[1] == 0) + { + HAL_NVIC_DisableIRQ(TIM16_FDCAN_IT0_IRQn); + HAL_NVIC_DisableIRQ(TIM17_FDCAN_IT1_IRQn); + } +#else HAL_NVIC_DisableIRQ(FDCAN1_IT0_IRQn); HAL_NVIC_DisableIRQ(FDCAN1_IT1_IRQn); +#endif } #if defined(FDCAN2_BASE) else if (can == CAN_2) { +#if defined(TARGET_STM32G0) + if(can_irq_contexts[0] == 0) + { + HAL_NVIC_DisableIRQ(TIM16_FDCAN_IT0_IRQn); + HAL_NVIC_DisableIRQ(TIM17_FDCAN_IT1_IRQn); + } +#else HAL_NVIC_DisableIRQ(FDCAN2_IT0_IRQn); HAL_NVIC_DisableIRQ(FDCAN2_IT1_IRQn); +#endif } #endif #if defined(FDCAN3_BASE) @@ -321,12 +413,15 @@ void can_reset(can_t *obj) } -int can_frequency(can_t *obj, int f) +int canfd_frequency(can_t *obj, int f, int data_f) { if (HAL_FDCAN_Stop(&obj->CanHandle) != HAL_OK) { error("HAL_FDCAN_Stop error\n"); } + /* Store frequency to be restored in case of reset */ + obj->hz = f; + obj->data_hz = data_f; /* See can_init_freq function for calculation details * @@ -348,6 +443,7 @@ int can_frequency(can_t *obj, int f) #endif uint32_t nominalPrescaler = 1; + uint32_t dataPrescaler = 1; // !When the sample point should be lower than 50%, this must be changed to // !IS_FDCAN_NOMINAL_TSEG2(ntq/nominalPrescaler), since // NTSEG2 and SJW max values are lower. For now the sample point is fix @75% @@ -358,15 +454,56 @@ int can_frequency(can_t *obj, int f) } } ntq = ntq / nominalPrescaler; + uint32_t ntq_data = ntq; - obj->CanHandle.Init.NominalPrescaler = nominalPrescaler; + if(data_f == 0) + { + obj->CanHandle.Init.FrameFormat = FDCAN_FRAME_CLASSIC; + dataPrescaler = nominalPrescaler; + } + else if(data_f == f) + { + obj->CanHandle.Init.FrameFormat = FDCAN_FRAME_FD_NO_BRS; + dataPrescaler = nominalPrescaler; + } + else + { + obj->CanHandle.Init.FrameFormat = FDCAN_FRAME_FD_BRS; +#if (defined TARGET_STM32H7) + ntq_data = pll1_clocks.PLL1_Q_Frequency / (uint32_t)data_f; +#elif (defined RCC_PERIPHCLK_FDCAN1) + ntq_data = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN1) / (uint32_t)data_f; +#else + ntq_data = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN) / (uint32_t)data_f; +#endif + while (!IS_FDCAN_DATA_TSEG1(ntq_data / dataPrescaler)) { + dataPrescaler ++; + if (!IS_FDCAN_DATA_PRESCALER(dataPrescaler)) { + error("Could not determine good dataPrescaler. Bad clock value\n"); + } + } + ntq_data = ntq_data / dataPrescaler; + } + obj->CanHandle.Init.Mode = FDCAN_MODE_NORMAL; + obj->CanHandle.Init.AutoRetransmission = ENABLE; + obj->CanHandle.Init.TransmitPause = DISABLE; + obj->CanHandle.Init.ProtocolException = ENABLE; + obj->CanHandle.Init.NominalPrescaler = nominalPrescaler; // Prescaler obj->CanHandle.Init.NominalTimeSeg1 = ntq * 0.75; // Phase_segment_1 obj->CanHandle.Init.NominalTimeSeg2 = ntq - 1 - obj->CanHandle.Init.NominalTimeSeg1; // Phase_segment_2 obj->CanHandle.Init.NominalSyncJumpWidth = obj->CanHandle.Init.NominalTimeSeg2; // Synchronization_Jump_width + obj->CanHandle.Init.DataPrescaler = dataPrescaler; + obj->CanHandle.Init.DataTimeSeg1 = ntq_data * 0.7; + obj->CanHandle.Init.DataTimeSeg2 = ntq_data - 1 - obj->CanHandle.Init.DataTimeSeg1; + obj->CanHandle.Init.DataSyncJumpWidth = obj->CanHandle.Init.DataTimeSeg2; return can_internal_init(obj); } +int can_frequency(can_t *obj, int f) +{ + return canfd_frequency(obj, f, 0); +} /** Filter out incoming messages * @@ -443,6 +580,75 @@ int can_write(can_t *obj, CAN_Message msg, int cc) return 1; } +int canfd_write(can_t *obj, CANFD_Message msg, int cc) +{ + FDCAN_TxHeaderTypeDef TxHeader = {0}; + + UNUSED(cc); + + // Configure Tx buffer message + TxHeader.Identifier = msg.id; + if (msg.format == CANStandard) { + TxHeader.IdType = FDCAN_STANDARD_ID; + } else { + TxHeader.IdType = FDCAN_EXTENDED_ID; + } + + TxHeader.TxFrameType = FDCAN_DATA_FRAME; + switch(msg.len) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + TxHeader.DataLength = msg.len; +#if defined(TARGET_STM32L5) || defined(TARGET_STM32G0) || defined(TARGET_STM32G4) + TxHeader.DataLength <<= 16; +#endif + break; + case 12: + TxHeader.DataLength = FDCAN_DLC_BYTES_12; + break; + case 16: + TxHeader.DataLength = FDCAN_DLC_BYTES_16; + break; + case 20: + TxHeader.DataLength = FDCAN_DLC_BYTES_20; + break; + case 24: + TxHeader.DataLength = FDCAN_DLC_BYTES_24; + break; + case 32: + TxHeader.DataLength = FDCAN_DLC_BYTES_32; + break; + case 48: + TxHeader.DataLength = FDCAN_DLC_BYTES_48; + break; + case 64: + TxHeader.DataLength = FDCAN_DLC_BYTES_64; + break; + default: + error("Invalid message length for can_write\n"); + return 0; + } + TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; + TxHeader.BitRateSwitch = obj->data_hz > obj->hz ? FDCAN_BRS_ON: FDCAN_BRS_OFF; + TxHeader.FDFormat = FDCAN_FD_CAN; + TxHeader.TxEventFifoControl = FDCAN_STORE_TX_EVENTS; + TxHeader.MessageMarker = 0; + + if (HAL_FDCAN_AddMessageToTxFifoQ(&obj->CanHandle, &TxHeader, msg.data) != HAL_OK) { + // Note for debug: you can get the error code calling HAL_FDCAN_GetError(&obj->CanHandle) + return 0; + } + + return 1; +} + int can_read(can_t *obj, CAN_Message *msg, int handle) { UNUSED(handle); // Not supported, RXFIFO0 is set default by can_filter and cannot be changed. @@ -471,6 +677,57 @@ int can_read(can_t *obj, CAN_Message *msg, int handle) return 1; } +int canfd_read(can_t *obj, CANFD_Message *msg, int handle) +{ + UNUSED(handle); // Not supported, RXFIFO0 is set default by can_filter and cannot be changed. + + if (HAL_FDCAN_GetRxFifoFillLevel(&obj->CanHandle, FDCAN_RX_FIFO0) == 0) { + return 0; // No message arrived + } + + FDCAN_RxHeaderTypeDef RxHeader = {0}; + if (HAL_FDCAN_GetRxMessage(&obj->CanHandle, FDCAN_RX_FIFO0, &RxHeader, msg->data) != HAL_OK) { + error("HAL_FDCAN_GetRxMessage error\n"); // Should not occur as previous HAL_FDCAN_GetRxFifoFillLevel call reported some data + return 0; + } + + if (RxHeader.IdType == FDCAN_STANDARD_ID) { + msg->format = CANStandard; + } else { + msg->format = CANExtended; + } + msg->id = RxHeader.Identifier; + msg->type = (RxHeader.RxFrameType == FDCAN_DATA_FRAME) ? CANData : CANRemote; + msg->len = RxHeader.DataLength; +#if defined(TARGET_STM32L5) || defined(TARGET_STM32G0) || defined(TARGET_STM32G4) + msg->len >>= 16; +#endif + switch(msg->len) { // see FDCAN_data_length_code value + case 9: + msg->len = 12; + break; + case 10: + msg->len = 16; + break; + case 11: + msg->len = 20; + break; + case 12: + msg->len = 24; + break; + case 13: + msg->len = 32; + break; + case 14: + msg->len = 48; + break; + case 15: + msg->len = 64; + break; + } + return 1; +} + unsigned char can_rderror(can_t *obj) { FDCAN_ErrorCountersTypeDef ErrorCounters; @@ -604,6 +861,22 @@ static void can_irq(CANName name, int id) } } +#if defined(TARGET_STM32G0) + +void FDCAN_IT0_IRQHandler(void) +{ + can_irq(CAN_1, 0); + can_irq(CAN_2, 1); +} + +void FDCAN_IT1_IRQHandler(void) +{ + can_irq(CAN_1, 0); + can_irq(CAN_2, 1); +} + +#else + void FDCAN1_IT0_IRQHandler(void) { can_irq(CAN_1, 0); @@ -638,6 +911,7 @@ void FDCAN3_IT1_IRQHandler(void) } #endif //FDCAN3_BASE +#endif // TODO Add other interrupts ? void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable) @@ -668,8 +942,8 @@ void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable) } if (enable) { - /* The TXBTIE register controls the TX complete interrupt in FDCAN - * and is only used in case of TX interrupts, Hence in case of enabling the + /* The TXBTIE register controls the TX complete interrupt in FDCAN + * and is only used in case of TX interrupts, Hence in case of enabling the * TX interrupts the bufferIndexes of TXBTIE are to be set */ #ifdef TARGET_STM32H7 // TXBTIE for STM32H7 is 2 bytes long @@ -682,6 +956,12 @@ void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable) HAL_FDCAN_DeactivateNotification(&obj->CanHandle, interrupts); } +#if defined(TARGET_STM32G0) + NVIC_SetVector(TIM16_FDCAN_IT0_IRQn, (uint32_t)&FDCAN_IT0_IRQHandler); + NVIC_EnableIRQ(TIM16_FDCAN_IT0_IRQn); + NVIC_SetVector(TIM17_FDCAN_IT1_IRQn, (uint32_t)&FDCAN_IT1_IRQHandler); + NVIC_EnableIRQ(TIM17_FDCAN_IT1_IRQn); +#else NVIC_SetVector(FDCAN1_IT0_IRQn, (uint32_t)&FDCAN1_IT0_IRQHandler); NVIC_EnableIRQ(FDCAN1_IT0_IRQn); NVIC_SetVector(FDCAN1_IT1_IRQn, (uint32_t)&FDCAN1_IT1_IRQHandler); @@ -698,6 +978,7 @@ void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable) NVIC_SetVector(FDCAN3_IT1_IRQn, (uint32_t)&FDCAN3_IT1_IRQHandler); NVIC_EnableIRQ(FDCAN3_IT1_IRQn); #endif +#endif } #else /* FDCAN1 */ diff --git a/targets/targets.json5 b/targets/targets.json5 index 4b4c7102e41..940e9ec30b9 100644 --- a/targets/targets.json5 +++ b/targets/targets.json5 @@ -2822,7 +2822,9 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "STM32G0B1xx" ], "device_has_add": [ - "ANALOGOUT" + "ANALOGOUT", + "CAN", + "CAN_FD" ] }, "NUCLEO_G0B1RE": { @@ -2902,6 +2904,7 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "SERIAL_ASYNCH", "TRNG", "CAN", + "CAN_FD", "CRC" ], "is_mcu_family_target": true @@ -3108,6 +3111,7 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "TRNG", "FLASH", "CAN", + "CAN_FD", "CRC" ], "device_has_remove": [ @@ -3251,6 +3255,7 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "device_has_add": [ "ANALOGOUT", "CAN", + "CAN_FD", "CRC", "TRNG", "FLASH", @@ -4739,6 +4744,7 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "device_has_add": [ "ANALOGOUT", "CAN", + "CAN_FD", "CRC", "FLASH", "MPU", @@ -4941,6 +4947,7 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "device_has_add": [ "ANALOGOUT", "CAN", + "CAN_FD", "CRC", "FLASH", "MPU", From eebd68dc2d40b47554ca4428e7082006f2628c54 Mon Sep 17 00:00:00 2001 From: wdx04 <25487439@qq.com> Date: Mon, 14 Jul 2025 14:46:03 +0800 Subject: [PATCH 2/6] add changes to can_api.h and can_helper.h --- drivers/include/drivers/CAN.h | 2 +- .../include/drivers/interfaces/InterfaceCAN.h | 2 +- drivers/source/CAN.cpp | 8 ++++---- hal/include/hal/can_api.h | 8 ++++++++ hal/include/hal/can_helper.h | 20 +++++++++++++++++++ 5 files changed, 34 insertions(+), 6 deletions(-) diff --git a/drivers/include/drivers/CAN.h b/drivers/include/drivers/CAN.h index c18019275a8..0222d2b1743 100644 --- a/drivers/include/drivers/CAN.h +++ b/drivers/include/drivers/CAN.h @@ -148,7 +148,7 @@ class CAN */ int read(CANMessage &msg, int handle = 0); -#ifdef DEVICE_CAN_FD +#if DEVICE_CAN_FD /** Write a CANFDMessage to the bus. * diff --git a/drivers/include/drivers/interfaces/InterfaceCAN.h b/drivers/include/drivers/interfaces/InterfaceCAN.h index 1aa7045083a..aea46e31f90 100644 --- a/drivers/include/drivers/interfaces/InterfaceCAN.h +++ b/drivers/include/drivers/interfaces/InterfaceCAN.h @@ -140,7 +140,7 @@ class CANMessage : public CAN_Message { } }; -#ifdef DEVICE_CAN_FD +#if DEVICE_CAN_FD /** CANFDMessage class * diff --git a/drivers/source/CAN.cpp b/drivers/source/CAN.cpp index 9f361e689bb..bfbbcfa6258 100644 --- a/drivers/source/CAN.cpp +++ b/drivers/source/CAN.cpp @@ -33,7 +33,7 @@ CAN::CAN(PinName rd, PinName td) : _can(), _irq() CAN::CAN(PinName rd, PinName td, int hz, int data_hz) : _can(), _irq() { // No lock needed in constructor -#ifdef DEVICE_CAN_FD +#if DEVICE_CAN_FD canfd_init_freq(&_can, rd, td, hz, data_hz); #else can_init_freq(&_can, rd, td, hz); @@ -51,7 +51,7 @@ CAN::CAN(const can_pinmap_t &pinmap) : _can(), _irq() CAN::CAN(const can_pinmap_t &pinmap, int hz, int data_hz) : _can(), _irq() { // No lock needed in constructor -#ifdef DEVICE_CAN_FD +#if DEVICE_CAN_FD canfd_init_freq_direct(&_can, &pinmap, hz, data_hz); #else can_init_freq_direct(&_can, &pinmap, hz); @@ -74,7 +74,7 @@ CAN::~CAN() int CAN::frequency(int f, int data_f) { lock(); -#ifdef DEVICE_CAN_FD +#if DEVICE_CAN_FD int ret = canfd_frequency(&_can, f, data_f); #else int ret = can_frequency(&_can, f); @@ -102,7 +102,7 @@ int CAN::read(CANMessage &msg, int handle) return ret; } -#ifdef DEVICE_CAN_FD +#if DEVICE_CAN_FD int CAN::write(CANFDMessage msg) { diff --git a/hal/include/hal/can_api.h b/hal/include/hal/can_api.h index 61d96441d75..6656405ff59 100644 --- a/hal/include/hal/can_api.h +++ b/hal/include/hal/can_api.h @@ -87,6 +87,14 @@ unsigned char can_rderror(can_t *obj); unsigned char can_tderror(can_t *obj); void can_monitor(can_t *obj, int silent); +#if DEVICE_CAN_FD +void canfd_init_freq(can_t *obj, PinName rd, PinName td, int hz, int data_hz); +void canfd_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz, int data_hz); +int canfd_frequency(can_t *obj, int hz, int data_hz); +int canfd_write(can_t *obj, CANFD_Message, int cc); +int canfd_read(can_t *obj, CANFD_Message *msg, int handle); +#endif + /** Get the pins that support CAN RD * * Return a PinMap array of pins that support CAN RD. The diff --git a/hal/include/hal/can_helper.h b/hal/include/hal/can_helper.h index c9a66981daa..0f67ce4cfe8 100644 --- a/hal/include/hal/can_helper.h +++ b/hal/include/hal/can_helper.h @@ -67,6 +67,26 @@ struct CAN_Message { }; typedef struct CAN_Message CAN_Message; +#if DEVICE_CAN_FD + +/** + * + * \struct CAN_Message + * + * \brief Holder for single CAN message. + * +**/ +struct CANFD_Message { + unsigned int id; // 29 bit identifier + unsigned char data[64]; // Data field + unsigned char len; // Length of data field in bytes + CANFormat format; // Format ::CANFormat + CANType type; // Type ::CANType +}; +typedef struct CANFD_Message CANFD_Message; + +#endif + #ifdef __cplusplus } #endif From 8b8e0b7ca3926d4131d6fccecf9462410d8551ca Mon Sep 17 00:00:00 2001 From: wdx04 <25487439@qq.com> Date: Thu, 17 Jul 2025 10:50:50 +0800 Subject: [PATCH 3/6] fix wrong received message length for L5,G0,G4 serieses enable MSIPLL auto calibration for L5,U5 serieses adjusted PLL1Q clock for H5, H7 series to enable CAN FD a data rate of 5 MBit/s --- .../TARGET_STM32H5/clock_cfg/system_clock.c | 9 ++- .../TARGET_STM32H7_280MHZ/system_clock.c | 14 ++-- .../TARGET_STM32H7_480MHZ/system_clock.c | 16 ++-- .../TARGET_STM32H7_550MHZ/system_clock.c | 14 ++-- .../TARGET_STM/TARGET_STM32L5/system_clock.c | 5 +- .../TARGET_STM32U545xE/system_clock.c | 1 + .../TARGET_STM32U575xG/system_clock.c | 12 ++- .../TARGET_STM32U575xI/system_clock.c | 73 ++++++++++++++++++- .../TARGET_STM32U585xI/system_clock.c | 6 ++ .../TARGET_STM32U5A5xJ/system_clock.c | 1 + targets/TARGET_STM/can_api.c | 8 +- 11 files changed, 124 insertions(+), 35 deletions(-) diff --git a/targets/TARGET_STM/TARGET_STM32H5/clock_cfg/system_clock.c b/targets/TARGET_STM/TARGET_STM32H5/clock_cfg/system_clock.c index 6cae8fa5b4c..39d664ce182 100644 --- a/targets/TARGET_STM/TARGET_STM32H5/clock_cfg/system_clock.c +++ b/targets/TARGET_STM/TARGET_STM32H5/clock_cfg/system_clock.c @@ -125,8 +125,9 @@ else // Divisible by 5MHz RCC_OscInitStruct.PLL.PLLP = 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 + // its clock resolution. So, give it a lower input clock. + // Note PLL1Q is also used by the CAN FD, 100MHz is needed to support a data rate of 5Mbit/s. + RCC_OscInitStruct.PLL.PLLQ = 5; // output freq = 100MHz RCC_OscInitStruct.PLL.PLLR = 2; RCC_OscInitStruct.PLL.PLLFRACN = 0; RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1_VCORANGE_WIDE; @@ -194,8 +195,8 @@ uint8_t SetSysClock_PLL_HSI(void) RCC_OscInitStruct.PLL.PLLP = 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 + // its clock resolution. So, give it a lower input clock. + RCC_OscInitStruct.PLL.PLLQ = 5; // output freq = 100MHz RCC_OscInitStruct.PLL.PLLR = 2; RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1_VCIRANGE_3; RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1_VCORANGE_WIDE; diff --git a/targets/TARGET_STM/TARGET_STM32H7/clock_cfg/TARGET_STM32H7_280MHZ/system_clock.c b/targets/TARGET_STM/TARGET_STM32H7/clock_cfg/TARGET_STM32H7_280MHZ/system_clock.c index d603fd207dd..5617fce62ec 100644 --- a/targets/TARGET_STM/TARGET_STM32H7/clock_cfg/TARGET_STM32H7_280MHZ/system_clock.c +++ b/targets/TARGET_STM/TARGET_STM32H7/clock_cfg/TARGET_STM32H7_280MHZ/system_clock.c @@ -27,12 +27,12 @@ * It is used for all STM32H7 family microcontrollers with a top speed of 280MHz. * The input clock from the external oscillator may be any frequency evenly divisible by * 5MHz or 2MHz, and must be between 4MHz and 50MHz. - * + * * Note that 280MHz is the "overdrive" mode and is basically an overclock. It is only supported * under certain conditions (LDO in use) and cannot be used over the full temperature range. * For industrial applications it is recommended to disable overdrive. Overdrive can be enabled/ * disabled via the "target.enable-overdrive-mode" option in mbed_app.json. - * + * **/ #include "stm32h7xx.h" @@ -160,9 +160,9 @@ MBED_WEAK uint8_t SetSysClock_PLL_HSE(uint8_t bypass) RCC_OscInitStruct.PLL.PLLP = 2; // PLLCLK = SYSCLK = 280/225 MHz #if MBED_CONF_TARGET_ENABLE_OVERDRIVE_MODE - RCC_OscInitStruct.PLL.PLLQ = 56; // PLL1Q used for FDCAN = 10 MHz + RCC_OscInitStruct.PLL.PLLQ = 7; // PLL1Q used for FDCAN = 80 MHz #else - RCC_OscInitStruct.PLL.PLLQ = 45; // PLL1Q used for FDCAN = 10 MHz + RCC_OscInitStruct.PLL.PLLQ = 5; // PLL1Q used for FDCAN = 90 MHz #endif RCC_OscInitStruct.PLL.PLLR = 2; @@ -234,11 +234,11 @@ uint8_t SetSysClock_PLL_HSI(void) RCC_OscInitStruct.PLL.PLLP = 2; // PLLCLK = SYSCLK = 280/225 MHz #if MBED_CONF_TARGET_ENABLE_OVERDRIVE_MODE - RCC_OscInitStruct.PLL.PLLQ = 56; // PLL1Q used for FDCAN = 10 MHz + RCC_OscInitStruct.PLL.PLLQ = 7; // PLL1Q used for FDCAN = 80 MHz #else - RCC_OscInitStruct.PLL.PLLQ = 45; // PLL1Q used for FDCAN = 10 MHz + RCC_OscInitStruct.PLL.PLLQ = 5; // PLL1Q used for FDCAN = 90 MHz #endif - + RCC_OscInitStruct.PLL.PLLR = 2; RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE; // PLL1 VCO clock is between 128 and 560 MHz RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_1; // PLL1 input clock is between 2 and 4 MHz diff --git a/targets/TARGET_STM/TARGET_STM32H7/clock_cfg/TARGET_STM32H7_480MHZ/system_clock.c b/targets/TARGET_STM/TARGET_STM32H7/clock_cfg/TARGET_STM32H7_480MHZ/system_clock.c index 9ada72d1f31..cf4562441a2 100644 --- a/targets/TARGET_STM/TARGET_STM32H7/clock_cfg/TARGET_STM32H7_480MHZ/system_clock.c +++ b/targets/TARGET_STM/TARGET_STM32H7/clock_cfg/TARGET_STM32H7_480MHZ/system_clock.c @@ -32,12 +32,12 @@ * It is used for all STM32H7 family microcontrollers with a top speed of 480MHz. * The input clock from the external oscillator may be any frequency evenly divisible by * 5MHz or 2MHz, and must be between 4MHz and 50MHz. - * + * * Note that 480MHz is the "overdrive" mode and is basically an overclock. It is only supported * under certain conditions (LDO in use) and cannot be used over the full temperature range. * For industrial applications it is recommended to disable overdrive. Overdrive can be enabled/ * disabled via the "target.enable-overdrive-mode" option in mbed_app.json. - * + * **/ #include "stm32h7xx.h" @@ -171,9 +171,9 @@ MBED_WEAK uint8_t SetSysClock_PLL_HSE(uint8_t bypass) RCC_OscInitStruct.PLL.PLLP = 2; // PLLCLK = SYSCLK = 480/400 MHz #if MBED_CONF_TARGET_ENABLE_OVERDRIVE_MODE - RCC_OscInitStruct.PLL.PLLQ = 96; // PLL1Q used for FDCAN = 10 MHz + RCC_OscInitStruct.PLL.PLLQ = 12; // PLL1Q used for FDCAN = 80 MHz #else - RCC_OscInitStruct.PLL.PLLQ = 80; // PLL1Q used for FDCAN = 10 MHz + RCC_OscInitStruct.PLL.PLLQ = 10; // PLL1Q used for FDCAN = 80 MHz #endif RCC_OscInitStruct.PLL.PLLR = 2; @@ -251,11 +251,11 @@ uint8_t SetSysClock_PLL_HSI(void) #endif RCC_OscInitStruct.PLL.PLLP = 2; // 480/400 MHz - + #if MBED_CONF_TARGET_ENABLE_OVERDRIVE_MODE - RCC_OscInitStruct.PLL.PLLQ = 96; // PLL1Q used for FDCAN = 10 MHz + RCC_OscInitStruct.PLL.PLLQ = 12; // PLL1Q used for FDCAN = 80 MHz #else - RCC_OscInitStruct.PLL.PLLQ = 80; // PLL1Q used for FDCAN = 10 MHz + RCC_OscInitStruct.PLL.PLLQ = 10; // PLL1Q used for FDCAN = 80 MHz #endif RCC_OscInitStruct.PLL.PLLR = 2; @@ -278,7 +278,7 @@ uint8_t SetSysClock_PLL_HSI(void) if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY) != HAL_OK) { return 0; // FAIL } - + return 1; // OK } #endif /* ((CLOCK_SOURCE) & USE_PLL_HSI) */ diff --git a/targets/TARGET_STM/TARGET_STM32H7/clock_cfg/TARGET_STM32H7_550MHZ/system_clock.c b/targets/TARGET_STM/TARGET_STM32H7/clock_cfg/TARGET_STM32H7_550MHZ/system_clock.c index e28c90c3ce7..86d1121209d 100644 --- a/targets/TARGET_STM/TARGET_STM32H7/clock_cfg/TARGET_STM32H7_550MHZ/system_clock.c +++ b/targets/TARGET_STM/TARGET_STM32H7/clock_cfg/TARGET_STM32H7_550MHZ/system_clock.c @@ -32,12 +32,12 @@ * It is used for all STM32H7 family microcontrollers with a top speed of 550MHz. * The input clock from the external oscillator may be any frequency evenly divisible by * 5MHz or 2MHz, and must be between 4MHz and 50MHz. - * + * * Note that 550MHz is the "overdrive" mode and is basically an overclock. It is only supported * under certain conditions (LDO in use) and cannot be used over the full temperature range. * For industrial applications it is recommended to disable overdrive. Overdrive can be enabled/ * disabled via the "target.enable-overdrive-mode" option in mbed_app.json. - * + * **/ #include "stm32h7xx.h" @@ -167,10 +167,10 @@ MBED_WEAK uint8_t SetSysClock_PLL_HSE(uint8_t bypass) #if MBED_CONF_TARGET_ENABLE_OVERDRIVE_MODE RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE; // PLL1 VCO clock is between 192 and 836 MHz - RCC_OscInitStruct.PLL.PLLQ = 55; // PLL1Q used for FDCAN = 10 MHz + RCC_OscInitStruct.PLL.PLLQ = 5; // PLL1Q used for FDCAN = 110 MHz #else RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOMEDIUM; // PLL1 VCO clock is between 150 and 420 MHz - RCC_OscInitStruct.PLL.PLLQ = 40; // PLL1Q used for FDCAN = 10 MHz + RCC_OscInitStruct.PLL.PLLQ = 5; // PLL1Q used for FDCAN = 80 MHz #endif if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { @@ -244,15 +244,15 @@ uint8_t SetSysClock_PLL_HSI(void) #if MBED_CONF_TARGET_ENABLE_OVERDRIVE_MODE RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE; // PLL1 VCO clock is between 192 and 836 MHz - RCC_OscInitStruct.PLL.PLLQ = 55; // PLL1Q used for FDCAN = 10 MHz + RCC_OscInitStruct.PLL.PLLQ = 5; // PLL1Q used for FDCAN = 110 MHz #else RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOMEDIUM; // PLL1 VCO clock is between 150 and 420 MHz - RCC_OscInitStruct.PLL.PLLQ = 40; // PLL1Q used for FDCAN = 10 MHz + RCC_OscInitStruct.PLL.PLLQ = 5; // PLL1Q used for FDCAN = 80 MHz #endif RCC_OscInitStruct.PLL.PLLR = 2; // 275 MHz RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_1; // PLL1 input clock is between 2 and 4 MHz - + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { return 0; // FAIL } diff --git a/targets/TARGET_STM/TARGET_STM32L5/system_clock.c b/targets/TARGET_STM/TARGET_STM32L5/system_clock.c index 49252f4f5a5..df7aa35cb8d 100644 --- a/targets/TARGET_STM/TARGET_STM32L5/system_clock.c +++ b/targets/TARGET_STM/TARGET_STM32L5/system_clock.c @@ -121,7 +121,7 @@ uint8_t SetSysClock_PLL_MSI(void) { RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_OscInitTypeDef RCC_OscInitStruct = {0}; - + /* Configure LSE Drive Capability */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_RCC_SYSCFG_CLK_ENABLE(); @@ -192,6 +192,9 @@ uint8_t SetSysClock_PLL_MSI(void) } #endif + /* Enable MSI Auto calibration */ + HAL_RCCEx_EnableMSIPLLMode(); + return 1; // OK } #endif /* ((CLOCK_SOURCE) & USE_PLL_MSI) */ diff --git a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U545xE/system_clock.c b/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U545xE/system_clock.c index 06faff9af28..b90b5f780f3 100644 --- a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U545xE/system_clock.c +++ b/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U545xE/system_clock.c @@ -218,6 +218,7 @@ MBED_WEAK uint8_t SetSysClock_PLL_MSI(void) */ HAL_RCCEx_EnableMSIPLLModeSelection(RCC_MSIKPLL_MODE_SEL); HAL_RCCEx_EnableMSIPLLMode(); + HAL_RCCEx_EnableMSIPLLFastStartup(); return 1; // OK } diff --git a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U575xG/system_clock.c b/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U575xG/system_clock.c index 76b327bff81..63e49d13e1c 100644 --- a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U575xG/system_clock.c +++ b/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U575xG/system_clock.c @@ -98,7 +98,7 @@ MBED_WEAK void SetSysClock(void) // Output clock on MCO pin(PA8) for debugging purpose #if DEBUG_MCO == 1 - HAL_RCC_MCOConfig(RCC_MCO, RCC_MCOSOURCE_SYSCLK, RCC_MCO_NODIV); // 160 MHz + HAL_RCC_MCOConfig(RCC_MCO, RCC_MCOSOURCE_SYSCLK, RCC_MCO_NODIV); // 160 MHz #endif // Output clock on LSCO pin(PA2) for debugging purpose @@ -121,7 +121,7 @@ MBED_WEAK uint8_t SetSysClock_PLL_HSE(uint8_t bypass) #if DEVICE_USBDEVICE RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit = {0}; #endif /* DEVICE_USBDEVICE */ - + /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); @@ -176,7 +176,7 @@ MBED_WEAK uint8_t SetSysClock_PLL_HSE(uint8_t bypass) RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; // 160 MHz RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // 160 MHz RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1; // 160 MHz - + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) { return 0; // FAIL } @@ -274,6 +274,12 @@ MBED_WEAK uint8_t SetSysClock_PLL_MSI(void) return 0; // FAIL } + /** Enable MSI Auto calibration + */ + HAL_RCCEx_EnableMSIPLLModeSelection(RCC_MSIKPLL_MODE_SEL); + HAL_RCCEx_EnableMSIPLLMode(); + HAL_RCCEx_EnableMSIPLLFastStartup(); + return 1; // OK } #endif /* ((CLOCK_SOURCE) & USE_PLL_MSI) */ diff --git a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U575xI/system_clock.c b/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U575xI/system_clock.c index 29568a85ad3..3ac8182d985 100644 --- a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U575xI/system_clock.c +++ b/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U575xI/system_clock.c @@ -98,7 +98,73 @@ MBED_WEAK void SetSysClock(void) /******************************************************************************/ MBED_WEAK uint8_t SetSysClock_PLL_HSE(uint8_t bypass) { - return 0; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + +#if DEVICE_USBDEVICE + RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit = {0}; +#endif /* DEVICE_USBDEVICE */ + + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOH_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_PWR_CLK_ENABLE(); + if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK) { + return 0; // FAIL + } + + // Enable HSE oscillator and activate PLL with HSE as source + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI48; + if (bypass == 0) { + RCC_OscInitStruct.HSEState = RCC_HSE_ON; // External xtal on OSC_IN/OSC_OUT + } else { + RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS; // External clock on OSC_IN + } +#if DEVICE_USBDEVICE + RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; +#else + RCC_OscInitStruct.HSI48State = RCC_HSI48_OFF; +#endif /* DEVICE_USBDEVICE */ +#if HSE_VALUE==10000000UL + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLMBOOST = RCC_PLLMBOOST_DIV1; + RCC_OscInitStruct.PLL.PLLM = 1; // VCO input clock = 10 MHz (10 MHz / 1) +#else +#error Unsupported external clock value, check HSE_VALUE define +#endif + RCC_OscInitStruct.PLL.PLLN = 16; // VCO output clock = 160 MHz (10 MHz * 16) + RCC_OscInitStruct.PLL.PLLP = 2; + RCC_OscInitStruct.PLL.PLLQ = 2; + RCC_OscInitStruct.PLL.PLLR = 1; // PLL clock = 160 MHz + RCC_OscInitStruct.PLL.PLLRGE = RCC_PLLVCIRANGE_1; + RCC_OscInitStruct.PLL.PLLFRACN = 0; + + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { + return 0; // FAIL + } + +#if DEVICE_USBDEVICE + RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB; + PeriphClkIniRCC_PeriphClkInittStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48; /* 48 MHz */ + if (HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit) != HAL_OK) { + return 0; // FAIL + } +#endif /* DEVICE_USBDEVICE */ + + // Select PLL clock as system clock source and configure the HCLK, PCLK1 and PCLK2 clock dividers + RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2 | RCC_CLOCKTYPE_PCLK3); + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 160 MHz + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // 160 MHz + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; // 160 MHz + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // 160 MHz + RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1; // 160 MHz + + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) { + return 0; // FAIL + } + return 1; // OK + } #endif /* ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) || ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) */ @@ -167,6 +233,11 @@ MBED_WEAK uint8_t SetSysClock_PLL_MSI(void) return 0; // FAIL } + /** Enable MSI Auto calibration + */ + HAL_RCCEx_EnableMSIPLLModeSelection(RCC_MSIKPLL_MODE_SEL); + HAL_RCCEx_EnableMSIPLLMode(); + HAL_RCCEx_EnableMSIPLLFastStartup(); return 1; // OK } diff --git a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U585xI/system_clock.c b/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U585xI/system_clock.c index 3504c0152d4..ad6b93dba86 100644 --- a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U585xI/system_clock.c +++ b/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U585xI/system_clock.c @@ -167,6 +167,12 @@ MBED_WEAK uint8_t SetSysClock_PLL_MSI(void) return 0; // FAIL } + /** Enable MSI Auto calibration + */ + HAL_RCCEx_EnableMSIPLLModeSelection(RCC_MSIKPLL_MODE_SEL); + HAL_RCCEx_EnableMSIPLLMode(); + HAL_RCCEx_EnableMSIPLLFastStartup(); + return 1; // OK } #endif /* ((CLOCK_SOURCE) & USE_PLL_MSI) */ diff --git a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U5A5xJ/system_clock.c b/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U5A5xJ/system_clock.c index 6e623e371a2..a806e005007 100644 --- a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U5A5xJ/system_clock.c +++ b/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U5A5xJ/system_clock.c @@ -219,6 +219,7 @@ MBED_WEAK uint8_t SetSysClock_PLL_MSI(void) */ HAL_RCCEx_EnableMSIPLLModeSelection(RCC_MSIKPLL_MODE_SEL); HAL_RCCEx_EnableMSIPLLMode(); + HAL_RCCEx_EnableMSIPLLFastStartup(); return 1; // OK } diff --git a/targets/TARGET_STM/can_api.c b/targets/TARGET_STM/can_api.c index dd82c86a8f4..961cf5f5454 100644 --- a/targets/TARGET_STM/can_api.c +++ b/targets/TARGET_STM/can_api.c @@ -670,10 +670,10 @@ int can_read(can_t *obj, CAN_Message *msg, int handle) } msg->id = RxHeader.Identifier; msg->type = (RxHeader.RxFrameType == FDCAN_DATA_FRAME) ? CANData : CANRemote; - msg->len = RxHeader.DataLength; #if defined(TARGET_STM32L5) || defined(TARGET_STM32G0) || defined(TARGET_STM32G4) - msg->len >>= 16; + RxHeader.DataLength >>= 16; #endif + msg->len = RxHeader.DataLength; return 1; } @@ -698,10 +698,10 @@ int canfd_read(can_t *obj, CANFD_Message *msg, int handle) } msg->id = RxHeader.Identifier; msg->type = (RxHeader.RxFrameType == FDCAN_DATA_FRAME) ? CANData : CANRemote; - msg->len = RxHeader.DataLength; #if defined(TARGET_STM32L5) || defined(TARGET_STM32G0) || defined(TARGET_STM32G4) - msg->len >>= 16; + RxHeader.DataLength >>= 16; #endif + msg->len = RxHeader.DataLength; switch(msg->len) { // see FDCAN_data_length_code value case 9: msg->len = 12; From 8e636185a6760436c6948d40e6cc1b2a182a3270 Mon Sep 17 00:00:00 2001 From: wdx04 <25487439@qq.com> Date: Mon, 21 Jul 2025 07:52:16 +0800 Subject: [PATCH 4/6] unify system_clock.c for STM32U5 --- .../TARGET_STM/TARGET_STM32U5/CMakeLists.txt | 1 + .../TARGET_STM32U545xE/CMakeLists.txt | 1 - .../TARGET_STM32U545xE/system_clock.c | 225 ---------------- .../TARGET_STM32U575xG/CMakeLists.txt | 1 - .../TARGET_STM32U575xI/CMakeLists.txt | 1 - .../TARGET_STM32U575xI/system_clock.c | 244 ------------------ .../TARGET_STM32U585xI/CMakeLists.txt | 1 - .../TARGET_STM32U585xI/system_clock.c | 178 ------------- .../TARGET_STM32U5A5xJ/CMakeLists.txt | 1 - .../TARGET_STM32U5A5xJ/system_clock.c | 226 ---------------- .../system_clock.c | 109 +++++--- 11 files changed, 74 insertions(+), 914 deletions(-) delete mode 100644 targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U545xE/system_clock.c delete mode 100644 targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U575xI/system_clock.c delete mode 100644 targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U585xI/system_clock.c delete mode 100644 targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U5A5xJ/system_clock.c rename targets/TARGET_STM/TARGET_STM32U5/{TARGET_STM32U575xG => clock_cfg}/system_clock.c (77%) diff --git a/targets/TARGET_STM/TARGET_STM32U5/CMakeLists.txt b/targets/TARGET_STM/TARGET_STM32U5/CMakeLists.txt index 9b2a390f6ae..df26c6bf293 100644 --- a/targets/TARGET_STM/TARGET_STM32U5/CMakeLists.txt +++ b/targets/TARGET_STM/TARGET_STM32U5/CMakeLists.txt @@ -18,6 +18,7 @@ target_include_directories(mbed-stm32u5 target_sources(mbed-stm32u5 INTERFACE + clock_cfg/system_clock.c analogin_device.c analogout_device.c flash_api.c diff --git a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U545xE/CMakeLists.txt b/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U545xE/CMakeLists.txt index 9a8e8702b9b..279da555067 100644 --- a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U545xE/CMakeLists.txt +++ b/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U545xE/CMakeLists.txt @@ -21,7 +21,6 @@ target_include_directories(mbed-stm32u545xe target_sources(mbed-stm32u545xe INTERFACE ${STARTUP_FILE} - system_clock.c ) mbed_set_linker_script(mbed-stm32u545xe ${CMAKE_CURRENT_SOURCE_DIR}/${LINKER_FILE}) diff --git a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U545xE/system_clock.c b/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U545xE/system_clock.c deleted file mode 100644 index b90b5f780f3..00000000000 --- a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U545xE/system_clock.c +++ /dev/null @@ -1,225 +0,0 @@ -/* mbed Microcontroller Library - * SPDX-License-Identifier: BSD-3-Clause - ****************************************************************************** - * - * Copyright (c) 2015-2021 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 - * - ****************************************************************************** - */ - -/** - * This file configures the system clock depending on config from targets.json: - *----------------------------------------------------------------------------- - * System clock source | 1- USE_PLL_HSE_EXTC (external clock) - * | 2- USE_PLL_HSE_XTAL (external xtal) - * | 3- USE_PLL_HSI (internal 16 MHz) - * | 4- USE_PLL_MSI (internal 100kHz to 48 MHz) - *----------------------------------------------------------------------------- - * SYSCLK(MHz) | 160 - * AHBCLK (MHz) | 160 - * APB1CLK (MHz) | 160 - * APB2CLK (MHz) | 160 - * APB3CLK (MHz) | 160 - * USB capable | TODO - *----------------------------------------------------------------------------- -**/ - -#include "stm32u5xx.h" -#include "mbed_error.h" - -// clock source is selected with CLOCK_SOURCE in json config -#define USE_PLL_HSE_EXTC 0x8 // Use external clock (OSC_IN) -#define USE_PLL_HSE_XTAL 0x4 // Use external xtal (OSC_IN/OSC_OUT) -#define USE_PLL_HSI 0x2 // Use HSI internal clock -#define USE_PLL_MSI 0x1 // Use MSI internal clock - -#if ( ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) || ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) ) -uint8_t SetSysClock_PLL_HSE(uint8_t bypass); -#endif /* ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) || ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) */ - -#if ((CLOCK_SOURCE) & USE_PLL_HSI) -uint8_t SetSysClock_PLL_HSI(void); -#endif /* ((CLOCK_SOURCE) & USE_PLL_HSI) */ - -#if ((CLOCK_SOURCE) & USE_PLL_MSI) -uint8_t SetSysClock_PLL_MSI(void); -#endif /* ((CLOCK_SOURCE) & USE_PLL_MSI) */ - - -/** - * @brief Configures the System clock source, PLL Multiplier and Divider factors, - * AHB/APBx prescalers and Flash settings - * @note This function is called in mbed_sdk_init() function (targets/TARGET_STM/mbed_overrides.c) - * and after each deepsleep period in hal_deepsleep() (targets/TARGET_STM/sleep.c) - * @param None - * @retval None - */ - -MBED_WEAK void SetSysClock(void) -{ -#if ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) - /* 1- Try to start with HSE and external clock */ - if (SetSysClock_PLL_HSE(1) == 0) -#endif - { -#if ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) - /* 2- If fail try to start with HSE and external xtal */ - if (SetSysClock_PLL_HSE(0) == 0) -#endif - { -#if ((CLOCK_SOURCE) & USE_PLL_HSI) - /* 3- If fail start with HSI clock */ - if (SetSysClock_PLL_HSI() == 0) -#endif - { -#if ((CLOCK_SOURCE) & USE_PLL_MSI) - /* 4- If fail start with MSI clock */ - if (SetSysClock_PLL_MSI() == 0) -#endif - { - { - error("SetSysClock failed\n"); - } - } - } - } - } -} - -#if ( ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) || ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) ) -/******************************************************************************/ -/* PLL (clocked by HSE) used as System clock source */ -/******************************************************************************/ -MBED_WEAK uint8_t SetSysClock_PLL_HSE(uint8_t bypass) -{ - return 0; -} -#endif /* ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) || ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) */ - -#if ((CLOCK_SOURCE) & USE_PLL_HSI) -/******************************************************************************/ -/* PLL (clocked by HSI) used as System clock source */ -/******************************************************************************/ -uint8_t SetSysClock_PLL_HSI(void) -{ - RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; - RCC_OscInitTypeDef RCC_OscInitStruct = {0}; - RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; - - __HAL_RCC_PWR_CLK_ENABLE(); - HAL_PWREx_EnableVddA(); - HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); - - RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48 | RCC_OSCILLATORTYPE_HSI - | RCC_OSCILLATORTYPE_MSI; - RCC_OscInitStruct.HSIState = RCC_HSI_ON; - RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; - RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; - RCC_OscInitStruct.MSIState = RCC_MSI_ON; - RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT; - RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_0; - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; - RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; - RCC_OscInitStruct.PLL.PLLMBOOST = RCC_PLLMBOOST_DIV1; - RCC_OscInitStruct.PLL.PLLM = 1; - RCC_OscInitStruct.PLL.PLLN = 10; - RCC_OscInitStruct.PLL.PLLP = 2; - RCC_OscInitStruct.PLL.PLLQ = 2; - RCC_OscInitStruct.PLL.PLLR = 1; - RCC_OscInitStruct.PLL.PLLRGE = RCC_PLLVCIRANGE_1; - RCC_OscInitStruct.PLL.PLLFRACN = 0; - if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { - return 0; // FAIL - } - - RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK - | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2 - | RCC_CLOCKTYPE_PCLK3; - RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; - RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; - RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; - RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; - RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1; - if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) { - return 0; // FAIL - } - - PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RNG; - PeriphClkInit.RngClockSelection = RCC_RNGCLKSOURCE_HSI48; - if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { - return 0; // FAIL - } - - return 1; // OK -} -#endif /* ((CLOCK_SOURCE) & USE_PLL_HSI) */ - -#if ((CLOCK_SOURCE) & USE_PLL_MSI) -/******************************************************************************/ -/* PLL (clocked by MSI) used as System clock source */ -/******************************************************************************/ -MBED_WEAK uint8_t SetSysClock_PLL_MSI(void) -{ - RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; - RCC_OscInitTypeDef RCC_OscInitStruct = {0}; - RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; - - __HAL_RCC_PWR_CLK_ENABLE(); - HAL_PWREx_EnableVddA(); - HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); - - RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48 | RCC_OSCILLATORTYPE_HSI - | RCC_OSCILLATORTYPE_MSI; - RCC_OscInitStruct.HSIState = RCC_HSI_ON; - RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; - RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; - RCC_OscInitStruct.MSIState = RCC_MSI_ON; - RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT; - RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_0; - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; - RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI; - RCC_OscInitStruct.PLL.PLLMBOOST = RCC_PLLMBOOST_DIV4; - RCC_OscInitStruct.PLL.PLLM = 3; - RCC_OscInitStruct.PLL.PLLN = 10; - RCC_OscInitStruct.PLL.PLLP = 2; - RCC_OscInitStruct.PLL.PLLQ = 2; - RCC_OscInitStruct.PLL.PLLR = 1; - RCC_OscInitStruct.PLL.PLLRGE = RCC_PLLVCIRANGE_1; - RCC_OscInitStruct.PLL.PLLFRACN = 0; - if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { - return 0; // FAIL - } - - RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK - | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2 - | RCC_CLOCKTYPE_PCLK3; - RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; - RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; - RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; - RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; - RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1; - if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) { - return 0; // FAIL - } - - PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RNG; - PeriphClkInit.RngClockSelection = RCC_RNGCLKSOURCE_HSI48; - if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { - return 0; // FAIL - } - - /** Enable MSI Auto calibration - */ - HAL_RCCEx_EnableMSIPLLModeSelection(RCC_MSIKPLL_MODE_SEL); - HAL_RCCEx_EnableMSIPLLMode(); - HAL_RCCEx_EnableMSIPLLFastStartup(); - - return 1; // OK -} -#endif /* ((CLOCK_SOURCE) & USE_PLL_MSI) */ diff --git a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U575xG/CMakeLists.txt b/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U575xG/CMakeLists.txt index f7d6cd17821..6e6f2dfa2fd 100644 --- a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U575xG/CMakeLists.txt +++ b/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U575xG/CMakeLists.txt @@ -19,7 +19,6 @@ target_include_directories(mbed-stm32u575xg target_sources(mbed-stm32u575xg INTERFACE ${STARTUP_FILE} - system_clock.c ) mbed_set_linker_script(mbed-stm32u575xg ${CMAKE_CURRENT_SOURCE_DIR}/${LINKER_FILE}) diff --git a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U575xI/CMakeLists.txt b/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U575xI/CMakeLists.txt index c15d70b0891..64cadd44847 100644 --- a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U575xI/CMakeLists.txt +++ b/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U575xI/CMakeLists.txt @@ -21,7 +21,6 @@ target_include_directories(mbed-stm32u575xi target_sources(mbed-stm32u575xi INTERFACE ${STARTUP_FILE} - system_clock.c ) mbed_set_linker_script(mbed-stm32u575xi ${CMAKE_CURRENT_SOURCE_DIR}/${LINKER_FILE}) diff --git a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U575xI/system_clock.c b/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U575xI/system_clock.c deleted file mode 100644 index 3ac8182d985..00000000000 --- a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U575xI/system_clock.c +++ /dev/null @@ -1,244 +0,0 @@ -/* mbed Microcontroller Library - * SPDX-License-Identifier: BSD-3-Clause - ****************************************************************************** - * - * Copyright (c) 2015-2021 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 - * - ****************************************************************************** - */ - -/** - * This file configures the system clock depending on config from targets.json: - *----------------------------------------------------------------------------- - * System clock source | 1- USE_PLL_HSE_EXTC (external clock) - * | 2- USE_PLL_HSE_XTAL (external xtal) - * | 3- USE_PLL_HSI (internal 16 MHz) - * | 4- USE_PLL_MSI (internal 100kHz to 48 MHz) - *----------------------------------------------------------------------------- - * SYSCLK(MHz) | 160 - * AHBCLK (MHz) | 160 - * APB1CLK (MHz) | 160 - * APB2CLK (MHz) | 160 - * APB3CLK (MHz) | 160 - * USB capable | TODO - *----------------------------------------------------------------------------- -**/ - -#include "stm32u5xx.h" -#include "mbed_error.h" - -// clock source is selected with CLOCK_SOURCE in json config -#define USE_PLL_HSE_EXTC 0x8 // Use external clock (OSC_IN) -#define USE_PLL_HSE_XTAL 0x4 // Use external xtal (OSC_IN/OSC_OUT) -#define USE_PLL_HSI 0x2 // Use HSI internal clock -#define USE_PLL_MSI 0x1 // Use MSI internal clock - -#if ( ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) || ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) ) -uint8_t SetSysClock_PLL_HSE(uint8_t bypass); -#endif /* ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) || ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) */ - -#if ((CLOCK_SOURCE) & USE_PLL_HSI) -uint8_t SetSysClock_PLL_HSI(void); -#endif /* ((CLOCK_SOURCE) & USE_PLL_HSI) */ - -#if ((CLOCK_SOURCE) & USE_PLL_MSI) -uint8_t SetSysClock_PLL_MSI(void); -#endif /* ((CLOCK_SOURCE) & USE_PLL_MSI) */ - - -/** - * @brief Configures the System clock source, PLL Multiplier and Divider factors, - * AHB/APBx prescalers and Flash settings - * @note This function is called in mbed_sdk_init() function (targets/TARGET_STM/mbed_overrides.c) - * and after each deepsleep period in hal_deepsleep() (targets/TARGET_STM/sleep.c) - * @param None - * @retval None - */ - -MBED_WEAK void SetSysClock(void) -{ -#if ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) - /* 1- Try to start with HSE and external clock */ - if (SetSysClock_PLL_HSE(1) == 0) -#endif - { -#if ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) - /* 2- If fail try to start with HSE and external xtal */ - if (SetSysClock_PLL_HSE(0) == 0) -#endif - { -#if ((CLOCK_SOURCE) & USE_PLL_HSI) - /* 3- If fail start with HSI clock */ - if (SetSysClock_PLL_HSI() == 0) -#endif - { -#if ((CLOCK_SOURCE) & USE_PLL_MSI) - /* 4- If fail start with MSI clock */ - if (SetSysClock_PLL_MSI() == 0) -#endif - { - { - error("SetSysClock failed\n"); - } - } - } - } - } -} - -#if ( ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) || ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) ) -/******************************************************************************/ -/* PLL (clocked by HSE) used as System clock source */ -/******************************************************************************/ -MBED_WEAK uint8_t SetSysClock_PLL_HSE(uint8_t bypass) -{ - RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; - RCC_OscInitTypeDef RCC_OscInitStruct = {0}; - -#if DEVICE_USBDEVICE - RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit = {0}; -#endif /* DEVICE_USBDEVICE */ - - /* GPIO Ports Clock Enable */ - __HAL_RCC_GPIOH_CLK_ENABLE(); - __HAL_RCC_GPIOB_CLK_ENABLE(); - __HAL_RCC_PWR_CLK_ENABLE(); - if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK) { - return 0; // FAIL - } - - // Enable HSE oscillator and activate PLL with HSE as source - RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI48; - if (bypass == 0) { - RCC_OscInitStruct.HSEState = RCC_HSE_ON; // External xtal on OSC_IN/OSC_OUT - } else { - RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS; // External clock on OSC_IN - } -#if DEVICE_USBDEVICE - RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; -#else - RCC_OscInitStruct.HSI48State = RCC_HSI48_OFF; -#endif /* DEVICE_USBDEVICE */ -#if HSE_VALUE==10000000UL - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; - RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; - RCC_OscInitStruct.PLL.PLLMBOOST = RCC_PLLMBOOST_DIV1; - RCC_OscInitStruct.PLL.PLLM = 1; // VCO input clock = 10 MHz (10 MHz / 1) -#else -#error Unsupported external clock value, check HSE_VALUE define -#endif - RCC_OscInitStruct.PLL.PLLN = 16; // VCO output clock = 160 MHz (10 MHz * 16) - RCC_OscInitStruct.PLL.PLLP = 2; - RCC_OscInitStruct.PLL.PLLQ = 2; - RCC_OscInitStruct.PLL.PLLR = 1; // PLL clock = 160 MHz - RCC_OscInitStruct.PLL.PLLRGE = RCC_PLLVCIRANGE_1; - RCC_OscInitStruct.PLL.PLLFRACN = 0; - - if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { - return 0; // FAIL - } - -#if DEVICE_USBDEVICE - RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB; - PeriphClkIniRCC_PeriphClkInittStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48; /* 48 MHz */ - if (HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit) != HAL_OK) { - return 0; // FAIL - } -#endif /* DEVICE_USBDEVICE */ - - // Select PLL clock as system clock source and configure the HCLK, PCLK1 and PCLK2 clock dividers - RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2 | RCC_CLOCKTYPE_PCLK3); - RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 160 MHz - RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // 160 MHz - RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; // 160 MHz - RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // 160 MHz - RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1; // 160 MHz - - if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) { - return 0; // FAIL - } - return 1; // OK - -} -#endif /* ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) || ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) */ - -#if ((CLOCK_SOURCE) & USE_PLL_HSI) -/******************************************************************************/ -/* PLL (clocked by HSI) used as System clock source */ -/******************************************************************************/ -uint8_t SetSysClock_PLL_HSI(void) -{ - return 0; // TODO -} -#endif /* ((CLOCK_SOURCE) & USE_PLL_HSI) */ - -#if ((CLOCK_SOURCE) & USE_PLL_MSI) -/******************************************************************************/ -/* PLL (clocked by MSI) used as System clock source */ -/******************************************************************************/ -MBED_WEAK uint8_t SetSysClock_PLL_MSI(void) -{ - RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; - RCC_OscInitTypeDef RCC_OscInitStruct = {0}; - RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; - - __HAL_RCC_PWR_CLK_ENABLE(); - HAL_PWREx_DisableUCPDDeadBattery(); /* Disable the internal Pull-Up in Dead Battery pins of UCPD peripheral */ - HAL_PWREx_EnableVddA(); - HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); - - RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48 | RCC_OSCILLATORTYPE_HSI - | RCC_OSCILLATORTYPE_MSI; - RCC_OscInitStruct.HSIState = RCC_HSI_ON; - RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; - RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; - RCC_OscInitStruct.MSIState = RCC_MSI_ON; - RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT; - RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_0; - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; - RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI; - RCC_OscInitStruct.PLL.PLLMBOOST = RCC_PLLMBOOST_DIV4; - RCC_OscInitStruct.PLL.PLLM = 3; - RCC_OscInitStruct.PLL.PLLN = 10; - RCC_OscInitStruct.PLL.PLLP = 2; - RCC_OscInitStruct.PLL.PLLQ = 2; - RCC_OscInitStruct.PLL.PLLR = 1; - RCC_OscInitStruct.PLL.PLLRGE = RCC_PLLVCIRANGE_1; - RCC_OscInitStruct.PLL.PLLFRACN = 0; - if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { - return 0; // FAIL - } - - RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK - | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2 - | RCC_CLOCKTYPE_PCLK3; - RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; - RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; - RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; - RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; - RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1; - if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) { - return 0; // FAIL - } - - PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RNG; - PeriphClkInit.RngClockSelection = RCC_RNGCLKSOURCE_HSI48; - if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { - return 0; // FAIL - } - - /** Enable MSI Auto calibration - */ - HAL_RCCEx_EnableMSIPLLModeSelection(RCC_MSIKPLL_MODE_SEL); - HAL_RCCEx_EnableMSIPLLMode(); - HAL_RCCEx_EnableMSIPLLFastStartup(); - - return 1; // OK -} -#endif /* ((CLOCK_SOURCE) & USE_PLL_MSI) */ diff --git a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U585xI/CMakeLists.txt b/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U585xI/CMakeLists.txt index 727669ca11d..c6feb70ea4f 100644 --- a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U585xI/CMakeLists.txt +++ b/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U585xI/CMakeLists.txt @@ -21,7 +21,6 @@ target_include_directories(mbed-stm32u585xi target_sources(mbed-stm32u585xi INTERFACE ${STARTUP_FILE} - system_clock.c ) mbed_set_linker_script(mbed-stm32u585xi ${CMAKE_CURRENT_SOURCE_DIR}/${LINKER_FILE}) diff --git a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U585xI/system_clock.c b/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U585xI/system_clock.c deleted file mode 100644 index ad6b93dba86..00000000000 --- a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U585xI/system_clock.c +++ /dev/null @@ -1,178 +0,0 @@ -/* mbed Microcontroller Library - * SPDX-License-Identifier: BSD-3-Clause - ****************************************************************************** - * - * Copyright (c) 2015-2021 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 - * - ****************************************************************************** - */ - -/** - * This file configures the system clock depending on config from targets.json: - *----------------------------------------------------------------------------- - * System clock source | 1- USE_PLL_HSE_EXTC (external clock) - * | 2- USE_PLL_HSE_XTAL (external xtal) - * | 3- USE_PLL_HSI (internal 16 MHz) - * | 4- USE_PLL_MSI (internal 100kHz to 48 MHz) - *----------------------------------------------------------------------------- - * SYSCLK(MHz) | 160 - * AHBCLK (MHz) | 160 - * APB1CLK (MHz) | 160 - * APB2CLK (MHz) | 160 - * APB3CLK (MHz) | 160 - * USB capable | TODO - *----------------------------------------------------------------------------- -**/ - -#include "stm32u5xx.h" -#include "mbed_error.h" - -// clock source is selected with CLOCK_SOURCE in json config -#define USE_PLL_HSE_EXTC 0x8 // Use external clock (OSC_IN) -#define USE_PLL_HSE_XTAL 0x4 // Use external xtal (OSC_IN/OSC_OUT) -#define USE_PLL_HSI 0x2 // Use HSI internal clock -#define USE_PLL_MSI 0x1 // Use MSI internal clock - -#if ( ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) || ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) ) -uint8_t SetSysClock_PLL_HSE(uint8_t bypass); -#endif /* ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) || ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) */ - -#if ((CLOCK_SOURCE) & USE_PLL_HSI) -uint8_t SetSysClock_PLL_HSI(void); -#endif /* ((CLOCK_SOURCE) & USE_PLL_HSI) */ - -#if ((CLOCK_SOURCE) & USE_PLL_MSI) -uint8_t SetSysClock_PLL_MSI(void); -#endif /* ((CLOCK_SOURCE) & USE_PLL_MSI) */ - - -/** - * @brief Configures the System clock source, PLL Multiplier and Divider factors, - * AHB/APBx prescalers and Flash settings - * @note This function is called in mbed_sdk_init() function (targets/TARGET_STM/mbed_overrides.c) - * and after each deepsleep period in hal_deepsleep() (targets/TARGET_STM/sleep.c) - * @param None - * @retval None - */ - -MBED_WEAK void SetSysClock(void) -{ -#if ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) - /* 1- Try to start with HSE and external clock */ - if (SetSysClock_PLL_HSE(1) == 0) -#endif - { -#if ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) - /* 2- If fail try to start with HSE and external xtal */ - if (SetSysClock_PLL_HSE(0) == 0) -#endif - { -#if ((CLOCK_SOURCE) & USE_PLL_HSI) - /* 3- If fail start with HSI clock */ - if (SetSysClock_PLL_HSI() == 0) -#endif - { -#if ((CLOCK_SOURCE) & USE_PLL_MSI) - /* 4- If fail start with MSI clock */ - if (SetSysClock_PLL_MSI() == 0) -#endif - { - { - error("SetSysClock failed\n"); - } - } - } - } - } -} - -#if ( ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) || ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) ) -/******************************************************************************/ -/* PLL (clocked by HSE) used as System clock source */ -/******************************************************************************/ -MBED_WEAK uint8_t SetSysClock_PLL_HSE(uint8_t bypass) -{ - return 0; -} -#endif /* ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) || ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) */ - -#if ((CLOCK_SOURCE) & USE_PLL_HSI) -/******************************************************************************/ -/* PLL (clocked by HSI) used as System clock source */ -/******************************************************************************/ -uint8_t SetSysClock_PLL_HSI(void) -{ - return 0; // TODO -} -#endif /* ((CLOCK_SOURCE) & USE_PLL_HSI) */ - -#if ((CLOCK_SOURCE) & USE_PLL_MSI) -/******************************************************************************/ -/* PLL (clocked by MSI) used as System clock source */ -/******************************************************************************/ -MBED_WEAK uint8_t SetSysClock_PLL_MSI(void) -{ - RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; - RCC_OscInitTypeDef RCC_OscInitStruct = {0}; - RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; - - __HAL_RCC_PWR_CLK_ENABLE(); - HAL_PWREx_DisableUCPDDeadBattery(); /* Disable the internal Pull-Up in Dead Battery pins of UCPD peripheral */ - HAL_PWREx_EnableVddA(); - HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); - - RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48 | RCC_OSCILLATORTYPE_HSI - | RCC_OSCILLATORTYPE_MSI; - RCC_OscInitStruct.HSIState = RCC_HSI_ON; - RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; - RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; - RCC_OscInitStruct.MSIState = RCC_MSI_ON; - RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT; - RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_0; - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; - RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI; - RCC_OscInitStruct.PLL.PLLMBOOST = RCC_PLLMBOOST_DIV4; - RCC_OscInitStruct.PLL.PLLM = 3; - RCC_OscInitStruct.PLL.PLLN = 10; - RCC_OscInitStruct.PLL.PLLP = 2; - RCC_OscInitStruct.PLL.PLLQ = 2; - RCC_OscInitStruct.PLL.PLLR = 1; - RCC_OscInitStruct.PLL.PLLRGE = RCC_PLLVCIRANGE_1; - RCC_OscInitStruct.PLL.PLLFRACN = 0; - if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { - return 0; // FAIL - } - - RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK - | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2 - | RCC_CLOCKTYPE_PCLK3; - RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; - RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; - RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; - RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; - RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1; - if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) { - return 0; // FAIL - } - - PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RNG; - PeriphClkInit.RngClockSelection = RCC_RNGCLKSOURCE_HSI48; - if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { - return 0; // FAIL - } - - /** Enable MSI Auto calibration - */ - HAL_RCCEx_EnableMSIPLLModeSelection(RCC_MSIKPLL_MODE_SEL); - HAL_RCCEx_EnableMSIPLLMode(); - HAL_RCCEx_EnableMSIPLLFastStartup(); - - return 1; // OK -} -#endif /* ((CLOCK_SOURCE) & USE_PLL_MSI) */ diff --git a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U5A5xJ/CMakeLists.txt b/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U5A5xJ/CMakeLists.txt index e9c20b7dd80..907f0e313cb 100644 --- a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U5A5xJ/CMakeLists.txt +++ b/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U5A5xJ/CMakeLists.txt @@ -21,7 +21,6 @@ target_include_directories(mbed-stm32u5a5xj target_sources(mbed-stm32u5a5xj INTERFACE ${STARTUP_FILE} - system_clock.c ) mbed_set_linker_script(mbed-stm32u5a5xj ${CMAKE_CURRENT_SOURCE_DIR}/${LINKER_FILE}) diff --git a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U5A5xJ/system_clock.c b/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U5A5xJ/system_clock.c deleted file mode 100644 index a806e005007..00000000000 --- a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U5A5xJ/system_clock.c +++ /dev/null @@ -1,226 +0,0 @@ -/* mbed Microcontroller Library - * SPDX-License-Identifier: BSD-3-Clause - ****************************************************************************** - * - * Copyright (c) 2015-2021 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 - * - ****************************************************************************** - */ - -/** - * This file configures the system clock depending on config from targets.json: - *----------------------------------------------------------------------------- - * System clock source | 1- USE_PLL_HSE_EXTC (external clock) - * | 2- USE_PLL_HSE_XTAL (external xtal) - * | 3- USE_PLL_HSI (internal 16 MHz) - * | 4- USE_PLL_MSI (internal 100kHz to 48 MHz) - *----------------------------------------------------------------------------- - * SYSCLK(MHz) | 160 - * AHBCLK (MHz) | 160 - * APB1CLK (MHz) | 160 - * APB2CLK (MHz) | 160 - * APB3CLK (MHz) | 160 - * USB capable | TODO - *----------------------------------------------------------------------------- -**/ - -#include "stm32u5xx.h" -#include "mbed_error.h" - -// clock source is selected with CLOCK_SOURCE in json config -#define USE_PLL_HSE_EXTC 0x8 // Use external clock (OSC_IN) -#define USE_PLL_HSE_XTAL 0x4 // Use external xtal (OSC_IN/OSC_OUT) -#define USE_PLL_HSI 0x2 // Use HSI internal clock -#define USE_PLL_MSI 0x1 // Use MSI internal clock - -#if ( ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) || ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) ) -uint8_t SetSysClock_PLL_HSE(uint8_t bypass); -#endif /* ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) || ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) */ - -#if ((CLOCK_SOURCE) & USE_PLL_HSI) -uint8_t SetSysClock_PLL_HSI(void); -#endif /* ((CLOCK_SOURCE) & USE_PLL_HSI) */ - -#if ((CLOCK_SOURCE) & USE_PLL_MSI) -uint8_t SetSysClock_PLL_MSI(void); -#endif /* ((CLOCK_SOURCE) & USE_PLL_MSI) */ - - -/** - * @brief Configures the System clock source, PLL Multiplier and Divider factors, - * AHB/APBx prescalers and Flash settings - * @note This function is called in mbed_sdk_init() function (targets/TARGET_STM/mbed_overrides.c) - * and after each deepsleep period in hal_deepsleep() (targets/TARGET_STM/sleep.c) - * @param None - * @retval None - */ - -MBED_WEAK void SetSysClock(void) -{ -#if ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) - /* 1- Try to start with HSE and external clock */ - if (SetSysClock_PLL_HSE(1) == 0) -#endif - { -#if ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) - /* 2- If fail try to start with HSE and external xtal */ - if (SetSysClock_PLL_HSE(0) == 0) -#endif - { -#if ((CLOCK_SOURCE) & USE_PLL_HSI) - /* 3- If fail start with HSI clock */ - if (SetSysClock_PLL_HSI() == 0) -#endif - { -#if ((CLOCK_SOURCE) & USE_PLL_MSI) - /* 4- If fail start with MSI clock */ - if (SetSysClock_PLL_MSI() == 0) -#endif - { - { - error("SetSysClock failed\n"); - } - } - } - } - } -} - -#if ( ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) || ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) ) -/******************************************************************************/ -/* PLL (clocked by HSE) used as System clock source */ -/******************************************************************************/ -MBED_WEAK uint8_t SetSysClock_PLL_HSE(uint8_t bypass) -{ - return 0; -} -#endif /* ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) || ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) */ - -#if ((CLOCK_SOURCE) & USE_PLL_HSI) -/******************************************************************************/ -/* PLL (clocked by HSI) used as System clock source */ -/******************************************************************************/ -uint8_t SetSysClock_PLL_HSI(void) -{ - RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; - RCC_OscInitTypeDef RCC_OscInitStruct = {0}; - RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; - - __HAL_RCC_PWR_CLK_ENABLE(); - HAL_PWREx_EnableVddA(); - HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); - - RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48 | RCC_OSCILLATORTYPE_HSI - | RCC_OSCILLATORTYPE_MSI; - RCC_OscInitStruct.HSIState = RCC_HSI_ON; - RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; - RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; - RCC_OscInitStruct.MSIState = RCC_MSI_ON; - RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT; - RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_0; - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; - RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; - RCC_OscInitStruct.PLL.PLLMBOOST = RCC_PLLMBOOST_DIV1; - RCC_OscInitStruct.PLL.PLLM = 1; - RCC_OscInitStruct.PLL.PLLN = 10; - RCC_OscInitStruct.PLL.PLLP = 2; - RCC_OscInitStruct.PLL.PLLQ = 2; - RCC_OscInitStruct.PLL.PLLR = 1; - RCC_OscInitStruct.PLL.PLLRGE = RCC_PLLVCIRANGE_1; - RCC_OscInitStruct.PLL.PLLFRACN = 0; - if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { - return 0; // FAIL - } - - RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK - | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2 - | RCC_CLOCKTYPE_PCLK3; - RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; - RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; - RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; - RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; - RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1; - if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) { - return 0; // FAIL - } - - PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RNG; - PeriphClkInit.RngClockSelection = RCC_RNGCLKSOURCE_HSI48; - if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { - return 0; // FAIL - } - - return 1; // OK -} -#endif /* ((CLOCK_SOURCE) & USE_PLL_HSI) */ - -#if ((CLOCK_SOURCE) & USE_PLL_MSI) -/******************************************************************************/ -/* PLL (clocked by MSI) used as System clock source */ -/******************************************************************************/ -MBED_WEAK uint8_t SetSysClock_PLL_MSI(void) -{ - RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; - RCC_OscInitTypeDef RCC_OscInitStruct = {0}; - RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; - - __HAL_RCC_PWR_CLK_ENABLE(); - HAL_PWREx_DisableUCPDDeadBattery(); /* Disable the internal Pull-Up in Dead Battery pins of UCPD peripheral */ - HAL_PWREx_EnableVddA(); - HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); - - RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48 | RCC_OSCILLATORTYPE_HSI - | RCC_OSCILLATORTYPE_MSI; - RCC_OscInitStruct.HSIState = RCC_HSI_ON; - RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; - RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; - RCC_OscInitStruct.MSIState = RCC_MSI_ON; - RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT; - RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_0; - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; - RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI; - RCC_OscInitStruct.PLL.PLLMBOOST = RCC_PLLMBOOST_DIV4; - RCC_OscInitStruct.PLL.PLLM = 3; - RCC_OscInitStruct.PLL.PLLN = 10; - RCC_OscInitStruct.PLL.PLLP = 2; - RCC_OscInitStruct.PLL.PLLQ = 2; - RCC_OscInitStruct.PLL.PLLR = 1; - RCC_OscInitStruct.PLL.PLLRGE = RCC_PLLVCIRANGE_1; - RCC_OscInitStruct.PLL.PLLFRACN = 0; - if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { - return 0; // FAIL - } - - RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK - | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2 - | RCC_CLOCKTYPE_PCLK3; - RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; - RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; - RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; - RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; - RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1; - if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) { - return 0; // FAIL - } - - PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RNG; - PeriphClkInit.RngClockSelection = RCC_RNGCLKSOURCE_HSI48; - if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { - return 0; // FAIL - } - - /** Enable MSI Auto calibration - */ - HAL_RCCEx_EnableMSIPLLModeSelection(RCC_MSIKPLL_MODE_SEL); - HAL_RCCEx_EnableMSIPLLMode(); - HAL_RCCEx_EnableMSIPLLFastStartup(); - - return 1; // OK -} -#endif /* ((CLOCK_SOURCE) & USE_PLL_MSI) */ diff --git a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U575xG/system_clock.c b/targets/TARGET_STM/TARGET_STM32U5/clock_cfg/system_clock.c similarity index 77% rename from targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U575xG/system_clock.c rename to targets/TARGET_STM/TARGET_STM32U5/clock_cfg/system_clock.c index 63e49d13e1c..b4df7d1f9a6 100644 --- a/targets/TARGET_STM/TARGET_STM32U5/TARGET_STM32U575xG/system_clock.c +++ b/targets/TARGET_STM/TARGET_STM32U5/clock_cfg/system_clock.c @@ -117,10 +117,7 @@ MBED_WEAK uint8_t SetSysClock_PLL_HSE(uint8_t bypass) { RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_OscInitTypeDef RCC_OscInitStruct = {0}; - -#if DEVICE_USBDEVICE - RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit = {0}; -#endif /* DEVICE_USBDEVICE */ + RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOH_CLK_ENABLE(); @@ -137,20 +134,22 @@ MBED_WEAK uint8_t SetSysClock_PLL_HSE(uint8_t bypass) } else { RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS; // External clock on OSC_IN } -#if DEVICE_USBDEVICE RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; -#else - RCC_OscInitStruct.HSI48State = RCC_HSI48_OFF; -#endif /* DEVICE_USBDEVICE */ -#if HSE_VALUE==10000000UL +#if (HSE_VALUE % 5000000) == 0UL + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLMBOOST = RCC_PLLMBOOST_DIV1; + RCC_OscInitStruct.PLL.PLLM = HSE_VALUE/ 5000000; // VCO input clock = 5 MHz + RCC_OscInitStruct.PLL.PLLN = 32; // VCO output clock = 160 MHz (5 MHz * 32) +#elif (HSE_VALUE % 4000000) == 0UL RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLMBOOST = RCC_PLLMBOOST_DIV1; - RCC_OscInitStruct.PLL.PLLM = 1; // VCO input clock = 10 MHz (10 MHz / 1) + RCC_OscInitStruct.PLL.PLLM = HSE_VALUE/ 4000000; // VCO input clock = 4 MHz + RCC_OscInitStruct.PLL.PLLN = 40; // VCO output clock = 160 MHz (4 MHz * 40) #else #error Unsupported external clock value, check HSE_VALUE define #endif - RCC_OscInitStruct.PLL.PLLN = 16; // VCO output clock = 160 MHz (10 MHz * 16) RCC_OscInitStruct.PLL.PLLP = 2; RCC_OscInitStruct.PLL.PLLQ = 2; RCC_OscInitStruct.PLL.PLLR = 1; // PLL clock = 160 MHz @@ -161,14 +160,6 @@ MBED_WEAK uint8_t SetSysClock_PLL_HSE(uint8_t bypass) return 0; // FAIL } -#if DEVICE_USBDEVICE - RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB; - PeriphClkIniRCC_PeriphClkInittStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48; /* 48 MHz */ - if (HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit) != HAL_OK) { - return 0; // FAIL - } -#endif /* DEVICE_USBDEVICE */ - // Select PLL clock as system clock source and configure the HCLK, PCLK1 and PCLK2 clock dividers RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2 | RCC_CLOCKTYPE_PCLK3); RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 160 MHz @@ -180,8 +171,14 @@ MBED_WEAK uint8_t SetSysClock_PLL_HSE(uint8_t bypass) if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) { return 0; // FAIL } - return 1; // OK + PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RNG; + PeriphClkInit.RngClockSelection = RCC_RNGCLKSOURCE_HSI48; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { + return 0; // FAIL + } + + return 1; // OK } #endif /* ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) || ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) */ @@ -191,7 +188,55 @@ MBED_WEAK uint8_t SetSysClock_PLL_HSE(uint8_t bypass) /******************************************************************************/ uint8_t SetSysClock_PLL_HSI(void) { - return 0; // TODO + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; + + __HAL_RCC_PWR_CLK_ENABLE(); + HAL_PWREx_EnableVddA(); + HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); + + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48 | RCC_OSCILLATORTYPE_HSI + | RCC_OSCILLATORTYPE_MSI; + RCC_OscInitStruct.HSIState = RCC_HSI_ON; + RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; + RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; + RCC_OscInitStruct.MSIState = RCC_MSI_ON; + RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT; + RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_0; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; + RCC_OscInitStruct.PLL.PLLMBOOST = RCC_PLLMBOOST_DIV1; + RCC_OscInitStruct.PLL.PLLM = 1; + RCC_OscInitStruct.PLL.PLLN = 10; + RCC_OscInitStruct.PLL.PLLP = 2; + RCC_OscInitStruct.PLL.PLLQ = 2; + RCC_OscInitStruct.PLL.PLLR = 1; + RCC_OscInitStruct.PLL.PLLRGE = RCC_PLLVCIRANGE_1; + RCC_OscInitStruct.PLL.PLLFRACN = 0; + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { + return 0; // FAIL + } + + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK + | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2 + | RCC_CLOCKTYPE_PCLK3; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; + RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1; + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) { + return 0; // FAIL + } + + PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RNG; + PeriphClkInit.RngClockSelection = RCC_RNGCLKSOURCE_HSI48; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { + return 0; // FAIL + } + + return 1; // OK } #endif /* ((CLOCK_SOURCE) & USE_PLL_HSI) */ @@ -206,7 +251,9 @@ MBED_WEAK uint8_t SetSysClock_PLL_MSI(void) RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; __HAL_RCC_PWR_CLK_ENABLE(); +#if defined(UCPD1) HAL_PWREx_DisableUCPDDeadBattery(); /* Disable the internal Pull-Up in Dead Battery pins of UCPD peripheral */ +#endif HAL_PWREx_EnableVddA(); HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); @@ -244,17 +291,13 @@ MBED_WEAK uint8_t SetSysClock_PLL_MSI(void) } #if MBED_CONF_TARGET_LSE_AVAILABLE - /* Enable MSI Auto-calibration through LSE */ - HAL_RCCEx_EnableMSIPLLMode(); + /** Enable MSI Auto calibration + */ + HAL_RCCEx_EnableMSIPLLModeSelection(RCC_MSIKPLL_MODE_SEL); + HAL_RCCEx_EnableMSIPLLMode(); + HAL_RCCEx_EnableMSIPLLFastStartup(); #endif /* MBED_CONF_TARGET_LSE_AVAILABLE */ -#if DEVICE_USBDEVICE - /* Select MSI output as USB clock source */ - PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB; - PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_MSI; /* 48 MHz */ - HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); -#endif /* DEVICE_USBDEVICE */ - // Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2 @@ -274,12 +317,6 @@ MBED_WEAK uint8_t SetSysClock_PLL_MSI(void) return 0; // FAIL } - /** Enable MSI Auto calibration - */ - HAL_RCCEx_EnableMSIPLLModeSelection(RCC_MSIKPLL_MODE_SEL); - HAL_RCCEx_EnableMSIPLLMode(); - HAL_RCCEx_EnableMSIPLLFastStartup(); - return 1; // OK } #endif /* ((CLOCK_SOURCE) & USE_PLL_MSI) */ From 4cc99e3ce97b6db011273f885ac5eea957d22f10 Mon Sep 17 00:00:00 2001 From: wdx04 <25487439@qq.com> Date: Tue, 22 Jul 2025 19:18:30 +0800 Subject: [PATCH 5/6] disable ForceOscOutofDeepSleep() and ForcePeriphOutofDeepSleep() on STM32U5 improve the speed of recovery from stop mode --- targets/TARGET_STM/sleep.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/targets/TARGET_STM/sleep.c b/targets/TARGET_STM/sleep.c index 8d1184194bf..32bfc4e4b27 100644 --- a/targets/TARGET_STM/sleep.c +++ b/targets/TARGET_STM/sleep.c @@ -265,10 +265,13 @@ __WEAK void hal_deepsleep(void) /* We've seen unstable PLL CLK configuration when DEEP SLEEP exits just few µs after being entered * So we need to force clock init out of Deep Sleep. * This init has been split into 2 separate functions so that the involved structures are not allocated on the stack in parallel. - * This will reduce the maximum stack usage in case on non-optimized / debug compilers settings + * This will reduce the maximum stack usage in case on non-optimized / debug compilers settings. + * This is very slow on STM32U5 (up to 6ms), so we disable it on that family of devices. */ +#ifndef TARGET_STM32U5 ForceOscOutofDeepSleep(); ForcePeriphOutofDeepSleep(); +#endif SetSysClock(); #endif From 9ce4ae1fcfd339f7dda6288e36e0a046ebaf65cc Mon Sep 17 00:00:00 2001 From: wdx04 <25487439@qq.com> Date: Wed, 23 Jul 2025 08:25:48 +0800 Subject: [PATCH 6/6] remove duplicate code in TARGET_STM32U5/clock_cfg/system_clock.c --- targets/TARGET_STM/TARGET_STM32U5/clock_cfg/system_clock.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/targets/TARGET_STM/TARGET_STM32U5/clock_cfg/system_clock.c b/targets/TARGET_STM/TARGET_STM32U5/clock_cfg/system_clock.c index b4df7d1f9a6..70f203d6452 100644 --- a/targets/TARGET_STM/TARGET_STM32U5/clock_cfg/system_clock.c +++ b/targets/TARGET_STM/TARGET_STM32U5/clock_cfg/system_clock.c @@ -135,16 +135,13 @@ MBED_WEAK uint8_t SetSysClock_PLL_HSE(uint8_t bypass) RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS; // External clock on OSC_IN } RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; -#if (HSE_VALUE % 5000000) == 0UL RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLMBOOST = RCC_PLLMBOOST_DIV1; +#if (HSE_VALUE % 5000000) == 0UL RCC_OscInitStruct.PLL.PLLM = HSE_VALUE/ 5000000; // VCO input clock = 5 MHz RCC_OscInitStruct.PLL.PLLN = 32; // VCO output clock = 160 MHz (5 MHz * 32) #elif (HSE_VALUE % 4000000) == 0UL - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; - RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; - RCC_OscInitStruct.PLL.PLLMBOOST = RCC_PLLMBOOST_DIV1; RCC_OscInitStruct.PLL.PLLM = HSE_VALUE/ 4000000; // VCO input clock = 4 MHz RCC_OscInitStruct.PLL.PLLN = 40; // VCO output clock = 160 MHz (4 MHz * 40) #else