summaryrefslogtreecommitdiffstats
path: root/app/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/main.c')
-rw-r--r--app/main.c241
1 files changed, 184 insertions, 57 deletions
diff --git a/app/main.c b/app/main.c
index 4793f78..e3e3f63 100644
--- a/app/main.c
+++ b/app/main.c
@@ -78,7 +78,7 @@ static void pd_set (uint32_t g, uint32_t b)
}
-static void pd(void)
+static void pd (void)
{
pd_port (GPIOA);
pd_port (GPIOB);
@@ -138,6 +138,7 @@ static const clock_scale_t hse_10mhz_3v3_168 = {
.apb2_frequency = 84000000,
};
+#if 0
static const clock_scale_t hse_10mhz_3v3_120 = {
/* 120 */
.pllm = 10,
@@ -194,82 +195,200 @@ static const clock_scale_t hse_10mhz_3v3_10 = {
.ppre1 = RCC_CFGR_PPRE_DIV_NONE,
.ppre2 = RCC_CFGR_PPRE_DIV_NONE,
.flash_config = FLASH_ACR_ICE | FLASH_ACR_DCE | FLASH_ACR_LATENCY_0WS,
-// .ahb_frequency = 10000000,
+ // .ahb_frequency = 10000000,
.apb1_frequency = 10000000,
.apb2_frequency = 10000000,
};
+#endif
+
/*
- * Erugh the STM32F4's PLL is shite, we need
- * to drive the entire clock tree from the 10MHz
- * input, we use the PLL only to drive the 48MHz
- * clock tree.
+ * Erugh the STM32F4's PLL is shite, we need
+ * to drive the entire clock tree from the 10MHz
+ * input, we use the PLL only to drive the 48MHz
+ * clock tree.
*
- * So PTP, AHB, APB1, APB2 all are directly from
- * the HSE input
+ * So PTP, AHB, APB1, APB2 all are directly from
+ * the HSE input
*/
-void rcc_clock_setup_hse_3v3_no_pll(const clock_scale_t *clock)
+void rcc_clock_setup_hse_3v3_no_pll (const clock_scale_t *clock)
{
- /* Enable internal high-speed oscillator. */
- rcc_osc_on(HSI);
- rcc_wait_for_osc_ready(HSI);
-
- /* Select HSI as SYSCLK source. */
- rcc_set_sysclk_source(RCC_CFGR_SW_HSI);
-
- /* Enable external high-speed oscillator 8MHz. */
- rcc_osc_on(HSE);
- rcc_wait_for_osc_ready(HSE);
-
- /* Enable/disable high performance mode */
- if (!clock->power_save) {
- pwr_set_vos_scale(SCALE1);
- } else {
- pwr_set_vos_scale(SCALE2);
- }
-
- /*
- * Set prescalers for AHB, ADC, ABP1, ABP2.
- * Do this before touching the PLL (TODO: why?).
- */
- rcc_set_hpre(clock->hpre);
- rcc_set_ppre1(clock->ppre1);
- rcc_set_ppre2(clock->ppre2);
-
- rcc_set_main_pll_hse(clock->pllm, clock->plln,
+ /* Enable internal high-speed oscillator. */
+ rcc_osc_on (HSI);
+ rcc_wait_for_osc_ready (HSI);
+
+ /* Select HSI as SYSCLK source. */
+ rcc_set_sysclk_source (RCC_CFGR_SW_HSI);
+
+ /* receive the 10MHz external oscillator */
+ rcc_osc_bypass_enable (HSE);
+ rcc_osc_on (HSE);
+ rcc_wait_for_osc_ready (HSE);
+
+ /* Enable/disable high performance mode */
+ if (!clock->power_save)
+ pwr_set_vos_scale (SCALE1);
+ else
+ pwr_set_vos_scale (SCALE2);
+
+ /*
+ * Set prescalers for AHB, ADC, ABP1, ABP2.
+ * Do this before touching the PLL (TODO: why?).
+ */
+ rcc_set_hpre (clock->hpre);
+ rcc_set_ppre1 (clock->ppre1);
+ rcc_set_ppre2 (clock->ppre2);
+
+ rcc_set_main_pll_hse (clock->pllm, clock->plln,
clock->pllp, clock->pllq);
- /* Enable PLL oscillator and wait for it to stabilize. */
- rcc_osc_on(PLL);
- rcc_wait_for_osc_ready(PLL);
+ /* Enable PLL oscillator and wait for it to stabilize. */
+ rcc_osc_on (PLL);
+ rcc_wait_for_osc_ready (PLL);
- /* Configure flash settings. */
- flash_set_ws(clock->flash_config);
+ /* Configure flash settings. */
+ flash_set_ws (clock->flash_config);
- /* Select PLL as SYSCLK source. */
- rcc_set_sysclk_source(RCC_CFGR_SW_HSE);
+ /* Select HSE as SYSCLK source. */
+ rcc_set_sysclk_source (RCC_CFGR_SW_HSE);
- /* Wait for PLL clock to be selected. */
- rcc_wait_for_sysclk_status(HSE);
+ /* Wait for HSE clock to be selected. */
+ rcc_wait_for_sysclk_status (HSE);
- /* Set the peripheral clock frequencies used. */
- rcc_apb1_frequency = clock->apb1_frequency;
- rcc_apb2_frequency = clock->apb2_frequency;
+ /* Set the peripheral clock frequencies used. */
+ rcc_apb1_frequency = clock->apb1_frequency;
+ rcc_apb2_frequency = clock->apb2_frequency;
- /* Disable internal high-speed oscillator. */
- rcc_osc_off(HSI);
+ /* Disable internal high-speed oscillator. */
+ rcc_osc_off (HSI);
}
+static void ptp_clock_start (void)
+{
+ /* Get the PTP clock running early */
+ ETH_PTPTSCR |= ETH_PTPTSCR_TSE;
+ ETH_PTPSSIR = 1;
-static void
-board_setup (void)
+ ETH_PTPTSCR &= ~ETH_PTPTSCR_TSFCU;
+ ETH_PTPTSCR &= ~ETH_PTPTSCR_TSSSR;
+
+ ETH_PTPTSHUR = 0;
+ ETH_PTPTSLUR = 0;
+
+ ETH_PTPTSCR |= ETH_PTPTSCR_TSSTI;
+}
+
+
+static void clock_setup (void)
{
+ /*
+ * Caution, The PLL is somewhat rubbish, and causes all sorts of misery
+ * so sysclk isn't really a reference, if we use it, however not using it
+ * means sysclk is 10MHz which is too slow to do ntp and ptp, instead
+ * we route HSE out through MCO1 (as it's not necessarily LVTTL at the
+ * input) and connect that to TIM1_ETR
+ *
+ */
+
+ /* confiure HSE as input not oscillator */
rcc_osc_bypass_enable (HSE);
+
+ /* turn off SSC */
RCC_SSCGR = 0;
-// rcc_clock_setup_hse_3v3 (&hse_10mhz_3v3_168);
- rcc_clock_setup_hse_3v3_no_pll (&hse_10mhz_3v3_10);
+
+ /* Route HSE out through MCO1 (PA8) which we connect to TIM1_ETR (PE7)*/
+
+ RCC_CFGR &= ~ (RCC_CFGR_MCO1_PLL << RCC_CFGR_MCO1_SHIFT);
+ RCC_CFGR |= RCC_CFGR_MCO1_HSE << RCC_CFGR_MCO1_SHIFT;
+
+ RCC_CFGR &= ~ (RCC_CFGR_MCOPRE_DIV_5 << RCC_CFGR_MCO1PRE_SHIFT);
+ RCC_CFGR |= RCC_CFGR_MCOPRE_DIV_NONE << RCC_CFGR_MCO1PRE_SHIFT;
+
+ rcc_clock_setup_hse_3v3 (&hse_10mhz_3v3_168);
+ /* rcc_clock_setup_hse_3v3_no_pll (&hse_10mhz_3v3_10); */
+
+
+}
+#define REFCLK_OUT (GPIO8)
+#define REFCLK_OUT_PORT GPIOA
+
+#define REFCLK_IN (GPIO7)
+#define REFCLK_IN_PORT GPIOE
+
+static void timer_setup (void)
+{
+ MAP_INPUT (REFCLK_OUT);
+ MAP_INPUT (REFCLK_IN);
+ MAP_AF (REFCLK_OUT, GPIO_AF0);
+ MAP_AF (REFCLK_IN, GPIO_AF1);
+
+
+#if 0
+ /* Divide by 2 to trigger TIM2 */
+ timer_reset (TIM1);
+ timer_set_mode (TIM1, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
+ timer_set_master_mode (TIM1, TIM_CR2_MMS_UPDATE);
+ timer_set_period (TIM1, 1);
+ timer_slave_set_filter (TIM1, TIM_SMCR_ETF_OFF);
+ timer_slave_set_prescaler (TIM1, TIM_SMCR_ETPS_OFF);
+ TIM1_SMCR |= TIM_SMCR_ECE;
+ timer_enable_counter (TIM1);
+
+ timer_reset (TIM2);
+ timer_set_mode (TIM2, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
+ timer_slave_set_filter (TIM2, TIM_SMCR_ETF_OFF); /*no filter*/
+ timer_slave_set_prescaler (TIM2, TIM_SMCR_ETPS_OFF); /*no prescaler */
+ timer_slave_set_polarity (TIM2, TIM_ET_RISING); /*rising edge */
+ timer_slave_set_mode (TIM2, TIM_SMCR_SMS_ECM1); /*external clock mode 1*/
+ timer_slave_set_trigger (TIM2, TIM_SMCR_TS_ITR0); /*clock from timer 1*/
+ timer_enable_counter (TIM2);
+#endif
+
+
+
+ /*
+ * so TIM1 which I wired the 10MHz in to turns out to be only 16 bit
+ * so it's a chocolate teapot for this application
+ *
+ * after much faffing what works is the following, configure
+ * the TIM1_ETR to synchronously reset TIM1
+ * connect the TIM1_RESET line to the TIM1_TRGO line
+ * use TIM1_TRGO as TIM2_TRGI, and set TIM2 to upcount
+ * on each rising edge of TRGI
+ *
+ * there's a promising tim2 ETRF input on one of the unused jtag pins
+ * but that requires going up a ladder...
+ *
+ */
+
+
+ timer_reset (TIM1);
+ timer_set_mode (TIM1, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); /* meh */
+ timer_slave_set_filter (TIM1, TIM_SMCR_ETF_OFF); /* No filter */
+ timer_slave_set_prescaler (TIM1, TIM_SMCR_ETPS_OFF); /* no prescaler */
+ timer_slave_set_trigger (TIM1, TIM_SMCR_TS_ETRF); /* Trigger from ETR input */
+ timer_slave_set_mode (TIM1, TIM_SMCR_SMS_RM); /* trigger resets timer */
+ timer_set_master_mode (TIM1, TIM_CR2_MMS_RESET); /* output reset on TRGO */
+ timer_enable_counter (TIM1); /* go */
+
+ timer_reset (TIM2);
+ timer_set_mode (TIM2, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); /* count up with clock*/
+ timer_slave_set_filter (TIM2, TIM_SMCR_ETF_OFF); /*no filter*/
+ timer_slave_set_prescaler (TIM2, TIM_SMCR_ETPS_OFF); /*no prescaler */
+ timer_slave_set_polarity (TIM2, TIM_ET_RISING); /*rising edge */
+ timer_slave_set_mode (TIM2, TIM_SMCR_SMS_ECM1); /*external clock mode 1*/
+ timer_slave_set_trigger (TIM2, TIM_SMCR_TS_ITR0); /*clock from timer 1*/
+ timer_enable_counter (TIM2);
+
+
+}
+
+static void
+board_setup (void)
+{
+ clock_setup();
rcc_periph_clock_enable (RCC_SYSCFG);
rcc_periph_clock_enable (RCC_GPIOA);
@@ -285,6 +404,8 @@ board_setup (void)
rcc_periph_clock_enable (RCC_ETHMACTX);
rcc_periph_clock_enable (RCC_ETHMACRX);
rcc_periph_clock_enable (RCC_ETHMACPTP);
+ rcc_periph_clock_enable (RCC_TIM1);
+ rcc_periph_clock_enable (RCC_TIM2);
nvic_set_priority (NVIC_EXTI9_5_IRQ, 0x00);
nvic_set_priority (NVIC_EXTI3_IRQ, 0x10);
@@ -294,6 +415,7 @@ board_setup (void)
nvic_set_priority (NVIC_ETH_IRQ, 0x40);
nvic_set_priority (NVIC_SYSTICK_IRQ, 0x50);
+
// nvic_enable_irq (NVIC_EXTI15_10_IRQ);
}
@@ -303,6 +425,9 @@ system_init (void)
{
board_setup();
+
+ timer_setup();
+
led_init();
ticker_init();
@@ -316,6 +441,8 @@ system_init (void)
printf ("STETH\r\n");
steth_init();
+ ptp_clock_start();
+
max7219_init (1);
gps_init();
@@ -335,7 +462,7 @@ main (void)
#if 0
while (1) {
- uint32_t now = SCS_DWT_CYCCNT;
+ uint32_t now = HW_CLOCK_REG;
uint64_t abs = abs_extend (now);
EPOCH e = pll_decompose (abs);
time_print_epoch ("TEST: ", e);
@@ -349,7 +476,7 @@ main (void)
while (1) {
#if 0
{
- uint32_t now = SCS_DWT_CYCCNT;
+ uint32_t now = HW_CLOCK_REG;
uint64_t abs = abs_extend (now);
EPOCH e = pll_decompose (abs);
time_print_epoch ("TEST: ", e);
@@ -362,8 +489,8 @@ main (void)
msf_dispatch();
dcf77_dispatch();
-
gps_dispatch();
+ sysclk_dispatch();
cmd_dispatch();
dispatch_lwip();