1062 lines
42 KiB
C
1062 lines
42 KiB
C
/**
|
||
* @file sdrv_multicapture
|
||
* @brief SemiDrive etimer capture driver source file.
|
||
*
|
||
* @copyright Copyright (c) 2022 Semidrive Semiconductor.
|
||
* All rights reserved.
|
||
*/
|
||
#include <config.h>
|
||
#include <debug.h>
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <regs_base.h>
|
||
#include <clock_cfg.h>
|
||
#include <reset_cfg.h>
|
||
#include <pinmux_cfg.h>
|
||
#include <sdrv_uart.h>
|
||
#include <irq.h>
|
||
#include <irq_num.h>
|
||
#include "sdrv_etimer.h"
|
||
#include "sdrv_xtrg.h"
|
||
#include "board.h"
|
||
#include "sdrv_multicapture.h"
|
||
#include "sdrv_dma.h"
|
||
#include <armv7-r/cache.h>
|
||
#include <reset_ip.h>
|
||
|
||
uint32_t ETMR_BASE[ETIMER_IP_MAX_MODULE];
|
||
|
||
|
||
#ifndef CONFIG_E3L
|
||
#define ICU_MULTI_ETMR_SCR_CFG_ADDR(tm) (0x100CU + ((uint32_t)tm*0x4U))
|
||
#else
|
||
#define ICU_MULTI_ETMR_SCR_CFG_ADDR (0x1070U)
|
||
#endif
|
||
#define ICU_INT_STA_ADDR32(tm) (ETMR_BASE[tm])
|
||
#define ICU_INT_STA_EN_ADDR32(tm) (ETMR_BASE[tm] + (uint32_t)0x4U)
|
||
#define ICU_INT_SIG_EN_ADDR32(tm) (ETMR_BASE[tm] + (uint32_t)0x8U)
|
||
|
||
#define ICU_FIFO_ADDR32(tm, cha) (ETMR_BASE[tm] + (uint32_t)0xC0U + ((uint32_t)cha*0x4u))
|
||
|
||
#define ICU_TIM_CLK_CONFIG(tm) (ETMR_BASE[tm] + (uint32_t)0xA0U)
|
||
#define ICU_BM_TIM_CLK_CONFIG_CLK_CHANGE_UPD (0x01U << 31U)
|
||
#define ICU_FM_TIM_CLK_CONFIG_SRC_CLK_SEL (0x3U << 16U)
|
||
#define ICU_FV_TIM_CLK_CONFIG_SRC_CLK_SEL(v) (((v) << 16U) & ICU_FM_TIM_CLK_CONFIG_SRC_CLK_SEL)
|
||
#define ICU_FM_TIM_CLK_CONFIG_DIV_NUM (0xffffU << 0U)
|
||
#define ICU_FV_TIM_CLK_CONFIG_DIV_NUM(v) (((v) << 0U) & ICU_FM_TIM_CLK_CONFIG_DIV_NUM)
|
||
|
||
#define ICU_FIFO_STA(tm) (ETMR_BASE[tm] + (uint32_t)0xD0U)
|
||
|
||
#define ICU_CLK_MON_EN(tm) (ETMR_BASE[tm] + (uint32_t)0xA4U)
|
||
#define ICU_BM_CLK_MON_EN_CMP_SET (0x01U << 2U)
|
||
#define ICU_BM_CLK_MON_EN_EN_N (0x01U << 1U)
|
||
#define ICU_BM_CLK_MON_EN_EN_P (0x01U << 0U)
|
||
|
||
|
||
#define ICU_LOCAL_CNT_CFG(tm,cha) (ETMR_BASE[tm] + 0x148U + (cha)*0x20)
|
||
#define ICU_CNT_CFG_START_BY_FIRST_CPT_START_BIT 25
|
||
#define ICU_CNT_CFG_CPT1_CLR_EN_START_BIT 24
|
||
#define ICU_CNT_CFG_CPT0_CLR_EN_START_BIT 23
|
||
#define ICU_CNT_CFG_INIT_UPD_START_BIT 16
|
||
#define ICU_CNT_CFG_OVF_UPD_START_BIT 17
|
||
|
||
#define ICU_LOCAL_CNT(tm,cha) (ETMR_BASE[tm] + 0x150U + (cha)*0x20)
|
||
|
||
#define ICU_LOCAL_CNT_EN(tm, cha) (ETMR_BASE[tm] + 0x14Cu + ((uint32_t)cha*0x20u))
|
||
#define ICU_LOCAL_CNT_OVF_VAL(tm, cha) (ETMR_BASE[tm] + 0x144u + ((uint32_t)cha*0x20u))
|
||
|
||
#define ICU_CPT_CONFIG(tm, cha) (ETMR_BASE[tm] + 0x200u + ((uint32_t)cha*0x4u))
|
||
#define ICU_CPT_CONFIG_DUAL_MODE_BIT (1u)
|
||
#define ICU_CPT_CONFIG_CPT0_TRIG_MODE_START_BIT (2u)
|
||
#define ICU_CPT_CONFIG_CPT1_TRIG_MODE_START_BIT (4u)
|
||
#define ICU_CPT_CONFIG_CNT_SEL_START_BIT (6u)
|
||
|
||
|
||
#define ICU_CHN_DMA_CTRL(tm) (ETMR_BASE[tm] + (uint32_t)0xB0U)
|
||
#define ICU_BM_CHN_DMA_CTRL_CHN_16BIT_MODE(cha) (0x01U << (16U + (cha)))
|
||
#define ICU_BM_CHN_DMA_CTRL_CHN_SIG_MASK(cha) (0x01U << (12U + (cha)))
|
||
#define ICU_FM_CHN_DMA_CTRL_CHN_SEL(cha) (0x3U << (4U + (cha)*0x2U))
|
||
#define ICU_FV_CHN_DMA_CTRL_CHN_SEL(v, cha) (((v) << (4U + (cha)*0x2U)) & ICU_FM_CHN_DMA_CTRL_CHN_SEL(cha))
|
||
#define ICU_BM_CHN_DMA_CTRL_CHN_EN(cha) (0x01U << (cha))
|
||
|
||
|
||
#define ICU_CHN_DMA_WML(tm) (ETMR_BASE[tm] + (uint32_t)0xB4U)
|
||
#define ICU_FM_DMA_WML_CHN(cha) (0xfU << ((cha)*0x8U))
|
||
#define ICU_FV_DMA_WML_CHN(v, cha) (((v) << ((cha)*0x8U)) & ICU_FM_DMA_WML_CHN(cha))
|
||
|
||
#define ICU_CHN_FIFO_ADDR(tm, cha) (ETMR_BASE[tm] + (uint32_t)0xC0U + cha*0x4)
|
||
|
||
#define ICU_CPT_CTRL(tm) (ETMR_BASE[tm] + (uint32_t)0x210U)
|
||
#define ICU_CPT_CTRL_CPT_CONFIG_SET_START_BIT(cha) (4U + (cha))
|
||
#define ICU_CPT_CTRL_CPT_EN_START_BIT(cha) (cha)
|
||
|
||
#define ICU_CPT_SSE_CTRL_OFF(tm, cha) (ETMR_BASE[tm] + (uint32_t)0x300U + (cha)*0x8U)
|
||
#define ICU_FM_CPT_SSE_CTRL_EDGE_SEL (0x3ffU << 6U)
|
||
#define ICU_FV_CPT_SSE_CTRL_EDGE_SEL(v) (((v) << 6U) & ICU_FM_CPT_SSE_CTRL_EDGE_SEL)
|
||
#define ICU_FM_CPT_SSE_CTRL_SSE_MODE (0x1fU << 1U)
|
||
#define ICU_FV_CPT_SSE_CTRL_SSE_MODE(v) (((v) << 1U) & ICU_FM_CPT_SSE_CTRL_SSE_MODE)
|
||
#define ICU_BM_CPT_SSE_CTRL_SSE_EN (0x01U << 0U)
|
||
|
||
#define ICU_CPT_SSE_REG_OFF(tm, cha) (ETMR_BASE[tm] + (uint32_t)0x304U + (cha)*0x8U)
|
||
|
||
#define ICU_CPT_X0_FLT(tm, cha) (ETMR_BASE[tm] + 0x400u + ((uint32_t)cha*0x4u))
|
||
|
||
/**************************************************************************************************************/
|
||
/**************************************************************************************************************/
|
||
|
||
|
||
static uint32_t ICU_MULTI_CPT_B_BUFFER[MULTI_CPT_MODULE_NUM][4] __attribute__((__aligned__
|
||
(CONFIG_ARCH_CACHE_LINE)));
|
||
static uint32_t ICU_MULTI_CPT_C_BUFFER[MULTI_CPT_MODULE_NUM][4] __attribute__((__aligned__
|
||
(CONFIG_ARCH_CACHE_LINE)));
|
||
/*虽然ICU_MULTI_CPT_B_BUFFER 和 ICU_MULTI_CPT_C_BUFFER 只使用了8字节,但是为了cache对齐,需要占满32字节,以防止影响到其它的变量*/
|
||
|
||
static bool g_multicpt_clk_info[ETIMER_IP_MAX_MODULE];
|
||
static bool g_multicpt_timer_enable[MULTI_CPT_MODULE_NUM]; /*module*/
|
||
static bool
|
||
g_multicpt_dma_enable[MULTI_CPT_MODULE_NUM]; /*是否使用DMA*/
|
||
static bool g_multicpt_channel_enable[MULTI_CPT_MODULE_NUM][MULTI_CPT_MAX_IO_NUM]; /*channel*/
|
||
static sdrv_dma_t g_dma_instance[2 * MULTI_CPT_MODULE_NUM];
|
||
static sdrv_dma_channel_t g_channel[2 * MULTI_CPT_MODULE_NUM];
|
||
|
||
|
||
uint8_t sdrv_get_chip_version(void)
|
||
{
|
||
/*1.1芯片返回1, 1.0芯片返回0*/
|
||
static uint8_t version = 0xFFu;
|
||
|
||
if (version == 0xFFu) {
|
||
version = (uint8_t)(readl(APB_EFUSEC_BASE + 0x1018) >> 16u);
|
||
}
|
||
else {
|
||
|
||
}
|
||
|
||
return version;
|
||
}
|
||
|
||
|
||
uint32_t timer_fifo_a(uint8_t timer_module)
|
||
{
|
||
return readl(ICU_FIFO_ADDR32(timer_module, 0));
|
||
}
|
||
|
||
uint32_t timer_fifo_b(uint8_t timer_module)
|
||
{
|
||
return readl(ICU_FIFO_ADDR32(timer_module, 1));
|
||
}
|
||
|
||
uint32_t timer_fifo_c(uint8_t timer_module)
|
||
{
|
||
return readl(ICU_FIFO_ADDR32(timer_module, 2));
|
||
}
|
||
|
||
uint32_t timer_fifo_d(uint8_t timer_module)
|
||
{
|
||
return readl(ICU_FIFO_ADDR32(timer_module, 3));
|
||
}
|
||
|
||
|
||
|
||
void sdrv_etimer_multicpt_set_base_addr(void)
|
||
{
|
||
uint8_t i = 0u;
|
||
sdrv_recovery_module_t *recovery_module = &recovery_module_array;
|
||
memset(&ETMR_BASE[0], 0, sizeof(ETMR_BASE));
|
||
|
||
for (i = 0; i < recovery_module->etimer_list->etimer_num; i++) {
|
||
ETMR_BASE[i] = recovery_module->etimer_list->etimer_base[i];
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief sdrv_etimer_multicpt_xtrig_config
|
||
* @details set multi cpt xtrg config.
|
||
* @param[in] timer The etimer module.
|
||
* @param[in] multinum used multi cpt io number.
|
||
* @implements sdrv_etimer_multicpt_xtrig_config
|
||
* @return none
|
||
*/
|
||
void sdrv_etimer_multicpt_xtrig_config(uint8_t timer_module, uint8_t multinum)
|
||
{
|
||
sdrv_xtrg_sse5_config_t sse5_config_0;
|
||
sdrv_xtrg_config_t xtrg_config;
|
||
memset(&sse5_config_0, 0, sizeof(sse5_config_0));
|
||
memset(&xtrg_config, 0, sizeof(xtrg_config));
|
||
sdrv_xtrg_t xtrg_dev = {
|
||
.base = APB_XTRG_BASE
|
||
};
|
||
|
||
uint8_t IoIndex = 0U;
|
||
/* single group ssm5 io num : 8 */
|
||
uint8_t Ssm5Num = multinum / 8U;
|
||
uint8_t Ssm5NumReminder = multinum % 8U;
|
||
/* single group ssm io num : 4 */
|
||
uint8_t RemainSsmNum = ((Ssm5NumReminder % 4U) == 0U) ? (Ssm5NumReminder / 4U) : ((
|
||
Ssm5NumReminder / 4U) + 1U);
|
||
|
||
if (RemainSsmNum % 2U == 0U) {
|
||
Ssm5Num = Ssm5Num + 1U;
|
||
}
|
||
|
||
if (Ssm5Num == 0U) {
|
||
for (IoIndex = 0; IoIndex < multinum; IoIndex++) {
|
||
sse5_config_0.in[IoIndex].sig = IO_i((32 * timer_module) + IoIndex);
|
||
sse5_config_0.in[IoIndex].edge_detect = 1U;
|
||
sse5_config_0.in[IoIndex].edge = SDRV_XTRG_BOTHEDGE;
|
||
}
|
||
|
||
sse5_config_0.synthesis_val =
|
||
0xFFFEFFFEU; /*表示当前SSM的增值值 0xFFFEFFFEU */
|
||
sse5_config_0.ssm_sel = (sdrv_xtrg_ssm_sel_e)(8U *
|
||
timer_module); /*ssm_sel表示使用的是哪一个SSM,总共有16个SSM。*/
|
||
sdrv_xtrg_sse5_config(&xtrg_dev, &sse5_config_0,
|
||
true); /*etimer1使用0 -7 SSM; etimer2使用8-15 SSM。*/
|
||
memset(&xtrg_config, 0, sizeof(xtrg_config));
|
||
xtrg_config.sig_i = (uint32_t)SSIG(8 * timer_module);
|
||
xtrg_config.sig_o = ETIMER_CPT0(timer_module,
|
||
0); /*表示使用SSM0与capture A0连接*/
|
||
sdrv_xtrg_smux_config(&xtrg_dev, &xtrg_config);
|
||
}
|
||
else {
|
||
uint8_t LoopSsm5 = ((Ssm5Num * 8U) > multinum) ? multinum : (Ssm5Num * 8U);
|
||
|
||
for (IoIndex = 0; IoIndex < LoopSsm5; IoIndex++) {
|
||
if ((IoIndex % 4U == 0U) && (IoIndex > 0U)) {
|
||
sse5_config_0.synthesis_val = 0xFFFEFFFEU;
|
||
sse5_config_0.ssm_sel = (sdrv_xtrg_ssm_sel_e)((8U * timer_module) + ((IoIndex / 4U) - 1U));
|
||
|
||
if ((IoIndex % 8U == 0U) && (IoIndex > 0U)) {
|
||
uint8_t MuxIdx = (2U * ((IoIndex / 8U) - 1U));
|
||
/* sse5 mux cfg */
|
||
sse5_config_0.in[4].sig = SSIG((uint8_t)((8u * timer_module) + MuxIdx));
|
||
sse5_config_0.in[4].edge_detect = 0U;
|
||
sse5_config_0.in[4].edge = SDRV_XTRG_BOTHEDGE;
|
||
sse5_config_0.synthesis_val = 0xFFFFFFFE;
|
||
/* xtrg-etimer mux config */
|
||
xtrg_config.sig_i = SSIG((uint8_t)((8u * timer_module) + (IoIndex / 4U) - 1U));
|
||
xtrg_config.sig_o = ETIMER_CPT0(timer_module, MuxIdx);
|
||
sdrv_xtrg_smux_config(&xtrg_dev, &xtrg_config);
|
||
}
|
||
|
||
/*sdrv_xtrg_sse5_enable(&xtrg_dev, &sse5_config_0, true);*/
|
||
sdrv_xtrg_sse5_config(&xtrg_dev, &sse5_config_0, true);
|
||
/* set xtrg_config and sse5_config_0 to 0 */
|
||
memset(&xtrg_config, 0, sizeof(xtrg_config));
|
||
memset(&sse5_config_0, 0, sizeof(sse5_config_0));
|
||
}
|
||
|
||
uint8_t Sse5Idx = IoIndex % 4;
|
||
sse5_config_0.in[Sse5Idx].sig = IO_i((32 * timer_module) + IoIndex);
|
||
sse5_config_0.in[Sse5Idx].edge_detect = 1U;
|
||
sse5_config_0.in[Sse5Idx].edge = SDRV_XTRG_BOTHEDGE;
|
||
|
||
/* the last time for ss5 cfg xtrg */
|
||
if (IoIndex == LoopSsm5 - 1U) {
|
||
uint8_t MuxIdx = (2U * (IoIndex / 8U));
|
||
/* sse5 mux cfg */
|
||
sse5_config_0.in[4].sig = SSIG(MuxIdx + (8 * timer_module));
|
||
sse5_config_0.in[4].edge_detect = 0U;
|
||
sse5_config_0.in[4].edge = SDRV_XTRG_BOTHEDGE;
|
||
/* xtrg-etimer mux config */
|
||
xtrg_config.sig_i = SSIG((uint8_t)((8 * timer_module) + (IoIndex / 4U)));
|
||
xtrg_config.sig_o = ETIMER_CPT0(timer_module, MuxIdx);
|
||
sdrv_xtrg_smux_config(&xtrg_dev, &xtrg_config);
|
||
sse5_config_0.synthesis_val = 0xFFFFFFFEU;
|
||
sse5_config_0.ssm_sel = (sdrv_xtrg_ssm_sel_e)((8U * timer_module) + (IoIndex / 4U));
|
||
/*sdrv_xtrg_sse5_enable(&xtrg_dev, &sse5_config_0, true);*/
|
||
sdrv_xtrg_sse5_config(&xtrg_dev, &sse5_config_0, true);
|
||
/* set xtrg_config and sse5_config_0 to 0 */
|
||
memset(&xtrg_config, 0, sizeof(xtrg_config));
|
||
memset(&sse5_config_0, 0, sizeof(sse5_config_0));
|
||
}
|
||
}
|
||
|
||
if (RemainSsmNum == 1) {
|
||
/* the last ssm cfg */
|
||
for (uint8_t RemainSSmIo = IoIndex; RemainSSmIo < multinum; RemainSSmIo++) {
|
||
uint8_t RemianSse5Idx = RemainSSmIo % 4U;
|
||
sse5_config_0.in[RemianSse5Idx].sig = IO_i((32 * timer_module) + RemainSSmIo);
|
||
sse5_config_0.in[RemianSse5Idx].edge_detect = 1U;
|
||
sse5_config_0.in[RemianSse5Idx].edge = SDRV_XTRG_BOTHEDGE;
|
||
|
||
if (RemainSSmIo == multinum - 1U) {
|
||
sse5_config_0.synthesis_val = 0xFFFEFFFE;
|
||
sse5_config_0.ssm_sel = (sdrv_xtrg_ssm_sel_e)((8U * timer_module) + (RemainSSmIo / 4U));
|
||
/*sdrv_xtrg_sse5_enable(&xtrg_dev, &sse5_config_0, true);*/
|
||
sdrv_xtrg_sse5_config(&xtrg_dev, &sse5_config_0, true);
|
||
/* xtrg-etimer mux config */
|
||
xtrg_config.sig_i = SSIG((uint8_t)((8U * timer_module) + (RemainSSmIo / 4U)));
|
||
xtrg_config.sig_o = ETIMER_CPT0(timer_module, (2U * (RemainSSmIo / 8U)));
|
||
sdrv_xtrg_smux_config(&xtrg_dev, &xtrg_config);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
uint32_t sdrv_etimer_GetInterrupt(uint8_t eModule)
|
||
{
|
||
return readl(ICU_INT_STA_ADDR32(eModule));
|
||
}
|
||
|
||
void sdrv_etimer_ClearInterrupt(uint8_t eModule, uint8_t Position)
|
||
{
|
||
writel( 1UL << Position, ICU_INT_STA_ADDR32(eModule));
|
||
/* Delay a while unitl setting be synced */
|
||
uint32_t i = readl(ICU_LOCAL_CNT(eModule, Position));
|
||
|
||
/* Delay a while unitl setting be synced */
|
||
while (readl(ICU_LOCAL_CNT(eModule, Position)) == i) {
|
||
/*wait*/
|
||
};
|
||
}
|
||
|
||
bool sdrv_etimer_CheckFifoSta(uint8_t eModule, uint8_t Position)
|
||
{
|
||
bool errStatus = false;
|
||
uint32_t FifoSta = readl(ICU_FIFO_STA(eModule));
|
||
uint32_t FifoErr = (FifoSta >> ((8u * Position) + 7u)) & 0x1u;
|
||
|
||
if (FifoErr > 0) {
|
||
/* fifo frror generate : clear fifo */
|
||
uint32_t FifoEntry = (FifoSta >> ((8u * Position) + 2u)) & 0x1fu;
|
||
|
||
for (uint8_t i = 0; i < FifoEntry; i++) {
|
||
readl(ICU_FIFO_ADDR32(eModule, Position));
|
||
}
|
||
|
||
errStatus = true;
|
||
}
|
||
|
||
return errStatus;
|
||
}
|
||
|
||
uint32_t sdrv_etimer_GetFifoVal(uint8_t TimerModule, uint8_t Channel)
|
||
{
|
||
uint32_t value = (uint32_t)0u;
|
||
value = readl(ICU_FIFO_ADDR32(TimerModule, Channel));
|
||
return value;
|
||
}
|
||
|
||
/*中断触发方式*/
|
||
static int sdrv_etimer_multicpt_irq_handle(uint32_t irq, void *arg)
|
||
{
|
||
uint8_t timer_module = 0u;
|
||
uint8_t MultiCptChanNum = 0u;
|
||
uint32_t Irq_Status = 0u; /*中断状态*/
|
||
uint32_t Chn_B_Val = 0u; /*capture b 的值 电平的值*/
|
||
uint32_t Chn_C_Val = 0u; /*capture c 的值 时间搓的值*/
|
||
uint8_t Channel_B = 1u;
|
||
uint8_t Channel_C = 2u;
|
||
static uint32_t pre_iochange[MULTI_CPT_MODULE_NUM] = {0u, 0u};
|
||
static uint32_t last_stamp[MULTI_CPT_MODULE_NUM][MULTI_CPT_MAX_IO_NUM] = {0};
|
||
uint32_t IoChange[MULTI_CPT_MODULE_NUM] = {0u, 0u};
|
||
uint32_t curr_stamp[MULTI_CPT_MODULE_NUM][MULTI_CPT_MAX_IO_NUM] = {0};
|
||
sdrv_multicpt_edge_change_type edge_type;
|
||
uint32_t time_cost = 0u;
|
||
|
||
sdrv_multicpt_config *pmulticpt_config = NULL;
|
||
pmulticpt_config = (sdrv_multicpt_config *)arg;
|
||
timer_module = (uint8_t)pmulticpt_config->u8TimerModule;
|
||
MultiCptChanNum = (uint8_t)pmulticpt_config->u8MultiCptChannum;
|
||
|
||
Irq_Status = sdrv_etimer_GetInterrupt(timer_module);
|
||
|
||
if (Irq_Status & (0x1 << Channel_C)) {
|
||
/* clear interrupt */
|
||
sdrv_etimer_ClearInterrupt(timer_module, Channel_C);
|
||
|
||
/* check chan b if fifo has error generate */
|
||
bool fifoErrChnb = sdrv_etimer_CheckFifoSta(timer_module, Channel_B);
|
||
/* check chan c if fifo has error generate */
|
||
bool fifoErrChnc = sdrv_etimer_CheckFifoSta(timer_module, Channel_C);
|
||
|
||
if (fifoErrChnb || fifoErrChnc) {
|
||
return -1;
|
||
}
|
||
|
||
Chn_B_Val = sdrv_etimer_GetFifoVal(timer_module, Channel_B);
|
||
Chn_C_Val = sdrv_etimer_GetFifoVal(timer_module, Channel_C);
|
||
}
|
||
|
||
IoChange[timer_module] = Chn_B_Val ^ pre_iochange[timer_module];
|
||
/*ssdk_printf(SSDK_ERR, "%u\n", unIoChange[TimerModule]);*/
|
||
|
||
for (uint8_t IoIdx = 0; IoIdx < MultiCptChanNum; IoIdx++) {
|
||
|
||
/*表示当前IoIdx通道未开启输入捕获的功能*/
|
||
if (g_multicpt_channel_enable[timer_module][IoIdx] == false)
|
||
continue;
|
||
|
||
bool IoEdgeChange = (IoChange[timer_module] & (0x1u << IoIdx)) ? true : false;
|
||
|
||
/*判断IO是否有电平变化*/
|
||
if (IoEdgeChange == true) {
|
||
/*判断边沿触发类型*/
|
||
if (((pre_iochange[timer_module] >> IoIdx) & 0x1u) == 0) {
|
||
edge_type = MULTI_CPT_RISING_EDGE;
|
||
}
|
||
else {
|
||
edge_type = MULTI_CPT_FALLING_EDGE;
|
||
}
|
||
|
||
curr_stamp[timer_module][IoIdx] = Chn_C_Val;
|
||
|
||
if (Chn_C_Val < last_stamp[timer_module][IoIdx]) {
|
||
time_cost = (0xFFFFFFFFU - last_stamp[timer_module][IoIdx]) + Chn_C_Val;
|
||
}
|
||
else {
|
||
time_cost = Chn_C_Val - last_stamp[timer_module][IoIdx];
|
||
}
|
||
|
||
ssdk_printf(SSDK_ERR, "timer:%u CPTB=%u ch=%u timecost=%u stamp=%u type=%u\n", timer_module,
|
||
Chn_B_Val, IoIdx, time_cost, curr_stamp[timer_module][IoIdx], edge_type);
|
||
|
||
last_stamp[timer_module][IoIdx] = curr_stamp[timer_module][IoIdx];
|
||
|
||
}
|
||
|
||
}
|
||
|
||
pre_iochange[timer_module] = Chn_B_Val;
|
||
//ssdk_printf(SSDK_ERR, "sdrv_etimer_multicpt_irq_handle\n");
|
||
return 0;
|
||
}
|
||
|
||
|
||
/*DMA触发方式*/
|
||
static void sdrv_etimer_multicpt_dma_irq_handler(uint32_t status, uint32_t param, void *Arg)
|
||
{
|
||
sdrv_multicpt_config *pmulticpt_config = (sdrv_multicpt_config *)Arg;
|
||
static uint32_t pre_iochange[MULTI_CPT_MODULE_NUM] = {0u, 0u};
|
||
static uint32_t last_stamp[MULTI_CPT_MODULE_NUM][MULTI_CPT_MAX_IO_NUM] = {0};
|
||
uint32_t IoChange[MULTI_CPT_MODULE_NUM] = {0u, 0u};
|
||
uint32_t curr_stamp[MULTI_CPT_MODULE_NUM][MULTI_CPT_MAX_IO_NUM] = {0};
|
||
sdrv_multicpt_edge_change_type edge_type;
|
||
uint32_t time_cost = 0u;
|
||
|
||
uint8_t timer_module = (uint8_t)pmulticpt_config->u8TimerModule;
|
||
uint8_t multicpt_chan_num = (uint8_t)pmulticpt_config->u8MultiCptChannum;
|
||
|
||
if ((status != SDRV_DMA_BLOCK_DONE) && (status != SDRV_DMA_PENDING)) {
|
||
return;
|
||
}
|
||
|
||
/*刷新Capture_B 和 Capture_C的数据*/
|
||
arch_invalidate_cache_range((addr_t)(&ICU_MULTI_CPT_B_BUFFER[timer_module][0]),
|
||
MULTI_CPT_BURST_LEN * SDRV_DMA_BUSWIDTH_4_BYTES);
|
||
arch_invalidate_cache_range((addr_t)(&ICU_MULTI_CPT_C_BUFFER[timer_module][0]),
|
||
MULTI_CPT_BURST_LEN * SDRV_DMA_BUSWIDTH_4_BYTES);
|
||
|
||
IoChange[timer_module] = ICU_MULTI_CPT_B_BUFFER[timer_module][0] ^ pre_iochange[timer_module];
|
||
/*ssdk_printf(SSDK_ERR, "%u\n", unIoChange[TimerModule]);*/
|
||
|
||
for (uint8_t IoIdx = 0; IoIdx < multicpt_chan_num; IoIdx++) {
|
||
|
||
/*表示当前IoIdx通道未开启输入捕获的功能*/
|
||
if (g_multicpt_channel_enable[timer_module][IoIdx] == false)
|
||
continue;
|
||
|
||
bool IoEdgeChange = (IoChange[timer_module] & (0x1u << IoIdx)) ? true : false;
|
||
|
||
/*判断IO是否有电平变化*/
|
||
if (IoEdgeChange == true) {
|
||
/*判断边沿触发类型*/
|
||
if (((pre_iochange[timer_module] >> IoIdx) & 0x1u) == 0) {
|
||
edge_type = MULTI_CPT_RISING_EDGE;
|
||
}
|
||
else {
|
||
edge_type = MULTI_CPT_FALLING_EDGE;
|
||
}
|
||
|
||
curr_stamp[timer_module][IoIdx] = ICU_MULTI_CPT_C_BUFFER[timer_module][0];
|
||
|
||
if (ICU_MULTI_CPT_C_BUFFER[timer_module][0] < last_stamp[timer_module][IoIdx]) {
|
||
time_cost = (0xFFFFFFFFU - last_stamp[timer_module][IoIdx]) +
|
||
ICU_MULTI_CPT_C_BUFFER[timer_module][0];
|
||
}
|
||
else {
|
||
time_cost = ICU_MULTI_CPT_C_BUFFER[timer_module][0] - last_stamp[timer_module][IoIdx];
|
||
}
|
||
|
||
ssdk_printf(SSDK_ERR, "timer:%u CPTB=%u ch=%u timecost=%u stamp=%u type=%u\n", timer_module,
|
||
ICU_MULTI_CPT_B_BUFFER[timer_module][0], IoIdx, time_cost, curr_stamp[timer_module][IoIdx],
|
||
edge_type);
|
||
last_stamp[timer_module][IoIdx] = curr_stamp[timer_module][IoIdx];
|
||
}
|
||
}
|
||
|
||
pre_iochange[timer_module] = ICU_MULTI_CPT_B_BUFFER[timer_module][0];
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief sdrv_etimer_multicpt_dma_config
|
||
* @details set multi cpt dma config.
|
||
* @param[in] pstMultiCptConfig const channel config .
|
||
* @implements sdrv_etimer_multicpt_dma_config
|
||
* @return none
|
||
*/
|
||
void sdrv_etimer_multicpt_dma_config(sdrv_multicpt_config *pmulticpt_config)
|
||
{
|
||
/*etimer1 module use DMA channel 0 and channel 1*/
|
||
/*etimer2 module use DMA channel 2 and channel 3*/
|
||
static uint8_t first_flag = true;
|
||
uint8_t timer_module = 0u;
|
||
timer_module = (uint8_t)pmulticpt_config->u8TimerModule;
|
||
/*************************** timer channel B start ****************************/
|
||
if (first_flag) {
|
||
first_flag = false;
|
||
/* init dma controller (only one time) */
|
||
sdrv_dma_init_dmac(APB_DMA_SF0_BASE);
|
||
}
|
||
|
||
sdrv_dma_channel_config_t xfer_config;
|
||
|
||
/* 1.create dma instance */
|
||
sdrv_dma_create_instance(&g_dma_instance[2 * timer_module], APB_DMA_SF0_BASE);
|
||
|
||
/* 2.get default config */
|
||
sdrv_dma_init_channel_config(&xfer_config, &g_dma_instance[2 * timer_module]);
|
||
|
||
/* 3.modify config param */
|
||
xfer_config.channel_id = (sdrv_dma_channel_id_e)((2 * timer_module) +
|
||
SDRV_DMA_CHANNEL_0); /* select channel */
|
||
xfer_config.xfer_type =
|
||
SDRV_DMA_DIR_DEV2MEM; /* mem2mem or mem2dev or dev2mem */
|
||
xfer_config.xfer_mode =
|
||
SDRV_DMA_TRANSFER_MODE_CONTINUOUS; /* single or continuous or linklist*/
|
||
xfer_config.src_inc =
|
||
SDRV_DMA_ADDR_NO_INC; /* source address increase or not */
|
||
xfer_config.dst_inc =
|
||
SDRV_DMA_ADDR_INC; /* destination address increase or not */
|
||
xfer_config.src_width = SDRV_DMA_BUSWIDTH_4_BYTES; /* source address width */
|
||
xfer_config.dst_width =
|
||
SDRV_DMA_BUSWIDTH_4_BYTES; /* destination address width */
|
||
xfer_config.src_burst_len =
|
||
MULTI_CPT_DMA_BURST_LEN; /* source burst_length (transfer level) */
|
||
xfer_config.dst_burst_len = MULTI_CPT_DMA_BURST_LEN; /* source burst_length */
|
||
xfer_config.loop_mode =
|
||
SDRV_DMA_LOOP_MODE_1; /* mem2mem(MODE_0) mem2dev/dev2mem(MODE_1) */
|
||
xfer_config.buffer_mode = SDRV_DMA_CIRCULAR_BUFFER;
|
||
xfer_config.src_port_sel =
|
||
SDRV_DMA_PORT_AHB32; /* periph -> SDRV_DMA_PORT_AHB32 */
|
||
xfer_config.dst_port_sel = SDRV_DMA_PORT_AXI64;
|
||
xfer_config.interrupt_type = SDRV_DMA_EVERY_MAD_DONE; /* set interrupt type */
|
||
xfer_config.trig_mode = SDRV_DMA_TRIGGER_BY_HARDWARE; /* by hardware trig */
|
||
xfer_config.src_addr = ETMR_BASE[timer_module] + ETMR_FIFO_OFF(1); /* FIFO B*/
|
||
xfer_config.dst_addr = (paddr_t)(&ICU_MULTI_CPT_B_BUFFER[timer_module][0]);
|
||
xfer_config.xfer_bytes = MULTI_CPT_BURST_LEN * sizeof(uint32_t); /* transaction bytes */
|
||
|
||
/* 4.init channel config */
|
||
sdrv_dma_init_channel(&g_channel[2 * timer_module], &xfer_config);
|
||
|
||
/* 5.set interrupt callback */
|
||
g_channel[2 * timer_module].irq_callback = NULL;
|
||
g_channel[2 * timer_module].irq_context = NULL;
|
||
|
||
/* 6.start channel transfer */
|
||
sdrv_dma_start_channel_xfer(&g_channel[2 * timer_module]);
|
||
|
||
|
||
/*************************** timer channel C start ****************************/
|
||
sdrv_dma_channel_config_t xfer_config2;
|
||
|
||
/* 1.create dma instance */
|
||
sdrv_dma_create_instance(&g_dma_instance[2 * timer_module + 1], APB_DMA_SF0_BASE);
|
||
|
||
/* 2.get default config */
|
||
sdrv_dma_init_channel_config(&xfer_config2, &g_dma_instance[2 * timer_module + 1]);
|
||
|
||
/* 3.modify config param */
|
||
xfer_config2.channel_id = (sdrv_dma_channel_id_e)((2 * timer_module) +
|
||
SDRV_DMA_CHANNEL_1); /* select channel */
|
||
xfer_config2.xfer_type =
|
||
SDRV_DMA_DIR_DEV2MEM; /* mem2mem or mem2dev or dev2mem */
|
||
xfer_config2.xfer_mode =
|
||
SDRV_DMA_TRANSFER_MODE_CONTINUOUS; /* single or continuous or linklist*/
|
||
xfer_config2.src_inc =
|
||
SDRV_DMA_ADDR_NO_INC; /* source address increase or not */
|
||
xfer_config2.dst_inc =
|
||
SDRV_DMA_ADDR_INC; /* destination address increase or not */
|
||
xfer_config2.src_width = SDRV_DMA_BUSWIDTH_4_BYTES; /* source address width */
|
||
xfer_config2.dst_width =
|
||
SDRV_DMA_BUSWIDTH_4_BYTES; /* destination address width */
|
||
xfer_config2.src_burst_len =
|
||
MULTI_CPT_DMA_BURST_LEN; /* source burst_length (transfer level) */
|
||
xfer_config2.dst_burst_len = MULTI_CPT_DMA_BURST_LEN; /* source burst_length */
|
||
xfer_config2.loop_mode =
|
||
SDRV_DMA_LOOP_MODE_1; /* mem2mem(MODE_0) mem2dev/dev2mem(MODE_1) */
|
||
xfer_config2.buffer_mode = SDRV_DMA_CIRCULAR_BUFFER;
|
||
xfer_config2.src_port_sel =
|
||
SDRV_DMA_PORT_AHB32; /* periph -> SDRV_DMA_PORT_AHB32 */
|
||
xfer_config2.dst_port_sel = SDRV_DMA_PORT_AXI64;
|
||
xfer_config2.interrupt_type = SDRV_DMA_EVERY_MAD_DONE; /* set interrupt type */
|
||
xfer_config2.trig_mode = SDRV_DMA_TRIGGER_BY_HARDWARE; /* by hardware trig */
|
||
xfer_config2.src_addr = ETMR_BASE[timer_module] + ETMR_FIFO_OFF(2); /* FIFO C*/
|
||
xfer_config2.dst_addr = (paddr_t)(&ICU_MULTI_CPT_C_BUFFER[timer_module][0]);
|
||
xfer_config2.xfer_bytes = MULTI_CPT_BURST_LEN * sizeof(uint32_t); /* transaction bytes */
|
||
|
||
|
||
/* 4.init channel config */
|
||
sdrv_dma_init_channel(&g_channel[2 * timer_module + 1], &xfer_config2);
|
||
|
||
/* 5.set interrupt callback */
|
||
g_channel[2 * timer_module + 1].irq_callback = sdrv_etimer_multicpt_dma_irq_handler;
|
||
g_channel[2 * timer_module + 1].irq_context = (void *)pmulticpt_config;
|
||
|
||
/* 6.start channel transfer */
|
||
sdrv_dma_start_channel_xfer(&g_channel[2 * timer_module + 1]);
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief sdrv_etimer_multicpt_dma_req_config
|
||
* @details set multi cpt etimer dma reg config.
|
||
* @param[in] timer selected etimer module.
|
||
* @param[in] waterlevel dma water level.
|
||
* @implements sdrv_etimer_multicpt_dma_req_config
|
||
* @return none
|
||
*/
|
||
void sdrv_etimer_multicpt_dma_req_config(uint8_t timer_module, bool intMode, uint8_t waterlevel)
|
||
{
|
||
if (intMode == false) {
|
||
/* set fifo wml */
|
||
uint32_t Chn_Wml = readl(ICU_CHN_DMA_WML(timer_module));
|
||
/* set fifo b wml */
|
||
Chn_Wml &= ~ICU_FM_DMA_WML_CHN(1);
|
||
Chn_Wml |= ICU_FV_DMA_WML_CHN(waterlevel, 1); /*set fifo b dma water level*/
|
||
/* set fifo c wml */
|
||
Chn_Wml &= ~ICU_FM_DMA_WML_CHN(2);
|
||
Chn_Wml |= ICU_FV_DMA_WML_CHN(waterlevel, 2); /*set fifo c dma water level*/
|
||
writel(Chn_Wml, ICU_CHN_DMA_WML(timer_module));
|
||
}
|
||
|
||
/* clear fifo */
|
||
uint32_t FifoSta = readl(ICU_FIFO_STA(timer_module));
|
||
|
||
/* clear fifo b */
|
||
for (uint8_t i = 0; i < ((FifoSta >> ((8U * 1U) + 2U)) & 0x1fU); i++) {
|
||
readl(ICU_FIFO_ADDR32(timer_module, 1));
|
||
}
|
||
|
||
/* clear fifo c */
|
||
for (uint8_t i = 0; i < ((FifoSta >> ((8U * 2U) + 2U)) & 0x1fU); i++) {
|
||
readl(ICU_FIFO_ADDR32(timer_module, 2));
|
||
}
|
||
|
||
/* select the dma block */
|
||
uint32_t Dma_Ctrl = readl(ICU_CHN_DMA_CTRL(timer_module));
|
||
/* enable dma channel b */
|
||
Dma_Ctrl |= ICU_BM_CHN_DMA_CTRL_CHN_EN(1);
|
||
/* set channel b dma block as capture */
|
||
Dma_Ctrl |= ICU_FV_CHN_DMA_CTRL_CHN_SEL(1, 1);
|
||
/* enable dma channel c */
|
||
Dma_Ctrl |= ICU_BM_CHN_DMA_CTRL_CHN_EN(2);
|
||
/* set channel c dma block as capture */
|
||
Dma_Ctrl |= ICU_FV_CHN_DMA_CTRL_CHN_SEL(1, 2);
|
||
writel(Dma_Ctrl, ICU_CHN_DMA_CTRL(timer_module));
|
||
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief sdrv_etimer_multicpt_sse_config
|
||
* @details set multi cpt etimer sse config.
|
||
* @param[in] timer selected etimer module .
|
||
* @implements sdrv_etimer_multicpt_sse_config
|
||
* @return none
|
||
*/
|
||
void sdrv_etimer_multicpt_sse_config(uint8_t timer_module)
|
||
{
|
||
/* set cpt b sse */
|
||
/* sse b reg : cpt_a0 | cpt_b0 | cpt_c0 | cpt_d0*/
|
||
uint32_t Sse_Reg = 0xFFFEFFFEU;
|
||
writel(Sse_Reg, ICU_CPT_SSE_REG_OFF(timer_module, 1));
|
||
uint32_t Sse_Ctrl = readl(ICU_CPT_SSE_CTRL_OFF(timer_module, 1));
|
||
Sse_Ctrl &= ~ICU_FM_CPT_SSE_CTRL_SSE_MODE;
|
||
/* set cpt b sse1-sse5 mode : all edge mode */
|
||
Sse_Ctrl |= ICU_FV_CPT_SSE_CTRL_SSE_MODE(0x1F);
|
||
Sse_Ctrl &= ~ICU_FM_CPT_SSE_CTRL_EDGE_SEL;
|
||
/* set cpt b sse1-sse5 edge mode : rising edge */
|
||
Sse_Ctrl |= ICU_FV_CPT_SSE_CTRL_EDGE_SEL(0x0);
|
||
/* sse cpt b enable */
|
||
Sse_Ctrl |= ICU_BM_CPT_SSE_CTRL_SSE_EN;
|
||
writel(Sse_Ctrl, ICU_CPT_SSE_CTRL_OFF(timer_module, 1));
|
||
|
||
/* set cpt c sse */
|
||
/* sse c reg : cpt_a0 | cpt_b0 | cpt_c0 | cpt_d0*/
|
||
Sse_Reg = 0xFFFEFFFE;
|
||
writel(Sse_Reg, ICU_CPT_SSE_REG_OFF(timer_module, 2));
|
||
Sse_Ctrl = readl(ICU_CPT_SSE_CTRL_OFF(timer_module, 2));
|
||
Sse_Ctrl &= ~ICU_FM_CPT_SSE_CTRL_SSE_MODE;
|
||
/* set cpt c sse1-sse5 mode : all edge mode */
|
||
Sse_Ctrl |= ICU_FV_CPT_SSE_CTRL_SSE_MODE(0x1F);
|
||
Sse_Ctrl &= ~ICU_FM_CPT_SSE_CTRL_EDGE_SEL;
|
||
/* set cpt c sse1-sse5 edge mode : rising edge */
|
||
Sse_Ctrl |= ICU_FV_CPT_SSE_CTRL_EDGE_SEL(0x0);
|
||
/* sse cpt c enable */
|
||
Sse_Ctrl |= ICU_BM_CPT_SSE_CTRL_SSE_EN;
|
||
writel(Sse_Ctrl, ICU_CPT_SSE_CTRL_OFF(timer_module, 2));
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief sdrv_etimer_multicpt_module_init
|
||
* @details multi cpt channel init.
|
||
* @param[in] pmulticpt_config multi cpt channel config .
|
||
* @implements sdrv_etimer_multicpt_module_init
|
||
* @return none
|
||
*/
|
||
void sdrv_etimer_multicpt_module_init(sdrv_multicpt_config *pmulticpt_config)
|
||
{
|
||
uint8_t timer_module = (uint8_t)pmulticpt_config->u8TimerModule;
|
||
uint8_t MultiCptChanNum = (uint8_t)pmulticpt_config->u8MultiCptChannum;
|
||
|
||
/* set timer clock and predivider */
|
||
if (g_multicpt_clk_info[timer_module] == false) {
|
||
uint32_t Clk_Mon = 0u;
|
||
Clk_Mon = ICU_BM_CLK_MON_EN_CMP_SET | ICU_BM_CLK_MON_EN_EN_N;
|
||
/* disable clk mon first */
|
||
writel(Clk_Mon, ICU_CLK_MON_EN(timer_module));
|
||
|
||
|
||
/* set clk info */
|
||
uint32_t Clk_Set = 0u;
|
||
Clk_Set = ICU_FV_TIM_CLK_CONFIG_DIV_NUM(pmulticpt_config->u16Prescaler);
|
||
/* multi cpt clk select same with xtrg */
|
||
Clk_Set |= ICU_FV_TIM_CLK_CONFIG_SRC_CLK_SEL(1);
|
||
Clk_Set |= ICU_BM_TIM_CLK_CONFIG_CLK_CHANGE_UPD;
|
||
writel(Clk_Set, ICU_TIM_CLK_CONFIG(timer_module));
|
||
|
||
while (readl(ICU_TIM_CLK_CONFIG(timer_module)) & ICU_BM_TIM_CLK_CONFIG_CLK_CHANGE_UPD) {
|
||
};
|
||
|
||
Clk_Mon = ICU_BM_CLK_MON_EN_CMP_SET | ICU_BM_CLK_MON_EN_EN_P;
|
||
|
||
/* enable clk mon */
|
||
writel(Clk_Mon, ICU_CLK_MON_EN(timer_module));
|
||
|
||
g_multicpt_clk_info[timer_module] = true;
|
||
}
|
||
|
||
#ifndef CONFIG_E3L
|
||
/* set scr multi cpt mux enable */
|
||
uint32_t Scr_Cfg = readl(APB_SCR_SF_BASE + ICU_MULTI_ETMR_SCR_CFG_ADDR(timer_module));
|
||
/* bit1 : mux cpt en */
|
||
Scr_Cfg |= 0x2U;
|
||
writel(Scr_Cfg, APB_SCR_SF_BASE + ICU_MULTI_ETMR_SCR_CFG_ADDR(timer_module));
|
||
#else
|
||
/* set scr multi cpt mux enable */
|
||
uint32_t Scr_Cfg = readl(APB_SCR_SF_BASE + ICU_MULTI_ETMR_SCR_CFG_ADDR);
|
||
Scr_Cfg |= (0x1 << timer_module);
|
||
writel(Scr_Cfg, APB_SCR_SF_BASE + ICU_MULTI_ETMR_SCR_CFG_ADDR);
|
||
#endif
|
||
/* xtrg.io mux cfg */
|
||
sdrv_etimer_multicpt_xtrig_config(timer_module, MultiCptChanNum);
|
||
|
||
/*保存中断还是DMA的触发方式*/
|
||
g_multicpt_dma_enable[timer_module] = pmulticpt_config->int_en;
|
||
|
||
if (pmulticpt_config->int_en) {
|
||
/*使能中断*/
|
||
/* set etimer dma reg */
|
||
sdrv_etimer_multicpt_dma_req_config(timer_module, true, 1);
|
||
}
|
||
else {
|
||
/*使能DMA*/
|
||
/* setup multi cpt dma config */
|
||
sdrv_etimer_multicpt_dma_config(pmulticpt_config);
|
||
|
||
/* set etimer dma reg */
|
||
sdrv_etimer_multicpt_dma_req_config(timer_module, false, 1);
|
||
}
|
||
|
||
/* set etimer sse reg */
|
||
sdrv_etimer_multicpt_sse_config(timer_module);
|
||
|
||
/* set local counter c ovf value 0xffffffff */
|
||
writel(0xFFFFFFFF, ICU_LOCAL_CNT_OVF_VAL(timer_module, 2));
|
||
RMWREG32(ICU_LOCAL_CNT_CFG(timer_module, 2), ICU_CNT_CFG_OVF_UPD_START_BIT, 1u, 1u);
|
||
uint32_t PollTime = 0u;
|
||
|
||
while (readl(ICU_LOCAL_CNT_CFG(timer_module, 2)) & (1 << ICU_CNT_CFG_OVF_UPD_START_BIT)) {
|
||
/* prevent system hang */
|
||
if (PollTime > 1000u) {
|
||
break;
|
||
}
|
||
|
||
PollTime ++;
|
||
}
|
||
|
||
/* enable timer local counter c */
|
||
writel(1, ICU_LOCAL_CNT_EN(timer_module, 2));
|
||
|
||
/* set cpt config */
|
||
/* Set the cpt b triggered edge : for multi cpt , 3 means multi cpt level mode */
|
||
RMWREG32(ICU_CPT_CONFIG(timer_module, 1), ICU_CPT_CONFIG_CPT0_TRIG_MODE_START_BIT, 2u, 3);
|
||
/* set the local timer as cpt b counter */
|
||
RMWREG32(ICU_CPT_CONFIG(timer_module, 1), ICU_CPT_CONFIG_CNT_SEL_START_BIT, 2u,
|
||
2u); /*select local count*/
|
||
RMWREG32(ICU_CPT_CTRL(timer_module), ICU_CPT_CTRL_CPT_CONFIG_SET_START_BIT(1), 1u,
|
||
1u); /*Enable capture B channel*/
|
||
/* Set the cpt c triggered edge : for multi cpt , 3 means multi cpt level mode */
|
||
RMWREG32(ICU_CPT_CONFIG(timer_module, 2), ICU_CPT_CONFIG_CPT0_TRIG_MODE_START_BIT, 2u, 3);
|
||
/* set the local timer as cpt c counter */
|
||
RMWREG32(ICU_CPT_CONFIG(timer_module, 2), ICU_CPT_CONFIG_CNT_SEL_START_BIT, 2u,
|
||
2u); /*select local count*/
|
||
RMWREG32(ICU_CPT_CTRL(timer_module), ICU_CPT_CTRL_CPT_CONFIG_SET_START_BIT(2), 1u,
|
||
1u); /*Enable capture C channel*/
|
||
|
||
if (pmulticpt_config->irq > 0u) {
|
||
irq_attach(pmulticpt_config->irq, sdrv_etimer_multicpt_irq_handle, pmulticpt_config);
|
||
irq_enable(pmulticpt_config->irq);
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief sdrv_etimer_multicpt_free_dma
|
||
* @details stop multi capture dma transfer.
|
||
* @param[in] TimerModule selected etimer module .
|
||
* @implements sdrv_etimer_multicpt_free_dma
|
||
* @return none
|
||
*/
|
||
void sdrv_etimer_multicpt_free_dma(uint8_t timer_module)
|
||
{
|
||
if (g_channel[2 * timer_module].dma != NULL) {
|
||
/*stop cpt b dma*/
|
||
sdrv_dma_stop_channel_xfer(&g_channel[2 * timer_module]);
|
||
g_channel[2 * timer_module].dma = NULL;
|
||
}
|
||
|
||
if (g_channel[2 * timer_module + 1].dma != NULL) {
|
||
/*stop cpt c dma*/
|
||
sdrv_dma_stop_channel_xfer(&g_channel[2 * timer_module + 1]);
|
||
g_channel[2 * timer_module + 1].dma = NULL;
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief sdrv_etimer_multicpt_turnon_capture
|
||
* @details turn on etimer multi cpt.
|
||
* @param[in] timer_module selected etimer module .
|
||
* @implements sdrv_etimer_multicpt_turnon_capture
|
||
* @return none
|
||
*/
|
||
static void sdrv_etimer_multicpt_turnon_capture(uint8_t timer_module, bool intMode)
|
||
{
|
||
/* bit1 :cpt b en bit2 : cpt c en */
|
||
uint32_t MultiCptEn = readl(ICU_CPT_CTRL(timer_module));
|
||
MultiCptEn |= 0x6U; /*enable capture b and capture c*/
|
||
uint32_t cpt_ctrl = ICU_CPT_CTRL(timer_module);
|
||
writel(MultiCptEn, cpt_ctrl);
|
||
|
||
if (intMode) {
|
||
/* Turn on channel C Capture interrupt */
|
||
RMWREG32(ICU_INT_STA_EN_ADDR32(timer_module), 2, 1u, 1u);
|
||
RMWREG32(ICU_INT_SIG_EN_ADDR32(timer_module), 2, 1u, 1u);
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief sdrv_etimer_multicpt_turnoff_capture
|
||
* @details turn off etimer multi cpt.
|
||
* @param[in] timer_module selected etimer module .
|
||
* @implements sdrv_etimer_multicpt_turnoff_capture
|
||
* @return none
|
||
*/
|
||
static void sdrv_etimer_multicpt_turnoff_capture(uint8_t timer_module, bool intMode)
|
||
{
|
||
/* bit1 :cpt b en bit2 : cpt c en */
|
||
uint32_t MultiCptEn = readl(ICU_CPT_CTRL(timer_module));
|
||
MultiCptEn &= ~0x6u; /*disable capture b and capture c*/
|
||
uint32_t cpt_ctrl = ICU_CPT_CTRL(timer_module);
|
||
writel(MultiCptEn, cpt_ctrl);
|
||
|
||
if (intMode) {
|
||
/* Turn off channel C Capture interrupt */
|
||
RMWREG32(ICU_INT_STA_EN_ADDR32(timer_module), 2, 1u, 0u);
|
||
RMWREG32(ICU_INT_SIG_EN_ADDR32(timer_module), 2, 1u, 0u);
|
||
}
|
||
|
||
/* clear fifo */
|
||
uint32_t FifoSta = readl(ICU_FIFO_STA(timer_module));
|
||
uint32_t fifoEntry = (FifoSta >> ((8U * 1U) + 2U)) & 0x1fU;
|
||
|
||
/* clear fifo b */
|
||
for (uint8_t i = 0; i < fifoEntry; i++) {
|
||
readl(ICU_FIFO_ADDR32(timer_module, 1));
|
||
}
|
||
|
||
fifoEntry = (FifoSta >> ((8U * 2U) + 2U)) & 0x1fU;
|
||
|
||
/* clear fifo c */
|
||
for (uint8_t i = 0; i < fifoEntry; i++) {
|
||
readl(ICU_FIFO_ADDR32(timer_module, 2));
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief sdrv_etimer_multicpt_module_deinit
|
||
* @details multi cpt channel deinit.
|
||
* @param[in] timer_module selected etimer module.
|
||
* @implements sdrv_etimer_multicpt_module_deinit
|
||
* @return none
|
||
*/
|
||
void sdrv_etimer_multicpt_module_deinit(uint8_t timer_module)
|
||
{
|
||
|
||
#ifndef CONFIG_E3L
|
||
/* disable set scr multi cpt mux */
|
||
uint32_t Scr_Cfg = readl(APB_SCR_SF_BASE + ICU_MULTI_ETMR_SCR_CFG_ADDR(timer_module));
|
||
/* bit1 : mux cpt en */
|
||
Scr_Cfg &= ~0x2;
|
||
writel(Scr_Cfg, APB_SCR_SF_BASE + ICU_MULTI_ETMR_SCR_CFG_ADDR(timer_module));
|
||
#else
|
||
/* disable set scr multi cpt mux */
|
||
uint32_t Scr_Cfg = readl(APB_SCR_SF_BASE + ICU_MULTI_ETMR_SCR_CFG_ADDR);
|
||
Scr_Cfg &= ~(0x1 << timer_module);
|
||
writel(Scr_Cfg, APB_SCR_SF_BASE + ICU_MULTI_ETMR_SCR_CFG_ADDR);
|
||
#endif
|
||
|
||
if (g_multicpt_dma_enable[timer_module] == false) {
|
||
/*表示当前是DMA方式*/
|
||
/* setup multi cpt dma config */
|
||
sdrv_etimer_multicpt_free_dma(timer_module);
|
||
}
|
||
|
||
/* select the dma block */
|
||
uint32_t Dma_Ctrl = readl(ICU_CHN_DMA_CTRL(timer_module));
|
||
/* disable dma channel b */
|
||
Dma_Ctrl &= ~ ICU_BM_CHN_DMA_CTRL_CHN_EN(1);
|
||
/* disable dma channel c */
|
||
Dma_Ctrl &= ~ ICU_BM_CHN_DMA_CTRL_CHN_EN(2);
|
||
writel(Dma_Ctrl, ICU_CHN_DMA_CTRL(timer_module));
|
||
|
||
/* disable sse b */
|
||
uint32_t Sse_Ctrl = readl(ICU_CPT_SSE_CTRL_OFF(timer_module, 1));
|
||
Sse_Ctrl &= ~ICU_BM_CPT_SSE_CTRL_SSE_EN;
|
||
writel(Sse_Ctrl, ICU_CPT_SSE_REG_OFF(timer_module, 1));
|
||
/* disable sse c */
|
||
Sse_Ctrl = readl(ICU_CPT_SSE_CTRL_OFF(timer_module, 2));
|
||
Sse_Ctrl &= ~ICU_BM_CPT_SSE_CTRL_SSE_EN;
|
||
writel(Sse_Ctrl, ICU_CPT_SSE_REG_OFF(timer_module, 2));
|
||
|
||
if (g_multicpt_dma_enable[timer_module] == false) {
|
||
/*表示当前是DMA方式*/
|
||
/* turn off capture module */
|
||
sdrv_etimer_multicpt_turnoff_capture(timer_module, false);
|
||
}
|
||
else {
|
||
/*表示当前是中断方式*/
|
||
/* turn off capture module */
|
||
sdrv_etimer_multicpt_turnoff_capture(timer_module, true);
|
||
}
|
||
|
||
/* disable timer local counter c */
|
||
writel(0, ICU_LOCAL_CNT_EN(timer_module, 2));
|
||
g_multicpt_clk_info[timer_module] = false;
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief sdrv_etimer_multicpt_init
|
||
* @details multi cpt init.
|
||
* @implements sdrv_etimer_multicpt_init
|
||
* @return none
|
||
*/
|
||
void sdrv_etimer_multicpt_init(void)
|
||
{
|
||
|
||
if (sdrv_get_chip_version() == 0x1U) {
|
||
sdrv_etimer_multicpt_set_base_addr();
|
||
memset(ICU_MULTI_CPT_B_BUFFER, 0, sizeof(ICU_MULTI_CPT_B_BUFFER));
|
||
memset(ICU_MULTI_CPT_C_BUFFER, 0, sizeof(ICU_MULTI_CPT_C_BUFFER));
|
||
memset(g_multicpt_clk_info, 0, sizeof(g_multicpt_clk_info));
|
||
memset(g_multicpt_timer_enable, 0, sizeof(g_multicpt_timer_enable));
|
||
memset(g_multicpt_dma_enable, 0, sizeof(g_multicpt_dma_enable));
|
||
memset(g_multicpt_channel_enable, 0, sizeof(g_multicpt_channel_enable));
|
||
memset(g_dma_instance, 0, sizeof(g_dma_instance));
|
||
memset(g_channel, 0, sizeof(g_channel));
|
||
}
|
||
else {
|
||
ssdk_printf(SSDK_ERR, "sdrv_etimer_multicpt_init sdrv_get_chip_version err\n");
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief sdrv_etimer_multicpt_channel_start_capture
|
||
* @details multi cpt channel start capture.
|
||
* @param[in] timer_module selected etimer module.
|
||
* @param[in] channel selected etimer channel.
|
||
* @implements sdrv_etimer_multicpt_channel_start_capture
|
||
* @return none
|
||
*/
|
||
void sdrv_etimer_multicpt_channel_start_capture(uint8_t timer_module, uint8_t channel)
|
||
{
|
||
if ((timer_module >= MULTI_CPT_MODULE_NUM) || (channel >= MULTI_CPT_MAX_IO_NUM))
|
||
return;
|
||
|
||
if (sdrv_get_chip_version() == 0x1U) {
|
||
g_multicpt_channel_enable[timer_module][channel] = true;
|
||
|
||
if (g_multicpt_timer_enable[timer_module] == false) {
|
||
g_multicpt_timer_enable[timer_module] = true;
|
||
|
||
if (g_multicpt_dma_enable[timer_module] == false) {
|
||
/*表示当前是DMA方式*/
|
||
sdrv_etimer_multicpt_turnon_capture(timer_module, false);
|
||
}
|
||
else {
|
||
/*表示当前是中断方式*/
|
||
sdrv_etimer_multicpt_turnon_capture(timer_module, true);
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
ssdk_printf(SSDK_ERR, "sdrv_etimer_multicpt_channel_start_capture sdrv_get_chip_version err\n");
|
||
}
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief sdrv_etimer_multicpt_channel_stop_capture
|
||
* @details multi cpt channel stop capture.
|
||
* @param[in] timer_module selected etimer module.
|
||
* @param[in] channel selected etimer channel.
|
||
* @implements sdrv_etimer_multicpt_channel_stop_capture
|
||
* @return none
|
||
*/
|
||
void sdrv_etimer_multicpt_channel_stop_capture(uint8_t timer_module, uint8_t channel)
|
||
{
|
||
if ((timer_module >= MULTI_CPT_MODULE_NUM) || (channel >= MULTI_CPT_MAX_IO_NUM))
|
||
return;
|
||
|
||
if (sdrv_get_chip_version() == 0x1U) {
|
||
g_multicpt_channel_enable[timer_module][channel] = false;
|
||
}
|
||
else {
|
||
ssdk_printf(SSDK_ERR, "sdrv_etimer_multicpt_channel_stop_capture sdrv_get_chip_version err\n");
|
||
}
|
||
}
|
||
|
||
|