Слияние кода завершено, страница обновится автоматически
/*!
* \file rtc-board.c
*
* \brief Target board RTC timer and low power modes management
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013-2017 Semtech
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Marten Lootsma(TWTG) on behalf of Microchip/Atmel (c)2017
*/
#include <hal_init.h>
#include <hw_timer.h>
#include "board-config.h"
#include "board.h"
#include "timer.h"
#include "systime.h"
#include "gpio.h"
#include "rtc-board.h"
#define RTC_DEBUG_ENABLE 1
#define RTC_DEBUG_DISABLE 0
#define RTC_DEBUG_GPIO_STATE RTC_DEBUG_DISABLE
#define RTC_DEBUG_PRINTF_STATE RTC_DEBUG_DISABLE
#define MIN_ALARM_DELAY 3 // in ticks
/*!
* \brief Indicates if the RTC is already Initialized or not
*/
static bool RtcInitialized = false;
static volatile bool RtcTimeoutPendingInterrupt = false;
static volatile bool RtcTimeoutPendingPolling = false;
typedef enum AlarmStates_e
{
ALARM_STOPPED = 0,
ALARM_RUNNING = !ALARM_STOPPED
} AlarmStates_t;
/*!
* RTC timer context
*/
typedef struct
{
uint32_t Time; // Reference time
uint32_t Delay; // Reference Timeout duration
uint32_t AlarmState;
}RtcTimerContext_t;
/*!
* Keep the value of the RTC timer when the RTC alarm is set
* Set with the \ref RtcSetTimerContext function
* Value is kept as a Reference to calculate alarm
*/
static RtcTimerContext_t RtcTimerContext;
#if( RTC_DEBUG_GPIO_STATE == RTC_DEBUG_ENABLE )
Gpio_t DbgRtcPin0;
Gpio_t DbgRtcPin1;
#endif
/*!
* Used to store the Seconds and SubSeconds.
*
* WARNING: Temporary fix fix. Should use MCU NVM internal
* registers
*/
uint32_t RtcBkupRegisters[] = { 0, 0 };
/*!
* \brief Callback for the hw_timer when alarm expired
*/
static void RtcAlarmIrq( void );
/*!
* \brief Callback for the hw_timer when counter overflows
*/
static void RtcOverflowIrq( void );
void RtcInit( void )
{
if( RtcInitialized == false )
{
#if( RTC_DEBUG_GPIO_STATE == RTC_DEBUG_ENABLE )
GpioInit( &DbgRtcPin0, RTC_DBG_PIN_0, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
GpioInit( &DbgRtcPin1, RTC_DBG_PIN_1, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
#endif
// RTC timer
HwTimerInit( );
HwTimerAlarmSetCallback( RtcAlarmIrq );
HwTimerOverflowSetCallback( RtcOverflowIrq );
RtcTimerContext.AlarmState = ALARM_STOPPED;
RtcSetTimerContext( );
RtcInitialized = true;
}
}
uint32_t RtcSetTimerContext( void )
{
RtcTimerContext.Time = ( uint32_t )HwTimerGetTime( );
return ( uint32_t )RtcTimerContext.Time;
}
uint32_t RtcGetTimerContext( void )
{
return RtcTimerContext.Time;
}
uint32_t RtcGetMinimumTimeout( void )
{
return( MIN_ALARM_DELAY );
}
uint32_t RtcMs2Tick( TimerTime_t milliseconds )
{
return ( uint32_t )( milliseconds );
}
TimerTime_t RtcTick2Ms( uint32_t tick )
{
uint32_t seconds = tick >> 10;
tick = tick & 0x3FF;
return ( ( seconds * 1000 ) + ( ( tick * 1000 ) >> 10 ) );
}
void RtcDelayMs( TimerTime_t milliseconds )
{
uint32_t delayTicks = 0;
uint32_t refTicks = RtcGetTimerValue( );
delayTicks = RtcMs2Tick( milliseconds );
// Wait delay ms
while( ( ( RtcGetTimerValue( ) - refTicks ) ) < delayTicks )
{
__NOP( );
}
}
void RtcSetAlarm( uint32_t timeout )
{
RtcStartAlarm( timeout );
}
void RtcStopAlarm( void )
{
RtcTimerContext.AlarmState = ALARM_STOPPED;
}
void RtcStartAlarm( uint32_t timeout )
{
CRITICAL_SECTION_BEGIN( );
RtcStopAlarm( );
RtcTimerContext.Delay = timeout;
#if( RTC_DEBUG_PRINTF_STATE == RTC_DEBUG_ENABLE )
printf( "TIMEOUT \t%010ld\t%010ld\n", RtcTimerContext.Time, RtcTimerContext.Delay );
#endif
#if( RTC_DEBUG_GPIO_STATE == RTC_DEBUG_ENABLE )
GpioWrite( &DbgRtcPin0, 0 );
GpioWrite( &DbgRtcPin1, 0 );
#endif
RtcTimeoutPendingInterrupt = true;
RtcTimeoutPendingPolling = false;
RtcTimerContext.AlarmState = ALARM_RUNNING;
if( HwTimerLoadAbsoluteTicks( RtcTimerContext.Time + RtcTimerContext.Delay ) == false )
{
// If timer already passed
if( RtcTimeoutPendingInterrupt == true )
{
// And interrupt not handled, mark as polling
RtcTimeoutPendingPolling = true;
RtcTimeoutPendingInterrupt = false;
#if( RTC_DEBUG_GPIO_STATE == RTC_DEBUG_ENABLE )
GpioWrite( &DbgRtcPin0, 1 );
#endif
}
}
CRITICAL_SECTION_END( );
}
uint32_t RtcGetTimerValue( void )
{
return ( uint32_t )HwTimerGetTime( );
}
uint32_t RtcGetTimerElapsedTime( void )
{
return ( uint32_t)( HwTimerGetTime( ) - RtcTimerContext.Time );
}
uint32_t RtcGetCalendarTime( uint16_t *milliseconds )
{
uint32_t ticks = 0;
uint32_t calendarValue = HwTimerGetTime( );
uint32_t seconds = ( uint32_t )calendarValue >> 10;
ticks = ( uint32_t )calendarValue & 0x3FF;
*milliseconds = RtcTick2Ms( ticks );
return seconds;
}
void RtcBkupWrite( uint32_t data0, uint32_t data1 )
{
CRITICAL_SECTION_BEGIN( );
RtcBkupRegisters[0] = data0;
RtcBkupRegisters[1] = data1;
CRITICAL_SECTION_END( );
}
void RtcBkupRead( uint32_t* data0, uint32_t* data1 )
{
CRITICAL_SECTION_BEGIN( );
*data0 = RtcBkupRegisters[0];
*data1 = RtcBkupRegisters[1];
CRITICAL_SECTION_END( );
}
void RtcProcess( void )
{
CRITICAL_SECTION_BEGIN( );
if( ( RtcTimerContext.AlarmState == ALARM_RUNNING ) && ( RtcTimeoutPendingPolling == true ) )
{
if( RtcGetTimerElapsedTime( ) >= RtcTimerContext.Delay )
{
RtcTimerContext.AlarmState = ALARM_STOPPED;
// Because of one shot the task will be removed after the callback
RtcTimeoutPendingPolling = false;
#if( RTC_DEBUG_GPIO_STATE == RTC_DEBUG_ENABLE )
GpioWrite( &DbgRtcPin0, 0 );
GpioWrite( &DbgRtcPin1, 1 );
#endif
// NOTE: The handler should take less then 1 ms otherwise the clock shifts
TimerIrqHandler( );
#if( RTC_DEBUG_GPIO_STATE == RTC_DEBUG_ENABLE )
GpioWrite( &DbgRtcPin1, 0 );
#endif
}
}
CRITICAL_SECTION_END( );
}
TimerTime_t RtcTempCompensation( TimerTime_t period, float temperature )
{
return period;
}
static void RtcAlarmIrq( void )
{
RtcTimerContext.AlarmState = ALARM_STOPPED;
// Because of one shot the task will be removed after the callback
RtcTimeoutPendingInterrupt = false;
#if( RTC_DEBUG_GPIO_STATE == RTC_DEBUG_ENABLE )
GpioWrite( &DbgRtcPin1, 1 );
#endif
// NOTE: The handler should take less then 1 ms otherwise the clock shifts
TimerIrqHandler( );
#if( RTC_DEBUG_GPIO_STATE == RTC_DEBUG_ENABLE )
GpioWrite( &DbgRtcPin1, 0 );
#endif
}
static void RtcOverflowIrq( void )
{
//RtcTimerContext.Time += ( uint64_t )( 1 << 32 );
}
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарий ( 0 )