From a803d10b035865ef3049168777d1069b5e1917f4 Mon Sep 17 00:00:00 2001 From: jaseg Date: Wed, 1 Apr 2020 14:45:11 +0200 Subject: gm_platform: Add support for OCXO and GPS sync --- gm_platform/fw/Makefile | 2 +- gm_platform/fw/adc.c | 4 +- gm_platform/fw/global.h | 1 + gm_platform/fw/main.c | 119 +++++++++++++++++++++++++++++++++++++----------- 4 files changed, 98 insertions(+), 28 deletions(-) diff --git a/gm_platform/fw/Makefile b/gm_platform/fw/Makefile index ea874eb..77b2a09 100644 --- a/gm_platform/fw/Makefile +++ b/gm_platform/fw/Makefile @@ -40,7 +40,7 @@ LIBS = -lgcc # Technically we're using an STM32F030F4, but apart from the TSSOP20 package that one is largely identical to the # STM32F030*6 and there is no separate device header provided for it, so we're faking a *6 device here. This is # even documented in stm32f0xx.h. Thanks ST! -CFLAGS += -DSTM32F030x6 -DHSE_VALUE=8000000 +CFLAGS += -DSTM32F030x6 -DHSE_VALUE=19440000 LDFLAGS += -Tstm32_flash.ld CFLAGS += -I$(CMSIS_DEV_PATH)/Include -I$(CMSIS_PATH)/Include -I$(HAL_PATH)/Inc -Iconfig -Wno-unused -I../common diff --git a/gm_platform/fw/adc.c b/gm_platform/fw/adc.c index e3aba5b..ab9d6b5 100644 --- a/gm_platform/fw/adc.c +++ b/gm_platform/fw/adc.c @@ -25,6 +25,7 @@ static struct __attribute__((__packed__)) hl_adc_pkt { struct ll_pkt ll; uint16_t seq; + int32_t gps_1pps_period_sysclk; volatile uint16_t data[32]; } adc_pkt[2]; static uint16_t current_seq = 0; @@ -99,7 +100,7 @@ static void adc_timer_init(int psc, int ivl) { TIM1->PSC = psc-1; TIM1->ARR = ivl-1; /* Preload all values */ - TIM1->EGR |= TIM_EGR_UG; + TIM1->EGR = TIM_EGR_UG; TIM1->CR1 = TIM_CR1_ARPE; /* And... go! */ TIM1->CR1 |= TIM_CR1_CEN; @@ -118,6 +119,7 @@ void DMA1_Channel1_IRQHandler(void) { gdb_dump(); adc_pkt[!current_buf].seq = current_seq++; + adc_pkt[!current_buf].gps_1pps_period_sysclk = gps_1pps_period_sysclk; /* Ignore return value since we can't do anything here. Overruns are logged in serial.c. */ usart_send_packet_nonblocking(&adc_pkt[!current_buf].ll, sizeof(adc_pkt[!current_buf])); diff --git a/gm_platform/fw/global.h b/gm_platform/fw/global.h index 9c454bc..28ac6cd 100644 --- a/gm_platform/fw/global.h +++ b/gm_platform/fw/global.h @@ -57,5 +57,6 @@ union leds { }; extern volatile union leds leds; +extern volatile int32_t gps_1pps_period_sysclk; #endif/*__GLOBAL_H__*/ diff --git a/gm_platform/fw/main.c b/gm_platform/fw/main.c index 74f305b..811b27f 100644 --- a/gm_platform/fw/main.c +++ b/gm_platform/fw/main.c @@ -22,25 +22,11 @@ volatile unsigned int sys_time_seconds = 0; volatile union leds leds; +volatile int32_t gps_1pps_period_sysclk = -1; int main(void) { - RCC->CR |= RCC_CR_HSEON; - while (!(RCC->CR&RCC_CR_HSERDY)); - RCC->CFGR &= ~RCC_CFGR_PLLMUL_Msk & ~RCC_CFGR_SW_Msk & ~RCC_CFGR_PPRE_Msk & ~RCC_CFGR_HPRE_Msk; - RCC->CFGR |= ((6-2)< 48.0MHz */ - RCC->CR |= RCC_CR_PLLON; - while (!(RCC->CR&RCC_CR_PLLRDY)); - RCC->CFGR |= (2<AHBENR |= RCC_AHBENR_DMAEN | RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_FLITFEN | RCC_AHBENR_CRCEN; - RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN | RCC_APB2ENR_ADCEN | RCC_APB2ENR_SPI1EN | RCC_APB2ENR_DBGMCUEN |\ - RCC_APB2ENR_TIM1EN | RCC_APB2ENR_TIM16EN | RCC_APB2ENR_USART1EN; - RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; + RCC->AHBENR |= RCC_AHBENR_GPIOAEN; + RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; GPIOA->MODER |= (3<AFR[0] = (0<AFR[1] = (1<<8) | (1<<4); - GPIOB->MODER |= - (0<CR1 = SPI_CR1_SSM | SPI_CR1_SSI @@ -75,8 +58,38 @@ int main(void) { | SPI_CR1_MSTR; SPI1->CR2 = (7<CR1 |= SPI_CR1_SPE; + *((volatile uint8_t*)&(SPI1->DR)) = 0xff; + + for (int i=0; i<1000000; i++) + ; + + RCC->CR |= RCC_CR_HSEBYP; + RCC->CR |= RCC_CR_HSEON; + RCC->CFGR &= ~RCC_CFGR_PLLMUL_Msk & ~RCC_CFGR_SW_Msk & ~RCC_CFGR_PPRE_Msk & ~RCC_CFGR_HPRE_Msk; + /* PLL config: 19.44MHz /2 x5 -> 48.6MHz */ + RCC->CFGR |= ((5-2)<CFGR2 = ((2-1)<CR |= RCC_CR_PLLON; + while (!(RCC->CR&RCC_CR_PLLRDY)); + RCC->CFGR |= (2<AHBENR |= RCC_AHBENR_DMAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_FLITFEN | RCC_AHBENR_CRCEN; + RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN | RCC_APB2ENR_ADCEN | RCC_APB2ENR_DBGMCUEN |\ + RCC_APB2ENR_TIM1EN | RCC_APB2ENR_TIM16EN | RCC_APB2ENR_USART1EN; + RCC->APB1ENR |= RCC_APB1ENR_TIM3EN | RCC_APB1ENR_TIM14EN; + + GPIOB->MODER |= + (2<AFR[0] = (0<PUPDR = 2<CR2 = 0; + TIM16->DIER = TIM_DIER_UIE | TIM_DIER_CC1IE; TIM16->CCMR1 = 0; TIM16->CCR1 = 32; @@ -85,17 +98,70 @@ int main(void) { TIM16->CR1 = TIM_CR1_CEN; NVIC_EnableIRQ(TIM16_IRQn); - NVIC_SetPriority(TIM16_IRQn, 3<<5); + + TIM14->CCMR1 = (1<CCER = TIM_CCER_CC1E; + TIM14->PSC = 1; + TIM14->ARR = 0xffff; + TIM14->DIER = TIM_DIER_CC1IE | TIM_DIER_UIE; + TIM14->EGR = TIM_EGR_UG; + TIM14->CR1 |= TIM_CR1_CEN; + + NVIC_EnableIRQ(TIM14_IRQn); adc_configure_scope_mode(1000000); usart_dma_init(); while (42) { - //int pol = GPIOB->IDR & (1<<1); /* Sample current polarity */ - //leds.error = pol ? 100 : 0; - //for (int i=0; i<10000; i++) ; - //leds.error = 100; + /* Do nothing and let the interrupts do all the work. */ + } +} + +void tim14_sr_cc1of(void) {} /* gdb hook */ + +void TIM14_IRQHandler(void) { + static uint32_t gps_1pps_period = 0; + static uint32_t update_inc = 0; + static bool in_sync = false; + + uint32_t sr = TIM14->SR; + if (sr & TIM_SR_CC1OF) { + TIM14->SR &= ~(TIM_SR_CC1IF | TIM_SR_CC1OF); + tim14_sr_cc1of(); + } else if (sr & TIM_SR_CC1IF) { /* CC1 event (GPS 1pps input) */ + /* Don't reset update event: If update event arrives while CC1 event is being processed leave UIF set to process + * update event immediately after return from ISR. */ + uint16_t ccr = TIM14->CCR1; + if (in_sync) { + uint32_t new_period = gps_1pps_period + ccr; + if (new_period < 20000000 || new_period > 30000000) { /* Signal out of range */ + in_sync = false; + gps_1pps_period_sysclk = -1; + gps_1pps_period = (uint32_t)-1; + } else { + gps_1pps_period_sysclk = new_period; + gps_1pps_period = 0; + update_inc = 0x10000 - ccr; /* remaining cycles in this period */ + leds.pps = 200; /* ms */ + } + } else { + gps_1pps_period = 0; + update_inc = 0x10000 - ccr; /* remaining cycles in this period */ + in_sync = true; + } + + } else { /* update */ + TIM14->SR &= ~TIM_SR_UIF; + if (in_sync) { + gps_1pps_period += update_inc; + if (gps_1pps_period > 30000000) { /* Signal out of range */ + in_sync = false; + gps_1pps_period_sysclk = -1; + gps_1pps_period = (uint32_t)-1; + } + } + update_inc = 0x10000; } } @@ -151,7 +217,8 @@ void SysTick_Handler(void) { if (n++ == 10) { n = 0; sys_time_seconds++; - leds.pps = 200; /* ms */ + if (gps_1pps_period_sysclk < 0) + leds.pps = 200; /* ms */ } } -- cgit