altos: Make STM clock configuration per-product. Fix 32MHz CPU speed
authorKeith Packard <keithp@keithp.com>
Tue, 10 Apr 2012 05:17:33 +0000 (22:17 -0700)
committerKeith Packard <keithp@keithp.com>
Tue, 10 Apr 2012 05:17:33 +0000 (22:17 -0700)
This moves all of the STM clock configuration into ao_pins.h so that
each product can configure it separately. While doing this, I
discovered that the flash memory mode (64-bit, prefetch, latency 1)
wasn't actually getting set, which is why the CPU refused to work at
32MHz.

Signed-off-by: Keith Packard <keithp@keithp.com>
src/megametrum-v0.1/ao_pins.h
src/stm-demo/ao_pins.h
src/stm/ao_arch.h
src/stm/ao_beep_stm.c
src/stm/ao_serial_stm.c
src/stm/ao_timer.c
src/stm/stm32l.h

index 803678b2b5b08fa8b99c0e13fce0f95250b49cfe..f5789cf9df993d2b3bdd277fb3d6e359cbe9497d 100644 (file)
 #ifndef _AO_PINS_H_
 #define _AO_PINS_H_
 
 #ifndef _AO_PINS_H_
 #define _AO_PINS_H_
 
+/* 8MHz High speed external crystal */
+#define AO_HSE                 8000000
+
+/* PLLVCO = 96MHz (so that USB will work*/
+#define AO_PLLMUL              12
+#define AO_RCC_CFGR_PLLMUL     (STM_RCC_CFGR_PLLMUL_12)
+
+/* SYSCLK = 32MHz (no need to go faster than CPU) */
+#define AO_PLLDIV              3
+#define AO_RCC_CFGR_PLLDIV     (STM_RCC_CFGR_PLLDIV_3)
+
+/* HCLK = 32MHz (CPU clock) */
+#define AO_AHB_PRESCALER       1
+#define AO_RCC_CFGR_HPRE_DIV   STM_RCC_CFGR_HPRE_DIV_1
+
+/* Run APB1 at 16MHz (HCLK/2) */
+#define AO_APB1_PRESCALER      2
+#define AO_RCC_CFGR_PPRE1_DIV  STM_RCC_CFGR_PPRE2_DIV_2
+
+/* Run APB2 at 16MHz (HCLK/2) */
+#define AO_APB2_PRESCALER      2
+#define AO_RCC_CFGR_PPRE2_DIV  STM_RCC_CFGR_PPRE2_DIV_2
+
 #define HAS_SERIAL_1           1
 #define USE_SERIAL_1_STDIN     1
 #define SERIAL_1_PB6_PB7       0
 #define HAS_SERIAL_1           1
 #define USE_SERIAL_1_STDIN     1
 #define SERIAL_1_PB6_PB7       0
index 9fd1175ddcaaf34a4c6f3daefc427710596bf735..3192c2b702d19875c8a6d139c33af2c3f1736e29 100644 (file)
 #ifndef _AO_PINS_H_
 #define _AO_PINS_H_
 
 #ifndef _AO_PINS_H_
 #define _AO_PINS_H_
 
+/* No external crystal */
+#define AO_HSE         0
+
+#define AO_AHB_PRESCALER       1
+#define AO_RCC_CFGR_HPRE_DIV   STM_RCC_CFGR_HPRE_DIV_1
+
+#define AO_APB1_PRESCALER      2
+#define AO_RCC_CFGR_PPRE1_DIV  STM_RCC_CFGR_PPRE2_DIV_2
+
+#define AO_APB2_PRESCALER      2
+#define AO_RCC_CFGR_PPRE2_DIV  STM_RCC_CFGR_PPRE2_DIV_2
+
+#define AO_PLLMUL              6
+#define AO_PLLDIV              4
+#define AO_RCC_CFGR_PLLMUL     (STM_RCC_CFGR_PLLMUL_6)
+#define AO_RCC_CFGR_PLLDIV     (STM_RCC_CFGR_PLLDIV_4)
+
 #define HAS_SERIAL_1           1
 #define USE_SERIAL_1_STDIN     1
 #define SERIAL_1_PB6_PB7       1
 #define HAS_SERIAL_1           1
 #define USE_SERIAL_1_STDIN     1
 #define SERIAL_1_PB6_PB7       1
index ce3a22e262e6ce8c7a7c330c3aa66b732b9b4620..dd9579f1093252b303cfff84506ebb68d5734b6b 100644 (file)
@@ -148,7 +148,30 @@ extern const uint16_t ao_serial_number;
 /*
  * For now, we're running at a weird frequency
  */
 /*
  * For now, we're running at a weird frequency
  */
-#define STM_APB1       (16000000 * 6 / 4)
+
+#if AO_HSE
+#define AO_PLLSRC      AO_HSE
+#else
+#define AO_PLLSRC      STM_HSI_FREQ
+#endif
+
+#define AO_PLLVCO      (AO_PLLSRC * AO_PLLMUL)
+#define AO_SYSCLK      (AO_PLLVCO / AO_PLLDIV)
+#define AO_HCLK                (AO_SYSCLK / AO_AHB_PRESCALER)
+#define AO_PCLK1       (AO_HCLK / AO_APB1_PRESCALER)
+#define AO_PCLK2       (AO_HCLK / AO_APB2_PRESCALER)
+
+#if AO_APB1_PRESCALER == 1
+#define AO_TIM23467_CLK                AO_PCLK1
+#else
+#define AO_TIM23467_CLK                (2 * AO_PCLK1)
+#endif
+
+#if AO_APB2_PRESCALER == 1
+#define AO_TIM91011_CLK                AO_PCLK2
+#else
+#define AO_TIM91011_CLK                (2 * AO_PCLK2)
+#endif
 
 void ao_lcd_stm_init(void);
 
 
 void ao_lcd_stm_init(void);
 
index 8c0c0ee33ea889f5006995eca28a200a046daa29..37c30e25b1374e3d791a1a131fd7c4686ae24031 100644 (file)
@@ -41,7 +41,7 @@ ao_beep(uint8_t beep)
 
                /* Set prescaler to match cc1111 clocks
                 */
 
                /* Set prescaler to match cc1111 clocks
                 */
-               stm_tim3.psc = STM_APB1 / 750000;
+               stm_tim3.psc = AO_TIM23467_CLK / 750000;
 
                /* 1. Select the counter clock (internal, external, prescaler).
                 *
 
                /* 1. Select the counter clock (internal, external, prescaler).
                 *
index f8db6883bfc47a5fa2688cd745ca8f66468fc5e8..3cebc0944d1359ecc828d6b8e34ca72382cbb062 100644 (file)
@@ -116,16 +116,16 @@ static const struct {
        uint32_t brr;
 } ao_usart_speeds[] = {
        [AO_SERIAL_SPEED_4800] = {
        uint32_t brr;
 } ao_usart_speeds[] = {
        [AO_SERIAL_SPEED_4800] = {
-               STM_APB1 / 4800
+               AO_PCLK1 / 4800
        },
        [AO_SERIAL_SPEED_9600] = {
        },
        [AO_SERIAL_SPEED_9600] = {
-               STM_APB1 / 9600
+               AO_PCLK1 / 9600
        },
        [AO_SERIAL_SPEED_19200] = {
        },
        [AO_SERIAL_SPEED_19200] = {
-               STM_APB1 / 19200
+               AO_PCLK1 / 19200
        },
        [AO_SERIAL_SPEED_57600] = {
        },
        [AO_SERIAL_SPEED_57600] = {
-               STM_APB1 / 57600
+               AO_PCLK1 / 57600
        },
 };
 
        },
 };
 
index 387df184c7747bb3f595c1c6d00d86a80d09993c..e7f1ddfe231cfe4db879a64108fbc35b14cf1937 100644 (file)
@@ -69,7 +69,7 @@ ao_timer_set_adc_interval(uint8_t interval) __critical
 }
 #endif
 
 }
 #endif
 
-#define TIMER_10kHz    (STM_APB1 / 10000)
+#define TIMER_10kHz    (AO_PCLK1 / 10000)
 
 void
 ao_timer_init(void)
 
 void
 ao_timer_init(void)
@@ -107,44 +107,41 @@ ao_clock_init(void)
        uint32_t        cr;
        
        /* Set flash latency to tolerate 32MHz SYSCLK  -> 1 wait state */
        uint32_t        cr;
        
        /* Set flash latency to tolerate 32MHz SYSCLK  -> 1 wait state */
-       uint32_t        acr = stm_flash.acr;
 
        /* Enable 64-bit access and prefetch */
 
        /* Enable 64-bit access and prefetch */
-       acr |= (1 << STM_FLASH_ACR_ACC64) | (1 << STM_FLASH_ACR_PRFEN);
-       stm_flash.acr = acr;
+       stm_flash.acr |= (1 << STM_FLASH_ACR_ACC64);
+       stm_flash.acr |= (1 << STM_FLASH_ACR_PRFEN);
 
        /* Enable 1 wait state so the CPU can run at 32MHz */
        /* (haven't managed to run the CPU at 32MHz yet, it's at 16MHz) */
 
        /* Enable 1 wait state so the CPU can run at 32MHz */
        /* (haven't managed to run the CPU at 32MHz yet, it's at 16MHz) */
-       acr |= (1 << STM_FLASH_ACR_LATENCY);
-       stm_flash.acr = acr;
+       stm_flash.acr |= (1 << STM_FLASH_ACR_LATENCY);
+
 
        /* HCLK to 16MHz -> AHB prescaler = /1 */
        cfgr = stm_rcc.cfgr;
        cfgr &= ~(STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE);
 
        /* HCLK to 16MHz -> AHB prescaler = /1 */
        cfgr = stm_rcc.cfgr;
        cfgr &= ~(STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE);
-       cfgr |= (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE);
+       cfgr |= (AO_RCC_CFGR_HPRE_DIV << STM_RCC_CFGR_HPRE);
        stm_rcc.cfgr = cfgr;
        while ((stm_rcc.cfgr & (STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE)) !=
        stm_rcc.cfgr = cfgr;
        while ((stm_rcc.cfgr & (STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE)) !=
-              (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE))
+              (AO_RCC_CFGR_HPRE_DIV << STM_RCC_CFGR_HPRE))
                asm ("nop");
                asm ("nop");
-#define STM_AHB_PRESCALER      1
 
 
-       /* PCLK1 to 16MHz -> APB1 Prescaler = 1 */
+       /* APB1 Prescaler = AO_APB1_PRESCALER */
        cfgr = stm_rcc.cfgr;
        cfgr &= ~(STM_RCC_CFGR_PPRE1_MASK << STM_RCC_CFGR_PPRE1);
        cfgr = stm_rcc.cfgr;
        cfgr &= ~(STM_RCC_CFGR_PPRE1_MASK << STM_RCC_CFGR_PPRE1);
-       cfgr |= (STM_RCC_CFGR_PPRE1_DIV_1 << STM_RCC_CFGR_PPRE1);
+       cfgr |= (AO_RCC_CFGR_PPRE1_DIV << STM_RCC_CFGR_PPRE1);
        stm_rcc.cfgr = cfgr;
        stm_rcc.cfgr = cfgr;
-#define STM_APB1_PRESCALER     1
 
 
-       /* PCLK2 to 16MHz -> APB2 Prescaler = 1 */
+       /* APB2 Prescaler = AO_APB2_PRESCALER */
        cfgr = stm_rcc.cfgr;
        cfgr &= ~(STM_RCC_CFGR_PPRE2_MASK << STM_RCC_CFGR_PPRE2);
        cfgr = stm_rcc.cfgr;
        cfgr &= ~(STM_RCC_CFGR_PPRE2_MASK << STM_RCC_CFGR_PPRE2);
-       cfgr |= (STM_RCC_CFGR_PPRE2_DIV_1 << STM_RCC_CFGR_PPRE2);
+       cfgr |= (AO_RCC_CFGR_PPRE2_DIV << STM_RCC_CFGR_PPRE2);
        stm_rcc.cfgr = cfgr;
        stm_rcc.cfgr = cfgr;
-#define STM_APB2_PRESCALER     1
 
        /* Enable power interface clock */
        stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN);
 
 
        /* Enable power interface clock */
        stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN);
 
+
        /* Set voltage range to 1.8V */
 
        /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */
        /* Set voltage range to 1.8V */
 
        /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */
@@ -161,23 +158,42 @@ ao_clock_init(void)
        while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0)
                asm("nop");
 
        while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0)
                asm("nop");
 
+#if AO_HSE
+       /* Enable HSE clock */
+       if (!(stm_rcc.cr & (1 << STM_RCC_CR_HSERDY))) {
+               stm_rcc.cr |= (1 << STM_RCC_CR_HSEON);
+               while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSERDY)))
+                       asm("nop");
+       }
+#define STM_RCC_CFGR_SWS_TARGET_CLOCK          (STM_RCC_CFGR_SWS_HSE << STM_RCC_CFGR_SWS)
+#define STM_RCC_CFGR_SW_TARGET_CLOCK           (STM_RCC_CFGR_SW_HSE)
+#define STM_PLLSRC                             AO_HSE
+#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK       (1 << STM_RCC_CFGR_PLLSRC)
+#else
+#define STM_HSI                                16000000
+#define STM_RCC_CFGR_SWS_TARGET_CLOCK          (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS)
+#define STM_RCC_CFGR_SW_TARGET_CLOCK           (STM_RCC_CFGR_SW_HSI)
+#define STM_PLLSRC                             STM_HSI
+#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK       (0 << STM_RCC_CFGR_PLLSRC)
+#endif
+
+#if !AO_HSE || HAS_ADC
        /* Enable HSI RC clock 16MHz */
        if (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) {
                stm_rcc.cr |= (1 << STM_RCC_CR_HSION);
                while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY)))
                        asm("nop");
        }
        /* Enable HSI RC clock 16MHz */
        if (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) {
                stm_rcc.cr |= (1 << STM_RCC_CR_HSION);
                while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY)))
                        asm("nop");
        }
-#define STM_HSI 16000000
-
-       /* Switch to direct HSI for SYSCLK */
+#endif
+       /* Switch to direct high speed clock for SYSCLK */
        if ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) !=
        if ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) !=
-           (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS)) {
+           STM_RCC_CFGR_SWS_TARGET_CLOCK) {
                cfgr = stm_rcc.cfgr;
                cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW);
                cfgr = stm_rcc.cfgr;
                cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW);
-               cfgr |= (STM_RCC_CFGR_SW_HSI << STM_RCC_CFGR_SW);
+               cfgr |= STM_RCC_CFGR_SW_TARGET_CLOCK;
                stm_rcc.cfgr = cfgr;
                while ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) !=
                stm_rcc.cfgr = cfgr;
                while ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) !=
-                      (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS))
+                      STM_RCC_CFGR_SWS_TARGET_CLOCK);
                        asm("nop");
        }
 
                        asm("nop");
        }
 
@@ -191,19 +207,12 @@ ao_clock_init(void)
        cfgr &= ~(STM_RCC_CFGR_PLLMUL_MASK << STM_RCC_CFGR_PLLMUL);
        cfgr &= ~(STM_RCC_CFGR_PLLDIV_MASK << STM_RCC_CFGR_PLLDIV);
 
        cfgr &= ~(STM_RCC_CFGR_PLLMUL_MASK << STM_RCC_CFGR_PLLMUL);
        cfgr &= ~(STM_RCC_CFGR_PLLDIV_MASK << STM_RCC_CFGR_PLLDIV);
 
-//     cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL);
-//     cfgr |= (STM_RCC_CFGR_PLLDIV_3 << STM_RCC_CFGR_PLLDIV);
-
-       cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL);
-       cfgr |= (STM_RCC_CFGR_PLLDIV_4 << STM_RCC_CFGR_PLLDIV);
+       cfgr |= (AO_RCC_CFGR_PLLMUL << STM_RCC_CFGR_PLLMUL);
+       cfgr |= (AO_RCC_CFGR_PLLDIV << STM_RCC_CFGR_PLLDIV);
 
 
-#define STM_PLLMUL     6
-#define STM_PLLDIV     4
-
-       /* PLL source to HSI */
+       /* PLL source */
        cfgr &= ~(1 << STM_RCC_CFGR_PLLSRC);
        cfgr &= ~(1 << STM_RCC_CFGR_PLLSRC);
-
-#define STM_PLLSRC     STM_HSI
+       cfgr |= STM_RCC_CFGR_PLLSRC_TARGET_CLOCK;
 
        stm_rcc.cfgr = cfgr;
 
 
        stm_rcc.cfgr = cfgr;
 
index 39dd710d8d4d3971e2883f3553f806fbf5ae7137..b922b6bc69b21ec09f65a08fbb190fa1a62ee997 100644 (file)
@@ -303,6 +303,9 @@ struct stm_rcc {
 
 extern struct stm_rcc stm_rcc;
 
 
 extern struct stm_rcc stm_rcc;
 
+/* Nominal high speed internal oscillator frequency is 16MHz */
+#define STM_HSI_FREQ           16000000
+
 #define STM_RCC_CR_RTCPRE      (29)
 #define  STM_RCC_CR_RTCPRE_HSE_DIV_2   0
 #define  STM_RCC_CR_RTCPRE_HSE_DIV_4   1
 #define STM_RCC_CR_RTCPRE      (29)
 #define  STM_RCC_CR_RTCPRE_HSE_DIV_2   0
 #define  STM_RCC_CR_RTCPRE_HSE_DIV_4   1