Explorar o código

AT32F403A: Run main firmware at 216MHz. Clock USB from auto-calibrated HSI clock.

Keir Fraser %!s(int64=2) %!d(string=hai) anos
pai
achega
09f777ea49
Modificáronse 3 ficheiros con 71 adicións e 12 borrados
  1. 8 4
      inc/mcu/at32/f4.h
  2. 21 1
      inc/mcu/at32/f4_regs.h
  3. 42 7
      src/mcu/at32f4/stm32.c

+ 8 - 4
inc/mcu/at32/f4.h

@@ -12,11 +12,13 @@
 #define CORTEX_M3 1
 
 /* C pointer types */
+#define ACC volatile struct acc * const
 #define BKP volatile struct bkp * const
 #define AFIO volatile struct afio * const
 #define DMA_CHN volatile struct dma_chn * const
 
 /* C-accessible registers. */
+static ACC acc = (struct acc *)ACC_BASE;
 static STK stk = (struct stk *)STK_BASE;
 static SCB scb = (struct scb *)SCB_BASE;
 static NVIC nvic = (struct nvic *)NVIC_BASE;
@@ -68,10 +70,12 @@ void early_fatal(int blinks) __attribute__((noreturn));
 #define early_delay_ms(ms) (delay_ticks((ms)*1000))
 #define early_delay_us(us) (delay_ticks((us)*1))
 
-#define SYSCLK_MHZ 144
-#define AHB_MHZ    144
-#define APB1_MHZ    72
-#define APB2_MHZ    72
+extern unsigned int sysclk_mhz;
+extern unsigned int apb_mhz;
+#define SYSCLK_MHZ sysclk_mhz
+#define AHB_MHZ    sysclk_mhz
+#define APB1_MHZ   apb_mhz
+#define APB2_MHZ   apb_mhz
 
 extern unsigned int FLASH_PAGE_SIZE;
 

+ 21 - 1
inc/mcu/at32/f4_regs.h

@@ -2,7 +2,6 @@
 #include "../stm32/f1_regs.h"
 
 #define RCC_CFGR_PLLRANGE_GT72MHZ (1u<<31)
-#define RCC_CFGR_PLLMUL_18 ((uint32_t)0x20040000)
 #define RCC_CFGR_USBPSC_3  ((uint32_t)0x08400000)
 #define RCC_CFGR_HSE_PREDIV2 (1u<<17)
 #define RCC_CFGR_APB2PSC_2 (4u<<11)
@@ -13,7 +12,28 @@
 #define RCC_PLL_FREF_MASK (7u<<24)
 #define RCC_PLL_FREF_8M   (2u<<24)
 
+#define RCC_APB2ENR_ACCEN (1u<<22)
+
+static volatile uint32_t * const RCC_MISC = (uint32_t *)(RCC_BASE + 0x30);
+#define RCC_MISC_HSI_NODIV    (1u<<25)
+
 static volatile uint32_t * const RCC_MISC2 = (uint32_t *)(RCC_BASE + 0x54);
+#define RCC_MISC2_HSI_FOR_USB (1u<< 8)
 #define RCC_MISC2_AUTOSTEP_EN (3u<< 4)
 
 #define TIM_CR1_PMEN (1u<<10)
+
+/* HSI Auto Clock Calibration */
+struct acc {
+    uint32_t sts;    /* 00: Status */
+    uint32_t ctrl1;  /* 04: Control #1 */
+    uint32_t ctrl2;  /* 08: Control #2 */
+    uint32_t c1;     /* 0C: Compare value #1 */
+    uint32_t c2;     /* 10: Compare value #2 */
+    uint32_t c3;     /* 14: Compare value #3 */
+};
+
+#define ACC_CTRL1_ENTRIM (1u<<1)
+#define ACC_CTRL1_CALON  (1u<<0)
+
+#define ACC_BASE 0x40015800

+ 42 - 7
src/mcu/at32f4/stm32.c

@@ -9,6 +9,17 @@
  * See the file COPYING for more details, or visit <http://unlicense.org>.
  */
 
+#if defined(BOOTLOADER)
+/* Don't trust the USB HSI clock strategy for the bootloader yet. 
+ * Using HSE divided to 48MHz is simpler and it's proven to work well.  */
+#define FAST_AT32F403A FALSE
+#else
+#define FAST_AT32F403A TRUE
+#endif
+
+unsigned int sysclk_mhz = 144;
+unsigned int apb_mhz = 72;
+
 unsigned int FLASH_PAGE_SIZE = 2048;
 unsigned int at32f4_series;
 
@@ -17,7 +28,7 @@ unsigned int sram_kb;
 
 static void clock_init(void)
 {
-    uint32_t cfgr;
+    uint32_t cfgr, pllmul;
     int i;
 
     if (at32f4_series == AT32F415) {
@@ -40,12 +51,13 @@ static void clock_init(void)
     }
 
     /* PLLs, scalers, muxes. */
-    cfgr = (RCC_CFGR_PLLMUL_18 |        /* PLL = 18*8MHz = 144MHz */
-            RCC_CFGR_USBPSC_3 |         /* USB = 144/3MHz = 48MHz */
+    pllmul = (sysclk_mhz / 8) - 1; /* PLLMUL(SYSCLK/HSE) */
+    cfgr = (((pllmul & 0x30) << 25) | ((pllmul & 0x0f) << 18) |
+            RCC_CFGR_USBPSC_3 |         /* USB = SYSCLK/3 */
             RCC_CFGR_PLLSRC_PREDIV1 |
             RCC_CFGR_ADCPRE_DIV8 |
-            RCC_CFGR_APB2PSC_2 |        /* APB2 = 144/2MHz = 72MHz */
-            RCC_CFGR_APB1PSC_2);        /* APB1 = 144/2MHz = 72MHz */
+            RCC_CFGR_APB2PSC_2 |        /* APB2 = SYSCLK/2 */
+            RCC_CFGR_APB1PSC_2);        /* APB1 = SYSCLK/2 */
 
     if (board_config->hse_mhz == 16)
         cfgr |= RCC_CFGR_HSE_PREDIV2;
@@ -97,8 +109,15 @@ static void clock_init(void)
         break;
     }
 
-    /* Internal oscillator no longer needed. */
-    rcc->cr &= ~RCC_CR_HSION;
+    if ((at32f4_series == AT32F403A) && FAST_AT32F403A) {
+        /* Internal oscillator is used as the USB clock because we cannot
+         * derive 48MHz from the faster 216MHz PLL output. */
+        *RCC_MISC |= RCC_MISC_HSI_NODIV;
+        *RCC_MISC2 |= RCC_MISC2_HSI_FOR_USB;
+    } else {
+        /* Internal oscillator no longer needed. */
+        rcc->cr &= ~RCC_CR_HSION;
+    }
 }
 
 static void peripheral_init(void)
@@ -112,6 +131,16 @@ static void peripheral_init(void)
                     RCC_APB2ENR_AFIOEN);
     rcc->ahbenr = RCC_AHBENR_DMA1EN;
 
+    if ((at32f4_series == AT32F403A) && FAST_AT32F403A) {
+        /* AT32F403A is clocking USB from the HSI. To achieve sufficient
+         * clock accuracy, enable automatic clock calibration. */
+        rcc->apb2enr |= RCC_APB2ENR_ACCEN;
+        acc->c1 = 7990;
+        acc->c2 = 8000;
+        acc->c3 = 8010;
+        acc->ctrl1 |= ACC_CTRL1_ENTRIM | ACC_CTRL1_CALON;
+    }
+
     /* Reclaim JTAG pins. */
     afio->mapr = AFIO_MAPR_SWJ_ON_JTAG_OFF;
     gpio_configure_pin(gpioa, 15, GPI_floating);
@@ -128,7 +157,13 @@ static void identify_mcu(void)
     at32f4_series = *(uint8_t *)0x1ffff7f3; /* UID[95:88] */
     switch (at32f4_series) {
     case AT32F403:
+        sram_kb = 96;
+        break;
     case AT32F403A:
+        if (FAST_AT32F403A) {
+            sysclk_mhz = 216;
+            apb_mhz = 108;
+        }
         sram_kb = 96;
         break;
     case AT32F415: