1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-01-18 03:52:11 +01:00

rtc: allow registration of callbacks on RTC tick

This separates the RTC device and interrupt handling
from the devices that rely on the tick notifications.

Drivers can now register tick notification functions
that will be called on each RTC tick event.
This commit is contained in:
Stacey Sheldon 2011-07-02 19:25:35 -04:00
parent 740b5f1584
commit 6415fc84a5
9 changed files with 191 additions and 95 deletions

View File

@ -422,6 +422,35 @@ const struct pios_usart_cfg pios_usart_gps_cfg = {
}; };
#endif #endif
#if defined(PIOS_INCLUDE_RTC)
/*
* Realtime Clock (RTC)
*/
#include <pios_rtc_priv.h>
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) #if defined(PIOS_INCLUDE_SPEKTRUM)
/* /*
* SPEKTRUM USART * SPEKTRUM USART
@ -476,8 +505,6 @@ void PIOS_USART_spektrum_irq_handler(void)
PIOS_SPEKTRUM_irq_handler(pios_usart_spektrum_id); 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 = { const struct pios_spektrum_cfg pios_spektrum_cfg = {
.pios_usart_spektrum_cfg = &pios_usart_spektrum_cfg, .pios_usart_spektrum_cfg = &pios_usart_spektrum_cfg,
.gpio_init = { //used for bind feature .gpio_init = { //used for bind feature
@ -485,30 +512,10 @@ const struct pios_spektrum_cfg pios_spektrum_cfg = {
.GPIO_Speed = GPIO_Speed_2MHz, .GPIO_Speed = GPIO_Speed_2MHz,
}, },
.remap = 0, .remap = 0,
.irq = {
.handler = RTC_IRQHandler,
.init = {
.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID,
.NVIC_IRQChannelSubPriority = 0,
.NVIC_IRQChannelCmd = ENABLE,
},
},
.port = PIOS_GPIO_SPEKTRUM, .port = PIOS_GPIO_SPEKTRUM,
.pin = PIOS_RXIO_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 */ #endif /* PIOS_INCLUDE_SPEKTRUM */
#if defined(PIOS_INCLUDE_SBUS) #if defined(PIOS_INCLUDE_SBUS)
@ -565,8 +572,6 @@ void PIOS_USART_sbus_irq_handler(void)
} }
#include <pios_sbus_priv.h> #include <pios_sbus_priv.h>
void RTC_IRQHandler();
void RTC_IRQHandler() __attribute__ ((alias ("PIOS_SUPV_irq_handler")));
const struct pios_sbus_cfg pios_sbus_cfg = { const struct pios_sbus_cfg pios_sbus_cfg = {
/* USART configuration structure */ /* USART configuration structure */
.pios_usart_sbus_cfg = &pios_usart_sbus_cfg, .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, .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 */ #endif /* PIOS_INCLUDE_SBUS */
#if defined(PIOS_INCLUDE_TELEMETRY_RF) #if defined(PIOS_INCLUDE_TELEMETRY_RF)
@ -909,6 +902,11 @@ void PIOS_Board_Init(void) {
UAVObjInitialize(); UAVObjInitialize();
UAVObjectsInitializeAll(); 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 */ /* Initialize the alarms library */
AlarmsInitialize(); AlarmsInitialize();

View File

@ -450,6 +450,35 @@ const struct pios_usart_cfg pios_usart_aux_cfg = {
}; };
#endif #endif
#if defined(PIOS_INCLUDE_RTC)
/*
* Realtime Clock (RTC)
*/
#include <pios_rtc_priv.h>
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 #ifdef PIOS_COM_SPEKTRUM
/* /*
* SPEKTRUM USART * SPEKTRUM USART
@ -504,8 +533,6 @@ void PIOS_USART_spektrum_irq_handler(void)
PIOS_SPEKTRUM_irq_handler(pios_usart_spektrum_id); 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 = { const struct pios_spektrum_cfg pios_spektrum_cfg = {
.pios_usart_spektrum_cfg = &pios_usart_spektrum_cfg, .pios_usart_spektrum_cfg = &pios_usart_spektrum_cfg,
.gpio_init = { //used for bind feature .gpio_init = { //used for bind feature
@ -513,30 +540,10 @@ const struct pios_spektrum_cfg pios_spektrum_cfg = {
.GPIO_Speed = GPIO_Speed_2MHz, .GPIO_Speed = GPIO_Speed_2MHz,
}, },
.remap = 0, .remap = 0,
.irq = {
.handler = RTC_IRQHandler,
.init = {
.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID,
.NVIC_IRQChannelSubPriority = 0,
.NVIC_IRQChannelCmd = ENABLE,
},
},
.port = GPIOA, .port = GPIOA,
.pin = GPIO_Pin_10, .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 */ #endif /* PIOS_COM_SPEKTRUM */
#if defined(PIOS_INCLUDE_SBUS) #if defined(PIOS_INCLUDE_SBUS)
@ -1062,6 +1069,11 @@ void PIOS_Board_Init(void) {
UAVObjInitialize(); UAVObjInitialize();
UAVObjectsInitializeAll(); 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 */ /* Initialize the alarms library */
AlarmsInitialize(); AlarmsInitialize();

View File

@ -32,30 +32,39 @@
#include "pios.h" #include "pios.h"
#if defined(PIOS_INCLUDE_RTC) #if defined(PIOS_INCLUDE_RTC)
#include <pios_rtc_priv.h>
#ifndef PIOS_RTC_PRESCALAR #ifndef PIOS_RTC_PRESCALER
#define PIOS_RTC_PRESCALAR 100 #define PIOS_RTC_PRESCALER 100
#endif #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, RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP | RCC_APB1Periph_PWR,
ENABLE); ENABLE);
PWR_BackupAccessCmd(ENABLE); PWR_BackupAccessCmd(ENABLE);
RCC_RTCCLKConfig(RCC_RTCCLKSource_HSE_Div128); RCC_RTCCLKConfig(cfg->clksrc);
RCC_RTCCLKCmd(ENABLE); RCC_RTCCLKCmd(ENABLE);
RTC_WaitForLastTask(); RTC_WaitForLastTask();
RTC_WaitForSynchro(); RTC_WaitForSynchro();
RTC_WaitForLastTask(); RTC_WaitForLastTask();
#if defined(PIOS_INCLUDE_SPEKTRUM) || defined(PIOS_INCLUDE_SBUS) /* Configure and enable the RTC Second interrupt */
/* Enable the RTC Second interrupt */ NVIC_Init(&cfg->irq.init);
RTC_ITConfig( RTC_IT_SEC, ENABLE ); RTC_ITConfig( RTC_IT_SEC, ENABLE );
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask(); RTC_WaitForLastTask();
#endif
RTC_SetPrescaler(PIOS_RTC_PRESCALAR); // counting at 8e6 / 128 RTC_SetPrescaler(cfg->prescaler);
RTC_WaitForLastTask(); RTC_WaitForLastTask();
RTC_SetCounter(0); RTC_SetCounter(0);
RTC_WaitForLastTask(); RTC_WaitForLastTask();
@ -66,9 +75,12 @@ uint32_t PIOS_RTC_Counter()
return RTC_GetCounter(); 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() float PIOS_RTC_Rate()
{ {
return (float) (8e6 / 128) / (1 + PIOS_RTC_PRESCALAR); return (float) (8e6 / 128) / (1 + PIOS_RTC_PRESCALER);
} }
float PIOS_RTC_MsPerTick() float PIOS_RTC_MsPerTick()
@ -76,6 +88,39 @@ float PIOS_RTC_MsPerTick()
return 1000.0f / PIOS_RTC_Rate(); 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 #endif
/** /**

View File

@ -50,6 +50,8 @@ static uint8_t receive_timer;
static uint8_t failsafe_timer; static uint8_t failsafe_timer;
static uint8_t frame_found; static uint8_t frame_found;
static void PIOS_SBUS_Supervisor(uint32_t sbus_id);
/** /**
* reset_channels() function clears all channel data in case of * reset_channels() function clears all channel data in case of
* lost signal or explicit failsafe flag from the S.Bus data stream * 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_init.GPIO_Pin,
pios_sbus_cfg.gpio_inv_enable); pios_sbus_cfg.gpio_inv_enable);
/* Init RTC supervisor timer interrupt */ if (!PIOS_RTC_RegisterTickCallback(PIOS_SBUS_Supervisor, 0)) {
static const NVIC_InitTypeDef NVIC_InitStructure = { PIOS_DEBUG_Assert(0);
.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();
} }
/** /**
@ -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 * data reception. If no new data received in 100ms, we must call the
* failsafe function which clears all channels. * 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 */ /* waiting for new frame if no bytes were received in 3.2ms */
if (++receive_timer > 2) { if (++receive_timer > 2) {

View File

@ -64,6 +64,8 @@ static uint8_t prev_byte = 0xFF, sync = 0, bytecount = 0, datalength=0, frame_er
uint8_t sync_of = 0; uint8_t sync_of = 0;
uint16_t supv_timer=0; uint16_t supv_timer=0;
static void PIOS_SPEKTRUM_Supervisor(uint32_t spektrum_id);
/** /**
* Bind and Initialise Spektrum satellite receiver * Bind and Initialise Spektrum satellite receiver
*/ */
@ -74,15 +76,9 @@ void PIOS_SPEKTRUM_Init(void)
PIOS_SPEKTRUM_Bind(); PIOS_SPEKTRUM_Bind();
} }
/* Init RTC supervisor timer interrupt */ if (!PIOS_RTC_RegisterTickCallback(PIOS_SPEKTRUM_Supervisor, 0)) {
NVIC_InitTypeDef NVIC_InitStructure; PIOS_DEBUG_Assert(0);
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();
} }
/** /**
@ -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 This function is called between frames and when a spektrum word hasnt been decoded for too long
*@brief clears the channel values *@brief clears the channel values
*/ */
void PIOS_SPEKTRUMSV_irq_handler() { static void PIOS_SPEKTRUM_Supervisor(uint32_t spektrum_id) {
/* 125hz */ /* 125hz */
supv_timer++; supv_timer++;
if(supv_timer > 5) { if(supv_timer > 5) {

View File

@ -30,13 +30,15 @@
#ifndef PIOS_RTC_H #ifndef PIOS_RTC_H
#define PIOS_RTC_H #define PIOS_RTC_H
#include <stdbool.h>
/* Public Functions */ /* Public Functions */
extern void PIOS_RTC_Init();
extern uint32_t PIOS_RTC_Counter(); extern uint32_t PIOS_RTC_Counter();
extern float PIOS_RTC_Rate(); extern float PIOS_RTC_Rate();
extern float PIOS_RTC_MsPerTick(); 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 */
/** /**
* @} * @}

View File

@ -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 <pios.h>
#include <pios_stm32.h>
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 */
/**
* @}
* @}
*/

View File

@ -78,7 +78,6 @@ struct pios_sbus_cfg {
}; };
extern void PIOS_SBUS_irq_handler(); extern void PIOS_SBUS_irq_handler();
extern void PIOS_SBUSSV_irq_handler();
extern uint8_t pios_sbus_num_channels; extern uint8_t pios_sbus_num_channels;
extern const struct pios_sbus_cfg pios_sbus_cfg; extern const struct pios_sbus_cfg pios_sbus_cfg;

View File

@ -39,13 +39,11 @@ struct pios_spektrum_cfg {
const struct pios_usart_cfg * pios_usart_spektrum_cfg; const struct pios_usart_cfg * pios_usart_spektrum_cfg;
GPIO_InitTypeDef gpio_init; GPIO_InitTypeDef gpio_init;
uint32_t remap; /* GPIO_Remap_* */ uint32_t remap; /* GPIO_Remap_* */
struct stm32_irq irq;
GPIO_TypeDef * port; GPIO_TypeDef * port;
uint16_t pin; uint16_t pin;
}; };
extern void PIOS_SPEKTRUM_irq_handler(); extern void PIOS_SPEKTRUM_irq_handler();
extern void PIOS_SPEKTRUMSV_irq_handler();
extern uint8_t pios_spektrum_num_channels; extern uint8_t pios_spektrum_num_channels;
extern const struct pios_spektrum_cfg pios_spektrum_cfg; extern const struct pios_spektrum_cfg pios_spektrum_cfg;