aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--system-clock/include/clock.h124
-rw-r--r--system-clock/include/common.h1
-rw-r--r--system-clock/include/flash.h20
-rw-r--r--system-clock/include/rcc.h82
-rw-r--r--system-clock/include/spin.h2
-rw-r--r--system-clock/src/clock.c230
-rw-r--r--system-clock/src/gpio.c5
-rw-r--r--system-clock/src/main.c34
-rw-r--r--system-clock/src/spin.c27
9 files changed, 339 insertions, 186 deletions
diff --git a/system-clock/include/clock.h b/system-clock/include/clock.h
index 2ba6880..98574d1 100644
--- a/system-clock/include/clock.h
+++ b/system-clock/include/clock.h
@@ -2,10 +2,10 @@
#define CLOCK_H__
#include <stdint.h>
+#include "rcc.h"
#define PERIPH_BASE ((uint32_t) 0x40000000)
#define AHBPERIPH_BASE (PERIPH_BASE + 0x00020000)
-#define RCC_BASE (AHBPERIPH_BASE + 0x00001000)
#define FLASH_R_BASE (AHBPERIPH_BASE + 0x00003C00)
#define PWR_BASE (PERIPH_BASE + 0x7000)
#define PWR_CSR_VOSF ((uint16_t)0x0010) /*!< Voltage Scaling select flag */
@@ -20,42 +20,102 @@ typedef struct {
__IO uint32_t csr;
} pwr_t;
-typedef struct {
- __IO uint32_t acr;
- __IO uint32_t pecr;
- __IO uint32_t pdkeyr;
- __IO uint32_t pekeyr;
- __IO uint32_t prgkeyr;
- __IO uint32_t optkeyr;
- __IO uint32_t sr;
- __IO uint32_t obr;
- __IO uint32_t wrpr;
-} flash_t;
+// typedef struct {
+// __IO uint32_t acr;
+// __IO uint32_t pecr;
+// __IO uint32_t pdkeyr;
+// __IO uint32_t pekeyr;
+// __IO uint32_t prgkeyr;
+// __IO uint32_t optkeyr;
+// __IO uint32_t sr;
+// __IO uint32_t obr;
+// __IO uint32_t wrpr;
+// } flash_t;
-typedef struct {
- __IO uint32_t cr;
- __IO uint32_t icscr;
- __IO uint32_t cfgr;
- __IO uint32_t cir;
- __IO uint32_t ahbrstr;
- __IO uint32_t apb2rstr;
- __IO uint32_t apb1rstr;
- __IO uint32_t ahbenr;
- __IO uint32_t apb2enr;
- __IO uint32_t apb1enr;
- __IO uint32_t ahblpenr;
- __IO uint32_t apb2lpenr;
- __IO uint32_t apb1lpenr;
- __IO uint32_t csr;
-} rcc_t;
-
-#define RCC (*(rcc_t*) (RCC_BASE))
-#define FLASH (*(flash_t*) (FLASH_R_BASE))
+// #define FLASH (*(flash_t*) (FLASH_R_BASE))
#define PWR (*(pwr_t*) (PWR_BASE))
+
+/* Valid values for the PLLR/PLLQ bits of the PLLCFG register. */
+typedef enum {
+ PLL_DIVISOR_2 = 1,
+ PLL_DIVISOR_4 = 3,
+ PLL_DIVISOR_6 = 5,
+ PLL_DIVISOR_8 = 7,
+ PLL_DIVISOR_OFF = 0,
+} pll_divisor_t;
+
+/* Valid values for the PLLP bits off the PLLCFG register. */
+typedef enum {
+ PLLP_DIVISOR_7 = 1,
+ PLLP_DIVISOR_17 = 3,
+ PLLP_DIVISOR_OFF = 0,
+} pllp_divisor_t;
+
+/* Valid values for the PLLM bits of the PLLCFG register. */
+typedef enum {
+ PLLM_DIVISOR_1 = 0,
+ PLLM_DIVISOR_2 = 1,
+ PLLM_DIVISOR_3 = 2,
+ PLLM_DIVISOR_4 = 3,
+ PLLM_DIVISOR_5 = 4,
+ PLLM_DIVISOR_6 = 5,
+ PLLM_DIVISOR_7 = 6,
+ PLLM_DIVISOR_8 = 7,
+} pllm_divisor_t;
+
+/* Possible sources for the input clock. */
+typedef enum {
+ PLL_SRC_NONE = 0,
+ PLL_SRC_MSI = 1,
+ PLL_SRC_HSI = 2,
+ PLL_SRC_HSE = 3,
+} pll_src_t;
+
+/* Valid sources for the system clock. */
+typedef enum {
+ SYSTEM_CLOCK_SRC_MSI = 0,
+ SYSTEM_CLOCK_SRC_HSI = 1,
+ SYSTEM_CLOCK_SRC_HSE = 2,
+ SYSTEM_CLOCK_SRC_PLL = 3,
+} system_clock_src_t;
+
+#define E_BADPLLN (-2)
+#define E_BADPLLP_DIV (-1)
+#define E_TIMEOUT (-3)
+#define E_NOT_OFF (-4)
+#define E_BAD_ARG (-5)
+
/*
* Sets the system clock to a full 80Mhz.
*/
-int set_sys_clock();
+int set_system_clock_MHz(uint8_t mhz);
+
+/*
+ * Set the PLL on.
+ */
+int pll_on();
+
+/*
+ * Set the PLL off.
+ */
+int pll_off();
+
+/*
+ * Sets the source of the system clock.
+ */
+int set_system_clock_src(system_clock_src_t src);
+
+/*
+ * Configure the PLL.
+ */
+int configure_pll(
+ uint8_t pllp_div_factor,
+ pll_divisor_t pllr, /* System clock divisor. */
+ pll_divisor_t pllq, /* Divison factor for PLL48M1CLK. */
+ pllp_divisor_t pllp, /* Divison factor for PLLSAI2CLK. */
+ uint8_t plln, /* PLL numerator. */
+ pllm_divisor_t pllm, /* PLL denominator. */
+ pll_src_t pllsrc /* PLL source */ );
#endif /* CLOCK_H__ */
diff --git a/system-clock/include/common.h b/system-clock/include/common.h
index f58f179..6fc701c 100644
--- a/system-clock/include/common.h
+++ b/system-clock/include/common.h
@@ -9,5 +9,6 @@
#define bool int
#define PACKED __attribute__((packed))
+#define BIT(n) (1 << (n))
#endif /* COMMON_H */
diff --git a/system-clock/include/flash.h b/system-clock/include/flash.h
new file mode 100644
index 0000000..ac63bf9
--- /dev/null
+++ b/system-clock/include/flash.h
@@ -0,0 +1,20 @@
+#ifndef H__FLASH_
+#define H__FLASH_
+
+#include "common.h"
+
+/*
+ * Header file for dealing with flash.
+ */
+
+#define FLASH_BASE 0x40022000
+
+typedef struct {
+ __IO uint32_t ac_r; /* Flash access control register. */
+
+ /* TODO fill out the rest. */
+} PACKED flash_t;
+
+#define FLASH (*(__IO flash_t*) FLASH_BASE)
+
+#endif /* H__FLASH_ */
diff --git a/system-clock/include/rcc.h b/system-clock/include/rcc.h
new file mode 100644
index 0000000..4206dc1
--- /dev/null
+++ b/system-clock/include/rcc.h
@@ -0,0 +1,82 @@
+#ifndef H__RCC_
+#define H__RCC_
+
+#include "common.h"
+
+#define RCC_BASE ((uint32_t) 0x40021000)
+
+typedef struct {
+ __IO uint32_t c_r; /* Clock control register. 0x00 */
+ __IO uint32_t icsc_r; /* Internal clock srcs calibration register. 0x04 */
+ __IO uint32_t cfg_r; /* clock confguration register. 0x08 */
+ __IO uint32_t pllcfg_r; /* PLL Configuration register. 0x0c */
+ __IO uint32_t pllsai1cfg_r; /* PLLSAI1 configuration register. 0x10 */
+
+ __IO uint32_t reserved_1; /* Not used. offset 0x14. */
+
+ __IO uint32_t cie_r; /* Clock interrupt enable register. 0x18 */
+ __IO uint32_t cif_r; /* Clock interrupt flag regiseter. 0x1c */
+ __IO uint32_t cic_r; /* Clock interrupt clear register. 0x20 */
+
+ __IO uint32_t reserved_2; /* Not used. offset 0x24. */
+
+ __IO uint32_t ahb1rst_r; /* AHB Peripheral 1 reset register. 0x28 */
+ __IO uint32_t ahb2rst_r; /* AHB Peripheral 2 reset register. 0x2c */
+ __IO uint32_t ahb3rst_r; /* AHB Peripheral 3 reset register. 0x30 */
+
+ __IO uint32_t reserved_3; /* Not used. offset 0x34. */
+
+ __IO uint32_t abp1rst1_r; /* APB Peripheral reset register 1. 0x38 */
+ __IO uint32_t abp1rst2_r; /* APB Peripheral reset register 2. 0x3C */
+ __IO uint32_t abp2rst_r; /* APB Peripheral reset register. 0x40 */
+
+ __IO uint32_t reserved_4; /* Not used. offset 0x44. */
+
+ __IO uint32_t ahb1en_r; /* AHB1 Peripheral enable register. 0x48 */
+ __IO uint32_t ahb2en_r; /* AHB2 Peripheral enable register. 0x4C */
+ __IO uint32_t ahb3en_r; /* AHB3 Peripheral enable register. 0x50 */
+
+ __IO uint32_t reserved_5; /* Not used. offset 0x54. */
+
+ __IO uint32_t apb1en1_r; /* APB1 Peripheral enable register 1. 0x58 */
+ __IO uint32_t apb1en2_r; /* APB1 Peripheral enable register 2. 0x5C */
+ __IO uint32_t apb2en_r; /* APB2 Peripheral enable register. 0x60 */
+
+ __IO uint32_t reserved_6; /* Not used. offset 0x64. */
+
+ /* TODO add the rest starting at offset 0x68. */
+
+} PACKED rcc_t;
+
+#define RCC (*(__IO rcc_t*) RCC_BASE)
+
+/* Macros to operate on the RCC registers. */
+
+/* Sets the HSE. rcc is the RCC to use, e is zero for off, non-zero for on. */
+#define set_hse(rcc, e) do \
+{ \
+ if (e) { \
+ (rcc).c_r |= 1 << 16; \
+ } else { \
+ (rcc).c_r &= ~(1 << 16); \
+ } \
+} while(0)
+
+/* Sets the HSI. rcc is the RCC to use, e is zero for off, non-zero for on. */
+#define set_hsi(rcc, e) do \
+{ \
+ if (e) { \
+ (rcc).c_r |= 1 << 8; \
+ } else { \
+ (rcc).c_r &= ~(1 << 8); \
+ } \
+} while(0)
+
+
+/* Checks to see if the hse is ready. */
+#define hse_ready(rcc) ((rcc).c_r & (1 << 17))
+
+/* Checks to see if the hse is ready. */
+#define hsi_ready(rcc) ((rcc).c_r & (1 << 10))
+
+#endif
diff --git a/system-clock/include/spin.h b/system-clock/include/spin.h
index a920847..a88d2f8 100644
--- a/system-clock/include/spin.h
+++ b/system-clock/include/spin.h
@@ -10,7 +10,7 @@
* is a 0. Each independent flashing is succeced by a break of 4 times that
* of a long flash.
*/
-void spin(uint8_t code);
+void spin(uint32_t base_delay, uint8_t code);
diff --git a/system-clock/src/clock.c b/system-clock/src/clock.c
index b846ceb..ec12240 100644
--- a/system-clock/src/clock.c
+++ b/system-clock/src/clock.c
@@ -3,147 +3,149 @@
*/
#include "clock.h"
+#include "gpio.h"
+#include "spin.h"
+#include "flash.h"
#include <stdint.h>
-#define RCC_CR_HSERDY ((uint32_t)0x00020000) /* High-speed clock ready? */
-#define RCC_CR_HSEON ((uint32_t)0x00020000) /*!< External High Speed clock ready flag */
-
-#define FLASH_ACR_LATENCY ((uint32_t)0x00000001) /*!< Latency */
-#define FLASH_ACR_PRFTEN ((uint32_t)0x00000002) /*!< Prefetch Buffer Enable */
-#define FLASH_ACR_ACC64 ((uint32_t)0x00000004) /*!< Access 64 bits */
-
-#define RCC_APB1ENR_PWREN ((uint32_t)0x10000000) /*!< Power interface clock enable */
-#define PWR_CR_VOS_0 ((uint16_t)0x0800) /*!< Bit 0 */
-
-/*!< HPRE configuration */
-#define RCC_CFGR_HPRE_DIV1 ((uint32_t)0x00000000) /*!< SYSCLK not divided */
-#define RCC_CFGR_HPRE_DIV2 ((uint32_t)0x00000080) /*!< SYSCLK divided by 2 */
-#define RCC_CFGR_HPRE_DIV4 ((uint32_t)0x00000090) /*!< SYSCLK divided by 4 */
-#define RCC_CFGR_HPRE_DIV8 ((uint32_t)0x000000A0) /*!< SYSCLK divided by 8 */
-#define RCC_CFGR_HPRE_DIV16 ((uint32_t)0x000000B0) /*!< SYSCLK divided by 16 */
-#define RCC_CFGR_HPRE_DIV64 ((uint32_t)0x000000C0) /*!< SYSCLK divided by 64 */
-#define RCC_CFGR_HPRE_DIV128 ((uint32_t)0x000000D0) /*!< SYSCLK divided by 128 */
-#define RCC_CFGR_HPRE_DIV256 ((uint32_t)0x000000E0) /*!< SYSCLK divided by 256 */
-#define RCC_CFGR_HPRE_DIV512 ((uint32_t)0x000000F0) /*!< SYSCLK divided by 512 */
-
-#define RCC_CFGR_PPRE1 ((uint32_t)0x00000700) /*!< PRE1[2:0] bits (APB1 prescaler) */
-#define RCC_CFGR_PPRE1_0 ((uint32_t)0x00000100) /*!< Bit 0 */
-#define RCC_CFGR_PPRE1_1 ((uint32_t)0x00000200) /*!< Bit 1 */
-#define RCC_CFGR_PPRE1_2 ((uint32_t)0x00000400) /*!< Bit 2 */
-
-/*!< PPRE1 configuration */
-#define RCC_CFGR_PPRE1_DIV1 ((uint32_t)0x00000000) /*!< HCLK not divided */
-#define RCC_CFGR_PPRE1_DIV2 ((uint32_t)0x00000400) /*!< HCLK divided by 2 */
-#define RCC_CFGR_PPRE1_DIV4 ((uint32_t)0x00000500) /*!< HCLK divided by 4 */
-#define RCC_CFGR_PPRE1_DIV8 ((uint32_t)0x00000600) /*!< HCLK divided by 8 */
-#define RCC_CFGR_PPRE1_DIV16 ((uint32_t)0x00000700) /*!< HCLK divided by 16 */
-
-#define RCC_CFGR_PPRE2 ((uint32_t)0x00003800) /*!< PRE2[2:0] bits (APB2 prescaler) */
-#define RCC_CFGR_PPRE2_0 ((uint32_t)0x00000800) /*!< Bit 0 */
-#define RCC_CFGR_PPRE2_1 ((uint32_t)0x00001000) /*!< Bit 1 */
-#define RCC_CFGR_PPRE2_2 ((uint32_t)0x00002000) /*!< Bit 2 */
-
-/*!< PPRE2 configuration */
-#define RCC_CFGR_PPRE2_DIV1 ((uint32_t)0x00000000) /*!< HCLK not divided */
-#define RCC_CFGR_PPRE2_DIV2 ((uint32_t)0x00002000) /*!< HCLK divided by 2 */
-#define RCC_CFGR_PPRE2_DIV4 ((uint32_t)0x00002800) /*!< HCLK divided by 4 */
-#define RCC_CFGR_PPRE2_DIV8 ((uint32_t)0x00003000) /*!< HCLK divided by 8 */
-#define RCC_CFGR_PPRE2_DIV16 ((uint32_t)0x00003800) /*!< HCLK divided by 16 */
-#define RCC_CFGR_PLLMUL ((uint32_t)0x003C0000) /*!< PLLMUL[3:0] bits (PLL multiplication factor) */
-#define RCC_CFGR_PLLDIV ((uint32_t)0x00C00000) /*!< PLLDIV[1:0] bits (PLL Output Division) */
-
-#define RCC_CFGR_PLLSRC ((uint32_t)0x00010000) /*!< PLL entry clock source */
-#define RCC_CFGR_PLLSRC_HSE ((uint32_t)0x00010000) /*!< HSE as PLL entry clock source */
-#define RCC_CFGR_PLLMUL8 ((uint32_t)0x000C0000) /*!< PLL input clock * 8 */
-#define RCC_CFGR_PLLDIV2 ((uint32_t)0x00400000) /*!< PLL clock output = CKVCO / 2 */
-#define RCC_CR_PLLON ((uint32_t)0x01000000) /*!< PLL enable */
-#define RCC_CR_PLLRDY ((uint32_t)0x02000000) /*!< PLL clock ready flag */
-#define RCC_CFGR_SW ((uint32_t)0x00000003) /*!< SW[1:0] bits (System clock Switch) */
-#define RCC_CFGR_SW_PLL ((uint32_t)0x00000003) /*!< PLL selected as system clock */
-#define RCC_CFGR_SWS ((uint32_t)0x0000000C) /*!< SWS[1:0] bits (System Clock Switch Status) */
-#define RCC_CFGR_SWS_PLL ((uint32_t)0x0000000C) /*!< PLL used as system clock */
-
-inline int is_hse_ready()
+#define TIMEOUT 10000
+
+int pll_off()
{
- return RCC.cr & RCC_CR_HSERDY;
+ uint32_t c;
+
+ RCC.c_r &= ~BIT(24); /* Turn off pll. */
+ for(c = 0; c < TIMEOUT && RCC.c_r & BIT(25); ++ c); /* Wait for OFF. */
+
+ if (c == TIMEOUT) {
+ return E_TIMEOUT;
+ }
+
+ return 0;
}
-inline void hse_on()
+int pll_on()
{
- RCC.cr |= RCC_CR_HSEON;
+ uint32_t c;
+
+ RCC.c_r |= BIT(24); /* Turn on PLL. */
+ for(c = 0; c < TIMEOUT && !(RCC.c_r & BIT(25)); ++ c); /* Wait for RDY. */
+
+ if (c == TIMEOUT) {
+ return E_TIMEOUT;
+ }
+
+ return 0;
}
-#define TIMER 1000000
-int set_sys_clock()
+int configure_pll(
+ uint8_t pllp_div_factor,
+ pll_divisor_t pllr, /* System clock divisor. */
+ pll_divisor_t pllq, /* Divison factor for PLL48M1CLK. */
+ pllp_divisor_t pllp, /* Divison factor for PLLSAI2CLK. */
+ uint8_t plln, /* PLL numerator. */
+ pllm_divisor_t pllm, /* PLL denominator. */
+ pll_src_t pllsrc /* PLL source */ )
{
- uint32_t c = 0; /* Time the PLL startup. */
+ if (RCC.c_r & BIT(25)) {
+ /* PLL must be off to configure it. */
+ return E_NOT_OFF;
+ }
- /* Turn on the HSE */
- hse_on();
+ /* Make sure inputs are valid. */
+ if (pllp_div_factor == 1 || pllp_div_factor > 31) {
+ return E_BADPLLP_DIV;
+ }
+ if (plln < 8 || plln > 86) {
+ return E_BADPLLN;
+ }
- /* Wait 'til ready, or if it takes tool long, (c == TIMER). */
- for (c = 0; !is_hse_ready() && c < TIMER; ++ c);
+ RCC.pllcfg_r =
+ (pllp_div_factor << 27) |
+ (pllr << 24) |
+ (pllq << 20) |
+ (pllp << 16) |
+ (plln << 8) |
+ (pllm << 4) |
+ (pllsrc << 0);
- if (c == TIMER) {
- /* The HSE never came up. That's not cool! */
- return -1;
- }
+ return 0;
+}
+
- /* The HSE came up, now we just need to set it to be the main clock. */
- /* Don't really know why we're touching the flash registers ... */
- FLASH.acr |= FLASH_ACR_ACC64; /* Enable 64-bit access. */
- FLASH.acr |= FLASH_ACR_PRFTEN; /* Enable prefetch buffer. */
- FLASH.acr |= FLASH_ACR_LATENCY; /* Flash 1 wait state. */
+int set_sys_clock_to_hsi()
+{
+ /* Turn on the HSI, and wait for it to come up. */
+ RCC.c_r |= BIT(8);
+ while(RCC.c_r & BIT(9));
- RCC.apb1enr |= RCC_APB1ENR_PWREN; /* Enable power. */
- PWR.cr = PWR_CR_VOS_0; /* Set voltage to 1.8v. */
+ /* Use the HSI. */
+ RCC.cfg_r |= BIT(0);
+ return 0;
+}
- /* Wait for the vwoltage regulator to turn on. */
- for (c = 0; (PWR.csr & PWR_CSR_VOSF) && c < TIMER; ++ c);
+int set_sys_clock_to_pll()
+{
+ RCC.c_r &= ~BIT(24); /* set PLL to OFF. */
- if (c == TIMER) {
- /* Timeout occurred. */
- return -2;
- }
+ RCC.pllcfg_r =
+ BIT(24) | /* Enable PLLR. This is for system clock output. */
+ /* Set PLLM to 2 and PLLN to 10. This gives us a 10/2 multiplier. */
+ (10 << 8) | /* Set PLLN to 10. */
+ (0 << 4) | /* Set PLLM to 2. */
+ /* Set the input to be HSI16. */
+ BIT(1);
- RCC.cfgr |= RCC_CFGR_HPRE_DIV1; /* HCLK = SYSCLK/1. */
- RCC.cfgr |= RCC_CFGR_PPRE2_DIV1; /* PCLK2 = HCLK/1 */
- RCC.cfgr |= RCC_CFGR_PPRE1_DIV1; /* PCLK1 = HCLK/1 */
- /* PLL Configuration */
- RCC.cfgr &= ~(
- RCC_CFGR_PLLSRC |
- RCC_CFGR_PLLMUL |
- RCC_CFGR_PLLDIV );
+ RCC.c_r |= BIT(24); /* Turn PLL on. */
+ while(!(RCC.c_r & BIT(25))); /* Wait for PLL to be ready. */
- RCC.cfgr |=
- RCC_CFGR_PLLSRC_HSE |
- RCC_CFGR_PLLMUL8 |
- RCC_CFGR_PLLDIV2;
+ /* Configure the flash to have 4 wait states. This is required at
+ * 80 MHz. */
+ FLASH.ac_r &= ~0x07;
+ FLASH.ac_r |= 0x04;
- /* Enable the PLL. */
- RCC.cr |= RCC_CR_PLLON;
+ /* Set the PLL as the system clock. */
+ RCC.cfg_r = 0x3;
+}
- /* Wait for PLL to become ready. */
- for(c = 0; !(RCC.cr & RCC_CR_PLLRDY) && c < TIMER; ++ c);
+int set_system_clock_MHz(uint8_t mhz)
+{
+ /* Set the source of the system colck to MSI temporarily. */
+ set_system_clock_src(SYSTEM_CLOCK_SRC_MSI);
- if (c == TIMER) {
- /* Timeout occurred. */
- return -3;
+ if (mhz <= 8 || mhz > 80) {
+ return E_BAD_ARG;
}
- /* Set PLL as the system clock. */
- RCC.cfgr &= ~RCC_CFGR_SW;
- RCC.cfgr |= RCC_CFGR_SW_PLL;
+ pll_off();
- /* Wait for PLL to be used as system clock. */
- for (c = 0; (RCC.cfgr & RCC_CFGR_SWS) != RCC_CFGR_SW_PLL && c < TIMER; ++ c);
+ configure_pll(
+ 0 /* pllp_div_factor */,
+ PLL_DIVISOR_4 /* pllr: VCO / 4 = mhz MHz. */,
+ PLL_DIVISOR_4 /* pllq: VCO / 4 = mhz MHz */,
+ PLLP_DIVISOR_7 /* pllp */,
- if (c == TIMER) {
- /* Timeout occurred. */
- return -4;
- }
+ /* The following set the frequency of VCO to (mhz*4)MHz: mhz * 1 * 4MHz. */
+ mhz /* plln | mhz */,
+ PLLM_DIVISOR_1 /* pllm | 01 */,
+ PLL_SRC_MSI /* pll src | 04 Mhz */);
+
+ pll_on();
+
+ /* Configure the flash to have 4 wait states. This is required at
+ * 80 MHz. */
+ FLASH.ac_r &= ~0x07;
+ FLASH.ac_r |= 0x04;
+ /* Set the source of the system colck to PLL. */
+ set_system_clock_src(SYSTEM_CLOCK_SRC_PLL);
return 0;
}
+
+int set_system_clock_src(system_clock_src_t src)
+{
+ uint8_t value = RCC.cfg_r & ~0x03;
+ RCC.cfg_r = value | src;
+}
diff --git a/system-clock/src/gpio.c b/system-clock/src/gpio.c
index ab3606d..f79f233 100644
--- a/system-clock/src/gpio.c
+++ b/system-clock/src/gpio.c
@@ -1,4 +1,5 @@
#include "gpio.h"
+#include "rcc.h"
/*
* Sets the mode of a pin on a gpio por.
@@ -38,11 +39,9 @@ void set_gpio_output_pin(
}
#define GPIO_PORTS_BASE_ADDR ((uint32_t)0x48000000)
-#define RCC_BASE ((uint32_t)0x40021000)
-#define RCC_AHB2ENR (*((__IO uint32_t*) (RCC_BASE + 0x4c)))
__IO gpio_port_t* enable_gpio(gpio_port_number_t gpio_port_number)
{
- RCC_AHB2ENR |= 1 << gpio_port_number; /* Enable the port. */
+ RCC.ahb2en_r |= 1 << gpio_port_number; /* Enable the GPIO port. */
return
(__IO gpio_port_t*) (GPIO_PORTS_BASE_ADDR + (gpio_port_number * 0x400));
}
diff --git a/system-clock/src/main.c b/system-clock/src/main.c
index da4afd0..39f4a80 100644
--- a/system-clock/src/main.c
+++ b/system-clock/src/main.c
@@ -1,8 +1,9 @@
#include "gpio.h"
#include "delay.h"
#include "clock.h"
+#include "spin.h"
-volatile uint32_t delay_amt = 65535;
+volatile uint32_t delay_amt = 20000000 / 4;
/* Main function. This gets executed from the interrupt vector defined above. */
int main()
@@ -14,35 +15,22 @@ int main()
gpio_output_pin_t pin1 = set_gpio_pin_output(port_b, PIN_1);
/* Enable a higher clock frequency. */
- set_sys_clock();
+ set_system_clock_MHz(80);
+ uint32_t count = 0;
while(1) {
/* Set the GPIO pin to high. */
- pin_on(pin3);
pin_off(pin1);
- delay(delay_amt);
- delay(delay_amt);
- delay(delay_amt);
- delay(delay_amt);
- delay(delay_amt);
- delay(delay_amt);
- delay(delay_amt);
- delay(delay_amt);
- delay(delay_amt);
+ pin_off(pin3);
delay(delay_amt);
/* Set the GPIO pin to low. */
- pin_off(pin3);
- pin_on(pin1);
- delay(delay_amt);
- delay(delay_amt);
- delay(delay_amt);
- delay(delay_amt);
- delay(delay_amt);
- delay(delay_amt);
- delay(delay_amt);
- delay(delay_amt);
- delay(delay_amt);
+ if (count % 4 == 0) {
+ pin_on(pin1);
+ }
+ pin_on(pin3);
delay(delay_amt);
+
+ ++ count;
}
}
diff --git a/system-clock/src/spin.c b/system-clock/src/spin.c
index f233054..f17f678 100644
--- a/system-clock/src/spin.c
+++ b/system-clock/src/spin.c
@@ -6,20 +6,21 @@
#define LONG_DELAY (SHORT_DELAY * 2)
static void flash_bit(
+ uint32_t base,
gpio_output_pin_t out_pin,
uint8_t bit /* 0 => 0, non-zero => 1 */)
{
pin_on(out_pin);
if (bit) {
- delay(LONG_DELAY);
+ delay(base * 2);
} else {
- delay(SHORT_DELAY);
+ delay(base);
}
pin_off(out_pin);
- delay(SHORT_DELAY);
+ delay(base);
}
-void spin(uint8_t c)
+void spin(uint32_t base, uint8_t c)
{
uint8_t code;
__IO gpio_port_t* port_b = enable_gpio(GPIO_PORT_B);
@@ -27,24 +28,24 @@ void spin(uint8_t c)
for(;;) {
code = c;
- flash_bit(pin3, code & 0x80);
+ flash_bit(base, pin3, code & 0x80);
code <<= 1;
- flash_bit(pin3, code & 0x80);
+ flash_bit(base, pin3, code & 0x80);
code <<= 1;
- flash_bit(pin3, code & 0x80);
+ flash_bit(base, pin3, code & 0x80);
code <<= 1;
- flash_bit(pin3, code & 0x80);
+ flash_bit(base, pin3, code & 0x80);
code <<= 1;
- flash_bit(pin3, code & 0x80);
+ flash_bit(base, pin3, code & 0x80);
code <<= 1;
- flash_bit(pin3, code & 0x80);
+ flash_bit(base, pin3, code & 0x80);
code <<= 1;
- flash_bit(pin3, code & 0x80);
+ flash_bit(base, pin3, code & 0x80);
code <<= 1;
- flash_bit(pin3, code & 0x80);
+ flash_bit(base, pin3, code & 0x80);
- delay(LONG_DELAY * 4);
+ delay(base * 4);
}
}