You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by je...@apache.org on 2025/10/24 16:47:07 UTC

(mynewt-core) branch master updated (d19b64f03 -> 352fb7cad)

This is an automated email from the ASF dual-hosted git repository.

jerzy pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git


    from d19b64f03 ci: No fail verdicts on remove workflow
     new 1044336da hw/mcu/stm32f4: Add PLL helper functions
     new 352fb7cad hw/mcu/stm32f4: Update mcu info command

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../stm/stm32f4xx/include/mcu/clock_stm32f4xx.h}   |  65 ++++---
 hw/mcu/stm/stm32f4xx/mcu_cli/src/mcu_cli.c         | 188 ++++++++++++++-------
 hw/mcu/stm/stm32f4xx/src/clock_stm32f4xx.c         |  88 +++++++++-
 3 files changed, 258 insertions(+), 83 deletions(-)
 copy hw/{hal/include/hal/hal_nvreg.h => mcu/stm/stm32f4xx/include/mcu/clock_stm32f4xx.h} (51%)


(mynewt-core) 01/02: hw/mcu/stm32f4: Add PLL helper functions

Posted by je...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jerzy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git

commit 1044336da6111341ce9607c8b0870aa84103d993
Author: Jerzy Kasenberg <je...@codecoup.pl>
AuthorDate: Thu Oct 23 22:26:28 2025 +0200

    hw/mcu/stm32f4: Add PLL helper functions
    
    This adds several function for PLL frequency checking.
    
    Signed-off-by: Jerzy Kasenberg <je...@apache.org>
---
 hw/mcu/stm/stm32f4xx/include/mcu/clock_stm32f4xx.h | 83 ++++++++++++++++++++
 hw/mcu/stm/stm32f4xx/src/clock_stm32f4xx.c         | 88 +++++++++++++++++++++-
 2 files changed, 169 insertions(+), 2 deletions(-)

diff --git a/hw/mcu/stm/stm32f4xx/include/mcu/clock_stm32f4xx.h b/hw/mcu/stm/stm32f4xx/include/mcu/clock_stm32f4xx.h
new file mode 100644
index 000000000..8ac14a5b0
--- /dev/null
+++ b/hw/mcu/stm/stm32f4xx/include/mcu/clock_stm32f4xx.h
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef __MCU_CLOCK_STM32F4XX_H_
+#define __MCU_CLOCK_STM32F4XX_H_
+
+#include <stdint.h>
+#include <stm32_common/mcu.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Return PLL VCO frequency
+ *
+ * @return PLL VCO frequency
+ */
+uint32_t stm32f4xx_pll_vco_freq(void);
+
+/**
+ * Return PLLI2S VCO frequency
+ *
+ * @return PLLI2S VCO frequency
+ */
+uint32_t stm32f4xx_plli2s_vco_freq(void);
+
+/**
+ * Return PLL P frequency (can be SYSCLK)
+ *
+ * @return PLL P frequency
+ */
+uint32_t stm32f4xx_pll_p_freq(void);
+
+/**
+ * Return PLL Q frequency (usually 48MHz)
+ *
+ * @return PLL Q frequency
+ */
+uint32_t stm32f4xx_pll_q_freq(void);
+
+/**
+ * Return PLL R frequency
+ *
+ * @return PLL R frequency
+ */
+uint32_t stm32f4xx_pll_r_freq(void);
+
+/**
+ * Return PLLI2S Q frequency
+ *
+ * @return PLLI2S Q frequency
+ */
+uint32_t stm32f4xx_plli2s_q_freq(void);
+
+/**
+ * Return PLLI2S R frequency
+ *
+ * @return PLLI2S R frequency
+ */
+uint32_t stm32f4xx_plli2s_r_freq(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MCU_CLOCK_STM32F4XX_H_ */
diff --git a/hw/mcu/stm/stm32f4xx/src/clock_stm32f4xx.c b/hw/mcu/stm/stm32f4xx/src/clock_stm32f4xx.c
index 6c305677d..b70420c64 100644
--- a/hw/mcu/stm/stm32f4xx/src/clock_stm32f4xx.c
+++ b/hw/mcu/stm/stm32f4xx/src/clock_stm32f4xx.c
@@ -24,9 +24,93 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "stm32f4xx_hal_pwr_ex.h"
-#include "stm32f4xx_hal.h"
 #include <assert.h>
+#include <stm32f4xx_hal_pwr_ex.h>
+#include <stm32f4xx_hal.h>
+#include <mcu/clock_stm32f4xx.h>
+
+#define FIELD_VAL(per, reg, field)                                            \
+    ((per->reg & per##_##reg##_##field##_Msk) >> per##_##reg##_##field##_Pos)
+
+uint32_t
+stm32f4xx_pll_vco_freq(void)
+{
+    uint32_t pll_vco;
+    uint32_t pll_source_freq;
+    uint32_t pll_m;
+
+    pll_source_freq = FIELD_VAL(RCC, PLLCFGR, PLLSRC) ? HSE_VALUE : HSI_VALUE;
+    pll_m = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;
+
+    pll_vco = (pll_source_freq / pll_m) * FIELD_VAL(RCC, PLLCFGR, PLLN);
+
+    return pll_vco;
+}
+
+uint32_t
+stm32f4xx_plli2s_vco_freq(void)
+{
+    uint32_t pll_vco;
+    uint32_t pll_source_freq;
+    uint32_t pll_m;
+
+#ifdef RCC_PLLI2SCFGR_PLLI2SSRC
+    pll_source_freq = FIELD_VAL(RCC, PLLI2SCFGR, PLLI2SSRC) ? HSE_VALUE : HSI_VALUE;
+    pll_m = FIELD_VAL(RCC, PLLI2SCFGR, PLLI2SM);
+#else
+    pll_source_freq = FIELD_VAL(RCC, PLLCFGR, PLLSRC) ? HSE_VALUE : HSI_VALUE;
+    pll_m = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;
+#endif
+
+    pll_vco = (pll_source_freq / pll_m);
+    pll_vco *= FIELD_VAL(RCC, PLLI2SCFGR, PLLI2SN);
+
+    return pll_vco;
+}
+
+uint32_t
+stm32f4xx_pll_p_freq(void)
+{
+    uint32_t pll_p = (FIELD_VAL(RCC, PLLCFGR, PLLP) + 1) * 2;
+
+    return stm32f4xx_pll_vco_freq() / pll_p;
+}
+
+uint32_t
+stm32f4xx_pll_q_freq(void)
+{
+    uint32_t pll_q = FIELD_VAL(RCC, PLLCFGR, PLLQ);
+
+    return stm32f4xx_pll_vco_freq() / pll_q;
+}
+
+#ifdef RCC_PLLCFGR_PLLR
+uint32_t
+stm32f4xx_pll_r_freq(void)
+{
+    uint32_t pll_r = FIELD_VAL(RCC, PLLCFGR, PLLR);
+
+    return stm32f4xx_pll_vco_freq() / pll_r;
+}
+#endif
+
+#ifdef RCC_PLLI2SCFGR_PLLP
+uint32_t
+stm32f4xx_plli2s_p_freq(void)
+{
+    uint32_t pll_p = (FIELD_VAL(RCC, PLLI2SCFGR, PLLP) + 1) * 2;
+
+    return stm32f4xx_plli2s_vco_freq() / pll_p;
+}
+#endif
+
+uint32_t
+stm32f4xx_plli2s_r_freq(void)
+{
+    uint32_t pll_r = FIELD_VAL(RCC, PLLI2SCFGR, PLLI2SR);
+
+    return stm32f4xx_pll_vco_freq() / pll_r;
+}
 
 /*
  * This allows an user to have a custom clock configuration by zeroing


(mynewt-core) 02/02: hw/mcu/stm32f4: Update mcu info command

Posted by je...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jerzy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git

commit 352fb7cad2262946688b3051db534296215c6b70
Author: Jerzy Kasenberg <je...@codecoup.pl>
AuthorDate: Thu Oct 23 22:34:00 2025 +0200

    hw/mcu/stm32f4: Update mcu info command
    
    Clocks are not printed with units
    instead of
    
    compat> /mcu info
    Clocks:
      SYSCLK: 168000000
        source PLL
      HSI: off
      HSE: on
      PLL: on
      LSI: on
      LSE: off
    
    Now output would look like this
    
    compat> /mcu info
    Clocks:
      SYSCLK: 168 MHz
        source PLL
      HSI: off
      HSE: on
      PLL: on
         PLLP: 168 MHz
         PLLQ: 48 MHz
      LSI: on
      LSE: off
      APB1 PCLK1: 42 MHz
        PWR    on
      APB2 PCLK2: 84 MHz
        USART1 on
        SDIO   on 1 MHz
        SYSCFG on
        TIM9   on 1 MHz
    
    Signed-off-by: Jerzy Kasenberg <je...@apache.org>
---
 hw/mcu/stm/stm32f4xx/mcu_cli/src/mcu_cli.c | 188 ++++++++++++++++++++---------
 1 file changed, 131 insertions(+), 57 deletions(-)

diff --git a/hw/mcu/stm/stm32f4xx/mcu_cli/src/mcu_cli.c b/hw/mcu/stm/stm32f4xx/mcu_cli/src/mcu_cli.c
index 349fe01b0..cbe28a8f4 100644
--- a/hw/mcu/stm/stm32f4xx/mcu_cli/src/mcu_cli.c
+++ b/hw/mcu/stm/stm32f4xx/mcu_cli/src/mcu_cli.c
@@ -23,6 +23,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <stm32f4xx_hal.h>
+#include <mcu/clock_stm32f4xx.h>
 #include <shell/shell.h>
 
 extern uint32_t SystemCoreClock;
@@ -35,10 +36,38 @@ on_off_state(uint32_t on)
     return on ? "on" : "off";
 }
 
+static char *
+freq_str(uint32_t freq, char buf[])
+{
+    int freq_m = (int)(freq / 1000000);
+    int freq_m_rem = (int)(freq % 1000000);
+    int freq_k = (int)(freq / 1000);
+    int freq_k_rem = (int)(freq % 1000);
+
+    if (freq == 0) {
+        strcpy(buf, "---");
+    } else if (freq_m && freq_m_rem == 0) {
+        sprintf(buf, "%d MHz", freq_m);
+    } else if (freq_m) {
+        while (freq_m_rem % 10 == 0) {
+            freq_m_rem /= 10;
+        }
+        sprintf(buf, "%d.%d MHz", freq_m, freq_m_rem);
+    } else if (freq_k && freq_k_rem == 0) {
+        sprintf(buf, "%d kHz", freq_k);
+    } else {
+        sprintf(buf, "%d Hz", (int)freq);
+    }
+    return buf;
+}
+
 static void
 print_ahb_peripherals(struct streamer *streamer, bool all)
 {
-    streamer_printf(streamer, "  AHB HCLK: %u\n", (unsigned int)HAL_RCC_GetHCLKFreq());
+    char freq_buf[20];
+
+    streamer_printf(streamer, "  AHB HCLK: %s\n",
+                    freq_str(HAL_RCC_GetHCLKFreq(), freq_buf));
 
     if (all || RCC->AHB1ENR & RCC_AHB1ENR_GPIOAEN) {
         streamer_printf(streamer, "    GPIOA  %s\n", on_off_state(RCC->AHB1ENR & RCC_AHB1ENR_GPIOAEN));
@@ -177,67 +206,85 @@ print_apb1_peripherals(struct streamer *streamer, bool all)
 {
     uint32_t pckl1 = HAL_RCC_GetPCLK1Freq();
     uint32_t timmul = RCC->CFGR & RCC_CFGR_PPRE2_2 ? 2 : 1;
+    char freq_buf[20];
 
-    streamer_printf(streamer, "  APB1 PCLK1: %u\n", (unsigned int)pckl1);
+    streamer_printf(streamer, "  APB1 PCLK1: %s\n", freq_str(pckl1, freq_buf));
     if (all || RCC->APB1ENR & RCC_APB1ENR_TIM2EN) {
-        streamer_printf(streamer, "    TIM2   %s %u (ARR %u)\n", on_off_state(RCC->APB1ENR & RCC_APB1ENR_TIM2EN),
-                        pckl1 * timmul / (TIM2->PSC + 1), (TIM2->ARR));
+        streamer_printf(streamer, "    TIM2   %s %s (ARR %u)\n",
+                        on_off_state(RCC->APB1ENR & RCC_APB1ENR_TIM2EN),
+                        freq_str(pckl1 * timmul / (TIM2->PSC + 1), freq_buf),
+                        (TIM2->ARR));
     }
     if (all || RCC->APB1ENR & RCC_APB1ENR_TIM3EN) {
-        streamer_printf(streamer, "    TIM3   %s %u (ARR %u)\n", on_off_state(RCC->APB1ENR & RCC_APB1ENR_TIM3EN),
-                        pckl1 * timmul / (TIM3->PSC + 1), (TIM3->ARR + 1));
+        streamer_printf(streamer, "    TIM3   %s %s (ARR %u)\n",
+                        on_off_state(RCC->APB1ENR & RCC_APB1ENR_TIM3EN),
+                        freq_str(pckl1 * timmul / (TIM3->PSC + 1), freq_buf),
+                        (TIM3->ARR + 1));
     }
     if (all || RCC->APB1ENR & RCC_APB1ENR_TIM4EN) {
-        streamer_printf(streamer, "    TIM4   %s %u\n", on_off_state(RCC->APB1ENR & RCC_APB1ENR_TIM4EN),
-                        pckl1 * timmul / (TIM4->PSC + 1));
+        streamer_printf(streamer, "    TIM4   %s %s\n",
+                        on_off_state(RCC->APB1ENR & RCC_APB1ENR_TIM4EN),
+                        freq_str(pckl1 * timmul / (TIM4->PSC + 1), freq_buf));
     }
 #ifdef RCC_APB1ENR_TIM5EN
     if (all || RCC->APB1ENR & RCC_APB1ENR_TIM5EN) {
-        streamer_printf(streamer, "    TIM5   %s %u\n", on_off_state(RCC->APB1ENR & RCC_APB1ENR_TIM5EN),
-                        pckl1 * timmul / (TIM5->PSC + 1));
+        streamer_printf(streamer, "    TIM5   %s %s\n",
+                        on_off_state(RCC->APB1ENR & RCC_APB1ENR_TIM5EN),
+                        freq_str(pckl1 * timmul / (TIM5->PSC + 1), freq_buf));
     }
 #endif
 #ifdef RCC_APB1ENR_TIM6EN
     if (all || RCC->APB1ENR & RCC_APB1ENR_TIM6EN) {
-        streamer_printf(streamer, "    TIM6   %s %u\n", on_off_state(RCC->APB1ENR & RCC_APB1ENR_TIM6EN),
-                        pckl1 * timmul / (TIM6->PSC + 1));
+        streamer_printf(streamer, "    TIM6   %s %s\n",
+                        on_off_state(RCC->APB1ENR & RCC_APB1ENR_TIM6EN),
+                        freq_str(pckl1 * timmul / (TIM6->PSC + 1), freq_buf));
     }
 #endif
 #ifdef RCC_APB1ENR_TIM7EN
     if (all || RCC->APB1ENR & RCC_APB1ENR_TIM7EN) {
-        streamer_printf(streamer, "    TIM7   %s %u\n", on_off_state(RCC->APB1ENR & RCC_APB1ENR_TIM7EN),
-                        pckl1 * timmul / (TIM7->PSC + 1));
+        streamer_printf(streamer, "    TIM7   %s %s\n",
+                        on_off_state(RCC->APB1ENR & RCC_APB1ENR_TIM7EN),
+                        freq_str(pckl1 * timmul / (TIM7->PSC + 1), freq_buf));
     }
 #endif
 #ifdef RCC_APB1ENR_TIM12EN
     if (all || RCC->APB1ENR & RCC_APB1ENR_TIM12EN) {
-        streamer_printf(streamer, "    TIM12  %s %u\n", on_off_state(RCC->APB1ENR & RCC_APB1ENR_TIM12EN),
-                        pckl1 * timmul / (TIM12->PSC + 1));
+        streamer_printf(streamer, "    TIM12  %s %s\n",
+                        on_off_state(RCC->APB1ENR & RCC_APB1ENR_TIM12EN),
+                        freq_str(pckl1 * timmul / (TIM12->PSC + 1), freq_buf));
     }
 #endif
 #ifdef RCC_APB1ENR_TIM13EN
     if (all || RCC->APB1ENR & RCC_APB1ENR_TIM13EN) {
-        streamer_printf(streamer, "    TIM13  %s %u\n", on_off_state(RCC->APB1ENR & RCC_APB1ENR_TIM13EN),
-                        pckl1 * timmul / (TIM3->PSC + 1));
+        streamer_printf(streamer, "    TIM13  %s %s\n",
+                        on_off_state(RCC->APB1ENR & RCC_APB1ENR_TIM13EN),
+                        freq_str(pckl1 * timmul / (TIM3->PSC + 1), freq_buf));
     }
 #endif
 #ifdef RCC_APB1ENR_TIM14EN
     if (all || RCC->APB1ENR & RCC_APB1ENR_TIM14EN) {
-        streamer_printf(streamer, "    TIM14  %s %u\n", on_off_state(RCC->APB1ENR & RCC_APB1ENR_TIM14EN),
-                        pckl1 * timmul / (TIM14->PSC + 1));
+        streamer_printf(streamer, "    TIM14  %s %s\n",
+                        on_off_state(RCC->APB1ENR & RCC_APB1ENR_TIM14EN),
+                        freq_str(pckl1 * timmul / (TIM14->PSC + 1), freq_buf));
     }
 #endif
     if (all || RCC->APB1ENR & RCC_APB1ENR_WWDGEN) {
         streamer_printf(streamer, "    WWD    %s\n", on_off_state(RCC->APB1ENR & RCC_APB1ENR_WWDGEN));
     }
     if (all || RCC->APB1ENR & RCC_APB1ENR_SPI2EN) {
-        streamer_printf(streamer, "    SPI2   %s\n", on_off_state(RCC->APB1ENR & RCC_APB1ENR_SPI2EN),
-                        pckl1 >> (1 + ((SPI2->CR1 & SPI_CR1_BR_Msk) >> SPI_CR1_BR_Pos)));
+        streamer_printf(
+            streamer, "    SPI2   %s %s\n",
+            on_off_state(RCC->APB1ENR & RCC_APB1ENR_SPI2EN),
+            freq_str(pckl1 >> (1 + ((SPI2->CR1 & SPI_CR1_BR_Msk) >> SPI_CR1_BR_Pos)),
+                     freq_buf));
     }
 #ifdef RCC_APB1ENR_SPI3EN
     if (all || RCC->APB1ENR & RCC_APB1ENR_SPI3EN) {
-        streamer_printf(streamer, "    SPI3   %s %u\n", on_off_state(RCC->APB1ENR & RCC_APB1ENR_SPI3EN),
-                        pckl1 >> (1 + ((SPI3->CR1 & SPI_CR1_BR_Msk) >> SPI_CR1_BR_Pos)));
+        streamer_printf(
+            streamer, "    SPI3   %s %s\n",
+            on_off_state(RCC->APB1ENR & RCC_APB1ENR_SPI3EN),
+            freq_str(pckl1 >> (1 + ((SPI3->CR1 & SPI_CR1_BR_Msk) >> SPI_CR1_BR_Pos)),
+                     freq_buf));
     }
 #endif
     if (all || RCC->APB1ENR & RCC_APB1ENR_USART2EN) {
@@ -293,8 +340,9 @@ print_apb2_peripherals(struct streamer *streamer, bool all)
     uint32_t pckl2 = HAL_RCC_GetPCLK2Freq();
     uint32_t adcpre = (((ADC->CCR & ADC_CCR_ADCPRE_Msk) >> ADC_CCR_ADCPRE_Pos) + 1) * 2;
     uint32_t timmul = RCC->CFGR & RCC_CFGR_PPRE2_2 ? 2 : 1;
+    char freq_buf[20];
 
-    streamer_printf(streamer, "  APB2 PCLK2: %u\n", (unsigned int)pckl2);
+    streamer_printf(streamer, "  APB2 PCLK2: %s\n", freq_str(pckl2, freq_buf));
 
     if (all || RCC->APB2ENR & RCC_APB2ENR_USART1EN) {
         streamer_printf(streamer, "    USART1 %s\n", on_off_state(RCC->APB2ENR & RCC_APB2ENR_USART1EN));
@@ -304,46 +352,56 @@ print_apb2_peripherals(struct streamer *streamer, bool all)
     }
 
     if (all || RCC->APB2ENR & RCC_APB2ENR_ADC1EN) {
-        streamer_printf(streamer, "    ADC1   %s %u\n", on_off_state(RCC->APB2ENR & RCC_APB2ENR_ADC1EN),
-                        pckl2 / adcpre);
+        streamer_printf(streamer, "    ADC1   %s %s\n",
+                        on_off_state(RCC->APB2ENR & RCC_APB2ENR_ADC1EN),
+                        freq_str(pckl2 / adcpre, freq_buf));
     }
 #ifdef RCC_APB2ENR_ADC2EN
     if (all || RCC->APB2ENR & RCC_APB2ENR_ADC2EN) {
-        streamer_printf(streamer, "    ADC2   %s %u\n", on_off_state(RCC->APB2ENR & RCC_APB2ENR_ADC2EN),
-                        pckl2 / adcpre);
+        streamer_printf(streamer, "    ADC2   %s %s\n",
+                        on_off_state(RCC->APB2ENR & RCC_APB2ENR_ADC2EN),
+                        freq_str(pckl2 / adcpre, freq_buf));
     }
 #endif
 #if defined(RCC_APB2ENR_ADC3EN)
     if (all || RCC->APB2ENR & RCC_APB2ENR_ADC3EN) {
-        streamer_printf(streamer, "    ADC3   %s %u\n", on_off_state(RCC->APB2ENR & RCC_APB2ENR_ADC3EN),
-                        pckl2 / adcpre);
-    }
-#endif
-#if defined(RCC_APB2ENR_ADC3EN)
-    if (all || RCC->APB2ENR & RCC_APB2ENR_ADC3EN) {
-        streamer_printf(streamer, "    SDIO   %s\n", on_off_state(RCC->APB2ENR & RCC_APB2ENR_ADC3EN));
+        streamer_printf(streamer, "    ADC3   %s %s\n",
+                        on_off_state(RCC->APB2ENR & RCC_APB2ENR_ADC3EN),
+                        freq_str(pckl2 / adcpre, freq_buf));
     }
 #endif
     if (all || RCC->APB2ENR & RCC_APB2ENR_SDIOEN) {
-        streamer_printf(streamer, "    SDIO   %s %u\n", on_off_state(RCC->APB2ENR & RCC_APB2ENR_SDIOEN),
-                        pckl2 / (2 + (SDIO->CLKCR & SDIO_CLKCR_CLKDIV_Msk)));
+        streamer_printf(streamer, "    SDIO   %s %s\n",
+                        on_off_state(RCC->APB2ENR & RCC_APB2ENR_SDIOEN),
+                        freq_str(stm32f4xx_pll_q_freq() /
+                                     (2 + (SDIO->CLKCR & SDIO_CLKCR_CLKDIV_Msk)),
+                                 freq_buf));
     }
     if (all || RCC->APB2ENR & RCC_APB2ENR_SPI1EN) {
-        streamer_printf(streamer, "    SPI1   %s %u\n", on_off_state(RCC->APB2ENR & RCC_APB2ENR_SPI1EN),
-                        pckl2 >> (1 + ((SPI1->CR1 & SPI_CR1_BR_Msk) >> SPI_CR1_BR_Pos)));
+        streamer_printf(
+            streamer, "    SPI1   %s %s\n",
+            on_off_state(RCC->APB2ENR & RCC_APB2ENR_SPI1EN),
+            freq_str(pckl2 >> (1 + ((SPI1->CR1 & SPI_CR1_BR_Msk) >> SPI_CR1_BR_Pos)),
+                     freq_buf));
     }
 #if defined(RCC_APB2ENR_SPI4EN)
     if (all || RCC->APB2ENR & RCC_APB2ENR_SPI4EN) {
-        streamer_printf(streamer, "    SPI4   %s %u%s\n", on_off_state(RCC->APB2ENR & RCC_APB2ENR_SPI4EN),
-                        pckl2 >> (1 + ((SPI4->CR1 & SPI_CR1_BR_Msk) >> SPI_CR1_BR_Pos)),
-                        (SPI4->I2SCFGR & SPI_I2SCFGR_I2SMOD) ? " (I2S)" : "");
+        streamer_printf(
+            streamer, "    SPI4   %s %s%s\n",
+            on_off_state(RCC->APB2ENR & RCC_APB2ENR_SPI4EN),
+            freq_str(pckl2 >> (1 + ((SPI4->CR1 & SPI_CR1_BR_Msk) >> SPI_CR1_BR_Pos)),
+                     freq_buf),
+            (SPI4->I2SCFGR & SPI_I2SCFGR_I2SMOD) ? " (I2S)" : "");
     }
 #endif
 #if defined(RCC_APB2ENR_SPI5EN)
     if (all || RCC->APB2ENR & RCC_APB2ENR_SPI5EN) {
-        streamer_printf(streamer, "    SPI5   %s %u%s\n", on_off_state(RCC->APB2ENR & RCC_APB2ENR_SPI5EN),
-                        pckl2 >> (1 + ((SPI5->CR1 & SPI_CR1_BR_Msk) >> SPI_CR1_BR_Pos)),
-                        (SPI5->I2SCFGR & SPI_I2SCFGR_I2SMOD) ? " (I2S)" : "");
+        streamer_printf(
+            streamer, "    SPI5   %s %s%s\n",
+            on_off_state(RCC->APB2ENR & RCC_APB2ENR_SPI5EN),
+            freq_str(pckl2 >> (1 + ((SPI5->CR1 & SPI_CR1_BR_Msk) >> SPI_CR1_BR_Pos)),
+                     freq_buf),
+            (SPI5->I2SCFGR & SPI_I2SCFGR_I2SMOD) ? " (I2S)" : "");
     }
 #endif
     if (all || RCC->APB2ENR & RCC_APB2ENR_SYSCFGEN) {
@@ -351,31 +409,36 @@ print_apb2_peripherals(struct streamer *streamer, bool all)
     }
 
     if (all || RCC->APB2ENR & RCC_APB2ENR_TIM1EN) {
-        streamer_printf(streamer, "    TIM1   %s %u\n", on_off_state(RCC->APB2ENR & RCC_APB2ENR_TIM1EN),
-                        pckl2 * timmul / (TIM1->PSC + 1));
+        streamer_printf(streamer, "    TIM1   %s %s\n",
+                        on_off_state(RCC->APB2ENR & RCC_APB2ENR_TIM1EN),
+                        freq_str(pckl2 * timmul / (TIM1->PSC + 1), freq_buf));
     }
 #ifdef RCC_APB2ENR_TIM8EN
     if (all || RCC->APB2ENR & RCC_APB2ENR_TIM8EN) {
-        streamer_printf(streamer, "    TIM8   %s %u\n", on_off_state(RCC->APB2ENR & RCC_APB2ENR_TIM8EN),
-                        pckl2 * timmul / (TIM8->PSC + 1));
+        streamer_printf(streamer, "    TIM8   %s %s\n",
+                        on_off_state(RCC->APB2ENR & RCC_APB2ENR_TIM8EN),
+                        freq_str(pckl2 * timmul / (TIM8->PSC + 1), freq_buf));
     }
 #endif
 #ifdef RCC_APB2ENR_TIM9EN
     if (all || RCC->APB2ENR & RCC_APB2ENR_TIM9EN) {
-        streamer_printf(streamer, "    TIM9   %s\n", on_off_state(RCC->APB2ENR & RCC_APB2ENR_TIM9EN),
-                        pckl2 * timmul / (TIM9->PSC + 1));
+        streamer_printf(streamer, "    TIM9   %s %s\n",
+                        on_off_state(RCC->APB2ENR & RCC_APB2ENR_TIM9EN),
+                        freq_str(pckl2 * timmul / (TIM9->PSC + 1), freq_buf));
     }
 #endif
 #ifdef RCC_APB2ENR_TIM10EN
     if (all || RCC->APB2ENR & RCC_APB2ENR_TIM10EN) {
-        streamer_printf(streamer, "    TIM10  %s\n", on_off_state(RCC->APB2ENR & RCC_APB2ENR_TIM10EN),
-                        pckl2 * timmul / (TIM10->PSC + 1));
+        streamer_printf(streamer, "    TIM10  %s %s\n",
+                        on_off_state(RCC->APB2ENR & RCC_APB2ENR_TIM10EN),
+                        freq_str(pckl2 * timmul / (TIM10->PSC + 1), freq_buf));
     }
 #endif
 #ifdef RCC_APB2ENR_TIM11EN
     if (all || RCC->APB2ENR & RCC_APB2ENR_TIM11EN) {
-        streamer_printf(streamer, "    TIM11  %s\n", on_off_state(RCC->APB2ENR & RCC_APB2ENR_TIM11EN),
-                        pckl2 * timmul / (TIM11->PSC + 1));
+        streamer_printf(streamer, "    TIM11  %s %s\n",
+                        on_off_state(RCC->APB2ENR & RCC_APB2ENR_TIM11EN),
+                        freq_str(pckl2 * timmul / (TIM11->PSC + 1), freq_buf));
     }
 #endif
 }
@@ -385,16 +448,27 @@ mcu_cli_info_cmd(const struct shell_cmd *cmd, int argc, char **argv,
                  struct streamer *streamer)
 {
     bool all;
+    char freq_buf[20];
     int sw = ((RCC->CFGR & RCC_CFGR_SWS) >> RCC_CFGR_SWS_Pos);
 
     all = argc > 1 && strcmp(argv[1], "all") == 0;
 
     streamer_printf(streamer, "Clocks:\n");
-    streamer_printf(streamer, "  SYSCLK: %u\n", (unsigned int)SystemCoreClock);
+    streamer_printf(streamer, "  SYSCLK: %s\n", freq_str(SystemCoreClock, freq_buf));
     streamer_printf(streamer, "    source %s\n", system_clock_source[sw]);
     streamer_printf(streamer, "  HSI: %s\n", on_off_state(RCC->CR & RCC_CR_HSION));
     streamer_printf(streamer, "  HSE: %s\n", on_off_state(RCC->CR & RCC_CR_HSEON));
     streamer_printf(streamer, "  PLL: %s\n", on_off_state(RCC->CR & RCC_CR_PLLON));
+    if (RCC->CR & RCC_CR_PLLON) {
+        streamer_printf(streamer, "     PLLP: %s\n",
+                        freq_str(stm32f4xx_pll_p_freq(), freq_buf));
+        streamer_printf(streamer, "     PLLQ: %s\n",
+                        freq_str(stm32f4xx_pll_q_freq(), freq_buf));
+#ifdef RCC_PLLCFGR_PLLR
+        streamer_printf(streamer, "     PLLR: %s\n",
+                        freq_str(stm32f4xx_pll_q_freq(), freq_buf));
+#endif
+    }
     streamer_printf(streamer, "  LSI: %s\n", on_off_state(RCC->CSR & RCC_CSR_LSION));
     streamer_printf(streamer, "  LSE: %s\n", on_off_state(RCC->BDCR & RCC_BDCR_LSEON));
     streamer_printf(streamer, "Peripherals:\n");