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 01/14] 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 02/14] 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 03/14] 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 04/14] 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 05/14] 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 06/14] 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 From 02e2c3512723da8510bda4b0b9aea44717bd4635 Mon Sep 17 00:00:00 2001 From: wdx04 <25487439@qq.com> Date: Sat, 26 Jul 2025 22:30:00 +0800 Subject: [PATCH 07/14] Fix some issues found in the review. --- drivers/include/drivers/interfaces/InterfaceCAN.h | 4 ---- drivers/source/CAN.cpp | 3 +++ targets/TARGET_STM/TARGET_STM32L5/system_clock.c | 2 ++ .../TARGET_STM32U5/clock_cfg/system_clock.c | 10 +++++++--- targets/TARGET_STM/can_api.c | 12 ++++++++++-- targets/targets.json5 | 5 +++++ 6 files changed, 27 insertions(+), 9 deletions(-) diff --git a/drivers/include/drivers/interfaces/InterfaceCAN.h b/drivers/include/drivers/interfaces/InterfaceCAN.h index aea46e31f90..8dbd81b71f6 100644 --- a/drivers/include/drivers/interfaces/InterfaceCAN.h +++ b/drivers/include/drivers/interfaces/InterfaceCAN.h @@ -44,8 +44,6 @@ class CAN; */ /** CANMessage class - * - * @note Synchronization level: Thread safe */ class CANMessage : public CAN_Message { @@ -143,8 +141,6 @@ class CANMessage : public CAN_Message { #if DEVICE_CAN_FD /** CANFDMessage class - * - * @note Synchronization level: Thread safe */ class CANFDMessage : public CANFD_Message { diff --git a/drivers/source/CAN.cpp b/drivers/source/CAN.cpp index bfbbcfa6258..d077f670e9e 100644 --- a/drivers/source/CAN.cpp +++ b/drivers/source/CAN.cpp @@ -36,6 +36,7 @@ CAN::CAN(PinName rd, PinName td, int hz, int data_hz) : _can(), _irq() #if DEVICE_CAN_FD canfd_init_freq(&_can, rd, td, hz, data_hz); #else + MBED_ASSERT(data_hz == 0); can_init_freq(&_can, rd, td, hz); #endif can_irq_init(&_can, (&CAN::_irq_handler), reinterpret_cast(this)); @@ -54,6 +55,7 @@ CAN::CAN(const can_pinmap_t &pinmap, int hz, int data_hz) : _can(), _irq() #if DEVICE_CAN_FD canfd_init_freq_direct(&_can, &pinmap, hz, data_hz); #else + MBED_ASSERT(data_hz == 0); can_init_freq_direct(&_can, &pinmap, hz); #endif can_irq_init(&_can, (&CAN::_irq_handler), reinterpret_cast(this)); @@ -77,6 +79,7 @@ int CAN::frequency(int f, int data_f) #if DEVICE_CAN_FD int ret = canfd_frequency(&_can, f, data_f); #else + MBED_ASSERT(data_f == 0); int ret = can_frequency(&_can, f); #endif unlock(); diff --git a/targets/TARGET_STM/TARGET_STM32L5/system_clock.c b/targets/TARGET_STM/TARGET_STM32L5/system_clock.c index df7aa35cb8d..ce85072ad67 100644 --- a/targets/TARGET_STM/TARGET_STM32L5/system_clock.c +++ b/targets/TARGET_STM/TARGET_STM32L5/system_clock.c @@ -193,7 +193,9 @@ uint8_t SetSysClock_PLL_MSI(void) #endif /* Enable MSI Auto calibration */ +#if MBED_CONF_TARGET_LSE_AVAILABLE HAL_RCCEx_EnableMSIPLLMode(); +#endif return 1; // OK } 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 70f203d6452..6f816753faf 100644 --- a/targets/TARGET_STM/TARGET_STM32U5/clock_cfg/system_clock.c +++ b/targets/TARGET_STM/TARGET_STM32U5/clock_cfg/system_clock.c @@ -119,10 +119,11 @@ MBED_WEAK uint8_t SetSysClock_PLL_HSE(uint8_t bypass) RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; - /* GPIO Ports Clock Enable */ - __HAL_RCC_GPIOH_CLK_ENABLE(); - __HAL_RCC_GPIOB_CLK_ENABLE(); __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(); if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK) { return 0; // FAIL } @@ -190,6 +191,9 @@ uint8_t SetSysClock_PLL_HSI(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); diff --git a/targets/TARGET_STM/can_api.c b/targets/TARGET_STM/can_api.c index 961cf5f5454..4d339b63d07 100644 --- a/targets/TARGET_STM/can_api.c +++ b/targets/TARGET_STM/can_api.c @@ -23,6 +23,7 @@ #include "pinmap.h" #include "PeripheralPins.h" #include "mbed_error.h" +#include // Some STM32G4 series (and others) have 3 FDCAN devices // while others have 2 @@ -632,7 +633,7 @@ int canfd_write(can_t *obj, CANFD_Message msg, int cc) TxHeader.DataLength = FDCAN_DLC_BYTES_64; break; default: - error("Invalid message length for can_write\n"); + error("Invalid message length for canfd_write\n"); return 0; } TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; @@ -658,7 +659,8 @@ int can_read(can_t *obj, CAN_Message *msg, int handle) } FDCAN_RxHeaderTypeDef RxHeader = {0}; - if (HAL_FDCAN_GetRxMessage(&obj->CanHandle, FDCAN_RX_FIFO0, &RxHeader, msg->data) != HAL_OK) { + unsigned char data[64]; + if (HAL_FDCAN_GetRxMessage(&obj->CanHandle, FDCAN_RX_FIFO0, &RxHeader, data) != HAL_OK) { error("HAL_FDCAN_GetRxMessage error\n"); // Should not occur as previous HAL_FDCAN_GetRxFifoFillLevel call reported some data return 0; } @@ -674,6 +676,12 @@ int can_read(can_t *obj, CAN_Message *msg, int handle) RxHeader.DataLength >>= 16; #endif msg->len = RxHeader.DataLength; + if(msg->len > 8) + { + error("can_read unexpectedly received a FD frame\n"); + return 0; + } + memcpy(msg->data, data, msg->len); return 1; } diff --git a/targets/targets.json5 b/targets/targets.json5 index 940e9ec30b9..0d9c4080828 100644 --- a/targets/targets.json5 +++ b/targets/targets.json5 @@ -4922,6 +4922,11 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "value": "USE_PLL_MSI", "macro_name": "CLOCK_SOURCE" }, + "hse_value": { + "help": "HSE default value is 16MHz in stm32u5xx_hal_conf.h", + "value": "16000000", + "macro_name": "HSE_VALUE" + }, "lpticker_lptim": { "help": "This target supports LPTIM. Set value 1 to use LPTIM for LPTICKER, or 0 to use RTC wakeup timer", "value": 1 From 7de365cc1c1111ba17efcf21c9b5de45ef5fcab3 Mon Sep 17 00:00:00 2001 From: wdx04 <25487439@qq.com> Date: Sun, 27 Jul 2025 16:26:57 +0800 Subject: [PATCH 08/14] added basic documentation for CAN HAL API functions removed the unused parameter 'cc' from can_write and canfd_write reverted changes in TARGET_STM/sleep.c --- drivers/source/CAN.cpp | 4 +- hal/include/hal/can_api.h | 173 +++++++++++++++++- .../TARGET_GD32F30X/can_api.c | 2 +- .../TARGET_GD32F4XX/can_api.c | 2 +- targets/TARGET_NUVOTON/TARGET_M261/can_api.c | 4 +- targets/TARGET_NUVOTON/TARGET_M451/can_api.c | 5 +- targets/TARGET_NUVOTON/TARGET_M460/can_api.c | 5 +- targets/TARGET_NUVOTON/TARGET_M480/can_api.c | 5 +- .../TARGET_NUVOTON/TARGET_NUC472/can_api.c | 5 +- targets/TARGET_NXP/TARGET_LPC176X/can_api.c | 3 +- .../TARGET_RENESAS/TARGET_RZ_A1XX/can_api.c | 2 +- .../TARGET_RENESAS/TARGET_RZ_A2XX/can_api.c | 2 +- targets/TARGET_STM/can_api.c | 171 ++++++++--------- targets/TARGET_STM/sleep.c | 3 - .../TARGET_EFM32/can_api.c | 2 +- targets/targets.json5 | 2 +- 16 files changed, 262 insertions(+), 128 deletions(-) diff --git a/drivers/source/CAN.cpp b/drivers/source/CAN.cpp index d077f670e9e..e0165349053 100644 --- a/drivers/source/CAN.cpp +++ b/drivers/source/CAN.cpp @@ -89,7 +89,7 @@ int CAN::frequency(int f, int data_f) int CAN::write(CANMessage msg) { lock(); - int ret = can_write(&_can, msg, 0); + int ret = can_write(&_can, msg); unlock(); return ret; } @@ -110,7 +110,7 @@ int CAN::read(CANMessage &msg, int handle) int CAN::write(CANFDMessage msg) { lock(); - int ret = canfd_write(&_can, msg, 0); + int ret = canfd_write(&_can, msg); unlock(); return ret; } diff --git a/hal/include/hal/can_api.h b/hal/include/hal/can_api.h index 6656405ff59..49ed718c855 100644 --- a/hal/include/hal/can_api.h +++ b/hal/include/hal/can_api.h @@ -67,31 +67,200 @@ typedef void (*can_irq_handler)(uintptr_t context, CanIrqType type); typedef struct can_s can_t; +/** Initialize the CAN peripheral. It sets the default parameters for CAN + * peripheral, and configures its specifieds pins. + * + * @param obj CAN object + * @param rd The CAN RD pin name + * @param td The CAN TD pin name + */ void can_init(can_t *obj, PinName rd, PinName td); + +/** Initialize the CAN peripheral. It sets the default parameters for CAN + * peripheral, and configures its specifieds pins. + * + * @param obj The CAN object + * @param pinmap pointer to structure which holds static pinmap + */ void can_init_direct(can_t *obj, const can_pinmap_t *pinmap); + +/** Initialize the CAN peripheral. It sets the default parameters for CAN + * peripheral, and configures its specifieds pins. + * + * @param obj CAN object + * @param rd The CAN RD pin name + * @param td The CAN TD pin name + * @param hz The bus frequency + */ void can_init_freq(can_t *obj, PinName rd, PinName td, int hz); + +/** Initialize the CAN peripheral. It sets the default parameters for CAN + * peripheral, and configures its specifieds pins. + * + * @param obj CAN object + * @param pinmap pointer to structure which holds static pinmap + * @param hz The bus frequency + */ void can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz); + +/** Release the CAN peripheral, not currently invoked. It requires further + * resource management. + * + * @param obj The CAN object + */ void can_free(can_t *obj); + +/** Configure the CAN bus frequency + * + * @param obj The CAN object + * @param hz The bus frequency + */ int can_frequency(can_t *obj, int hz); +/** Initialize the CAN IRQ handler + * + * @param obj The CAN object + * @param handler The handler to be attached to CAN IRQ + * @param context The context to be passed back to the handler (context != 0, 0 is reserved) + */ void can_irq_init(can_t *obj, can_irq_handler handler, uintptr_t context); + +/** Release the CAN object + * + * @param obj The CAN object + */ void can_irq_free(can_t *obj); + +/** Enable/disable the CAN IRQ event + * + * @param obj The CAN object + * @param irq The CAN IRQ event + * @param enable The enable flag + */ void can_irq_set(can_t *obj, CanIrqType irq, uint32_t enable); -int can_write(can_t *obj, CAN_Message, int cc); +/** Write a CAN message to the bus. + * + * @param obj The CAN object + * @param msg The CAN message to write. + * + * @return 0 if write failed, + * 1 if write was successful + */ +int can_write(can_t *obj, CAN_Message msg); + +/** Read a CAN message from the bus. + * + * @param obj CAN object + * @param msg A CAN message to read to. + * @param handle message filter handle (0 for any message). + * + * @return 0 if no message arrived, + * 1 if message arrived + */ int can_read(can_t *obj, CAN_Message *msg, int handle); + +/** Change CAN operation to the specified mode. + * + * @param obj The CAN object + * @param mode The new operation mode (MODE_NORMAL, MODE_SILENT, MODE_TEST_LOCAL, MODE_TEST_GLOBAL, MODE_TEST_SILENT). + * + * @return 0 if mode change failed or unsupported, + * 1 if mode change was successful + */ int can_mode(can_t *obj, CanMode mode); + +/** Filter out incomming messages. + * + * @param obj The CAN object + * @param id the id to filter on. + * @param mask the mask applied to the id. + * @param format format to filter on (Default CANAny). + * @param handle message filter handle (Optional). + * + * @return 0 if filter change failed or unsupported, + * new filter handle if successful + */ int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle); + +/** Reset CAN interface. + * + * @param obj CAN object + * + * To use after error overflow. + */ void can_reset(can_t *obj); + +/** Detects read errors - Used to detect read overflow errors. + * + * @param obj CAN object + * @return number of read errors + */ unsigned char can_rderror(can_t *obj); + +/** Detects write errors - Used to detect write overflow errors. + * + * @param obj CAN object + * @return number of write errors + */ unsigned char can_tderror(can_t *obj); + +/** Puts or removes the CAN interface into silent monitoring mode. + * + * @param obj CAN object + * @param silent boolean indicating whether to go into silent mode or not. + */ void can_monitor(can_t *obj, int silent); #if DEVICE_CAN_FD +/** Initialize the CAN FD peripheral. It sets the default parameters for CAN FD + * peripheral, and configures its specifieds pins. + * + * @param obj CAN object + * @param rd The CAN RD pin name + * @param td The CAN TD pin name + * @param hz The bus frequency of nominal phase + * @param data_hz The bus frequency of data phase, the CAN object is put into Classical CAN mode if this parameter is zero + */ void canfd_init_freq(can_t *obj, PinName rd, PinName td, int hz, int data_hz); + +/** Initialize the CAN FD peripheral. It sets the default parameters for CAN FD + * peripheral, and configures its specifieds pins. + * + * @param obj CAN object + * @param pinmap pointer to structure which holds static pinmap + * @param hz The bus frequency of nominal phase + * @param data_hz The bus frequency of data phase, the CAN object is put into Classical CAN mode if this parameter is zero + */ void canfd_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz, int data_hz); + +/** Configure the CAN FD bus frequency + * + * @param obj The CAN object + * @param hz The bus frequency of nominal phase + * @param data_hz The bus frequency of data phase, the CAN object is put into Classical CAN mode if this parameter is zero + */ int canfd_frequency(can_t *obj, int hz, int data_hz); -int canfd_write(can_t *obj, CANFD_Message, int cc); + +/** Write a CAN FD Message to the bus. + * + * @param obj The CAN object + * @param msg The CAN FD Message to write. + * + * @return 0 if write failed, + * 1 if write was successful + */ +int canfd_write(can_t *obj, CANFD_Message msg); + +/** Read a Classical CAN or CAN FD Message from the bus. + * + * @param obj CAN object + * @param msg A Classical CAN or CAN FD Message to read to. + * @param handle message filter handle (0 for any message). + * + * @return 0 if no message arrived, + * 1 if message arrived + */ int canfd_read(can_t *obj, CANFD_Message *msg, int handle); #endif diff --git a/targets/TARGET_GigaDevice/TARGET_GD32F30X/can_api.c b/targets/TARGET_GigaDevice/TARGET_GD32F30X/can_api.c index afdc8722cd3..fa25db29c12 100644 --- a/targets/TARGET_GigaDevice/TARGET_GD32F30X/can_api.c +++ b/targets/TARGET_GigaDevice/TARGET_GD32F30X/can_api.c @@ -410,7 +410,7 @@ void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable) * 0 if write failed, * 1 if write was successful */ -int can_write(can_t *obj, CAN_Message msg, int cc) +int can_write(can_t *obj, CAN_Message msg) { can_trasnmit_message_struct transmit_message; uint32_t i; diff --git a/targets/TARGET_GigaDevice/TARGET_GD32F4XX/can_api.c b/targets/TARGET_GigaDevice/TARGET_GD32F4XX/can_api.c index 79614ff053f..1545c78e9ca 100644 --- a/targets/TARGET_GigaDevice/TARGET_GD32F4XX/can_api.c +++ b/targets/TARGET_GigaDevice/TARGET_GD32F4XX/can_api.c @@ -411,7 +411,7 @@ void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable) * 0 if write failed, * 1 if write was successful */ -int can_write(can_t *obj, CAN_Message msg, int cc) +int can_write(can_t *obj, CAN_Message msg) { can_trasnmit_message_struct transmit_message; uint32_t i; diff --git a/targets/TARGET_NUVOTON/TARGET_M261/can_api.c b/targets/TARGET_NUVOTON/TARGET_M261/can_api.c index 0b1ccc5ea92..e7681f483f1 100644 --- a/targets/TARGET_NUVOTON/TARGET_M261/can_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M261/can_api.c @@ -216,7 +216,7 @@ void can_irq_set(can_t *obj, CanIrqType irq, uint32_t enable) } -int can_write(can_t *obj, CAN_Message msg, int cc) +int can_write(can_t *obj, CAN_Message msg) { STR_CANMSG_T CMsg; @@ -226,7 +226,7 @@ int can_write(can_t *obj, CAN_Message msg, int cc) CMsg.DLC = msg.len; memcpy((void *)&CMsg.Data[0],(const void *)&msg.data[0], (unsigned int)8); - return CAN_Transmit((CAN_T *)NU_MODBASE(obj->can), cc, &CMsg); + return CAN_Transmit((CAN_T *)NU_MODBASE(obj->can), 0, &CMsg); } int can_read(can_t *obj, CAN_Message *msg, int handle) diff --git a/targets/TARGET_NUVOTON/TARGET_M451/can_api.c b/targets/TARGET_NUVOTON/TARGET_M451/can_api.c index 20faf87a1aa..f90c86ecd92 100644 --- a/targets/TARGET_NUVOTON/TARGET_M451/can_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M451/can_api.c @@ -231,11 +231,8 @@ void can_irq_set(can_t *obj, CanIrqType irq, uint32_t enable) } -int can_write(can_t *obj, CAN_Message msg, int cc) +int can_write(can_t *obj, CAN_Message msg) { - /* Unused */ - (void) cc; - STR_CANMSG_T CMsg; CMsg.IdType = (uint32_t)msg.format; diff --git a/targets/TARGET_NUVOTON/TARGET_M460/can_api.c b/targets/TARGET_NUVOTON/TARGET_M460/can_api.c index 88a63e3d1b1..a61e123f3f9 100644 --- a/targets/TARGET_NUVOTON/TARGET_M460/can_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M460/can_api.c @@ -476,11 +476,8 @@ void can_irq_set(can_t *obj, CanIrqType irq, uint32_t enable) } } -int can_write(can_t *obj, CAN_Message msg, int cc) +int can_write(can_t *obj, CAN_Message msg) { - /* Unused */ - (void) cc; - const struct nu_modinit_s *modinit = get_modinit(obj->can, can_modinit_tab); MBED_ASSERT(modinit != NULL); MBED_ASSERT(modinit->modname == (int) obj->can); diff --git a/targets/TARGET_NUVOTON/TARGET_M480/can_api.c b/targets/TARGET_NUVOTON/TARGET_M480/can_api.c index c4910180c5e..adf8c953d23 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/can_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/can_api.c @@ -281,11 +281,8 @@ void can_irq_set(can_t *obj, CanIrqType irq, uint32_t enable) } -int can_write(can_t *obj, CAN_Message msg, int cc) +int can_write(can_t *obj, CAN_Message msg) { - /* Unused */ - (void) cc; - STR_CANMSG_T CMsg; CMsg.IdType = (uint32_t)msg.format; diff --git a/targets/TARGET_NUVOTON/TARGET_NUC472/can_api.c b/targets/TARGET_NUVOTON/TARGET_NUC472/can_api.c index 3b33bd61b91..44fa54728e0 100644 --- a/targets/TARGET_NUVOTON/TARGET_NUC472/can_api.c +++ b/targets/TARGET_NUVOTON/TARGET_NUC472/can_api.c @@ -284,11 +284,8 @@ void can_irq_set(can_t *obj, CanIrqType irq, uint32_t enable) } -int can_write(can_t *obj, CAN_Message msg, int cc) +int can_write(can_t *obj, CAN_Message msg) { - /* Unused */ - (void) cc; - STR_CANMSG_T CMsg; CMsg.IdType = (uint32_t)msg.format; diff --git a/targets/TARGET_NXP/TARGET_LPC176X/can_api.c b/targets/TARGET_NXP/TARGET_LPC176X/can_api.c index 689eb574218..e8b116b1d04 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/can_api.c +++ b/targets/TARGET_NXP/TARGET_LPC176X/can_api.c @@ -352,8 +352,9 @@ int can_frequency(can_t *obj, int f) { } } -int can_write(can_t *obj, CAN_Message msg, int cc) { +int can_write(can_t *obj, CAN_Message msg) { unsigned int CANStatus; + int cc = 0; CANMsg m; can_enable(obj); diff --git a/targets/TARGET_RENESAS/TARGET_RZ_A1XX/can_api.c b/targets/TARGET_RENESAS/TARGET_RZ_A1XX/can_api.c index 8909c5a873e..24963771867 100644 --- a/targets/TARGET_RENESAS/TARGET_RZ_A1XX/can_api.c +++ b/targets/TARGET_RENESAS/TARGET_RZ_A1XX/can_api.c @@ -628,7 +628,7 @@ void can_reset(can_t *obj) { can_reconfigure_channel(); } -int can_write(can_t *obj, CAN_Message msg, int cc) { +int can_write(can_t *obj, CAN_Message msg) { __IO uint32_t *dmy_sts; __IO uint32_t *dmy_cfsts; __IO uint32_t *dmy_cfid; diff --git a/targets/TARGET_RENESAS/TARGET_RZ_A2XX/can_api.c b/targets/TARGET_RENESAS/TARGET_RZ_A2XX/can_api.c index 5dc733395dd..9ad1657ee28 100644 --- a/targets/TARGET_RENESAS/TARGET_RZ_A2XX/can_api.c +++ b/targets/TARGET_RENESAS/TARGET_RZ_A2XX/can_api.c @@ -720,7 +720,7 @@ int can_frequency(can_t *obj, int f) return retval; } -int can_write(can_t *obj, CAN_Message msg, int cc) +int can_write(can_t *obj, CAN_Message msg) { can_frame_t frame; diff --git a/targets/TARGET_STM/can_api.c b/targets/TARGET_STM/can_api.c index 4d339b63d07..ba1d47b9a40 100644 --- a/targets/TARGET_STM/can_api.c +++ b/targets/TARGET_STM/can_api.c @@ -76,6 +76,64 @@ int can_internal_init(can_t *obj) return 1; } +/** Get the nominal phase clock prescaler and the number of time quantums for the specified frequency + */ +static uint32_t get_canfd_nominal_prescaler(int f, uint32_t *ntq_out) +{ +#if (defined TARGET_STM32H7) + // STM32H7 doesn't support yet HAL_RCCEx_GetPeriphCLKFreq for FDCAN + PLL1_ClocksTypeDef pll1_clocks; + HAL_RCCEx_GetPLL1ClockFreq(&pll1_clocks); + uint32_t ntq = pll1_clocks.PLL1_Q_Frequency / (uint32_t)f; +#else +#if (defined RCC_PERIPHCLK_FDCAN1) + uint32_t ntq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN1) / (uint32_t)f; +#else + uint32_t ntq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN) / (uint32_t)f; +#endif +#endif + uint32_t nominalPrescaler = 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% + while (!IS_FDCAN_NOMINAL_TSEG1(ntq / nominalPrescaler)) { + nominalPrescaler ++; + if (!IS_FDCAN_NOMINAL_PRESCALER(nominalPrescaler)) { + error("Could not determine good nominalPrescaler. Bad clock value\n"); + } + } + *ntq_out = ntq / nominalPrescaler; + return nominalPrescaler; +} + +/** Get the data phase clock prescaler and the number of time quantums for the specified frequency + */ +static uint32_t get_canfd_data_prescaler(int data_f, uint32_t *ntq_out) +{ +#if (defined TARGET_STM32H7) + // STM32H7 doesn't support yet HAL_RCCEx_GetPeriphCLKFreq for FDCAN + PLL1_ClocksTypeDef pll1_clocks; + HAL_RCCEx_GetPLL1ClockFreq(&pll1_clocks); + uint32_t ntq_data = pll1_clocks.PLL1_Q_Frequency / (uint32_t)data_f; +#elif (defined RCC_PERIPHCLK_FDCAN1) + uint32_t ntq_data = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN1) / (uint32_t)data_f; +#else + uint32_t ntq_data = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN) / (uint32_t)data_f; +#endif + 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 @70% + 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_out = ntq_data / dataPrescaler; + return dataPrescaler; +} + #if STATIC_PINMAP_READY #define CANFD_INIT_FREQ_DIRECT canfd_init_freq_direct void canfd_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz) @@ -160,64 +218,28 @@ static void _canfd_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int Synchronization_Jump_width | 9 tq | = */ - // !Attention Not all bitrates can be covered with all fdcan-core-clk values. When a clk - // does not work for the desired bitrate, change system_clock settings for FDCAN_CLK - // (default FDCAN_CLK is PLLQ) -#if (defined TARGET_STM32H7) - // STM32H7 doesn't support yet HAL_RCCEx_GetPeriphCLKFreq for FDCAN - // We use PLL1.Q clock right now so get its frequency - PLL1_ClocksTypeDef pll1_clocks; - HAL_RCCEx_GetPLL1ClockFreq(&pll1_clocks); - uint32_t ntq = pll1_clocks.PLL1_Q_Frequency / (uint32_t)hz; -#else -#if (defined RCC_PERIPHCLK_FDCAN1) - uint32_t ntq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN1) / (uint32_t)hz; -#else - uint32_t ntq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN) / (uint32_t)hz; -#endif -#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% - while (!IS_FDCAN_NOMINAL_TSEG1(ntq / nominalPrescaler)) { - nominalPrescaler ++; - if (!IS_FDCAN_NOMINAL_PRESCALER(nominalPrescaler)) { - error("Could not determine good nominalPrescaler. Bad clock value\n"); - } - } - ntq = ntq / nominalPrescaler; + /* See can_init_freq function for calculation details + * + * !Attention Not all bitrates can be covered with all fdcan-core-clk values. When a clk + * does not work for the desired bitrate, change system_clock settings for FDCAN_CLK + * (default FDCAN_CLK is PLLQ) + */ + uint32_t ntq = 0; + uint32_t nominalPrescaler = get_canfd_nominal_prescaler(hz, &ntq); uint32_t ntq_data = ntq; - + uint32_t dataPrescaler = nominalPrescaler; 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; + dataPrescaler = get_canfd_data_prescaler(data_hz, &ntq_data); } obj->CanHandle.Init.Mode = FDCAN_MODE_NORMAL; obj->CanHandle.Init.AutoRetransmission = ENABLE; @@ -413,7 +435,6 @@ void can_reset(can_t *obj) HAL_FDCAN_ResetTimestampCounter(&obj->CanHandle); } - int canfd_frequency(can_t *obj, int f, int data_f) { if (HAL_FDCAN_Stop(&obj->CanHandle) != HAL_OK) { @@ -430,60 +451,22 @@ int canfd_frequency(can_t *obj, int f, int data_f) * does not work for the desired bitrate, change system_clock settings for FDCAN_CLK * (default FDCAN_CLK is PLLQ) */ -#if (defined TARGET_STM32H7) - // STM32H7 doesn't support yet HAL_RCCEx_GetPeriphCLKFreq for FDCAN - PLL1_ClocksTypeDef pll1_clocks; - HAL_RCCEx_GetPLL1ClockFreq(&pll1_clocks); - uint32_t ntq = pll1_clocks.PLL1_Q_Frequency / (uint32_t)f; -#else -#if (defined RCC_PERIPHCLK_FDCAN1) - uint32_t ntq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN1) / (uint32_t)f; -#else - uint32_t ntq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN) / (uint32_t)f; -#endif -#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% - while (!IS_FDCAN_NOMINAL_TSEG1(ntq / nominalPrescaler)) { - nominalPrescaler ++; - if (!IS_FDCAN_NOMINAL_PRESCALER(nominalPrescaler)) { - error("Could not determine good nominalPrescaler. Bad clock value\n"); - } - } - ntq = ntq / nominalPrescaler; + uint32_t ntq = 0; + uint32_t nominalPrescaler = get_canfd_nominal_prescaler(f, &ntq); uint32_t ntq_data = ntq; - + uint32_t dataPrescaler = 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; + dataPrescaler = get_canfd_data_prescaler(data_f, &ntq_data); } obj->CanHandle.Init.Mode = FDCAN_MODE_NORMAL; obj->CanHandle.Init.AutoRetransmission = ENABLE; @@ -548,12 +531,10 @@ int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t } -int can_write(can_t *obj, CAN_Message msg, int cc) +int can_write(can_t *obj, CAN_Message msg) { FDCAN_TxHeaderTypeDef TxHeader = {0}; - UNUSED(cc); - // Configure Tx buffer message TxHeader.Identifier = msg.id; if (msg.format == CANStandard) { @@ -581,12 +562,10 @@ int can_write(can_t *obj, CAN_Message msg, int cc) return 1; } -int canfd_write(can_t *obj, CANFD_Message msg, int cc) +int canfd_write(can_t *obj, CANFD_Message msg) { FDCAN_TxHeaderTypeDef TxHeader = {0}; - UNUSED(cc); - // Configure Tx buffer message TxHeader.Identifier = msg.id; if (msg.format == CANStandard) { @@ -1270,7 +1249,7 @@ int can_frequency(can_t *obj, int f) return status; } -int can_write(can_t *obj, CAN_Message msg, int cc) +int can_write(can_t *obj, CAN_Message msg) { uint32_t transmitmailbox = CAN_TXSTATUS_NOMAILBOX; CAN_TypeDef *can = obj->CanHandle.Instance; diff --git a/targets/TARGET_STM/sleep.c b/targets/TARGET_STM/sleep.c index 32bfc4e4b27..0ae2e9dcbeb 100644 --- a/targets/TARGET_STM/sleep.c +++ b/targets/TARGET_STM/sleep.c @@ -266,12 +266,9 @@ __WEAK void hal_deepsleep(void) * 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 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 diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/can_api.c b/targets/TARGET_Silicon_Labs/TARGET_EFM32/can_api.c index 412e9a0bf4c..e506c4b44f7 100644 --- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/can_api.c +++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/can_api.c @@ -163,7 +163,7 @@ int can_frequency(can_t *obj, int f) return 0; } -int can_write(can_t *obj, CAN_Message msg, int cc) +int can_write(can_t *obj, CAN_Message msg) { CAN_MessageObject_TypeDef message; diff --git a/targets/targets.json5 b/targets/targets.json5 index 0d9c4080828..a88aa936109 100644 --- a/targets/targets.json5 +++ b/targets/targets.json5 @@ -4923,7 +4923,7 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "macro_name": "CLOCK_SOURCE" }, "hse_value": { - "help": "HSE default value is 16MHz in stm32u5xx_hal_conf.h", + "help": "HSE default value is 16MHz in stm32u5xx_hal_conf.h, The valid value range is between 4MHz and 50MHz", "value": "16000000", "macro_name": "HSE_VALUE" }, From 1b5eb70d1a0b2bae6f9eb553e1ae9212c85007e0 Mon Sep 17 00:00:00 2001 From: wdx04 <25487439@qq.com> Date: Sun, 27 Jul 2025 19:45:13 +0800 Subject: [PATCH 09/14] retrigger checks From 52934998f35a3aee4c555c0a022b78f9d7ccfb8a Mon Sep 17 00:00:00 2001 From: wdx04 <25487439@qq.com> Date: Mon, 28 Jul 2025 09:01:10 +0800 Subject: [PATCH 10/14] pass CAN FD input clock as a parameter to get_canfd_nominal_prescaler/get_canfd_data_prescaler functions --- targets/TARGET_STM/can_api.c | 64 +++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/targets/TARGET_STM/can_api.c b/targets/TARGET_STM/can_api.c index ba1d47b9a40..bdb14bb34ef 100644 --- a/targets/TARGET_STM/can_api.c +++ b/targets/TARGET_STM/can_api.c @@ -78,20 +78,9 @@ int can_internal_init(can_t *obj) /** Get the nominal phase clock prescaler and the number of time quantums for the specified frequency */ -static uint32_t get_canfd_nominal_prescaler(int f, uint32_t *ntq_out) +static uint32_t get_canfd_nominal_prescaler(uint32_t input_f, int f, uint32_t *ntq_out) { -#if (defined TARGET_STM32H7) - // STM32H7 doesn't support yet HAL_RCCEx_GetPeriphCLKFreq for FDCAN - PLL1_ClocksTypeDef pll1_clocks; - HAL_RCCEx_GetPLL1ClockFreq(&pll1_clocks); - uint32_t ntq = pll1_clocks.PLL1_Q_Frequency / (uint32_t)f; -#else -#if (defined RCC_PERIPHCLK_FDCAN1) - uint32_t ntq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN1) / (uint32_t)f; -#else - uint32_t ntq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN) / (uint32_t)f; -#endif -#endif + uint32_t ntq = input_f / (uint32_t)f; uint32_t nominalPrescaler = 1; // !When the sample point should be lower than 50%, this must be changed to // !IS_FDCAN_NOMINAL_TSEG2(ntq/nominalPrescaler), since @@ -108,21 +97,12 @@ static uint32_t get_canfd_nominal_prescaler(int f, uint32_t *ntq_out) /** Get the data phase clock prescaler and the number of time quantums for the specified frequency */ -static uint32_t get_canfd_data_prescaler(int data_f, uint32_t *ntq_out) +static uint32_t get_canfd_data_prescaler(uint32_t input_f, int data_f, uint32_t *ntq_out) { -#if (defined TARGET_STM32H7) - // STM32H7 doesn't support yet HAL_RCCEx_GetPeriphCLKFreq for FDCAN - PLL1_ClocksTypeDef pll1_clocks; - HAL_RCCEx_GetPLL1ClockFreq(&pll1_clocks); - uint32_t ntq_data = pll1_clocks.PLL1_Q_Frequency / (uint32_t)data_f; -#elif (defined RCC_PERIPHCLK_FDCAN1) - uint32_t ntq_data = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN1) / (uint32_t)data_f; -#else - uint32_t ntq_data = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN) / (uint32_t)data_f; -#endif + uint32_t ntq_data = input_f / (uint32_t)data_f; 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 + // !IS_FDCAN_DATA_TSEG2(ntq_data/dataPrescaler), since // NTSEG2 and SJW max values are lower. For now the sample point is fix @70% while (!IS_FDCAN_DATA_TSEG1(ntq_data / dataPrescaler)) { dataPrescaler ++; @@ -224,8 +204,20 @@ static void _canfd_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int * does not work for the desired bitrate, change system_clock settings for FDCAN_CLK * (default FDCAN_CLK is PLLQ) */ +#if (defined TARGET_STM32H7) + // STM32H7 doesn't support yet HAL_RCCEx_GetPeriphCLKFreq for FDCAN + PLL1_ClocksTypeDef pll1_clocks; + HAL_RCCEx_GetPLL1ClockFreq(&pll1_clocks); + uint32_t input_hz = pll1_clocks.PLL1_Q_Frequency; +#else +#if (defined RCC_PERIPHCLK_FDCAN1) + uint32_t input_hz = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN1); +#else + uint32_t input_hz = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN); +#endif +#endif uint32_t ntq = 0; - uint32_t nominalPrescaler = get_canfd_nominal_prescaler(hz, &ntq); + uint32_t nominalPrescaler = get_canfd_nominal_prescaler(input_hz, hz, &ntq); uint32_t ntq_data = ntq; uint32_t dataPrescaler = nominalPrescaler; if(data_hz == 0) @@ -239,7 +231,7 @@ static void _canfd_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int else { obj->CanHandle.Init.FrameFormat = FDCAN_FRAME_FD_BRS; - dataPrescaler = get_canfd_data_prescaler(data_hz, &ntq_data); + dataPrescaler = get_canfd_data_prescaler(input_hz, data_hz, &ntq_data); } obj->CanHandle.Init.Mode = FDCAN_MODE_NORMAL; obj->CanHandle.Init.AutoRetransmission = ENABLE; @@ -451,8 +443,20 @@ int canfd_frequency(can_t *obj, int f, int data_f) * does not work for the desired bitrate, change system_clock settings for FDCAN_CLK * (default FDCAN_CLK is PLLQ) */ +#if (defined TARGET_STM32H7) + // STM32H7 doesn't support yet HAL_RCCEx_GetPeriphCLKFreq for FDCAN + PLL1_ClocksTypeDef pll1_clocks; + HAL_RCCEx_GetPLL1ClockFreq(&pll1_clocks); + uint32_t input_f = pll1_clocks.PLL1_Q_Frequency; +#else +#if (defined RCC_PERIPHCLK_FDCAN1) + uint32_t input_f = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN1); +#else + uint32_t input_f = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_FDCAN); +#endif +#endif uint32_t ntq = 0; - uint32_t nominalPrescaler = get_canfd_nominal_prescaler(f, &ntq); + uint32_t nominalPrescaler = get_canfd_nominal_prescaler(input_f, f, &ntq); uint32_t ntq_data = ntq; uint32_t dataPrescaler = nominalPrescaler; if(data_f == 0) @@ -466,7 +470,7 @@ int canfd_frequency(can_t *obj, int f, int data_f) else { obj->CanHandle.Init.FrameFormat = FDCAN_FRAME_FD_BRS; - dataPrescaler = get_canfd_data_prescaler(data_f, &ntq_data); + dataPrescaler = get_canfd_data_prescaler(input_f, data_f, &ntq_data); } obj->CanHandle.Init.Mode = FDCAN_MODE_NORMAL; obj->CanHandle.Init.AutoRetransmission = ENABLE; @@ -1723,4 +1727,4 @@ const PinMap *can_td_pinmap() return PinMap_CAN_RD; } -#endif // DEVICE_CAN +#endif // DEVICE_CAN \ No newline at end of file From c12ac693759432c9f69eca8c472c80f4ca2351eb Mon Sep 17 00:00:00 2001 From: wdx04 <25487439@qq.com> Date: Wed, 30 Jul 2025 14:01:40 +0800 Subject: [PATCH 11/14] combine canfd_init_freq(), canfd_init_freq_direct(), and canfd_frequency() with the existing functions minor fixes on documentation --- drivers/source/CAN.cpp | 6 +-- hal/include/hal/can_api.h | 86 +++++++++++++++--------------------- hal/include/hal/can_helper.h | 20 ++++----- hal/source/static_pinmap.cpp | 13 +++++- targets/TARGET_STM/can_api.c | 39 ++++------------ targets/targets.json5 | 2 +- 6 files changed, 71 insertions(+), 95 deletions(-) diff --git a/drivers/source/CAN.cpp b/drivers/source/CAN.cpp index e0165349053..0694ab8ce9c 100644 --- a/drivers/source/CAN.cpp +++ b/drivers/source/CAN.cpp @@ -34,7 +34,7 @@ CAN::CAN(PinName rd, PinName td, int hz, int data_hz) : _can(), _irq() { // No lock needed in constructor #if DEVICE_CAN_FD - canfd_init_freq(&_can, rd, td, hz, data_hz); + can_init_freq(&_can, rd, td, hz, data_hz); #else MBED_ASSERT(data_hz == 0); can_init_freq(&_can, rd, td, hz); @@ -53,7 +53,7 @@ CAN::CAN(const can_pinmap_t &pinmap, int hz, int data_hz) : _can(), _irq() { // No lock needed in constructor #if DEVICE_CAN_FD - canfd_init_freq_direct(&_can, &pinmap, hz, data_hz); + can_init_freq_direct(&_can, &pinmap, hz, data_hz); #else MBED_ASSERT(data_hz == 0); can_init_freq_direct(&_can, &pinmap, hz); @@ -77,7 +77,7 @@ int CAN::frequency(int f, int data_f) { lock(); #if DEVICE_CAN_FD - int ret = canfd_frequency(&_can, f, data_f); + int ret = can_frequency(&_can, f, data_f); #else MBED_ASSERT(data_f == 0); int ret = can_frequency(&_can, f); diff --git a/hal/include/hal/can_api.h b/hal/include/hal/can_api.h index 49ed718c855..043ed9cdaf7 100644 --- a/hal/include/hal/can_api.h +++ b/hal/include/hal/can_api.h @@ -74,7 +74,7 @@ typedef struct can_s can_t; * @param rd The CAN RD pin name * @param td The CAN TD pin name */ -void can_init(can_t *obj, PinName rd, PinName td); +void can_init(can_t *obj, PinName rd, PinName td); /** Initialize the CAN peripheral. It sets the default parameters for CAN * peripheral, and configures its specifieds pins. @@ -82,7 +82,7 @@ void can_init(can_t *obj, PinName rd, PinName td); * @param obj The CAN object * @param pinmap pointer to structure which holds static pinmap */ -void can_init_direct(can_t *obj, const can_pinmap_t *pinmap); +void can_init_direct(can_t *obj, const can_pinmap_t *pinmap); /** Initialize the CAN peripheral. It sets the default parameters for CAN * peripheral, and configures its specifieds pins. @@ -90,32 +90,47 @@ void can_init_direct(can_t *obj, const can_pinmap_t *pinmap); * @param obj CAN object * @param rd The CAN RD pin name * @param td The CAN TD pin name - * @param hz The bus frequency + * @param hz The bus frequency in classical CAN mode, or nominal phase frequency in CAN FD mode + * @param data_hz The data phase frequency in CAN FD mode, the CAN object is put into Classical CAN mode if this parameter is zero */ -void can_init_freq(can_t *obj, PinName rd, PinName td, int hz); +void can_init_freq(can_t *obj, PinName rd, PinName td, int hz +#ifdef DEVICE_CAN_FD + , int data_hz +#endif + ); /** Initialize the CAN peripheral. It sets the default parameters for CAN * peripheral, and configures its specifieds pins. * * @param obj CAN object * @param pinmap pointer to structure which holds static pinmap - * @param hz The bus frequency + * @param hz The bus frequency in classical CAN mode, or nominal phase frequency in CAN FD mode + * @param data_hz The data phase frequency in CAN FD mode, the CAN object is put into Classical CAN mode if this parameter is zero */ -void can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz); +void can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz +#ifdef DEVICE_CAN_FD + , int data_hz +#endif + ); /** Release the CAN peripheral, not currently invoked. It requires further * resource management. * * @param obj The CAN object */ -void can_free(can_t *obj); +void can_free(can_t *obj); /** Configure the CAN bus frequency * * @param obj The CAN object - * @param hz The bus frequency + * @param hz The bus frequency in classical CAN mode, or nominal phase frequency in CAN FD mode + * @param data_hz The data phase frequency in CAN FD mode, the CAN object is put into Classical CAN mode if this parameter is zero */ -int can_frequency(can_t *obj, int hz); +int can_frequency(can_t *obj, int hz +#ifdef DEVICE_CAN_FD + , int data_hz +#endif + ); /** Initialize the CAN IRQ handler * @@ -123,13 +138,13 @@ int can_frequency(can_t *obj, int hz); * @param handler The handler to be attached to CAN IRQ * @param context The context to be passed back to the handler (context != 0, 0 is reserved) */ -void can_irq_init(can_t *obj, can_irq_handler handler, uintptr_t context); +void can_irq_init(can_t *obj, can_irq_handler handler, uintptr_t context); -/** Release the CAN object +/** Remove the CAN IRQ handler * * @param obj The CAN object */ -void can_irq_free(can_t *obj); +void can_irq_free(can_t *obj); /** Enable/disable the CAN IRQ event * @@ -137,7 +152,7 @@ void can_irq_free(can_t *obj); * @param irq The CAN IRQ event * @param enable The enable flag */ -void can_irq_set(can_t *obj, CanIrqType irq, uint32_t enable); +void can_irq_set(can_t *obj, CanIrqType irq, uint32_t enable); /** Write a CAN message to the bus. * @@ -147,7 +162,7 @@ void can_irq_set(can_t *obj, CanIrqType irq, uint32_t enable); * @return 0 if write failed, * 1 if write was successful */ -int can_write(can_t *obj, CAN_Message msg); +int can_write(can_t *obj, CAN_Message msg); /** Read a CAN message from the bus. * @@ -158,7 +173,7 @@ int can_write(can_t *obj, CAN_Message msg); * @return 0 if no message arrived, * 1 if message arrived */ -int can_read(can_t *obj, CAN_Message *msg, int handle); +int can_read(can_t *obj, CAN_Message *msg, int handle); /** Change CAN operation to the specified mode. * @@ -168,7 +183,7 @@ int can_read(can_t *obj, CAN_Message *msg, int handle); * @return 0 if mode change failed or unsupported, * 1 if mode change was successful */ -int can_mode(can_t *obj, CanMode mode); +int can_mode(can_t *obj, CanMode mode); /** Filter out incomming messages. * @@ -181,7 +196,7 @@ int can_mode(can_t *obj, CanMode mode); * @return 0 if filter change failed or unsupported, * new filter handle if successful */ -int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle); +int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle); /** Reset CAN interface. * @@ -189,7 +204,7 @@ int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat forma * * To use after error overflow. */ -void can_reset(can_t *obj); +void can_reset(can_t *obj); /** Detects read errors - Used to detect read overflow errors. * @@ -210,38 +225,9 @@ unsigned char can_tderror(can_t *obj); * @param obj CAN object * @param silent boolean indicating whether to go into silent mode or not. */ -void can_monitor(can_t *obj, int silent); +void can_monitor(can_t *obj, int silent); #if DEVICE_CAN_FD -/** Initialize the CAN FD peripheral. It sets the default parameters for CAN FD - * peripheral, and configures its specifieds pins. - * - * @param obj CAN object - * @param rd The CAN RD pin name - * @param td The CAN TD pin name - * @param hz The bus frequency of nominal phase - * @param data_hz The bus frequency of data phase, the CAN object is put into Classical CAN mode if this parameter is zero - */ -void canfd_init_freq(can_t *obj, PinName rd, PinName td, int hz, int data_hz); - -/** Initialize the CAN FD peripheral. It sets the default parameters for CAN FD - * peripheral, and configures its specifieds pins. - * - * @param obj CAN object - * @param pinmap pointer to structure which holds static pinmap - * @param hz The bus frequency of nominal phase - * @param data_hz The bus frequency of data phase, the CAN object is put into Classical CAN mode if this parameter is zero - */ -void canfd_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz, int data_hz); - -/** Configure the CAN FD bus frequency - * - * @param obj The CAN object - * @param hz The bus frequency of nominal phase - * @param data_hz The bus frequency of data phase, the CAN object is put into Classical CAN mode if this parameter is zero - */ -int canfd_frequency(can_t *obj, int hz, int data_hz); - /** Write a CAN FD Message to the bus. * * @param obj The CAN object @@ -250,7 +236,7 @@ int canfd_frequency(can_t *obj, int hz, int data_hz); * @return 0 if write failed, * 1 if write was successful */ -int canfd_write(can_t *obj, CANFD_Message msg); +int canfd_write(can_t *obj, CANFD_Message msg); /** Read a Classical CAN or CAN FD Message from the bus. * @@ -261,7 +247,7 @@ int canfd_write(can_t *obj, CANFD_Message msg); * @return 0 if no message arrived, * 1 if message arrived */ -int canfd_read(can_t *obj, CANFD_Message *msg, int handle); +int canfd_read(can_t *obj, CANFD_Message *msg, int handle); #endif /** Get the pins that support CAN RD diff --git a/hal/include/hal/can_helper.h b/hal/include/hal/can_helper.h index 0f67ce4cfe8..a2ecccab3e0 100644 --- a/hal/include/hal/can_helper.h +++ b/hal/include/hal/can_helper.h @@ -59,11 +59,11 @@ typedef enum CANType CANType; * **/ struct CAN_Message { - unsigned int id; // 29 bit identifier - unsigned char data[8]; // Data field - unsigned char len; // Length of data field in bytes - CANFormat format; // Format ::CANFormat - CANType type; // Type ::CANType + unsigned int id; ///< 29 bit identifier + unsigned char data[8]; ///< Data field + unsigned char len; ///< Length of data field in bytes + CANFormat format; ///< Format ::CANFormat + CANType type; ///< Type ::CANType }; typedef struct CAN_Message CAN_Message; @@ -77,11 +77,11 @@ typedef struct CAN_Message 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 + 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; diff --git a/hal/source/static_pinmap.cpp b/hal/source/static_pinmap.cpp index fe004c3c302..512264e53fb 100644 --- a/hal/source/static_pinmap.cpp +++ b/hal/source/static_pinmap.cpp @@ -74,6 +74,17 @@ MBED_WEAK void serial_set_flow_control_direct(serial_t *obj, FlowControl type, c #endif #if DEVICE_CAN +#if DEVICE_CAN_FD +MBED_WEAK void can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz, int data_hz) +{ + can_init_freq(obj, pinmap->rd_pin, pinmap->td_pin, hz, data_hz); +} + +MBED_WEAK void can_init_direct(can_t *obj, const can_pinmap_t *pinmap) +{ + can_init(obj, pinmap->rd_pin, pinmap->td_pin); +} +#else MBED_WEAK void can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz) { can_init_freq(obj, pinmap->rd_pin, pinmap->td_pin, hz); @@ -83,7 +94,7 @@ MBED_WEAK void can_init_direct(can_t *obj, const can_pinmap_t *pinmap) { can_init(obj, pinmap->rd_pin, pinmap->td_pin); } - +#endif #endif #if DEVICE_QSPI diff --git a/targets/TARGET_STM/can_api.c b/targets/TARGET_STM/can_api.c index bdb14bb34ef..16f36e3fc2c 100644 --- a/targets/TARGET_STM/can_api.c +++ b/targets/TARGET_STM/can_api.c @@ -115,11 +115,11 @@ static uint32_t get_canfd_data_prescaler(uint32_t input_f, int data_f, uint32_t } #if STATIC_PINMAP_READY -#define CANFD_INIT_FREQ_DIRECT canfd_init_freq_direct -void canfd_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz) +#define CAN_INIT_FREQ_DIRECT can_init_freq_direct +void can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz, int data_hz) #else -#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) +#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, int data_hz) #endif { MBED_ASSERT((int)pinmap->peripheral != NC); @@ -301,24 +301,13 @@ static void _canfd_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int 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); + can_init_freq_direct(obj, pinmap, 100000, 0); } -void canfd_init_freq(can_t *obj, PinName rd, PinName td, int hz, int data_hz) +void can_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); @@ -329,17 +318,12 @@ void canfd_init_freq(can_t *obj, PinName rd, PinName td, int hz, int data_hz) const can_pinmap_t static_pinmap = {peripheral, rd, function_rd, td, function_td}; - 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); + CAN_INIT_FREQ_DIRECT(obj, &static_pinmap, hz, data_hz); } void can_init(can_t *obj, PinName rd, PinName td) { - can_init_freq(obj, rd, td, 100000); + can_init_freq(obj, rd, td, 100000, 0); } void can_irq_init(can_t *obj, can_irq_handler handler, uintptr_t context) @@ -427,7 +411,7 @@ void can_reset(can_t *obj) HAL_FDCAN_ResetTimestampCounter(&obj->CanHandle); } -int canfd_frequency(can_t *obj, int f, int data_f) +int can_frequency(can_t *obj, int f, int data_f) { if (HAL_FDCAN_Stop(&obj->CanHandle) != HAL_OK) { error("HAL_FDCAN_Stop error\n"); @@ -488,11 +472,6 @@ int canfd_frequency(can_t *obj, int f, int data_f) return can_internal_init(obj); } -int can_frequency(can_t *obj, int f) -{ - return canfd_frequency(obj, f, 0); -} - /** Filter out incoming messages * * @param obj CAN object diff --git a/targets/targets.json5 b/targets/targets.json5 index a88aa936109..f7b5262cada 100644 --- a/targets/targets.json5 +++ b/targets/targets.json5 @@ -4923,7 +4923,7 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "macro_name": "CLOCK_SOURCE" }, "hse_value": { - "help": "HSE default value is 16MHz in stm32u5xx_hal_conf.h, The valid value range is between 4MHz and 50MHz", + "help": "HSE default value is 16MHz in stm32u5xx_hal_conf.h, The effective value is within the range of 4MHz to 50MHz and can be divided by 4MHz or 5MHz.", "value": "16000000", "macro_name": "HSE_VALUE" }, From 78b37fdce6b1c3eebdeb7b0f5f624f5c18d7ca88 Mon Sep 17 00:00:00 2001 From: wdx04 <25487439@qq.com> Date: Wed, 30 Jul 2025 14:54:34 +0800 Subject: [PATCH 12/14] try to fix the Doxygen and style problem --- hal/include/hal/can_api.h | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/hal/include/hal/can_api.h b/hal/include/hal/can_api.h index 043ed9cdaf7..c6e1362e98f 100644 --- a/hal/include/hal/can_api.h +++ b/hal/include/hal/can_api.h @@ -90,28 +90,36 @@ void can_init_direct(can_t *obj, const can_pinmap_t *pinmap); * @param obj CAN object * @param rd The CAN RD pin name * @param td The CAN TD pin name +#ifdef DEVICE_CAN_FD * @param hz The bus frequency in classical CAN mode, or nominal phase frequency in CAN FD mode * @param data_hz The data phase frequency in CAN FD mode, the CAN object is put into Classical CAN mode if this parameter is zero +#else + * @param hz The bus frequency +#endif */ void can_init_freq(can_t *obj, PinName rd, PinName td, int hz #ifdef DEVICE_CAN_FD - , int data_hz + , int data_hz #endif - ); + ); /** Initialize the CAN peripheral. It sets the default parameters for CAN * peripheral, and configures its specifieds pins. * * @param obj CAN object * @param pinmap pointer to structure which holds static pinmap +#ifdef DEVICE_CAN_FD * @param hz The bus frequency in classical CAN mode, or nominal phase frequency in CAN FD mode * @param data_hz The data phase frequency in CAN FD mode, the CAN object is put into Classical CAN mode if this parameter is zero +#else + * @param hz The bus frequency +#endif */ void can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz #ifdef DEVICE_CAN_FD - , int data_hz + , int data_hz #endif - ); + ); /** Release the CAN peripheral, not currently invoked. It requires further * resource management. @@ -123,14 +131,18 @@ void can_free(can_t *obj); /** Configure the CAN bus frequency * * @param obj The CAN object +#ifdef DEVICE_CAN_FD * @param hz The bus frequency in classical CAN mode, or nominal phase frequency in CAN FD mode * @param data_hz The data phase frequency in CAN FD mode, the CAN object is put into Classical CAN mode if this parameter is zero +#else + * @param hz The bus frequency +#endif */ int can_frequency(can_t *obj, int hz #ifdef DEVICE_CAN_FD - , int data_hz + , int data_hz #endif - ); + ); /** Initialize the CAN IRQ handler * From a0c1a64e1f75ac8b421cf9a2b8ac30a661eabdbe Mon Sep 17 00:00:00 2001 From: wdx04 <25487439@qq.com> Date: Wed, 30 Jul 2025 15:31:54 +0800 Subject: [PATCH 13/14] separate the CAN FD and non-CAN FD declarations of can_init_freq, can_init_freq_direct, can_frequency functions --- hal/include/hal/can_api.h | 50 +++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/hal/include/hal/can_api.h b/hal/include/hal/can_api.h index c6e1362e98f..c731927fcdf 100644 --- a/hal/include/hal/can_api.h +++ b/hal/include/hal/can_api.h @@ -84,42 +84,48 @@ void can_init(can_t *obj, PinName rd, PinName td); */ void can_init_direct(can_t *obj, const can_pinmap_t *pinmap); +#if DEVICE_CAN_FD /** Initialize the CAN peripheral. It sets the default parameters for CAN * peripheral, and configures its specifieds pins. * * @param obj CAN object * @param rd The CAN RD pin name * @param td The CAN TD pin name -#ifdef DEVICE_CAN_FD * @param hz The bus frequency in classical CAN mode, or nominal phase frequency in CAN FD mode * @param data_hz The data phase frequency in CAN FD mode, the CAN object is put into Classical CAN mode if this parameter is zero -#else - * @param hz The bus frequency -#endif */ -void can_init_freq(can_t *obj, PinName rd, PinName td, int hz -#ifdef DEVICE_CAN_FD - , int data_hz -#endif - ); +void can_init_freq(can_t *obj, PinName rd, PinName td, int hz, int data_hz); /** Initialize the CAN peripheral. It sets the default parameters for CAN * peripheral, and configures its specifieds pins. * * @param obj CAN object * @param pinmap pointer to structure which holds static pinmap -#ifdef DEVICE_CAN_FD * @param hz The bus frequency in classical CAN mode, or nominal phase frequency in CAN FD mode * @param data_hz The data phase frequency in CAN FD mode, the CAN object is put into Classical CAN mode if this parameter is zero + */ +void can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz, int data_hz); + #else +/** Initialize the CAN peripheral. It sets the default parameters for CAN + * peripheral, and configures its specifieds pins. + * + * @param obj CAN object + * @param rd The CAN RD pin name + * @param td The CAN TD pin name * @param hz The bus frequency -#endif */ -void can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz -#ifdef DEVICE_CAN_FD - , int data_hz +void can_init_freq(can_t *obj, PinName rd, PinName td, int hz); + +/** Initialize the CAN peripheral. It sets the default parameters for CAN + * peripheral, and configures its specifieds pins. + * + * @param obj CAN object + * @param pinmap pointer to structure which holds static pinmap + * @param hz The bus frequency + */ +void can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz); #endif - ); /** Release the CAN peripheral, not currently invoked. It requires further * resource management. @@ -128,21 +134,23 @@ void can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz */ void can_free(can_t *obj); +#if DEVICE_CAN_FD /** Configure the CAN bus frequency * * @param obj The CAN object -#ifdef DEVICE_CAN_FD * @param hz The bus frequency in classical CAN mode, or nominal phase frequency in CAN FD mode * @param data_hz The data phase frequency in CAN FD mode, the CAN object is put into Classical CAN mode if this parameter is zero + */ +int can_frequency(can_t *obj, int hz, int data_hz); + #else +/** Configure the CAN bus frequency + * + * @param obj The CAN object * @param hz The bus frequency -#endif */ -int can_frequency(can_t *obj, int hz -#ifdef DEVICE_CAN_FD - , int data_hz +int can_frequency(can_t *obj, int hz); #endif - ); /** Initialize the CAN IRQ handler * From 3223746ad0e1884ba68ace31e64d66cc28f1ee34 Mon Sep 17 00:00:00 2001 From: wdx04 <25487439@qq.com> Date: Thu, 31 Jul 2025 09:18:15 +0800 Subject: [PATCH 14/14] added DEVICE_CAN_FD definition in doxyfile_options --- doxyfile_options | 1 + hal/include/hal/can_api.h | 46 +++++++++++---------------------------- 2 files changed, 14 insertions(+), 33 deletions(-) diff --git a/doxyfile_options b/doxyfile_options index 7aa754c1aff..c914aa1c395 100644 --- a/doxyfile_options +++ b/doxyfile_options @@ -2305,6 +2305,7 @@ PREDEFINED = DOXYGEN_ONLY \ DEVICE_ANALOGIN \ DEVICE_ANALOGOUT \ DEVICE_CAN \ + DEVICE_CAN_FD \ DEVICE_CRC \ DEVICE_EMAC \ DEVICE_FLASH \ diff --git a/hal/include/hal/can_api.h b/hal/include/hal/can_api.h index c731927fcdf..459aea83fd1 100644 --- a/hal/include/hal/can_api.h +++ b/hal/include/hal/can_api.h @@ -84,7 +84,6 @@ void can_init(can_t *obj, PinName rd, PinName td); */ void can_init_direct(can_t *obj, const can_pinmap_t *pinmap); -#if DEVICE_CAN_FD /** Initialize the CAN peripheral. It sets the default parameters for CAN * peripheral, and configures its specifieds pins. * @@ -94,7 +93,11 @@ void can_init_direct(can_t *obj, const can_pinmap_t *pinmap); * @param hz The bus frequency in classical CAN mode, or nominal phase frequency in CAN FD mode * @param data_hz The data phase frequency in CAN FD mode, the CAN object is put into Classical CAN mode if this parameter is zero */ -void can_init_freq(can_t *obj, PinName rd, PinName td, int hz, int data_hz); +void can_init_freq(can_t *obj, PinName rd, PinName td, int hz +#ifdef DEVICE_CAN_FD + , int data_hz +#endif + ); /** Initialize the CAN peripheral. It sets the default parameters for CAN * peripheral, and configures its specifieds pins. @@ -104,28 +107,11 @@ void can_init_freq(can_t *obj, PinName rd, PinName td, int hz, int data_hz); * @param hz The bus frequency in classical CAN mode, or nominal phase frequency in CAN FD mode * @param data_hz The data phase frequency in CAN FD mode, the CAN object is put into Classical CAN mode if this parameter is zero */ -void can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz, int data_hz); - -#else -/** Initialize the CAN peripheral. It sets the default parameters for CAN - * peripheral, and configures its specifieds pins. - * - * @param obj CAN object - * @param rd The CAN RD pin name - * @param td The CAN TD pin name - * @param hz The bus frequency - */ -void can_init_freq(can_t *obj, PinName rd, PinName td, int hz); - -/** Initialize the CAN peripheral. It sets the default parameters for CAN - * peripheral, and configures its specifieds pins. - * - * @param obj CAN object - * @param pinmap pointer to structure which holds static pinmap - * @param hz The bus frequency - */ -void can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz); +void can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz +#ifdef DEVICE_CAN_FD + , int data_hz #endif + ); /** Release the CAN peripheral, not currently invoked. It requires further * resource management. @@ -134,23 +120,17 @@ void can_init_freq_direct(can_t *obj, const can_pinmap_t *pinmap, int hz); */ void can_free(can_t *obj); -#if DEVICE_CAN_FD /** Configure the CAN bus frequency * * @param obj The CAN object * @param hz The bus frequency in classical CAN mode, or nominal phase frequency in CAN FD mode * @param data_hz The data phase frequency in CAN FD mode, the CAN object is put into Classical CAN mode if this parameter is zero */ -int can_frequency(can_t *obj, int hz, int data_hz); - -#else -/** Configure the CAN bus frequency - * - * @param obj The CAN object - * @param hz The bus frequency - */ -int can_frequency(can_t *obj, int hz); +int can_frequency(can_t *obj, int hz +#ifdef DEVICE_CAN_FD + , int data_hz #endif + ); /** Initialize the CAN IRQ handler *