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

460 lines
13 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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: ftimer.c
* Date: 2022-02-10 14:53:42
* LastEditTime: 2022-02-18 09:09:49
* Description:  This file is for user timer API implmentation
*
* Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
* 1.0 liushengming 2022/02/18 first commit
*/
/***************************** Include Files *********************************/
#include <string.h>
#include "fassert.h"
#include "ftimer_tacho_hw.h"
#include "ftimer_tacho.h"
/************************** Function Prototypes ******************************/
/**
* @name: FTimerSoftwareReset
* @msg: 将控制器复位
* @return {FError} 驱动初始化的错误码信息FTIMER_TACHO_SUCCESS 表示初始化成功,其它返回值表示初始化失败
* @param {FTimerTachoCtrl} *instance_p 驱动控制数据结构
*/
FError FTimerSoftwareReset(FTimerTachoCtrl *instance_p)
{
FASSERT(instance_p);
if (instance_p->isready != FT_COMPONENT_IS_READY)
{
FTIMER_ERROR("Device is not ready!!!");
return FTIMER_TACHO_ERR_NOT_READY;
}
u32 reg_val = FTIMER_CTRL_READ(instance_p);
u32 Timeout = 0;
reg_val |= FTIMER_REG_TACHO_RESET;
FTIMER_CTRL_WRITE(instance_p, reg_val);
do
{
reg_val = FTIMER_CTRL_READ(instance_p);
Timeout++;
}
while ((reg_val & FTIMER_REG_TACHO_RESET) && (Timeout < FTIMER_TIMEOUT));
if (Timeout >= FTIMER_TIMEOUT)
{
FTIMER_ERROR("Software Reset Failed!!!");
return FTIMER_TACHO_ERR_FAILED;
}
return FTIMER_TACHO_SUCCESS;
}
/**
* @name: FTimerStart
* @msg: 启动timer_tacho外设,根据不同的功能,开启使能位
* @return {FError} 驱动初始化的错误码信息FTIMER_TACHO_SUCCESS 表示初始化成功,其它返回值表示初始化失败
* @param {FTimerTachoCtrl} *instance_p 驱动控制数据结构
*/
FError FTimerStart(FTimerTachoCtrl *instance_p)
{
FASSERT(instance_p);
FASSERT(FT_COMPONENT_IS_READY == instance_p->isready);
u32 reg_val;
reg_val = FTIMER_CTRL_READ(instance_p);
if (FTIMER_WORK_MODE_TIMER == instance_p->config.work_mode)
{
reg_val |= FTIMER_REG_ENABLE;
}
else
{
/* for tacho mode and capture mode */
reg_val |= FTIMER_REG_ENABLE | FTACHO_REG_CAP_IN_ENABLE;
}
FTIMER_CTRL_WRITE(instance_p, reg_val);
return FTIMER_TACHO_SUCCESS;
}
/**
* @name: FTimerStop
* @msg: 停止timer外设根据不同的功能关闭使能位计数值停止并冻结
* @return {FError} 驱动初始化的错误码信息FTIMER_TACHO_SUCCESS 表示初始化成功,其它返回值表示初始化失败
* @param {FTimerTachoCtrl} *instance_p 驱动控制数据结构
*/
FError FTimerStop(FTimerTachoCtrl *instance_p)
{
FASSERT(instance_p);
FASSERT(FT_COMPONENT_IS_READY == instance_p->isready);
u32 reg_val = FTIMER_CTRL_READ(instance_p);
if (FTIMER_WORK_MODE_TIMER == instance_p->config.work_mode)
{
reg_val &= (~FTIMER_REG_ENABLE);
}
else
{
/* for tacho mode and capture mode */
reg_val &= (~FTIMER_REG_ENABLE) & (~FTACHO_REG_CAP_IN_ENABLE);
}
FTIMER_CTRL_WRITE(instance_p, reg_val);
return FTIMER_TACHO_SUCCESS;
}
/**
* @name: TimerSwithBits
* @msg: 计数器32/64切换
* @return {FError} 驱动初始化的错误码信息FTIMER_TACHO_SUCCESS 表示初始化成功,其它返回值表示初始化失败
* @param {FTimerTachoCtrl} *instance_p 驱动控制数据结构
*/
static FError TimerSwithBits(FTimerTachoCtrl *instance_p)
{
u32 reg_val;
FASSERT(instance_p);
FASSERT(FT_COMPONENT_IS_READY == instance_p->isready);
reg_val = FTIMER_CTRL_READ(instance_p);
if (FTIMER_32_BITS == instance_p->config.timer_bits)
{
reg_val &= (~FTIMER_REG_CNT_SERIES_64BIT);
}
else if (FTIMER_64_BITS == instance_p->config.timer_bits)
{
reg_val |= FTIMER_REG_CNT_SERIES_64BIT;
}
else
{
FTIMER_ERROR("Invalid input");
return FTIMER_TACHO_ERR_INVAL_PARM;
}
FTIMER_CTRL_WRITE(instance_p, reg_val);
return FTIMER_TACHO_SUCCESS;
}
/**
* @name: TimerForceLoad
* @msg: 强制更新位置位
* @return {void} 无
* @param {FTimerTachoCtrl} *instance_p 驱动控制数据结构
*/
static void TimerForceLoad(FTimerTachoCtrl *instance_p)
{
u32 reg_val;
FASSERT(instance_p);
FASSERT(FT_COMPONENT_IS_READY == instance_p->isready);
reg_val = FTIMER_CTRL_READ(instance_p);
reg_val |= FTIMER_REG_TACHO_FORCE_LOAD;
FTIMER_CTRL_WRITE(instance_p, reg_val);
return;
}
/**
* @name: FTimerSetPeriod32
* @msg: 设置32位计数模式下计数器的compare的值达到此值如果开启中断则开启中断
* @return {FError} 驱动初始化的错误码信息FTIMER_TACHO_SUCCESS 表示初始化成功,其它返回值表示初始化失败
* @param {FTimerTachoCtrl} *instance_p 驱动控制数据结构
* @param {u32}NewCmpL
*/
FError FTimerSetPeriod32(FTimerTachoCtrl *instance_p, u32 new_cmp_l)
{
FASSERT(instance_p);
FASSERT(FT_COMPONENT_IS_READY == instance_p->isready);
if (FTIMER_64_BITS == instance_p->config.timer_bits)
{
return FTIMER_TACHO_ERR_INVAL_PARM;
}
/* update cmp val */
FTIMER_CMPL_WRITE(instance_p, new_cmp_l);
return FTIMER_TACHO_SUCCESS;
}
/**
* @name: FTimerSetPeriod64
* @msg: 设置64位计数模式下计数器的compare的值达到此值如果开启中断则开启中断
* @return {FError} 驱动初始化的错误码信息FTIMER_TACHO_SUCCESS 表示初始化成功,其它返回值表示初始化失败
* @param {FTimerTachoCtrl} *instance_p 驱动控制数据结构
* @param {u64}ticks
*/
FError FTimerSetPeriod64(FTimerTachoCtrl *instance_p, u64 ticks)
{
u32 low_cmp;
u32 up_cmp;
FASSERT(instance_p);
FASSERT(FT_COMPONENT_IS_READY == instance_p->isready);
if (FTIMER_32_BITS == instance_p->config.timer_bits)
{
return FTIMER_TACHO_ERR_INVAL_PARM;
}
low_cmp = (u32)(GENMASK_ULL(31, 0) & ticks);
up_cmp = (u32)((GENMASK_ULL(63, 32) & ticks) >> 32);
/* MUST write low 32 bit first !!! */
FTIMER_CMPL_WRITE(instance_p, low_cmp);
FTIMER_CMPU_WRITE(instance_p, up_cmp);
return FTIMER_TACHO_SUCCESS;
}
/**
* @name: FTimerSetStartVal
* @msg: 设置计数器初始值
* @return {FError} 驱动初始化的错误码信息FTIMER_TACHO_SUCCESS 表示初始化成功,其它返回值表示初始化失败
* @param {FTimerTachoCtrl} *instance_p 驱动控制数据结构
* @param {u32} cnt
*/
inline FError FTimerSetStartVal(FTimerTachoCtrl *instance_p, u32 cnt)
{
u32 ret = FTIMER_TACHO_SUCCESS;
FASSERT(instance_p);
FASSERT(FT_COMPONENT_IS_READY == instance_p->isready);
ret = TimerSwithBits(instance_p);
if (FTIMER_TACHO_SUCCESS != ret)
{
return ret;
}
FTIMER_STAR_WRITE(instance_p, cnt);
/* set force_load=1invalid previous cmp val,
otherwise the previous cmp val still work */
TimerForceLoad(instance_p);
FTIMER_INFO("Set start val 0x%x", FTIMER_STAR_READ(instance_p));
return ret;
}
/**
* @name: FTimerGetCurCnt32
* @msg: 32位模式下获取计数器当前计数值
* @return {u32}返回当前计数器的值
* @param {FTimerTachoCtrl} *instance_p 驱动控制数据结构
*/
u32 FTimerGetCurCnt32(FTimerTachoCtrl *instance_p)
{
FASSERT(instance_p);
FASSERT(FT_COMPONENT_IS_READY == instance_p->isready);
return FTIMER_CNTL_READ(instance_p);
}
/**
* @name: FTimerGetCurCnt64
* @msg: 64位模式下获取计数器当前计数值
* @return {u64}返回当前计数器的值
* @param {FTimerTachoCtrl} *instance_p 驱动控制数据结构
*/
inline u64 FTimerGetCurCnt64(FTimerTachoCtrl *instance_p)
{
u64 cnt = 0;
FASSERT(instance_p);
FASSERT(FT_COMPONENT_IS_READY == instance_p->isready);
/* must read lower 32 bits first */
cnt |= (u64)FTIMER_CNTL_READ(instance_p);
cnt |= (u64)(((u64)FTIMER_CNTU_READ(instance_p)) << 32);
return cnt;
}
/**
* @name: FTimerInit
* @msg: 完成TimerTacho驱动实例的初始化使之在就绪状态
* @return {FError} 驱动初始化的错误码信息FTIMER_TACHO_SUCCESS 表示初始化成功,其它返回值表示初始化失败
* @param {FTimerTachoCtrl} *instance_p 驱动控制数据结构
* @param {FTimerTachoConfig} *config_p 驱动配置数据结构
*/
FError FTimerInit(FTimerTachoCtrl *instance_p, const FTimerTachoConfig *config_p)
{
FASSERT(instance_p && config_p);
u32 reg_val = 0;
u32 Ret = FTIMER_TACHO_SUCCESS;
if ((FTIMER_ONCE_CMP == config_p->cmp_type) &&
(FTIMER_FREE_RUN != config_p->timer_mode))
{
FTIMER_ERROR("Time mode shall be free-run when use once timer!!");
return FTIMER_TACHO_ERR_INVAL_PARM;
}
if (instance_p->isready == FT_COMPONENT_IS_READY)
{
FTIMER_INFO("Device is already initialized.!!!\r\n");
return FTIMER_TACHO_ERR_IS_READ;
}
if (FTIMER_WORK_MODE_TIMER == config_p->work_mode)
{
reg_val |= FTIMER_REG_TACHO_MODE_TIMER;
}
else
{
FTIMER_ERROR("Not support");
return FTIMER_TACHO_ERR_INVAL_PARM;
}
if (FTIMER_FREE_RUN == config_p->timer_mode)
{
reg_val &= (~FTIMER_REG_CNT_RESTART);
}
else if (FTIMER_RESTART == config_p->timer_mode)
{
reg_val |= FTIMER_REG_CNT_RESTART;
}
else
{
FTIMER_ERROR("Invalid input");
return FTIMER_TACHO_ERR_INVAL_PARM;
}
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
{
FTIMER_ERROR("Invalid input");
return FTIMER_TACHO_ERR_INVAL_PARM;
}
if (FTIMER_ONCE_CMP == config_p->cmp_type)
{
reg_val |= FTIMER_REG_MODE_ONCE;
}
else if (FTIMER_CYC_CMP == config_p->cmp_type)
{
reg_val &= (~FTIMER_REG_MODE_ONCE);
}
else
{
FTIMER_ERROR("Invalid input");
return FTIMER_TACHO_ERR_INVAL_PARM;
}
if (TRUE == config_p->force_load)
{
reg_val |= FTIMER_REG_TACHO_FORCE_LOAD;
}
if (TRUE == config_p->clear_cnt)
{
reg_val |= FTIMER_REG_CNT_CLR;
}
/*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;
}
void FTimerDeInit(FTimerTachoCtrl *instance_p)
{
FASSERT(instance_p);
/* stop timer first */
FTimerStop(instance_p);
/* reset reg*/
FTimerSoftwareReset(instance_p);
instance_p->isready = 0;
memset(instance_p, 0, sizeof(*instance_p));
return;
}
/**
* @name: FTimeSettingDump
* @msg: 打印寄存器信息
* @return {FError} 驱动初始化的错误码信息FTIMER_TACHO_SUCCESS 表示初始化成功,其它返回值表示初始化失败
* @param {FTimerTachoCtrl} *instance_p 驱动控制数据结构
*/
FError FTimeSettingDump(const FTimerTachoCtrl *instance_p)
{
FASSERT(instance_p);
u32 CtrlReg = FTIMER_CTRL_READ(instance_p);
boolean is64Bit = ((CtrlReg & FTIMER_REG_CNT_SERIES_64BIT) != 0);
FASSERT(FT_COMPONENT_IS_READY == instance_p->isready);
FTIMER_DEBUG("ctrl: ");
FTIMER_DEBUG("===%d-bit timer", is64Bit ? 64 : 32);
FTIMER_DEBUG("===timer enabled: %d", (CtrlReg & FTIMER_REG_ENABLE) ? 1 : 0);
FTIMER_DEBUG("===timer mode: %d", (CtrlReg & FTIMER_REG_TACHO_MODE_TIMER) ? 1 : 0);
FTIMER_DEBUG("===once timer: %d", (CtrlReg & FTIMER_REG_MODE_ONCE) ? 1 : 0);
FTIMER_DEBUG("===restart mode: %d", (CtrlReg & FTIMER_REG_CNT_RESTART) ? 1 : 0);
FTIMER_DEBUG("===in reset: %d", (CtrlReg & FTIMER_REG_TACHO_RESET) ? 1 : 0);
FTIMER_DEBUG("===force load: %d", (CtrlReg & FTIMER_REG_TACHO_FORCE_LOAD) ? 1 : 0);
FTIMER_DEBUG("===clear cnt: %d", (CtrlReg & FTIMER_REG_CNT_CLR) ? 1 : 0);
FTIMER_DEBUG("start cnt: 0x%08x", FTIMER_STAR_READ(instance_p));
if (is64Bit)
{
FTIMER_DEBUG("cmp low: 0x%08x", FTIMER_CMPL_READ(instance_p));
FTIMER_DEBUG("high: 0x%08x", FTIMER_CMPU_READ(instance_p));
FTIMER_DEBUG("cur cnt: low: 0x%08x", FTIMER_CNTL_READ(instance_p));
FTIMER_DEBUG("high: 0x%08x", FTIMER_CNTU_READ(instance_p));
}
else
{
FTIMER_DEBUG("cmp low: 0x%08x", FTIMER_CMPL_READ(instance_p));
FTIMER_DEBUG("cur cnt: low: 0x%08x", FTIMER_CNTL_READ(instance_p));
}
FTIMER_DEBUG("intr mask: 0x%08x", FTIMER_INTR_M_READ(instance_p));
FTIMER_DEBUG("intr status: 0x%08x", FTIMER_INTR_S_READ(instance_p));
return FTIMER_TACHO_SUCCESS;
}