mirror of
https://github.com/oopuuu/zTC1.git
synced 2025-12-17 15:38:14 +08:00
258 lines
7.5 KiB
C
258 lines
7.5 KiB
C
/**
|
|
******************************************************************************
|
|
* @file paltform_watchdog.c
|
|
* @author William Xu
|
|
* @version V1.0.0
|
|
* @date 05-May-2014
|
|
* @brief This file provide WDG driver functions.
|
|
******************************************************************************
|
|
* UNPUBLISHED PROPRIETARY SOURCE CODE
|
|
* Copyright (c) 2016 MXCHIP Inc.
|
|
*
|
|
* The contents of this file may not be disclosed to third parties, copied or
|
|
* duplicated in any form, in whole or in part, without the prior written
|
|
* permission of MXCHIP Corporation.
|
|
******************************************************************************
|
|
*/
|
|
|
|
#include "common.h"
|
|
#include "debug.h"
|
|
|
|
#include "platform.h"
|
|
#include "platform_peripheral.h"
|
|
#include "stm32f2xx.h"
|
|
|
|
/******************************************************
|
|
* Constants
|
|
******************************************************/
|
|
|
|
/******************************************************
|
|
* Enumerations
|
|
******************************************************/
|
|
|
|
/******************************************************
|
|
* Type Definitions
|
|
******************************************************/
|
|
|
|
/******************************************************
|
|
* Structures
|
|
******************************************************/
|
|
|
|
/******************************************************
|
|
* Variables Definitions
|
|
******************************************************/
|
|
#ifndef MICO_DISABLE_WATCHDOG
|
|
static __IO uint32_t LsiFreq = 0;
|
|
static __IO uint32_t CaptureNumber = 0, PeriodValue = 0;
|
|
static mico_semaphore_t _measureLSIComplete_SEM = NULL;
|
|
uint16_t tmpCC4[2] = {0, 0};
|
|
#endif
|
|
|
|
/******************************************************
|
|
* Function Declarations
|
|
******************************************************/
|
|
#ifndef MICO_DISABLE_WATCHDOG
|
|
static uint32_t GetLSIFrequency(void);
|
|
#endif
|
|
|
|
/******************************************************
|
|
* Function Definitions
|
|
******************************************************/
|
|
|
|
OSStatus platform_watchdog_init( uint32_t timeout_ms )
|
|
{
|
|
// PLATFORM_TO_DO
|
|
#ifndef MICO_DISABLE_WATCHDOG
|
|
OSStatus err = kNoErr;
|
|
uint16_t reloadTick;
|
|
/* Get the LSI frequency: TIM5 is used to measure the LSI frequency */
|
|
LsiFreq = GetLSIFrequency();
|
|
|
|
/* Set counter reload value to obtain 250ms IWDG TimeOut.
|
|
Counter Reload Value = timeout_ms /IWDG counter clock period
|
|
= timeout_ms * (LSI/256) / 1000
|
|
*/
|
|
reloadTick = LsiFreq*timeout_ms/256000;
|
|
require_action( reloadTick <= 0xFFF, exit, err = kParamErr );
|
|
|
|
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
|
|
|
|
/* IWDG counter clock: LSI/256 */
|
|
IWDG_SetPrescaler(IWDG_Prescaler_256);
|
|
|
|
IWDG_SetReload(reloadTick);
|
|
|
|
/* Reload IWDG counter */
|
|
IWDG_ReloadCounter();
|
|
|
|
/* Enable IWDG (the LSI oscillator will be enabled by hardware) */
|
|
IWDG_Enable();
|
|
|
|
exit:
|
|
return err;
|
|
#else
|
|
UNUSED_PARAMETER( timeout_ms );
|
|
return kUnsupportedErr;
|
|
#endif
|
|
}
|
|
|
|
OSStatus MicoWdgFinalize( void )
|
|
{
|
|
// PLATFORM_TO_DO
|
|
return kNoErr;
|
|
}
|
|
|
|
OSStatus platform_watchdog_kick( void )
|
|
{
|
|
#ifndef MICO_DISABLE_WATCHDOG
|
|
IWDG_ReloadCounter();
|
|
return kNoErr;
|
|
#else
|
|
return kUnsupportedErr;
|
|
#endif
|
|
}
|
|
|
|
|
|
#ifndef MICO_DISABLE_WATCHDOG
|
|
/**
|
|
* @brief Configures TIM5 to measure the LSI oscillator frequency.
|
|
* @param None
|
|
* @retval LSI Frequency
|
|
*/
|
|
uint32_t GetLSIFrequency(void)
|
|
{
|
|
NVIC_InitTypeDef NVIC_InitStructure;
|
|
TIM_ICInitTypeDef TIM_ICInitStructure;
|
|
RCC_ClocksTypeDef RCC_ClockFreq;
|
|
|
|
#ifndef NO_MICO_RTOS
|
|
mico_rtos_init_semaphore(&_measureLSIComplete_SEM, 1);
|
|
#else
|
|
_measureLSIComplete_SEM = false;
|
|
#endif
|
|
|
|
|
|
/* Enable the LSI oscillator ************************************************/
|
|
RCC_LSICmd(ENABLE);
|
|
|
|
/* Wait till LSI is ready */
|
|
while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
|
|
{}
|
|
|
|
/* TIM5 configuration *******************************************************/
|
|
/* Enable TIM5 clock */
|
|
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
|
|
|
|
/* Connect internally the TIM5_CH4 Input Capture to the LSI clock output */
|
|
TIM_RemapConfig(TIM5, TIM5_LSI);
|
|
|
|
/* Configure TIM5 presclaer */
|
|
TIM_PrescalerConfig(TIM5, 0, TIM_PSCReloadMode_Immediate);
|
|
|
|
/* TIM5 configuration: Input Capture mode ---------------------
|
|
The LSI oscillator is connected to TIM5 CH4
|
|
The Rising edge is used as active edge,
|
|
The TIM5 CCR4 is used to compute the frequency value
|
|
------------------------------------------------------------ */
|
|
TIM_ICInitStructure.TIM_Channel = TIM_Channel_4;
|
|
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
|
|
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
|
|
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV8;
|
|
TIM_ICInitStructure.TIM_ICFilter = 0;
|
|
TIM_ICInit(TIM5, &TIM_ICInitStructure);
|
|
|
|
/* Enable TIM5 Interrupt channel */
|
|
NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
|
|
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
|
|
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 8;
|
|
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
|
NVIC_Init(&NVIC_InitStructure);
|
|
|
|
/* Enable TIM5 counter */
|
|
TIM_Cmd(TIM5, ENABLE);
|
|
|
|
/* Reset the flags */
|
|
TIM5->SR = 0;
|
|
|
|
/* Enable the CC4 Interrupt Request */
|
|
TIM_ITConfig(TIM5, TIM_IT_CC4, ENABLE);
|
|
|
|
/* Wait until the TIM5 get 2 LSI edges (refer to TIM5_IRQHandler()) *********/
|
|
#ifndef NO_MICO_RTOS
|
|
mico_rtos_get_semaphore(&_measureLSIComplete_SEM, MICO_WAIT_FOREVER);
|
|
mico_rtos_deinit_semaphore( &_measureLSIComplete_SEM );
|
|
_measureLSIComplete_SEM = NULL;
|
|
#else
|
|
while( _measureLSIComplete_SEM == false);
|
|
#endif
|
|
|
|
/* Deinitialize the TIM5 peripheral registers to their default reset values */
|
|
TIM_ITConfig(TIM5, TIM_IT_CC4, DISABLE);
|
|
TIM_DeInit(TIM5);
|
|
NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
|
|
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
|
|
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 8;
|
|
NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;
|
|
NVIC_Init(&NVIC_InitStructure);
|
|
|
|
/* Compute the LSI frequency, depending on TIM5 input clock frequency (PCLK1)*/
|
|
/* Get SYSCLK, HCLK and PCLKx frequency */
|
|
RCC_GetClocksFreq(&RCC_ClockFreq);
|
|
|
|
/* Get PCLK1 prescaler */
|
|
if ((RCC->CFGR & RCC_CFGR_PPRE1) == 0)
|
|
{
|
|
/* PCLK1 prescaler equal to 1 => TIMCLK = PCLK1 */
|
|
return ((RCC_ClockFreq.PCLK1_Frequency / PeriodValue) * 8);
|
|
}
|
|
else
|
|
{ /* PCLK1 prescaler different from 1 => TIMCLK = 2 * PCLK1 */
|
|
return (((2 * RCC_ClockFreq.PCLK1_Frequency) / PeriodValue) * 8) ;
|
|
}
|
|
}
|
|
|
|
bool platform_watchdog_check_last_reset( void )
|
|
{
|
|
#ifndef MICO_DISABLE_WATCHDOG
|
|
if ( RCC->CSR & RCC_CSR_WDGRSTF )
|
|
{
|
|
/* Clear the flag and return */
|
|
RCC->CSR |= RCC_CSR_RMVF;
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @brief This function handles TIM5 global interrupt request.
|
|
* @param None
|
|
* @retval None
|
|
*/
|
|
void TIM5_IRQHandler(void)
|
|
{
|
|
if (TIM_GetITStatus(TIM5, TIM_IT_CC4) != RESET)
|
|
{
|
|
/* Clear CC4 Interrupt pending bit */
|
|
TIM_ClearITPendingBit(TIM5, TIM_IT_CC4);
|
|
if (CaptureNumber >= 2)
|
|
return;
|
|
|
|
/* Get the Input Capture value */
|
|
tmpCC4[CaptureNumber++] = TIM_GetCapture4(TIM5);
|
|
|
|
if (CaptureNumber == 2)
|
|
{
|
|
/* Compute the period length */
|
|
PeriodValue = (uint16_t)(0xFFFF - tmpCC4[0] + tmpCC4[1] + 1);
|
|
if(_measureLSIComplete_SEM != NULL){
|
|
if(_measureLSIComplete_SEM != NULL){
|
|
mico_rtos_set_semaphore(&_measureLSIComplete_SEM);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|