rt-thread/bsp/phytium/libraries/standalone/drivers/timer/ftimer_tacho/ftacho.c

298 lines
8.3 KiB
C
Raw Normal View History

/*
* Copyright : (C) 2022 Phytium Information Technology, Inc.
* All Rights Reserved.
*
* This program is OPEN SOURCE software: you can redistribute it and/or modify it
* under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
* either version 1.0 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 Phytium Public License for more details.
*
*
* FilePath: ftacho.c
* Date: 2022-02-10 14:53:42
* LastEditTime: 2022-05-20 09:08:52
* Description:  This files is for
*
* Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
/***************************** Include Files *********************************/
#include <string.h>
#include "fassert.h"
#include "fkernel.h"
#include "fsleep.h"
#include "ftimer_tacho_hw.h"
#include "ftimer_tacho.h"
#include "fparameters.h"
/************************** Function Prototypes ******************************/
/**
* @name: FTachoInit
* @msg: Tacho使tachometer
* @return {FError} FTIMER_TACHO_SUCCESS
* @param {FTimerTachoCtrl} *instance_p
* @param {FTimerTachoConfig} *config_p
*/
FError FTachoInit(FTimerTachoCtrl *instance_p, const FTimerTachoConfig *config_p)
{
FASSERT(instance_p && config_p);
u32 reg_val = 0;
if (instance_p->isready == FT_COMPONENT_IS_READY)
{
FTIMER_INFO("device is already initialized.!!!\r\n");
return FTIMER_TACHO_ERR_IS_READ;
}
/* set work mode */
if (FTIMER_WORK_MODE_TACHO == config_p->work_mode)
{
reg_val |= FTIMER_REG_TACHO_MODE_TACHO;
reg_val |= FTACHO_REG_CAP_IN_ENABLE;
/* plus num of rpm calculate period */
FTIMER_CMPL_WRITE(instance_p, config_p->plus_num);
}
else if (FTIMER_WORK_MODE_CAPTURE == config_p->work_mode)
{
reg_val |= FTIMER_REG_TACHO_MODE_CAPTURE;
reg_val |= FTIMER_REG_TACHO_CAPTURE_ENABLE;
/* set capture cnt to assert capture intr */
reg_val |= FTIMER_REG_TACHO_CAPTURE_CNT_MASK & (config_p->captue_cnt << FTIMER_REG_TACHO_CAPTURE_CNT_SHIFT);
reg_val |= FTIMER_REG_ENABLE;
}
else
{
FTACHO_ERROR("not support work_mode.");
return FTIMER_TACHO_ERR_INVAL_PARM;
}
/* set timer bits */
if (FTIMER_32_BITS == config_p->timer_bits)
{
reg_val &= (~FTIMER_REG_CNT_SERIES_64BIT);
}
else if (FTIMER_64_BITS == config_p->timer_bits)
{
reg_val |= FTIMER_REG_CNT_SERIES_64BIT;
}
else
{
FTACHO_ERROR("invalid input 32/64bits.");
return FTIMER_TACHO_ERR_INVAL_PARM;
}
/* set edge mode */
if (FTACHO_FALLING_EDGE == config_p->edge_mode)
{
reg_val &= ~FTACHO_REG_MODE_MASK;
reg_val |= FTACHO_REG_MODE_FALLING_EDGE;
}
else if (FTACHO_RISING_EDGE == config_p->edge_mode)
{
reg_val &= ~FTACHO_REG_MODE_MASK;
reg_val |= FTACHO_REG_MODE_RISING_EDGE;
}
else if (FTACHO_DOUBLE_EDGE == config_p->edge_mode)
{
reg_val &= ~FTACHO_REG_MODE_MASK;
reg_val |= FTACHO_REG_MODE_DOUBLE_EDGE;
}
else
{
FTACHO_ERROR("invalid input edge.");
return FTIMER_TACHO_ERR_INVAL_PARM;
}
/* set jitter level */
reg_val |= FTACHO_REG_ANTI_JITTER_MASK &
(config_p->jitter_level << FTACHO_REG_ANTI_JITTER_SHIFT);
//use input config
if (config_p != &instance_p->config)
{
instance_p->config = *config_p;
}
FTIMER_CTRL_WRITE(instance_p, reg_val);
instance_p->isready = FT_COMPONENT_IS_READY;
return FTIMER_TACHO_SUCCESS;
}
/**
* @name: FTachoGetFanRPM
* @msg:
* @return {FError} FTIMER_TACHO_SUCCESS
* @param {FTimerTachoCtrl} *instance_p
* @param {u32} *rpm
*/
FError FTachoGetFanRPM(FTimerTachoCtrl *instance_p, u32 *rpm)
{
u32 loop_cnt;
u32 raw_dat;
FASSERT(instance_p);
if (instance_p->isready != FT_COMPONENT_IS_READY || instance_p->config.work_mode != FTIMER_WORK_MODE_TACHO)
{
FTIMER_ERROR("device is not already or not work on TACHO_MODE!!!");
return FTIMER_TACHO_ERR_NOT_READY;
}
u32 cnt_num = FTIMER_CMPL_READ(instance_p);
for (loop_cnt = 0;; loop_cnt++)
{
raw_dat = FTACHO_RESU_READ(instance_p);
/* wait for tacho result */
if (raw_dat & FTACHO_REG_RESU_ISVALID)
{
break;
}
if (loop_cnt < 300)
{
fsleep_millisec(20); //20ms
}
else
{
return FTIMER_TACHO_ERR_ABORT;
}
}
raw_dat &= FTACHO_REG_RESU_MASK;
if (0 == raw_dat)
{
*rpm = 0;
}
else
{
/* calculate rpm */
/* (60(second) * freq * tacho) / (2 * (cmp_l + 1)) cmp_l */
*rpm = (TIMER_CLK_FREQ_HZ * 60 * raw_dat) / (2 * (cnt_num + 1));
}
return FTIMER_TACHO_SUCCESS;
}
/**
* @name: FTachoGetCaptureCnt
* @msg: capture模式下tacho输入脉冲的个数
* @return {u32}
* @param {FTimerTachoCtrl} *instance_p
*/
u32 FTachoGetCaptureCnt(FTimerTachoCtrl *instance_p)
{
u32 cap_cnt = FTIMER_TACHO_SUCCESS;
FASSERT(instance_p);
if (instance_p->isready != FT_COMPONENT_IS_READY || instance_p->config.work_mode != FTIMER_WORK_MODE_CAPTURE)
{
FTIMER_ERROR("device is not already or not work on CAPTURE_MODE!!!");
return FTIMER_TACHO_ERR_NOT_READY;
}
/* read cap cnt */
cap_cnt = FTIMER_CNTL_READ(instance_p);
return cap_cnt;
}
/**
* @name: FTimerSwithMode
* @msg: tachometer-capture模式
* @return {FError} FTIMER_TACHO_SUCCESS
* @param {FTimerTachoCtrl} *instance_p
* @param {FTimerTachoConfig} *pNewConfig
*/
FError FTimerSwithMode(FTimerTachoCtrl *instance_p, FTimerTachoConfig *pNewConfig)
{
FASSERT(instance_p && pNewConfig);
u32 ret = FTIMER_TACHO_SUCCESS;
if (instance_p->config.work_mode == pNewConfig->work_mode)
{
return FTIMER_TACHO_SUCCESS;
}
/* disable and clear timer */
u32 reg_val = FTIMER_CTRL_READ(instance_p);
reg_val &= (~FTIMER_REG_ENABLE);
reg_val |= FTIMER_REG_CNT_CLR;
FTIMER_CTRL_WRITE(instance_p, reg_val);
if (FTIMER_WORK_MODE_TIMER == pNewConfig->work_mode)
{
ret = FTimerInit(instance_p, pNewConfig);
}
else
{
ret = FTachoInit(instance_p, pNewConfig);
}
return ret;
}
/**
* @name: FTachoSetCntPeriod
* @msg: tach计数周期 = pulse_num
* @return {void}
* @param {FTimerTachoCtrl} *instance_p
* @param {u32}ticks
*/
void FTachoSetCntPeriod(FTimerTachoCtrl *instance_p, u32 ticks)
{
FTIMER_CMPL_WRITE(instance_p, ticks);
}
/**
* @name: FTachoSetOverLimit
* @msg: tacho的最大值
* @return {void}
* @param {FTimerTachoCtrl} *instance_p
* @param {u32}
*/
void FTachoSetOverLimit(FTimerTachoCtrl *instance_p, u32 overLim)
{
FTACHO_OVER_WRITE(instance_p, overLim);
}
/**
* @name: FTachoSetUnderLimit
* @msg: tacho的最小值
* @return {void}
* @param {FTimerTachoCtrl} *instance_p
* @param {u32}
*/
void FTachoSetUnderLimit(FTimerTachoCtrl *instance_p, u32 underLim)
{
FTACHO_UNDER_WRITE(instance_p, underLim);
}
/**
* @name: FTachoDeInit
* @msg: 0
* @return {void}
* @param {FTimerTachoCtrl} *instance_p
*/
void FTachoDeInit(FTimerTachoCtrl *instance_p)
{
FASSERT(instance_p);
/* reset reg*/
FTimerSoftwareReset(instance_p);
instance_p->isready = 0;
memset(instance_p, 0, sizeof(*instance_p));
return;
}