瀏覽代碼

STM32F7: Set up system clocks, PLLs, divisors, etc.

Keir Fraser 5 年之前
父節點
當前提交
37e49e1f82
共有 8 個文件被更改,包括 89 次插入51 次删除
  1. 0 1
      inc/stm32/common.h
  2. 1 0
      inc/stm32/f1.h
  3. 5 0
      inc/stm32/f7.h
  4. 25 7
      inc/stm32/f7_regs.h
  5. 2 5
      src/fw_update.c
  6. 9 0
      src/main.c
  7. 34 36
      src/stm32f7.c
  8. 13 2
      src/timer.c

+ 0 - 1
inc/stm32/common.h

@@ -39,7 +39,6 @@ void stm32_bootloader_enter(void);
 void system_reset(void);
 
 /* Clocks */
-#define SYSCLK_MHZ 72
 #define SYSCLK     (SYSCLK_MHZ * 1000000)
 #define sysclk_ns(x) (((x) * SYSCLK_MHZ) / 1000)
 #define sysclk_us(x) ((x) * SYSCLK_MHZ)

+ 1 - 0
inc/stm32/f1.h

@@ -53,6 +53,7 @@ static USB usb = (struct usb *)USB_BASE;
 static USB_BUFD usb_bufd = (struct usb_bufd *)USB_BUF_BASE;
 static USB_BUF usb_buf = (uint32_t *)USB_BUF_BASE;
 
+#define SYSCLK_MHZ 72
 #define FLASH_PAGE_SIZE 1024
 
 /*

+ 5 - 0
inc/stm32/f7.h

@@ -65,8 +65,13 @@ static USART usart6 = (struct usart *)USART6_BASE;
 static USB_OTG usb_otg_fs = (struct usb_otg *)USB_OTG_FS_BASE;
 static USB_OTG usb_otg_hs = (struct usb_otg *)USB_OTG_HS_BASE;
 
+#define SYSCLK_MHZ 216
 #define FLASH_PAGE_SIZE 16384
 
+/* Delay after enabling peripheral clock, before accessing peripheral 
+ * (Ref STMicro RM0431, Section 5.2.12) */
+void peripheral_clock_delay(void);
+
 /*
  * Local variables:
  * mode: C

+ 25 - 7
inc/stm32/f7_regs.h

@@ -99,15 +99,15 @@ struct rcc {
     uint32_t apb2lpenr;/* 64: APB2 peripheral clock enable (low-power mode) */
     uint32_t _unused7; /* 68: - */
     uint32_t _unused8; /* 6C: - */
-    uint32_t rcc_bdcr; /* 70: Backup domain control */
-    uint32_t rcc_csr;  /* 74: Clock control & status */
+    uint32_t bdcr;     /* 70: Backup domain control */
+    uint32_t csr;      /* 74: Clock control & status */
     uint32_t _unused9; /* 78: - */
     uint32_t _unusedA; /* 7C: - */
-    uint32_t rcc_sscgr;/* 80: Spread spectrum clock generation */
-    uint32_t rcc_plli2scfgr;  /* 84: PLLI2S configuration */
-    uint32_t rcc_pllsaicfgr;  /* 88: PLLSAI configuration */
-    uint32_t rcc_plldckcfgr1; /* 8C: Dedicated clocks configuration #1 */
-    uint32_t rcc_plldckcfgr2; /* 90: Dedicated clocks configuration #2 */
+    uint32_t sscgr;    /* 80: Spread spectrum clock generation */
+    uint32_t plli2scfgr; /* 84: PLLI2S configuration */
+    uint32_t pllsaicfgr; /* 88: PLLSAI configuration */
+    uint32_t dckcfgr1; /* 8C: Dedicated clocks configuration #1 */
+    uint32_t dckcfgr2; /* 90: Dedicated clocks configuration #2 */
 };
 
 #define RCC_CR_SAIRDY        (1u<<29)
@@ -123,6 +123,24 @@ struct rcc {
 #define RCC_CR_HSIRDY        (1u<<1)
 #define RCC_CR_HSION         (1u<<0)
 
+#define RCC_PLLCFGR_PLLQ(x)  ((x)<<24)
+#define RCC_PLLCFGR_PLLSRC_HSE (1<<22)
+#define RCC_PLLCFGR_PLLP(x)  ((x)<<16)
+#define RCC_PLLCFGR_PLLN(x)  ((x)<< 6)
+#define RCC_PLLCFGR_PLLM(x)  ((x)<< 0)
+
+#define RCC_CFGR_MCO2(x)     ((x)<<30)
+#define RCC_CFGR_MCO2PRE(x)  ((x)<<27)
+#define RCC_CFGR_MCO1PRE(x)  ((x)<<24)
+#define RCC_CFGR_I2SSCR      (1  <<23)
+#define RCC_CFGR_MCO1(x)     ((x)<<21)
+#define RCC_CFGR_RTCPRE(x)   ((x)<<16)
+#define RCC_CFGR_PPRE2(x)    ((x)<<13)
+#define RCC_CFGR_PPRE1(x)    ((x)<<10)
+#define RCC_CFGR_HPRE(x)     ((x)<< 4)
+#define RCC_CFGR_SWS(x)      ((x)<< 2)
+#define RCC_CFGR_SW(x)       ((x)<< 0)
+
 #define RCC_AHB1ENR_OTGHSULPIEN (1u<<30)
 #define RCC_AHB1ENR_OTGHSEN  (1u<<29)
 #define RCC_AHB1ENR_DMA2EN   (1u<<22)

+ 2 - 5
src/fw_update.c

@@ -204,6 +204,8 @@ int main(void)
 
     /* Enter update mode only if PA14 (DCLK) is strapped to GND. */
     pa14_strapped = !gpio_read_pin(gpioa, 14);
+#endif
+
     if (!pa14_strapped) {
         /* Nope, so jump straight at the main firmware. */
         uint32_t sp = *(uint32_t *)FIRMWARE_START;
@@ -214,11 +216,6 @@ int main(void)
                 :: "r" (sp), "r" (pc));
         }
     }
-#else
-    rcc->ahb1enr |= RCC_AHB1ENR_GPIOAEN;
-    gpio_configure_pin(gpioa, 15, GPO_pushpull(_2MHz, HIGH));
-    for (;;);
-#endif
 
     stm32_init();
     console_init();

+ 9 - 0
src/main.c

@@ -34,6 +34,15 @@ int main(void)
     time_init();
     console_init();
     console_crash_on_input();
+
+    gpio_configure_pin(gpioa, 15, GPO_pushpull(_2MHz, HIGH));
+    for (;;) {
+        delay_ms(20);
+        gpio_write_pin(gpioa, 15, LOW);
+        delay_ms(20);
+        gpio_write_pin(gpioa, 15, HIGH);
+    }
+
     board_init();
 
     printk("\n** Greaseweazle v%u.%u\n", fw_major, fw_minor);

+ 34 - 36
src/stm32f7.c

@@ -24,20 +24,28 @@ int ep_rx_ready(uint8_t ep) { return -1; }
 
 static void clock_init(void)
 {
-#if 0
-    /* Flash controller: reads require 2 wait states at 72MHz. */
-    flash->acr = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY(2);
+    /* Flash controller: reads require 7 wait states at 216MHz. */
+    flash->acr = FLASH_ACR_ARTEN | FLASH_ACR_PRFTEN | FLASH_ACR_LATENCY(7);
+
+    /* Bus divisors. */
+    rcc->cfgr = (RCC_CFGR_PPRE2(4) | /* APB2 = 216MHz/2 = 108MHz  */
+                 RCC_CFGR_PPRE1(5) | /* APB1 = 216MHz/4 = 54MHz */
+                 RCC_CFGR_HPRE(0));  /* AHB  = 216MHz/1 = 216MHz */
+
+    /* Timers run from Host Clock (216MHz). */
+    rcc->dckcfgr1 = RCC_DCKCFGR1_TIMPRE;
 
     /* Start up the external oscillator. */
     rcc->cr |= RCC_CR_HSEON;
     while (!(rcc->cr & RCC_CR_HSERDY))
         cpu_relax();
 
-    /* PLLs, scalers, muxes. */
-    rcc->cfgr = (RCC_CFGR_PLLMUL(9) |        /* PLL = 9*8MHz = 72MHz */
-                 RCC_CFGR_PLLSRC_PREDIV1 |
-                 RCC_CFGR_ADCPRE_DIV8 |
-                 RCC_CFGR_PPRE1_DIV2);
+    /* Main PLL. */
+    rcc->pllcfgr = (RCC_PLLCFGR_PLLSRC_HSE | /* PLLSrc = HSE = 8MHz */
+                    RCC_PLLCFGR_PLLM(4) |    /* PLL In = HSE/4 = 2MHz */
+                    RCC_PLLCFGR_PLLN(216) |  /* PLLVCO = 2MHz*216 = 432MHz */
+                    RCC_PLLCFGR_PLLP(0) |    /* SYSCLK = 432MHz/2 = 216MHz */
+                    RCC_PLLCFGR_PLLQ(9));    /* USB    = 432MHz/9 = 48MHz */
 
     /* Enable and stabilise the PLL. */
     rcc->cr |= RCC_CR_PLLON;
@@ -45,48 +53,38 @@ static void clock_init(void)
         cpu_relax();
 
     /* Switch to the externally-driven PLL for system clock. */
-    rcc->cfgr |= RCC_CFGR_SW_PLL;
-    while ((rcc->cfgr & RCC_CFGR_SWS_MASK) != RCC_CFGR_SWS_PLL)
+    rcc->cfgr |= RCC_CFGR_SW(2);
+    while ((rcc->cfgr & RCC_CFGR_SWS(3)) != RCC_CFGR_SWS(2))
         cpu_relax();
 
     /* Internal oscillator no longer needed. */
     rcc->cr &= ~RCC_CR_HSION;
 
-    /* Enable SysTick counter at 72/8=9MHz. */
+    /* Enable SysTick counter at 216MHz/8 = 27MHz. */
     stk->load = STK_MASK;
     stk->ctrl = STK_CTRL_ENABLE;
-#endif
 }
 
-static void gpio_init(GPIO gpio)
+void peripheral_clock_delay(void)
 {
-    /* Floating Input. Reference Manual states that JTAG pins are in PU/PD
-     * mode at reset, so ensure all PU/PD are disabled. */
-    //gpio->crl = gpio->crh = 0x44444444u;
+    delay_ticks(2);
 }
 
 static void peripheral_init(void)
 {
-#if 0
-    /* Enable basic GPIO and AFIO clocks, all timers, and DMA. */
-    rcc->apb1enr = (RCC_APB1ENR_TIM2EN |
-                    RCC_APB1ENR_TIM3EN |
-                    RCC_APB1ENR_TIM4EN);
-    rcc->apb2enr = (RCC_APB2ENR_IOPAEN |
-                    RCC_APB2ENR_IOPBEN |
-                    RCC_APB2ENR_IOPCEN |
-                    RCC_APB2ENR_AFIOEN |
-                    RCC_APB2ENR_TIM1EN);
-    rcc->ahbenr = RCC_AHBENR_DMA1EN;
-
-    /* Turn off serial-wire JTAG and reclaim the GPIOs. */
-    afio->mapr = AFIO_MAPR_SWJ_CFG_DISABLED;
-#endif
-
-    /* All pins in a stable state. */
-    gpio_init(gpioa);
-    gpio_init(gpiob);
-    gpio_init(gpioc);
+    /* Enable basic GPIO clocks, DTCM RAM, and DMA. */
+    rcc->ahb1enr = (RCC_AHB1ENR_DMA2EN |
+                    RCC_AHB1ENR_DMA1EN |
+                    RCC_AHB1ENR_DTCMRAMEN |
+                    RCC_AHB1ENR_GPIOCEN |
+                    RCC_AHB1ENR_GPIOBEN | 
+                    RCC_AHB1ENR_GPIOAEN);
+    peripheral_clock_delay();
+
+    /* Release JTAG pins. */
+    gpio_configure_pin(gpioa, 15, GPI_floating);
+    gpio_configure_pin(gpiob,  3, GPI_floating);
+    gpio_configure_pin(gpiob,  4, GPI_floating);
 }
 
 void stm32_init(void)

+ 13 - 2
src/timer.c

@@ -9,10 +9,17 @@
  * See the file COPYING for more details, or visit <http://unlicense.org>.
  */
 
-/* TIM1_UP: IRQ 25. */
+#if STM32F == 1
 void IRQ_25(void) __attribute__((alias("IRQ_timer")));
 #define TIMER_IRQ 25
 #define tim tim1
+#define tim_bits 16
+#elif STM32F == 7
+void IRQ_50(void) __attribute__((alias("IRQ_timer")));
+#define TIMER_IRQ 50
+#define tim tim5 /* 32-bit timer */
+#define tim_bits 32
+#endif
 
 /* IRQ only on counter overflow, one-time enable. */
 #define TIM_CR1 (TIM_CR1_URS | TIM_CR1_OPM)
@@ -28,7 +35,7 @@ static struct timer *head;
 static void reprogram_timer(int32_t delta)
 {
     tim->cr1 = TIM_CR1;
-    if (delta < 0x10000) {
+    if ((tim_bits == 32) || (delta < 0x10000)) {
         /* Fine-grained deadline (sub-microsecond accurate) */
         tim->psc = SYSCLK_MHZ/TIME_MHZ-1;
         tim->arr = (delta <= SLACK_TICKS) ? 1 : delta-SLACK_TICKS;
@@ -107,6 +114,10 @@ void timer_cancel(struct timer *timer)
 
 void timers_init(void)
 {
+#if STM32F == 7
+    rcc->apb1enr |= RCC_APB1ENR_TIM5EN;
+    peripheral_clock_delay();
+#endif
     tim->cr2 = 0;
     tim->dier = TIM_DIER_UIE;
     IRQx_set_prio(TIMER_IRQ, TIMER_IRQ_PRI);