Part Number:TDA4VM
我复用mcu timer[4:9]做捕捉器,对MCU_TIMER_IO[0:9]分时捕捉。 启动捕捉时,首先切换TIMER IO, 后使能定时器捕捉。 一段时间后,关闭timer捕捉,读取数值。
但发现,尽管输入信号无变化,每次启动一次捕捉,总有1到2个数据采集到。
这是什么原因,正确的操作流程应该是怎样的,要注意哪些操作?
Cherry Zhou:
您好我们已收到您的问题并升级到英文论坛,如有答复将尽快回复您。谢谢!
,
Cherry Zhou:
您好,请问您的usecase是什么?
Qingyu Zhuang 说:尽管输入信号无变化,
以及您这里说的输入信号是什么?
,
Qingyu Zhuang:
我这是我们自动泊车项目。用捕捉功能做超声波雷达。
,
Cherry Zhou:
好的感谢您提供的信息,请问下输入信号是哪里的输入信号呢?
,
Qingyu Zhuang:
输入信号在10个mcu_timer_io
,
Cherry Zhou:
Qingyu Zhuang 说: 我复用mcu timer[4:9]做捕捉器,对MCU_TIMER_IO[0:9]分时捕捉。 启动捕捉时,首先切换TIMER IO, 后使能定时器捕捉。
您好,这里的捕捉器是什么意义?这些定时器是怎么使用的?
,
Qingyu Zhuang:
这里的捕捉器,就是AUTOSAR的ICU,输入捕捉单元。
目前使用mcu_timer[4:9],以timerIO为纲复用这些定时器。
Icu_StartTimestamp时,从空闲的mcu_timer列表中,分配一个给启动的IO;Icu_StopTimestamp时,停止硬件后,把对应的mcu_timer回收到空闲列表。
,
Cherry Zhou:
您好,请问您用的是SDK中的计时器吗?如果是的话,您能否告知一下SDK版本,以及SDK示例/驱动程序?
,
Qingyu Zhuang:
sdk: ti-processor-sdk-rtos-j721e-evm-08_00_00_12os: freertos
SDK示例: mcusw/mcuss_demos/profiling/can
,
Cherry Zhou:
您好,您使用哪些 ICU (ECAP) 进行捕获? ICU 驱动程序目前支持 3 个 ECAP 模块。 您的输入看起来比 ICU 多,这就是为什么您将不同的定时器模块多路复用到 ICU 的原因?
Qingyu Zhuang 说:
目前使用mcu_timer[4:9],以timerIO为纲复用这些定时器。
Icu_StartTimestamp时,从空闲的mcu_timer列表中,分配一个给启动的IO;Icu_StopTimestamp时,停止硬件后,把对应的mcu_timer回收到空闲列表。
在该示例中,您提到在定时器未运行时,您看到 1-2 个数据捕获。 代码是怎样的?
当您启动 ICM_StartTimestamp() 时,使用 "tiperIO" 将其中一个计时器分配给 ECAP 模块,您能详细说下这个硬件是什么吗?
此外您能否分享下您的参考代码,以便我们更好地了解 ICU 驱动程序的用法?
,
Qingyu Zhuang:
的确,原生ECAP只有三路,而我们需要12路。MCU这边暂时做10路。这10路完全用mcu_timer硬件捕捉。根ECAP没有关系。源码如下:
#define MULTIPLEX_ICU_TIMERS#define MCU_TIMER0_BASE (0x40400000UL)#define ICU_BASE_TIMER0 (0x02400000UL)#define ICU_BASE_TIMER1 (0x02410000UL)#define ICU_BASE_TIMER2 (0x02420000UL)#define ICU_BASE_TIMER3 (0x02430000UL)#define ICU_BASE_TIMER4 (0x02440000UL)#define ICU_BASE_TIMER5 (0x02450000UL)#define ICU_BASE_TIMER6 (0x02460000UL)#define ICU_BASE_TIMER7 (0x02470000UL)#define ICU_BASE_TIMER8 (0x02480000UL)#define ICU_BASE_TIMER9 (0x02490000UL)#define ICU_BASE_TIMER10 (0x024A0000UL)#define ICU_BASE_TIMER11 (0x024B0000UL)#define ICU_BASE_TIMER12 (0x024C0000UL)#define ICU_BASE_TIMER13 (0x024D0000UL)#define ICU_BASE_TIMER14 (0x024E0000UL)#define ICU_BASE_TIMER15 (0x024F0000UL)#define ICU_BASE_TIMER16 (0x02500000UL)#define ICU_BASE_TIMER17 (0x02510000UL)#define ICU_BASE_TIMER18 (0x02520000UL)#define ICU_BASE_TIMER19 (0x02530000UL)#define ICU_BASE_MCU_TIMER0 (0x40400000UL)#define ICU_BASE_MCU_TIMER1 (0x40410000UL)#define ICU_BASE_MCU_TIMER2 (0x40420000UL)#define ICU_BASE_MCU_TIMER3 (0x40430000UL)#define ICU_BASE_MCU_TIMER4 (0x40440000UL)#define ICU_BASE_MCU_TIMER5 (0x40450000UL)#define ICU_BASE_MCU_TIMER6 (0x40460000UL)#define ICU_BASE_MCU_TIMER7 (0x40470000UL)#define ICU_BASE_MCU_TIMER8 (0x40480000UL)#define ICU_BASE_MCU_TIMER9 (0x40490000UL)#define MCU_TIMER0_INTR_PEND_0 (38U)#define MCU_TIMER1_INTR_PEND_0 (39U)#define MCU_TIMER2_INTR_PEND_0 (40U)#define MCU_TIMER3_INTR_PEND_0 (41U)#define MCU_TIMER4_INTR_PEND_0 (108U) #define MCU_TIMER5_INTR_PEND_0 (109U) #define MCU_TIMER6_INTR_PEND_0 (110U) #define MCU_TIMER7_INTR_PEND_0 (111U) #define MCU_TIMER8_INTR_PEND_0 (112U) #define MCU_TIMER9_INTR_PEND_0 (113U)#define TIMER0_INTR_PEND_0 (256UL)#define TIMER1_INTR_PEND_0 (257UL)#define TIMER2_INTR_PEND_0 (258UL)#define TIMER3_INTR_PEND_0 (259UL)#define TIMER4_INTR_PEND_0 (260UL)#define TIMER5_INTR_PEND_0 (261UL)#define TIMER6_INTR_PEND_0 (262UL)#define TIMER7_INTR_PEND_0 (263UL)#define TIMER8_INTR_PEND_0 (264UL)#define TIMER9_INTR_PEND_0 (265UL)#define TIMER10_INTR_PEND_0 (266UL)#define TIMER11_INTR_PEND_0 (267UL)#define TIMER12_INTR_PEND_0 (268UL)#define TIMER13_INTR_PEND_0 (269UL)#define TIMER14_INTR_PEND_0 (270UL)#define TIMER15_INTR_PEND_0 (271UL)#define TIMER16_INTR_PEND_0 (272UL)#define TIMER17_INTR_PEND_0 (273UL)#define TIMER18_INTR_PEND_0 (274UL)#define TIMER19_INTR_PEND_0 (275UL)#ifdef MULTIPLEX_ICU_TIMERS#define FIRST_ICU_TMR_IDX (4U) /* MCU timer[0:3] used as GPT by RTOS. And here, mcu_timer[4:9] is for ICU */#define LAST_ICU_TMR_IDX (9U) /* mcu_timer[4:9] for ICU */#define NVLDIF (0xFFU)#define COUNT_OF_ICU_TMR (((LAST_ICU_TMR_IDX)+1)-(FIRST_ICU_TMR_IDX))#define COUNT_OF_ICU_IO (sizeof(IcuTmrInfo)/sizeof(IcuTmrInfo[0]))#define isIcuTmrUsed(Tmr) ((COUNT_OF_ICU_IO) > LnkIO[Tmr])#define isIoAssigned(nIO) ((COUNT_OF_ICU_TMR) > LnkTmr[nIO])#endiftypedef struct{ uint32 baseAddress; uint32 ClockRegister; uint32 PadConfigRegister; uint32 PadConfigVal; uint32 TimerControllRegster; uint32 TimerIoControllRegister; uint32 MmrVal; uint32 Vector;}tIcuePinmuxInfo;static const tIcuePinmuxInfo IcuTmrInfo[] = { [0] = { .baseAddress = ICU_BASE_MCU_TIMER0, .ClockRegister = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMER0_CLKSEL), .PadConfigRegister = (CSL_WKUP_CTRL_MMR0_CFG0_BASE + CSL_WKUP_CTRL_MMR_CFG0_PADCONFIG21), .PadConfigVal = 0x00050002UL, .TimerControllRegster = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMER0_CTRL), .TimerIoControllRegister = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMERIO0_CTRL), .MmrVal = 0x0UL, .Vector = MCU_TIMER0_INTR_PEND_0, }, [1] = { .baseAddress = ICU_BASE_MCU_TIMER1, .ClockRegister = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMER1_CLKSEL), .PadConfigRegister = (CSL_WKUP_CTRL_MMR0_CFG0_BASE + CSL_WKUP_CTRL_MMR_CFG0_PADCONFIG55), .PadConfigVal = 0x00050004UL, .TimerControllRegster = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMER1_CTRL), .TimerIoControllRegister = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMERIO1_CTRL), .MmrVal = 0x1UL, .Vector = MCU_TIMER1_INTR_PEND_0, }, [2] = { .baseAddress = ICU_BASE_MCU_TIMER2, .ClockRegister = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMER2_CLKSEL), .PadConfigRegister = (CSL_WKUP_CTRL_MMR0_CFG0_BASE + CSL_WKUP_CTRL_MMR_CFG0_PADCONFIG24), .PadConfigVal = 0x00050001UL, .TimerControllRegster = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMER2_CTRL), .TimerIoControllRegister = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMERIO2_CTRL), .MmrVal = 0x2UL, .Vector = MCU_TIMER2_INTR_PEND_0, }, [3] = { .baseAddress = ICU_BASE_MCU_TIMER3, .ClockRegister = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMER3_CLKSEL), .PadConfigRegister = (CSL_WKUP_CTRL_MMR0_CFG0_BASE + CSL_WKUP_CTRL_MMR_CFG0_PADCONFIG25), .PadConfigVal = 0x00050001UL, .TimerControllRegster = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMER3_CTRL), .TimerIoControllRegister = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMERIO3_CTRL), .MmrVal = 0x3UL, .Vector = MCU_TIMER3_INTR_PEND_0, }, [4] = { .baseAddress = ICU_BASE_MCU_TIMER4, .ClockRegister = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMER4_CLKSEL), .PadConfigRegister = (CSL_WKUP_CTRL_MMR0_CFG0_BASE + CSL_WKUP_CTRL_MMR_CFG0_PADCONFIG30), .PadConfigVal = 0x00050001UL, .TimerControllRegster = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMER4_CTRL), .TimerIoControllRegister = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMERIO4_CTRL), .MmrVal = 0x4UL, .Vector = MCU_TIMER4_INTR_PEND_0, }, [5] = { .baseAddress = ICU_BASE_MCU_TIMER5, .ClockRegister = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMER5_CLKSEL), .PadConfigRegister = (CSL_WKUP_CTRL_MMR0_CFG0_BASE + CSL_WKUP_CTRL_MMR_CFG0_PADCONFIG31), .PadConfigVal = 0x00050001UL, .TimerControllRegster = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMER5_CTRL), .TimerIoControllRegister = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMERIO5_CTRL), .MmrVal = 0x5UL, .Vector = MCU_TIMER5_INTR_PEND_0, }, [6] = { .baseAddress = ICU_BASE_MCU_TIMER6, .ClockRegister = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMER6_CLKSEL), .PadConfigRegister = (CSL_WKUP_CTRL_MMR0_CFG0_BASE + CSL_WKUP_CTRL_MMR_CFG0_PADCONFIG52), .PadConfigVal = 0x00050004UL, .TimerControllRegster = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMER6_CTRL), .TimerIoControllRegister = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMERIO6_CTRL), .MmrVal = 0x6UL, .Vector = MCU_TIMER6_INTR_PEND_0, }, [7] = { .baseAddress = ICU_BASE_MCU_TIMER7, .ClockRegister = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMER7_CLKSEL), .PadConfigRegister = (CSL_WKUP_CTRL_MMR0_CFG0_BASE + CSL_WKUP_CTRL_MMR_CFG0_PADCONFIG53), .PadConfigVal = 0x00050004UL, .TimerControllRegster = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMER7_CTRL), .TimerIoControllRegister = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMERIO7_CTRL), .MmrVal = 0x7UL, .Vector = MCU_TIMER7_INTR_PEND_0, }, [8] = { .baseAddress = ICU_BASE_MCU_TIMER8, .ClockRegister = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMER8_CLKSEL), .PadConfigRegister = (CSL_WKUP_CTRL_MMR0_CFG0_BASE + CSL_WKUP_CTRL_MMR_CFG0_PADCONFIG60), .PadConfigVal = 0x00050004UL, .TimerControllRegster = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMER8_CTRL), .TimerIoControllRegister = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMERIO8_CTRL), .MmrVal = 0x8UL, .Vector = MCU_TIMER8_INTR_PEND_0, }, [9] = { .baseAddress = ICU_BASE_MCU_TIMER9, .ClockRegister = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMER9_CLKSEL), .PadConfigRegister = (CSL_WKUP_CTRL_MMR0_CFG0_BASE + CSL_WKUP_CTRL_MMR_CFG0_PADCONFIG61), .PadConfigVal = 0x00050004UL, .TimerControllRegster = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMER9_CTRL), .TimerIoControllRegister = (CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_TIMERIO9_CTRL), .MmrVal = 0x9UL, .Vector = MCU_TIMER9_INTR_PEND_0, }, /* [10] = { .baseAddress = ICU_BASE_TIMER0, .ClockRegister = (CSL_CTRL_MMR0_CFG0_BASE + CSL_MAIN_CTRL_MMR_CFG0_TIMER0_CLKSEL), .PadConfigRegister = (CSL_CTRL_MMR0_CFG0_BASE + CSL_MAIN_CTRL_MMR_CFG0_PADCONFIG154), .PadConfigVal = 0x00050003UL, .TimerControllRegster = (CSL_CTRL_MMR0_CFG0_BASE + CSL_MAIN_CTRL_MMR_CFG0_TIMER0_CTRL), .TimerIoControllRegister = (CSL_CTRL_MMR0_CFG0_BASE + CSL_MAIN_CTRL_MMR_CFG0_TIMERIO0_CTRL), .MmrVal = 0x4UL, .Vector = TIMER0_INTR_PEND_0, }, [11] = { .baseAddress = ICU_BASE_TIMER1, .ClockRegister = (CSL_CTRL_MMR0_CFG0_BASE + CSL_MAIN_CTRL_MMR_CFG0_TIMER1_CLKSEL), .PadConfigRegister = (CSL_CTRL_MMR0_CFG0_BASE + CSL_MAIN_CTRL_MMR_CFG0_PADCONFIG155), .PadConfigVal = 0x00050003UL, .TimerControllRegster = (CSL_CTRL_MMR0_CFG0_BASE + CSL_MAIN_CTRL_MMR_CFG0_TIMER1_CTRL), .TimerIoControllRegister = (CSL_CTRL_MMR0_CFG0_BASE + CSL_MAIN_CTRL_MMR_CFG0_TIMERIO1_CTRL), .MmrVal = 0x5UL, .MmrVal = TIMER1_INTR_PEND_0, }, */};#ifdef MULTIPLEX_ICU_TIMERSstatic uint8 LnkIO[COUNT_OF_ICU_TMR] = {NVLDIF}; /* Recored IO index */static uint8 LnkTmr[COUNT_OF_ICU_IO];#endifextern void AppUtils_Printf (uint32 type,const char *pcString, …);extern FUNC(void, ICU_CODE) IcuE_ISR(Icu_ChannelType Channel, uint32 Value);static inline int32_t IcuE_timerWaitForWrite(uint32_t reg, uint32_t baseAddr){ int32_t retVal = CSL_PASS; volatile uint32_t exit_count = (uint32_t) 0U; uint32_t step_size = (uint32_t) 1U; if (0U != HW_RD_FIELD32(baseAddr + TIMER_TSICR, TIMER_TSICR_POSTED)) { while ((uint32_t) 0U != (reg & TIMERWritePostedStatusGet(baseAddr))) { exit_count += step_size; /* Do nothing – Busy wait, * quit the loop if posted transations are not complete * by one full cycle of counting * This check and break prevents getting stuck in the loop */ if (exit_count == 0U) { retVal = CSL_ETIMEOUT; break; } } } return (retVal);}static void ICUHW_Isr(uint32 Module){ uint32 baseAddr; uint32 status; //AppUtils_Printf(2, "isr%d\n", Module); if((sizeof(IcuTmrInfo)/sizeof(IcuTmrInfo[0])) > Module) { // SchM_Enter_Icu_ICU_EXCLUSIVE_AREA_0(); baseAddr = IcuTmrInfo[Module].baseAddress; status = TIMERIntStatusGet(baseAddr); #ifdef MULTIPLEX_ICU_TIMERS if((FIRST_ICU_TMR_IDX) <= Module && (LAST_ICU_TMR_IDX) >= Module) { Module = LnkIO[Module – (FIRST_ICU_TMR_IDX)]; #endif /* Wait until event detected? */ /* Read timer capture value */ if(0 != (TIMER_INT_TCAR_IT_FLAG & status)) { IcuE_ISR(Module, HW_RD_REG32(baseAddr + TIMER_TCAR1)); } if(0 != (TIMER_INT_OVF_IT_FLAG & status)) { } if(0!= (TIMER_INT_MAT_IT_FLAG & status)) { } /* Clear capture interrupt request. */ TIMERIntStatusClear(baseAddr, TIMER_INT_TCAR_IT_FLAG|TIMER_INT_OVF_IT_FLAG|TIMER_INT_MAT_IT_FLAG); #ifdef MULTIPLEX_ICU_TIMERS } #endif // SchM_Exit_Icu_ICU_EXCLUSIVE_AREA_0(); }}void ICUHW_init(uint32 nModule, Icu_ChannelConfigType* cfg){ uint32 baseAddr; int32_t regVal; OsalRegisterIntrParams_t intrPrms; HwiP_Handle hwiHandle; uint32 tmp32; tIcuePinmuxInfo *HwInfo; if ((sizeof(IcuTmrInfo)/sizeof(IcuTmrInfo[0])) > nModule) { HwInfo = (tIcuePinmuxInfo*)(&(IcuTmrInfo[nModule])); baseAddr = HwInfo->baseAddress;#ifdef MULTIPLEX_ICU_TIMERS LnkTmr[nModule] = NVLDIF; if(FIRST_ICU_TMR_IDX <= nModule) { LnkIO[nModule-FIRST_ICU_TMR_IDX] = NVLDIF;#endif /* Execute software reset. TIMER_TIOCP_CFG[0] SOFTRESET 0x1 */ /* Wait until reset release? TIMER_TIOCP_CFG[0] SOFTRESET 0x0 */ TIMERReset(baseAddr); /* Configure idle mode. TIMER_ TIOCP_CFG[3-2] IDLEMODE 0x- */ TIMERIdleModeConfigure(baseAddr, TIMER_SMART_IDLE); /* Enable wake-up interrupt events. TIMER_IRQWAKEEN[2-0] 0x- */ /* Select posted mode. TIMER_TSICR[2] POSTED 0x- */ /* ע\B2\E1\D6жϺ\AF\CA\FD */ Osal_RegisterInterrupt_initParams(&intrPrms); intrPrms.corepacConfig.arg = nModule; intrPrms.corepacConfig.isrRoutine = &ICUHW_Isr; intrPrms.corepacConfig.priority = 2U; intrPrms.corepacConfig.corepacEventNum = 0U; /* NOT USED ? */ intrPrms.corepacConfig.intVecNum = HwInfo->Vector; (void)Osal_RegisterInterrupt(&intrPrms, &hwiHandle); HW_WR_REG32(HwInfo->ClockRegister, 0x2UL/* CLK_12M_RC SPRUIL1B P1506 */); /* Select clock */ HW_WR_REG32(baseAddr + TIMER_TIOCP_CFG, 0xAUL); /* Initialize capture mode. See Section 12.10.3.5.2.3.2. */ /* Select autoreload mode. TIMER_TCLR[1] AR 0x- */ regVal = IcuE_timerWaitForWrite(TIMER_WRITE_POST_TCLR, baseAddr); if(CSL_PASS == regVal) { regVal = HW_RD_REG32(baseAddr + TIMER_TCLR); regVal |= (TIMER_TCLR_AR_MASK); HW_WR_REG32(baseAddr + TIMER_TCLR, regVal); } /* Set prescale timer value. TIMER_TCLR[4-2] PTV 0x- */ tmp32 = cfg->prescaler; if(8 <= tmp32) {tmp32 = 7;} else if(0 < tmp32) {tmp32–;} regVal = IcuE_timerWaitForWrite(TIMER_WRITE_POST_TCLR, baseAddr); if(CSL_PASS == regVal) { regVal = HW_RD_REG32(baseAddr + TIMER_TCLR); regVal &= (~(TIMER_TCLR_PTV_MASK)); regVal |= (tmp32 << (TIMER_TCLR_PTV_SHIFT)); HW_WR_REG32(baseAddr + TIMER_TCLR, regVal); } /* Enable prescaler. TIMER_TCLR[5] PRE 0x1 */ regVal = IcuE_timerWaitForWrite(TIMER_WRITE_POST_TCLR, baseAddr); if(CSL_PASS == regVal) { regVal = HW_RD_REG32(baseAddr + TIMER_TCLR); regVal |= (TIMER_TCLR_PRE_MASK); HW_WR_REG32(baseAddr + TIMER_TCLR, regVal); } /* Select TIMER[19-0] or MCU_TIMER[9-0] TIMER_TCLR[14] GPO_CFG 0x1 */ /* Capture input at device pins */ /* TIMER_IO[7-0] for TIMER[19-0] or at pins */ /* MCU_TIMER_IO[9-0] for MCU_TIMER[9-0]. */ regVal = IcuE_timerWaitForWrite(TIMER_WRITE_POST_TCLR, baseAddr); if(CSL_PASS == regVal) { regVal = HW_RD_REG32(baseAddr + TIMER_TCLR); regVal |= (TIMER_TCLR_GPO_CFG_MASK); HW_WR_REG32(baseAddr + TIMER_TCLR, regVal); } /* Binding IO */ #ifndef MULTIPLEX_ICU_TIMERS HW_WR_REG32(HwInfo->TimerControllRegster, HwInfo->MmrVal); HW_WR_REG32(HwInfo->TimerIoControllRegister, HwInfo->MmrVal); #endif /* Select single or second event capture. TIMER_TCLR[13] CAPT_MODE 0x- */ regVal = IcuE_timerWaitForWrite(TIMER_WRITE_POST_TCLR, baseAddr); if(CSL_PASS == regVal) { regVal = HW_RD_REG32(baseAddr + TIMER_TCLR); regVal &= (~(TIMER_TCLR_CAPT_MODE_MASK)); HW_WR_REG32(baseAddr + TIMER_TCLR, regVal); } /* Select transition capture mode. TIMER_TCLR[9-8] TCM 0x- */ if(ICU_RISING_EDGE == cfg->defaultStartEdge) { tmp32 = ((TIMER_TCLR_TCM_TCM_VALUE_0X1) << (TIMER_TCLR_TCM_SHIFT)); } else if(ICU_FALLING_EDGE == cfg->defaultStartEdge) { tmp32 = ((TIMER_TCLR_TCM_TCM_VALUE_0X2) << (TIMER_TCLR_TCM_SHIFT)); } else { tmp32 = ((TIMER_TCLR_TCM_TCM_VALUE_0X3) << (TIMER_TCLR_TCM_SHIFT)); } regVal = IcuE_timerWaitForWrite(TIMER_WRITE_POST_TCLR, baseAddr); if(CSL_PASS == regVal) { regVal = HW_RD_REG32(baseAddr + TIMER_TCLR); regVal &= (~(TIMER_TCLR_TCM_MASK)); regVal |= tmp32; HW_WR_REG32(baseAddr + TIMER_TCLR, regVal); } /* Enable capture interrupt. TIMER_IRQSTATUS_SET[2] TCAR_EN_FLAG 0x1 */ //TIMERIntEnable(baseAddr, TIMER_INT_TCAR_EN_FLAG/*|TIMER_INT_OVF_EN_FLAG*/); /* Start the timer. TIMER_TCLR[0] ST 0x1 */ //TIMEREnable(baseAddr); /* Detect event. See Section 12.10.3.5.2.3.3. */ #ifdef MULTIPLEX_ICU_TIMERS } #endif /* PAD work as timer IO */ HW_WR_REG32(HwInfo->PadConfigRegister, HwInfo->PadConfigVal); } }void ICUHW_deinit(uint32 nModule){ if(COUNT_OF_ICU_IO > nModule) { TIMERReset(IcuTmrInfo[nModule].baseAddress); }}#ifdef MULTIPLEX_ICU_TIMERS/******************************************************************************* \BA\AF\CA\FD\C3\FB\B3ƣ\BAICUHW_assignTimer *——————————————————————————* \BA\AF\CA\FD\B9\A6\C4ܣ\BAIf the module has be assigned a timer, return the timer index, oth-* erwise assigned a timer to it* \CA\E4\C8\EB\B2\CE\CA\FD\A3\BAnModule–Hardware module* \B7\B5\BB\D8ֵ \A3\BArelative timer index. The value 0xFFu means assignment filed.* \B1\B8 ע\A3\BA******************************************************************************/static uint8 ICUHW_assignTimer(uint32 nModule){ uint8 i = 0xFFu; tIcuePinmuxInfo *HwInfo; if(COUNT_OF_ICU_IO > nModule) { if(isIoAssigned(nModule)) /* \B7\D6\C5\E4Ӳ\BC\FE */ { i = LnkTmr[nModule]; } else { for(i=0; i<(COUNT_OF_ICU_TMR); i++) { if(!isIcuTmrUsed(i)) { LnkIO[i] = nModule; /* Timer link to witch IO */ LnkTmr[nModule] = i; /* Assigne timer */ HwInfo = (tIcuePinmuxInfo*)&IcuTmrInfo[i + FIRST_ICU_TMR_IDX]; HW_WR_REG32(HwInfo->TimerControllRegster, nModule); HW_WR_REG32(HwInfo->TimerIoControllRegister, nModule); break; } } if(COUNT_OF_ICU_TMR <= i) /* \CE\C9\D3\C3Ӳ\BC\FE\A3\AC\B7\D6\C5\E4ʧ\B0ܣ\ACֱ\BD\D3\CD˳\F6 */ { i = 0xFF; AppUtils_Printf(2, " f\n"); } } } return (i);}static void ICUHW_reclaimTimer(uint32 nModule){ if(COUNT_OF_ICU_IO > nModule) { if(isIoAssigned(nModule)) { LnkIO[LnkTmr[nModule]] = NVLDIF; LnkTmr[nModule] = NVLDIF; } }}#endifvoid IcuhW_SetActivationCondition( Icu_ChannelType nModule, Icu_ActivationType Activation ){ uint32 tmp32; int32_t regVal; uint32 baseAddr; if (COUNT_OF_ICU_IO > nModule) { #ifdef MULTIPLEX_ICU_TIMERS tmp32 = ICUHW_assignTimer(nModule); if(COUNT_OF_ICU_TMR > tmp32) { nModule = (Icu_ChannelType)(tmp32 + (FIRST_ICU_TMR_IDX)); #endif baseAddr = IcuTmrInfo[nModule].baseAddress; /* Select transition capture mode. TIMER_TCLR[9-8] TCM 0x- */ if(ICU_RISING_EDGE == Activation) { tmp32 = ((TIMER_TCLR_TCM_TCM_VALUE_0X1) << (TIMER_TCLR_TCM_SHIFT)); } else if(ICU_FALLING_EDGE == Activation) { tmp32 = ((TIMER_TCLR_TCM_TCM_VALUE_0X2) << (TIMER_TCLR_TCM_SHIFT)); } else { tmp32 = ((TIMER_TCLR_TCM_TCM_VALUE_0X3) << (TIMER_TCLR_TCM_SHIFT)); } regVal = IcuE_timerWaitForWrite(TIMER_WRITE_POST_TCLR, baseAddr); if(CSL_PASS == regVal) { regVal = HW_RD_REG32(baseAddr + TIMER_TCLR); regVal &= (~(TIMER_TCLR_TCM_MASK)); regVal |= tmp32; HW_WR_REG32(baseAddr + TIMER_TCLR, regVal); } #ifdef MULTIPLEX_ICU_TIMERS } #endif }}void ICUHW_startModule(Icu_ChannelType nModule){ uint32 baseAddr; if(COUNT_OF_ICU_IO > nModule) { #ifdef MULTIPLEX_ICU_TIMERS uint8 i; tIcuePinmuxInfo *HwInfo; AppUtils_Printf(2, ">%d", nModule); i = ICUHW_assignTimer(nModule); if(COUNT_OF_ICU_TMR > i) { nModule = i + FIRST_ICU_TMR_IDX; #endif baseAddr = IcuTmrInfo[nModule].baseAddress; HW_WR_REG32(baseAddr+TIMER_IRQSTATUS_RAW, 0UL); HW_WR_REG32(baseAddr+TIMER_IRQSTATUS, 7UL); /* Enable capture interrupt. TIMER_IRQSTATUS_SET[2] TCAR_EN_FLAG 0x1 */ TIMERIntEnable(baseAddr, TIMER_INT_TCAR_EN_FLAG/*|TIMER_INT_OVF_EN_FLAG*/); /* Start the timer. TIMER_TCLR[0] ST 0x1 */ TIMEREnable(baseAddr); #ifdef MULTIPLEX_ICU_TIMERS } #endif }}void ICUHW_stopModule(Icu_ChannelType nModule){ uint32 baseAddr; if(COUNT_OF_ICU_IO > nModule) { #ifdef MULTIPLEX_ICU_TIMERS //AppUtils_Printf(2, "<%d", nModule); if(isIoAssigned(nModule)) { nModule = LnkTmr[nModule] + (FIRST_ICU_TMR_IDX); #endif baseAddr = IcuTmrInfo[nModule].baseAddress; TIMERIntDisable(baseAddr, TIMER_INT_TCAR_EN_FLAG); TIMERDisable(baseAddr); #ifdef MULTIPLEX_ICU_TIMERS ICUHW_reclaimTimer(nModule); } #endif }}
,
Cherry Zhou:
您好,您能否试下用示波器或者其他仪器以查看 ICU 是否正在读取任何内容?或者更简单的测试,看下在断开 ICU 与任何这些外设的连接时,是否仍有读数? 这样我们可以确定 ICU 本身不会进行随机读数。
,
Qingyu Zhuang:
目前使用mcu_timer[4:9]六个,mcu_timer_io[0:9]十个。十个输入口都能捕捉,但频率低于550hz才能捕捉到双边沿,否则只捕捉到周期。不链接信号时,io[0:5]不会干扰,io[6:9]总捕捉到一个数值。优先级调整过到0,效果不明显。示波器跟踪过信号,硬件能保证10khz占空比1%的信号输入,到tda4管脚信号有完整的高和低电平。已对上面代码做排查调整,算法不变。
,
Cherry Zhou:
好的感谢您提供的信息,已经反馈给工程师这边了,有答复尽快给到您哈。
,
Cherry Zhou:
您好,有一点需要说明,我们不支持 MCAL/AUTOSAR 的 ICU 驱动器用于计时器输入捕获。 请问您是在哪里获得这个驱动程序的? 我们的 MCAL 驱动程序支持 ECAP,您是否使用定时器自己制作了 MCAL 驱动程序?
,
Qingyu Zhuang:
谢谢您耐心支持。
我们没有使用<sdk>/mcusw/mcal_drv/mcal/Icu
上面代码是我们自己的。
,
Cherry Zhou:
好的感谢您提供的信息,现在您这边和工程师是同步的了。您能否重新总结一下关于您在使用计时器时的问题?
有可能是硬件中的配置问题? 还是说您使用 TI 提供的软件?
,
Qingyu Zhuang:
上面代码是按自己的理解去配置这些寄存器的,所以没办法识别这样的配置问题在哪里。需要技术支持进一步给建议和帮助。
,
Cherry Zhou:
嗯嗯好的,能否请您重新总结下您的问题,您在使用定时器时出现的问题?
https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1082678/tda4vm-multiplexed-mcu-timer-as-a-grabber-with-false-touch-issue
以上链接是帮助您升级到英文论坛寻求帮助的帖子,您也可以持续关注。