This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi team,
Here's an issue from the customer may need your help:
The customer multiplexed the mcu timer[4:9] as a grabber to capture the MCU_TIMER_IO[0:9] minutes. When the capture is started, first toggle TIMER IO, and then enable the timer capture. After some time, turn off the timer capture and read the value. While the input signal does not change, 1 to 2 data are captured every capture initiated.
Could you help check what is the reason for this and what should be the correct process? Thanks.
Best Regards,
Cherry
Hi Cherry,
Can you please elaborate on the use case here?
While the input signal does not change, 1 to 2 data are captured every capture initiated.
Also, please mention what input signal are you talking about here?
Regards,
Parth
Hi Parth,
Thanks for your help.
Can you please elaborate on the use case here?
It's an Automated Parking Program. Use the capture function as an ultrasonic radar.
Also, please mention what input signal are you talking about here?
The input signal is at 10 mcu_timer_io.
Thanks and regards,
Cherry
Hi Cherry,
Sorry, I am still not clear on the issue here.
The customer multiplexed the mcu timer[4:9] as a grabber to capture the MCU_TIMER_IO[0:9] minutes. When the capture is started, first toggle TIMER IO, and then enable the timer captur
Can you please elaborate what do you mean by grabber here and how these timers are used?
Regards,
Parth
Hi Parth,
Can you please elaborate what do you mean by grabber here and how these timers are used?
The grabber here is the ICU of AUTOSAR, the input capture unit.
Mcu_timer[4:9] is currently used. The timers are multiplexed with tiperIO as the platform. When Icu_StartTimestamp is set, assign a to the boot IO from the idle mcu_timer list; When Icu_StopTimestamp is set, the corresponding mcu_timer is recycled to the idle list after stopping the hardware.
Thanks and regards,
Cherry
Hi Cherry,
Are you using timers from SDK?
If yes, can you also mention the SDK version and the example/driver from SDK you me be referring to?
Regards,
Parth
Hi Parth,
If yes, can you also mention the SDK version and the example/driver from SDK you me be referring to?
sdk: ti-processor-sdk-rtos-j721e-evm-08_00_00_12
os: freertos
SDK example: mcusw/mcuss_demos/profiling/can
Thanks and regards,
Cherry
Hi Cherry,
Which ICU (ECAP) modules are you using for the capture? There are 3 ECAP modules supported by the ICU driver currently.
It looks like you have more inputs than ICUs, so this is why you have multiplexed the different timer modules to the ICUs?
In the example, you mention that you are seeing 1-2 data captures while the timer is not running. Could you explain the code process for this:
Mcu_timer[4:9] is currently used. The timers are multiplexed with tiperIO as the platform. When Icu_StartTimestamp is set, assign a to the boot IO from the idle mcu_timer list; When Icu_StopTimestamp is set, the corresponding mcu_timer is recycled to the idle list after stopping the hardware.
So when you start Icu_StartTimestamp(), you assign one of the timers to the ECAP module using "tiperIO", can you elaborate what this hardware is? Do you have some reference code we can take a look at to better understand the usage of the Icu driver?
Thanks,
Erick
Hello Erick,
Thanks for your support.
There are 3 ECAP modules supported by the ICU driver currently.
Yes, while they need 12. The MCU is temporarily doing 10. These 10 modules are fully captured with mcu_timer hardware, and is not related to ECAP. The source code is as follows:
#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]) #endif typedef 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_TIMERS static uint8 LnkIO[COUNT_OF_ICU_TMR] = {NVLDIF}; /* Recored IO index */ static uint8 LnkTmr[COUNT_OF_ICU_IO]; #endif extern 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; } } } #endif void 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 } }
Thanks and regards,
Cherry
Cherry,
Could you get a trace to see if there is anything the ICU is reading, with an oscilloscope or something else? Or perhaps a simpler test is to see if you still see readings when the ICU is disconnected from any of these peripherals? This way we can isolate that the ICU is not making random readings itself.
Regards,
Erick
Hi Erick,
Now 6 mcu_timer[4:9] and 9 mcu_timer_io[0:9] are being used.
All ten inputs can be captured, but the frequency is less than 550 hz to capture the bilateral edge, otherwise only the period is captured. When the signal is not linked, io[0:5] does not interfere and io[6:9] always captures a value. The priority has been adjusted to 0, but there has been no significant improvement. The oscilloscope tracks the signal and the hardware guarantees a signal input of 1% duty cycle of 10khz and full high and low to the tda4 pin signal. The code above has been tuned for troubleshooting and the algorithm is unchanged.
Thanks and regards,
Cherry
Hi Cherry,
One thing to clarify, we do not support the ICU Driver from MCAL/AUTOSAR for the timer input captures. Where did the customer get this driver from? Our MCAL driver has support for ECAP, did they make an MCAL driver themselves using the Timer?
Regards,
Erick
Hi Erick,
Thanks. It has been confirmed that they don't use <sdk>/mcusw/mcal_drv/mcal/Icu, the code above is from the customer.
Thanks and regards,
Cherry
Cherry,
Thanks for confirming. Now that we are on the same page, can you re-summarize the issue the customer is seeing with their usage of the timers? Is this suspected to be an issue with their configuration in hardware? Or with SW provided by TI?
Regards,
Erick