#include "project.h" int time_known; #if 0 void exti15_10_isr (void) { nvic_disable_irq (NVIC_EXTI15_10_IRQ); if (exti_get_flag_status (EXTI10)) exti10_isr(); if (exti_get_flag_status (EXTI11)) exti11_isr(); nvic_enable_irq (NVIC_EXTI15_10_IRQ); } #endif static void process_key (uint8_t c) { static int unlocked; static unsigned unlock_sm; static uint8_t unlock[] = "unlock"; if (!unlocked) { if (c == unlock[unlock_sm]) { unlock_sm++; if (!unlock[unlock_sm]) { unlocked++; printf ("Serial now unlocked\n"); } return; } else { unlock_sm = 0; printf ("serial locked type unlock to unlock\r\n"); return; } } printf ("KEY> %c\r\n", c); switch (c) { case 'R': scb_reset_system(); break; case 'G': gps_reset(); break; case 'I': gps_bs(); break; case 'A': //gps_almanac(); gps_dump_almanac(); break; case 'D': break; } } static void cmd_dispatch (void) { uint8_t c; while (!ring_read_byte (&usart2_rx_ring, &c)) process_key (c); while (!ring_read_byte (&cdcacm_rx_ring, &c)) process_key (c); } const struct rcc_clock_scale hse_10mhz_3v3_168 = { .pllm = 10, .plln = 336, .pllp = 2, .pllq = 7, .pllr = 0, .pll_source = RCC_CFGR_PLLSRC_HSE_CLK, .hpre = RCC_CFGR_HPRE_NODIV, .ppre1 = RCC_CFGR_PPRE_DIV4, .ppre2 = RCC_CFGR_PPRE_DIV2, .voltage_scale = PWR_SCALE1, .flash_config = FLASH_ACR_DCEN | FLASH_ACR_ICEN | FLASH_ACR_LATENCY_5WS, .ahb_frequency = 168000000, .apb1_frequency = 42000000, .apb2_frequency = 84000000, }; static void ptp_clock_start (void) { /* Get the PTP clock running early */ ETH_PTPTSCR |= ETH_PTPTSCR_TSE; ETH_PTPSSIR = 1; 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) { static uint32_t fail; /* * 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 * */ /*Get us up and running on the 16MHz RC clock */ rcc_osc_on (RCC_HSI); rcc_wait_for_osc_ready (RCC_HSI); /* Select HSI as SYSCLK source. */ rcc_set_sysclk_source (RCC_CFGR_SW_HSI); /* confiure HSE as input not oscillator */ rcc_osc_bypass_enable (RCC_HSE); rcc_osc_on (RCC_HSE); while ((RCC_CR & RCC_CR_HSERDY) == 0) { if (fail++ == 4000000) { /*No external clock, try seeing if we have a crystal */ rcc_osc_off (RCC_HSE); rcc_osc_bypass_disable (RCC_HSE); rcc_osc_on (RCC_HSE); } } /* turn off SSC */ RCC_SSCGR = 0; /* 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_pll (&hse_10mhz_3v3_168); } #define REFCLK_OUT (GPIO8) #define REFCLK_OUT_PORT GPIOA static void timer_setup (void) { MAP_INPUT (REFCLK_OUT); MAP_AF (REFCLK_OUT, GPIO_AF0); #if 0 /*Old scheme 10MHz -> TIM1 ETR -> TIM2 */ #define REFCLK_IN (GPIO7) #define REFCLK_IN_PORT GPIOE MAP_INPUT (REFCLK_IN); MAP_AF (REFCLK_IN, GPIO_AF1); /* * 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... * */ rcc_periph_reset_pulse (RST_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 */ rcc_periph_reset_pulse (RST_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); #else /* New Scheme 10MHz -> TIM2_ETR PA8->PA15*/ #define REFCLK_IN (GPIO15) #define REFCLK_IN_PORT GPIOA MAP_INPUT (REFCLK_IN); MAP_AF (REFCLK_IN, GPIO_AF1); rcc_periph_reset_pulse (RST_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_ETRF); /*Trigger from ETRF input */ timer_enable_counter (TIM2); #endif } static void board_setup (void) { clock_setup(); rcc_periph_clock_enable (RCC_SYSCFG); rcc_periph_clock_enable (RCC_GPIOA); rcc_periph_clock_enable (RCC_GPIOB); rcc_periph_clock_enable (RCC_GPIOC); rcc_periph_clock_enable (RCC_GPIOD); rcc_periph_clock_enable (RCC_GPIOE); rcc_periph_clock_enable (RCC_GPIOF); rcc_periph_clock_enable (RCC_GPIOG); rcc_periph_clock_enable (RCC_USART1); rcc_periph_clock_enable (RCC_USART2); rcc_periph_clock_enable (RCC_ETHMAC); 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); rcc_periph_clock_enable (RCC_OTGFS); nvic_set_priority (NVIC_EXTI9_5_IRQ, 0x00); nvic_set_priority (NVIC_EXTI3_IRQ, 0x10); nvic_set_priority (NVIC_EXTI4_IRQ, 0x20); nvic_set_priority (NVIC_USART1_IRQ, 0x30); nvic_set_priority (NVIC_USART2_IRQ, 0x30); nvic_set_priority (NVIC_ETH_IRQ, 0x40); nvic_set_priority (NVIC_SYSTICK_IRQ, 0x50); nvic_set_priority (NVIC_OTG_FS_IRQ, 0x60); // nvic_enable_irq (NVIC_EXTI15_10_IRQ); } static void system_init (void) { cdcacm_rings_init(); usart_rings_init(); board_setup(); timer_setup(); led_init(); ticker_init(); usart_init(); usb_init(); msf_init(); dcf77_init(); steth_calculate_mac(); printf ("LWIP\r\n"); start_lwip(); printf ("STETH\r\n"); steth_init(); ptp_clock_start(); max7219_init (1); display_dispatch(); gps_init(); ntp_init(); adc_init(); } int main (void) { system_init(); printf ("Boot\r\n"); #if 0 while (1) { uint32_t now = HW_CLOCK_REG; uint64_t abs = ref_extend (now); EPOCH e = ref_decompose (abs); time_print_epoch ("TEST: ", e); delay_ms (100); } #endif while (1) { #if 0 { uint32_t now = HW_CLOCK_REG; uint64_t abs = ref_extend (now); EPOCH e = ref_decompose (abs); time_print_epoch ("TEST: ", e); delay_ms (100); } abs_meh(); #endif msf_dispatch(); dcf77_dispatch(); gps_dispatch(); sysclk_dispatch(); cmd_dispatch(); dispatch_lwip(); display_dispatch(); adc_dispatch(); alarm_dispatch(); pll_check(); } return 0; }