*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
return ao_tick_count;
}
+uint64_t
+ao_time_ns(void)
+{
+ AO_TICK_TYPE before, after;
+ uint32_t cvr;
+
+ do {
+ before = ao_tick_count;
+ cvr = stm_systick.cvr;
+ after = ao_tick_count;
+ } while (before != after);
+
+ return (uint64_t) after * (1000000000ULL / AO_HERTZ) +
+ (uint64_t) cvr * (1000000000ULL / AO_SYSTICK);
+}
+
#if AO_DATA_ALL
-volatile __data uint8_t ao_data_interval = 1;
-volatile __data uint8_t ao_data_count;
+volatile uint8_t ao_data_interval = 1;
+volatile uint8_t ao_data_count;
#endif
void stm_systick_isr(void)
{
if (stm_systick.csr & (1 << STM_SYSTICK_CSR_COUNTFLAG)) {
++ao_tick_count;
-#if HAS_TASK_QUEUE
- if (ao_task_alarm_tick && (int16_t) (ao_tick_count - ao_task_alarm_tick) >= 0)
- ao_task_check_alarm((uint16_t) ao_tick_count);
-#endif
+ ao_task_check_alarm();
#if AO_DATA_ALL
- if (++ao_data_count == ao_data_interval) {
+ if (++ao_data_count == ao_data_interval && ao_data_interval) {
ao_data_count = 0;
#if HAS_ADC
#if HAS_FAKE_FLIGHT
void
ao_timer_init(void)
{
+ stm_systick.csr = 0;
stm_systick.rvr = SYSTICK_RELOAD;
stm_systick.cvr = 0;
stm_systick.csr = ((1 << STM_SYSTICK_CSR_ENABLE) |
#if AO_HSE_BYPASS
stm_rcc.cr |= (1 << STM_RCC_CR_HSEBYP);
#else
- stm_rcc.cr &= ~(1 << STM_RCC_CR_HSEBYP);
+ stm_rcc.cr &= ~(1UL << STM_RCC_CR_HSEBYP);
#endif
/* Enable HSE clock */
stm_rcc.cr |= (1 << STM_RCC_CR_HSEON);
while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSERDY)))
asm("nop");
-#ifdef STM_PLLSRC
/* Disable the PLL */
- stm_rcc.cr &= ~(1 << STM_RCC_CR_PLLON);
- while (stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY))
+ stm_rcc.cr &= ~(1UL << STM_RCC_CR_PLLON);
+ while (stm_rcc.cr & (1UL << STM_RCC_CR_PLLRDY))
asm("nop");
- /* PLLVCO to 48MHz (for USB) -> PLLMUL = 3 */
+ /* Set multiplier */
cfgr = stm_rcc.cfgr;
cfgr &= ~(STM_RCC_CFGR_PLLMUL_MASK << STM_RCC_CFGR_PLLMUL);
cfgr |= (AO_RCC_CFGR_PLLMUL << STM_RCC_CFGR_PLLMUL);
/* PLL source */
- cfgr &= ~(1 << STM_RCC_CFGR_PLLSRC);
+ cfgr &= ~(1UL << STM_RCC_CFGR_PLLSRC);
cfgr |= (STM_RCC_CFGR_PLLSRC_TARGET_CLOCK << STM_RCC_CFGR_PLLSRC);
stm_rcc.cfgr = cfgr;
- /* Disable pre divider */
- stm_rcc.cfgr2 = (STM_RCC_CFGR2_PREDIV_1 << STM_RCC_CFGR2_PREDIV);
+ /* Set pre divider */
+ stm_rcc.cfgr2 = (AO_RCC_CFGR2_PLLDIV << STM_RCC_CFGR2_PREDIV);
/* Enable the PLL and wait for it */
stm_rcc.cr |= (1 << STM_RCC_CR_PLLON);
#endif
-#endif
-
-
#if AO_HSI48
#define STM_RCC_CFGR_SWS_TARGET_CLOCK STM_RCC_CFGR_SWS_HSI48
#define STM_RCC_CFGR_SW_TARGET_CLOCK STM_RCC_CFGR_SW_HSI48
#define STM_PLLSRC STM_HSI
#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK 0
#endif
+
+
}
static void
}
#if !AO_HSI && !AO_NEED_HSI
/* Turn off the HSI clock */
- stm_rcc.cr &= ~(1 << STM_RCC_CR_HSION);
+ stm_rcc.cr &= ~(1UL << STM_RCC_CR_HSION);
#endif
#ifdef STM_PLLSRC
/* USB PLL source */
/* Enable 1 wait state so the CPU can run at 48MHz */
stm_flash.acr |= (STM_FLASH_ACR_LATENCY_1 << STM_FLASH_ACR_LATENCY);
- /* Enable power interface clock */
- stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN);
-
/* HCLK to 48MHz -> AHB prescaler = /1 */
cfgr = stm_rcc.cfgr;
cfgr &= ~(STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE);
/* Clear reset flags */
stm_rcc.csr |= (1 << STM_RCC_CSR_RMVF);
+#ifdef AO_MCO_PORT
+ cfgr = stm_rcc.cfgr;
+
+ /* Send PLL clock to MCO */
+ cfgr &= ~(STM_RCC_CFGR_MCO_MASK << STM_RCC_CFGR_MCO);
+ cfgr |= (STM_RCC_CFGR_MCO_PLLCLK << STM_RCC_CFGR_MCO);
+
+ /* Divide by 1 */
+ cfgr &= ~(STM_RCC_CFGR_MCOPRE_DIV_MASK << STM_RCC_CFGR_MCOPRE);
+ cfgr |= (STM_RCC_CFGR_MCOPRE_DIV_1 << STM_RCC_CFGR_MCOPRE);
+
+ /* Don't divide PLL */
+ cfgr |= (1 << STM_RCC_CFGR_PLL_NODIV);
+
+ stm_rcc.cfgr = cfgr;
+
+ ao_enable_port(AO_MCO_PORT);
+ stm_ospeedr_set(AO_MCO_PORT, AO_MCO_PIN, STM_OSPEEDR_HIGH);
+ stm_afr_set(AO_MCO_PORT, AO_MCO_PIN, AO_MCO_AF);
+#endif
+
#if DEBUG_THE_CLOCK
/* Output SYSCLK on PA8 for measurments */
stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN);
stm_afr_set(&stm_gpioa, 8, STM_AFR_AF0);
- stm_moder_set(&stm_gpioa, 8, STM_MODER_ALTERNATE);
- stm_ospeedr_set(&stm_gpioa, 8, STM_OSPEEDR_40MHz);
+ stm_ospeedr_set(&stm_gpioa, 8, STM_OSPEEDR_HIGH);
stm_rcc.cfgr |= (STM_RCC_CFGR_MCOPRE_DIV_1 << STM_RCC_CFGR_MCOPRE);
stm_rcc.cfgr |= (STM_RCC_CFGR_MCOSEL_HSE << STM_RCC_CFGR_MCOSEL);