diff --git a/flight/CopterControl/System/pios_board.c b/flight/CopterControl/System/pios_board.c index b724cc806..c88c1fc9f 100644 --- a/flight/CopterControl/System/pios_board.c +++ b/flight/CopterControl/System/pios_board.c @@ -422,6 +422,35 @@ const struct pios_usart_cfg pios_usart_gps_cfg = { }; #endif +#if defined(PIOS_INCLUDE_RTC) +/* + * Realtime Clock (RTC) + */ +#include + +void PIOS_RTC_IRQ_Handler (void); +void RTC_IRQHandler() __attribute__ ((alias ("PIOS_RTC_IRQ_Handler"))); +const struct pios_rtc_cfg pios_rtc_main_cfg = { + .clksrc = RCC_RTCCLKSource_HSE_Div128, + .prescaler = 100, + .irq = { + .handler = PIOS_RTC_IRQ_Handler, + .init = { + .NVIC_IRQChannel = RTC_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +void PIOS_RTC_IRQ_Handler (void) +{ + PIOS_RTC_irq_handler (); +} + +#endif + #if defined(PIOS_INCLUDE_SPEKTRUM) /* * SPEKTRUM USART @@ -476,8 +505,6 @@ void PIOS_USART_spektrum_irq_handler(void) PIOS_SPEKTRUM_irq_handler(pios_usart_spektrum_id); } -void RTC_IRQHandler(); -void RTC_IRQHandler() __attribute__ ((alias ("PIOS_SUPV_irq_handler"))); const struct pios_spektrum_cfg pios_spektrum_cfg = { .pios_usart_spektrum_cfg = &pios_usart_spektrum_cfg, .gpio_init = { //used for bind feature @@ -485,30 +512,10 @@ const struct pios_spektrum_cfg pios_spektrum_cfg = { .GPIO_Speed = GPIO_Speed_2MHz, }, .remap = 0, - .irq = { - .handler = RTC_IRQHandler, - .init = { - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, .port = PIOS_GPIO_SPEKTRUM, .pin = PIOS_RXIO_SPEKTRUM, }; -void PIOS_SUPV_irq_handler() { - if (RTC_GetITStatus(RTC_IT_SEC)) - { - /* Call the right handler */ - PIOS_SPEKTRUMSV_irq_handler(pios_usart_spektrum_id); - - /* Wait until last write operation on RTC registers has finished */ - RTC_WaitForLastTask(); - /* Clear the RTC Second interrupt */ - RTC_ClearITPendingBit(RTC_IT_SEC); - } -} #endif /* PIOS_INCLUDE_SPEKTRUM */ #if defined(PIOS_INCLUDE_SBUS) @@ -565,8 +572,6 @@ void PIOS_USART_sbus_irq_handler(void) } #include -void RTC_IRQHandler(); -void RTC_IRQHandler() __attribute__ ((alias ("PIOS_SUPV_irq_handler"))); const struct pios_sbus_cfg pios_sbus_cfg = { /* USART configuration structure */ .pios_usart_sbus_cfg = &pios_usart_sbus_cfg, @@ -583,18 +588,6 @@ const struct pios_sbus_cfg pios_sbus_cfg = { .gpio_inv_enable = Bit_SET, }; -void PIOS_SUPV_irq_handler() { - if (RTC_GetITStatus(RTC_IT_SEC)) - { - /* Call the right handler */ - PIOS_SBUSSV_irq_handler(pios_usart_sbus_id); - - /* Wait until last write operation on RTC registers has finished */ - RTC_WaitForLastTask(); - /* Clear the RTC Second interrupt */ - RTC_ClearITPendingBit(RTC_IT_SEC); - } -} #endif /* PIOS_INCLUDE_SBUS */ #if defined(PIOS_INCLUDE_TELEMETRY_RF) @@ -909,6 +902,11 @@ void PIOS_Board_Init(void) { UAVObjInitialize(); UAVObjectsInitializeAll(); +#if defined(PIOS_INCLUDE_RTC) + /* Initialize the real-time clock and its associated tick */ + PIOS_RTC_Init(&pios_rtc_main_cfg); +#endif + /* Initialize the alarms library */ AlarmsInitialize(); diff --git a/flight/OpenPilot/System/pios_board.c b/flight/OpenPilot/System/pios_board.c index 7c9e13d82..3953f03d4 100644 --- a/flight/OpenPilot/System/pios_board.c +++ b/flight/OpenPilot/System/pios_board.c @@ -450,6 +450,35 @@ const struct pios_usart_cfg pios_usart_aux_cfg = { }; #endif +#if defined(PIOS_INCLUDE_RTC) +/* + * Realtime Clock (RTC) + */ +#include + +void PIOS_RTC_IRQ_Handler (void); +void RTC_IRQHandler() __attribute__ ((alias ("PIOS_RTC_IRQ_Handler"))); +const struct pios_rtc_cfg pios_rtc_main_cfg = { + .clksrc = RCC_RTCCLKSource_HSE_Div128, + .prescaler = 100, + .irq = { + .handler = PIOS_RTC_IRQ_Handler, + .init = { + .NVIC_IRQChannel = RTC_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +void PIOS_RTC_IRQ_Handler (void) +{ + PIOS_RTC_irq_handler (); +} + +#endif + #ifdef PIOS_COM_SPEKTRUM /* * SPEKTRUM USART @@ -504,8 +533,6 @@ void PIOS_USART_spektrum_irq_handler(void) PIOS_SPEKTRUM_irq_handler(pios_usart_spektrum_id); } -void RTC_IRQHandler(); -void RTC_IRQHandler() __attribute__ ((alias ("PIOS_SUPV_irq_handler"))); const struct pios_spektrum_cfg pios_spektrum_cfg = { .pios_usart_spektrum_cfg = &pios_usart_spektrum_cfg, .gpio_init = { //used for bind feature @@ -513,30 +540,10 @@ const struct pios_spektrum_cfg pios_spektrum_cfg = { .GPIO_Speed = GPIO_Speed_2MHz, }, .remap = 0, - .irq = { - .handler = RTC_IRQHandler, - .init = { - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, .port = GPIOA, .pin = GPIO_Pin_10, }; -void PIOS_SUPV_irq_handler(void) { - if (RTC_GetITStatus(RTC_IT_SEC)) - { - /* Call the right handler */ - PIOS_SPEKTRUMSV_irq_handler(pios_usart_spektrum_id); - - /* Wait until last write operation on RTC registers has finished */ - RTC_WaitForLastTask(); - /* Clear the RTC Second interrupt */ - RTC_ClearITPendingBit(RTC_IT_SEC); - } -} #endif /* PIOS_COM_SPEKTRUM */ #if defined(PIOS_INCLUDE_SBUS) @@ -1062,6 +1069,11 @@ void PIOS_Board_Init(void) { UAVObjInitialize(); UAVObjectsInitializeAll(); +#if defined(PIOS_INCLUDE_RTC) + /* Initialize the real-time clock and its associated tick */ + PIOS_RTC_Init(&pios_rtc_main_cfg); +#endif + /* Initialize the alarms library */ AlarmsInitialize(); diff --git a/flight/PiOS/STM32F10x/pios_rtc.c b/flight/PiOS/STM32F10x/pios_rtc.c index 2a0d55915..b80a9e0d1 100644 --- a/flight/PiOS/STM32F10x/pios_rtc.c +++ b/flight/PiOS/STM32F10x/pios_rtc.c @@ -32,30 +32,39 @@ #include "pios.h" #if defined(PIOS_INCLUDE_RTC) +#include -#ifndef PIOS_RTC_PRESCALAR -#define PIOS_RTC_PRESCALAR 100 +#ifndef PIOS_RTC_PRESCALER +#define PIOS_RTC_PRESCALER 100 #endif -void PIOS_RTC_Init() +struct rtc_callback_entry { + void (*fn)(uint32_t); + uint32_t data; +}; + +#define PIOS_RTC_MAX_CALLBACKS 3 +struct rtc_callback_entry rtc_callback_list[PIOS_RTC_MAX_CALLBACKS]; +static uint8_t rtc_callback_next = 0; + +void PIOS_RTC_Init(const struct pios_rtc_cfg * cfg) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP | RCC_APB1Periph_PWR, ENABLE); PWR_BackupAccessCmd(ENABLE); - RCC_RTCCLKConfig(RCC_RTCCLKSource_HSE_Div128); + RCC_RTCCLKConfig(cfg->clksrc); RCC_RTCCLKCmd(ENABLE); RTC_WaitForLastTask(); RTC_WaitForSynchro(); RTC_WaitForLastTask(); -#if defined(PIOS_INCLUDE_SPEKTRUM) || defined(PIOS_INCLUDE_SBUS) - /* Enable the RTC Second interrupt */ + /* Configure and enable the RTC Second interrupt */ + NVIC_Init(&cfg->irq.init); RTC_ITConfig( RTC_IT_SEC, ENABLE ); - /* Wait until last write operation on RTC registers has finished */ RTC_WaitForLastTask(); -#endif - RTC_SetPrescaler(PIOS_RTC_PRESCALAR); // counting at 8e6 / 128 + + RTC_SetPrescaler(cfg->prescaler); RTC_WaitForLastTask(); RTC_SetCounter(0); RTC_WaitForLastTask(); @@ -66,9 +75,12 @@ uint32_t PIOS_RTC_Counter() return RTC_GetCounter(); } +/* FIXME: This shouldn't use hard-coded clock rates, dividers or prescalers. + * Should get these from the cfg struct passed to init. + */ float PIOS_RTC_Rate() { - return (float) (8e6 / 128) / (1 + PIOS_RTC_PRESCALAR); + return (float) (8e6 / 128) / (1 + PIOS_RTC_PRESCALER); } float PIOS_RTC_MsPerTick() @@ -76,6 +88,39 @@ float PIOS_RTC_MsPerTick() return 1000.0f / PIOS_RTC_Rate(); } +/* TODO: This needs a mutex around rtc_callbacks[] */ +bool PIOS_RTC_RegisterTickCallback(void (*fn)(uint32_t id), uint32_t data) +{ + struct rtc_callback_entry * cb; + if (rtc_callback_next >= PIOS_RTC_MAX_CALLBACKS) { + return false; + } + + cb = &rtc_callback_list[rtc_callback_next++]; + + cb->fn = fn; + cb->data = data; + return true; +} + +void PIOS_RTC_irq_handler (void) +{ + if (RTC_GetITStatus(RTC_IT_SEC)) + { + /* Call all registered callbacks */ + for (uint8_t i = 0; i < rtc_callback_next; i++) { + struct rtc_callback_entry * cb = &rtc_callback_list[i]; + if (cb->fn) { + (cb->fn)(cb->data); + } + } + + /* Wait until last write operation on RTC registers has finished */ + RTC_WaitForLastTask(); + /* Clear the RTC Second interrupt */ + RTC_ClearITPendingBit(RTC_IT_SEC); + } +} #endif /** diff --git a/flight/PiOS/STM32F10x/pios_sbus.c b/flight/PiOS/STM32F10x/pios_sbus.c index 823597641..698beac94 100644 --- a/flight/PiOS/STM32F10x/pios_sbus.c +++ b/flight/PiOS/STM32F10x/pios_sbus.c @@ -50,6 +50,8 @@ static uint8_t receive_timer; static uint8_t failsafe_timer; static uint8_t frame_found; +static void PIOS_SBUS_Supervisor(uint32_t sbus_id); + /** * reset_channels() function clears all channel data in case of * lost signal or explicit failsafe flag from the S.Bus data stream @@ -142,17 +144,9 @@ void PIOS_SBUS_Init(void) pios_sbus_cfg.gpio_inv_init.GPIO_Pin, pios_sbus_cfg.gpio_inv_enable); - /* Init RTC supervisor timer interrupt */ - static const NVIC_InitTypeDef NVIC_InitStructure = { - .NVIC_IRQChannel = RTC_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }; - NVIC_Init(&NVIC_InitStructure); - - /* Init RTC clock */ - PIOS_RTC_Init(); + if (!PIOS_RTC_RegisterTickCallback(PIOS_SBUS_Supervisor, 0)) { + PIOS_DEBUG_Assert(0); + } } /** @@ -205,7 +199,7 @@ void PIOS_SBUS_irq_handler(uint32_t usart_id) * data reception. If no new data received in 100ms, we must call the * failsafe function which clears all channels. */ -void PIOS_SBUSSV_irq_handler() +static void PIOS_SBUS_Supervisor(uint32_t sbus_id) { /* waiting for new frame if no bytes were received in 3.2ms */ if (++receive_timer > 2) { diff --git a/flight/PiOS/STM32F10x/pios_spektrum.c b/flight/PiOS/STM32F10x/pios_spektrum.c index 6e236991d..4372fb4ef 100644 --- a/flight/PiOS/STM32F10x/pios_spektrum.c +++ b/flight/PiOS/STM32F10x/pios_spektrum.c @@ -64,6 +64,8 @@ static uint8_t prev_byte = 0xFF, sync = 0, bytecount = 0, datalength=0, frame_er uint8_t sync_of = 0; uint16_t supv_timer=0; +static void PIOS_SPEKTRUM_Supervisor(uint32_t spektrum_id); + /** * Bind and Initialise Spektrum satellite receiver */ @@ -74,15 +76,9 @@ void PIOS_SPEKTRUM_Init(void) PIOS_SPEKTRUM_Bind(); } - /* Init RTC supervisor timer interrupt */ - NVIC_InitTypeDef NVIC_InitStructure; - NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); - /* Init RTC clock */ - PIOS_RTC_Init(); + if (!PIOS_RTC_RegisterTickCallback(PIOS_SPEKTRUM_Supervisor, 0)) { + PIOS_DEBUG_Assert(0); + } } /** @@ -255,7 +251,7 @@ void PIOS_SPEKTRUM_irq_handler(uint32_t usart_id) { *@brief This function is called between frames and when a spektrum word hasnt been decoded for too long *@brief clears the channel values */ -void PIOS_SPEKTRUMSV_irq_handler() { +static void PIOS_SPEKTRUM_Supervisor(uint32_t spektrum_id) { /* 125hz */ supv_timer++; if(supv_timer > 5) { diff --git a/flight/PiOS/inc/pios_rtc.h b/flight/PiOS/inc/pios_rtc.h index f68b54af8..2e01912b9 100644 --- a/flight/PiOS/inc/pios_rtc.h +++ b/flight/PiOS/inc/pios_rtc.h @@ -30,13 +30,15 @@ #ifndef PIOS_RTC_H #define PIOS_RTC_H +#include + /* Public Functions */ -extern void PIOS_RTC_Init(); extern uint32_t PIOS_RTC_Counter(); extern float PIOS_RTC_Rate(); extern float PIOS_RTC_MsPerTick(); +extern bool PIOS_RTC_RegisterTickCallback(void (*fn)(uint32_t id), uint32_t data); -#endif /* PIOS_SERVO_H */ +#endif /* PIOS_RTC_H */ /** * @} diff --git a/flight/PiOS/inc/pios_rtc_priv.h b/flight/PiOS/inc/pios_rtc_priv.h new file mode 100644 index 000000000..0a8c1c9b1 --- /dev/null +++ b/flight/PiOS/inc/pios_rtc_priv.h @@ -0,0 +1,52 @@ +/** + ****************************************************************************** + * @addtogroup PIOS PIOS Core hardware abstraction layer + * @{ + * @addtogroup PIOS_RTC RTC Functions + * @brief PIOS interface for RTC tick + * @{ + * + * @file pios_rtc_priv.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief ADC private definitions. + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * 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; either version 3 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 MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PIOS_RTC_PRIV_H +#define PIOS_RTC_PRIV_H + +#include +#include + +struct pios_rtc_cfg { + uint32_t clksrc; + uint32_t prescaler; + struct stm32_irq irq; +}; + +extern void PIOS_RTC_Init(const struct pios_rtc_cfg * cfg); + +extern void PIOS_RTC_irq_handler(void); +#endif /* PIOS_RTC_PRIV_H */ + +/** + * @} + * @} + */ + diff --git a/flight/PiOS/inc/pios_sbus_priv.h b/flight/PiOS/inc/pios_sbus_priv.h index cb73b24cd..a0a97a860 100644 --- a/flight/PiOS/inc/pios_sbus_priv.h +++ b/flight/PiOS/inc/pios_sbus_priv.h @@ -78,7 +78,6 @@ struct pios_sbus_cfg { }; extern void PIOS_SBUS_irq_handler(); -extern void PIOS_SBUSSV_irq_handler(); extern uint8_t pios_sbus_num_channels; extern const struct pios_sbus_cfg pios_sbus_cfg; diff --git a/flight/PiOS/inc/pios_spektrum_priv.h b/flight/PiOS/inc/pios_spektrum_priv.h index 5b1ac616e..b300cb212 100644 --- a/flight/PiOS/inc/pios_spektrum_priv.h +++ b/flight/PiOS/inc/pios_spektrum_priv.h @@ -39,13 +39,11 @@ struct pios_spektrum_cfg { const struct pios_usart_cfg * pios_usart_spektrum_cfg; GPIO_InitTypeDef gpio_init; uint32_t remap; /* GPIO_Remap_* */ - struct stm32_irq irq; GPIO_TypeDef * port; uint16_t pin; }; extern void PIOS_SPEKTRUM_irq_handler(); -extern void PIOS_SPEKTRUMSV_irq_handler(); extern uint8_t pios_spektrum_num_channels; extern const struct pios_spektrum_cfg pios_spektrum_cfg;