/** * @file sdrv_multicapture * @brief SemiDrive etimer capture driver source file. * * @copyright Copyright (c) 2022 Semidrive Semiconductor. * All rights reserved. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "sdrv_etimer.h" #include "sdrv_xtrg.h" #include "board.h" #include "sdrv_multicapture.h" #include "sdrv_dma.h" #include #include 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"); } }