Part Number: AM13E23019
Other Parts Discussed in Thread: SYSCONFIG
-
The PWM frequency is configured to 16 kHz without any prescaler.
-
MCPWM is generating the SyncOut pulse for ECAP.
-
PWM1A is configured to:
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.
Part Number: AM13E23019
Other Parts Discussed in Thread: SYSCONFIG
#include "device.h"
#include "log.h"
#include <stdint.h>
#include "ti_sdk_dl_config.h"
#include "BSP_AM13E230_E2.hpp"
uint16_t tick_high_pulse = 245;
uint16_t tick_low_pulse = APP_MCPWM_4_PERIOD - 5; // 6244
volatile uint32_t cap1, cap2, cap3, cap4;
/******** Public Constants *************************************/
/******** Public Variables *************************************/
/******** Public Functions Prototype ***************************/
/******** Local Functions Definition ***************************/
/******** Public Functions Definition **************************/
void HAL_MotorControl_PulseGenerate_Callback_UpMode()
{
cap1 = DL_ECAP_getEventTimeStamp(APP_ECAP0_INST, DL_ECAP_EVENT_1);
cap2 = DL_ECAP_getEventTimeStamp(APP_ECAP0_INST, DL_ECAP_EVENT_2);
cap3 = DL_ECAP_getEventTimeStamp(APP_ECAP0_INST, DL_ECAP_EVENT_3);
cap4 = DL_ECAP_getEventTimeStamp(APP_ECAP0_INST, DL_ECAP_EVENT_4);
DL_MCPWM_setCounterCompareShadowValue(APP_MCPWM_4_INST, DL_MCPWM_COUNTER_COMPARE_1A, tick_high_pulse);
DL_MCPWM_setCounterCompareShadowValue(APP_MCPWM_4_INST, DL_MCPWM_COUNTER_COMPARE_1B, tick_low_pulse);
}
int main()
{
Device_Init();
SYSCFG_DL_init();
/* Enable ECAP timestamp capture */
DL_ECAP_startCounter(APP_ECAP0_INST);
DL_ECAP_enableTimeStampCapture(APP_ECAP0_INST);
DL_MCPWM_enableTBCLK();
LOG("Entering While Loop \r\n");
while (1)
{
}
return 0;
}
/*********************************************************************************************
************************ INTERRUPT HANDLERS **************************************************
*********************************************************************************************/
extern "C" void APP_MCPWM_4_INT_Handler()
{
// BSP_AM13E230_E2::Debug3Pin_High();
HAL_MotorControl_PulseGenerate_Callback_UpMode();
DL_MCPWM_clearInterrupt(APP_MCPWM_4_INST, DL_MCPWM_INT_ET_1);
DL_MCPWM_clearGlobalInterrupt(APP_MCPWM_4_INST);
// BSP_AM13E230_E2::Debug3Pin_Low();
}
extern "C" void APP_ECAP0_INT_Handler()
{
BSP_AM13E230_E2::Debug3Pin_Toggle();
DL_ECAP_clearInterrupt(APP_ECAP0_INST, DL_ECAP_ISR_SOURCE_CEVT1 | DL_ECAP_ISR_SOURCE_CEVT2 |
DL_ECAP_ISR_SOURCE_CEVT3 | DL_ECAP_ISR_SOURCE_CEVT4 |
DL_ECAP_ISR_SOURCE_CTROVF);
DL_ECAP_clearGlobalInterrupt(APP_ECAP0_INST);
}
Hello Dheeraj,
Thank you for the detailed description and excellent debug data with the logic analyzer captures and watch window screenshots. I can see the issue you're experiencing with the ECAP capture counts.
Based on your observations, this is related to ECAP synchronization timing. When your PWM pulse width approaches the full period (as shown in your second screenshot with tick_low_pulse: 6245), the following sequence occurs:
cap2 shows a very small value (~6 counts) instead of the expected valueFrom your logic analyzer, the PWM1A duty cycle is 96.72%, leaving only a very narrow low pulse. The MCPWM SyncOut appears to be generated at the end of the PWM period, which causes the ECAP counter to reset prematurely when the pulse width is near the period boundary.
Since you're measuring PWM pulse widths and don't appear to need synchronized capture across multiple ECAP modules, I recommend disabling ECAP's SYNCIN:
int main()
{
Device_Init();
SYSCFG_DL_init();
// Disable ECAP synchronization input
DL_ECAP_disableSyncIn(APP_ECAP0_INST);
/* Enable ECAP timestamp capture */
DL_ECAP_startCounter(APP_ECAP0_INST);
DL_ECAP_enableTimeStampCapture(APP_ECAP0_INST);
DL_MCPWM_enableTBCLK();
LOG("Entering While Loop \r\n");
while (1)
{
}
return 0;
}After implementing this change, please test with extreme duty cycles:
tick_low_pulse = APP_MCPWM_4_PERIOD - 1tick_low_pulse = 1You should now see consistent and accurate capture values in cap2 regardless of pulse width.
If you need to maintain ECAP synchronization for your application:
Configure MCPWM SyncOut timing - Change the SyncOut generation point to CTR=ZERO (beginning of period) instead of CTR=PRD (end of period) in your TBCTL register configuration
Set ECAP Phase Register - Ensure the counter phase is set to 0 with DL_ECAP_setCounterPhaseValue(APP_ECAP0_INST, 0)
Please try the recommended solution and let me know if the issue persists or if you have any questions.
Best Regards,
Zackary Fleenor
Hi Zackary Fleenor
this code is stripped down version of my application. In actual application, we need the synchronization of Counters of MCPWM and eCAP Modules.
I am generating the SyncOut pulse when time base counter is becoming zero. I will upload the sysconfig screenshots here





Here is some more information for explaining behaviour.
| Cap1 | Cap2 | Commanded Tick high pulse |
Commanded Tick Low Pulse |
| 212 | 6214 | 200 |
6200 |
| 212 | 6218 | 200 | 6205 |
| 212-214 | 6222-6224 | 200 | 6210 |
| 212-214 | 6226-6228 | 200 | 6215 |
| 212-214 | 6232-6234 | 200 | 6220 |
| 212-214 | 6236-6238 | 200 | 6225 |
| 212-214 | 6242-6244 | 200 | 6230 |
| 212-214 | 6246-6248 | 200 | 6235 |
| 212-214 | 2-4 | 200 | 6240 |
| 212-214 | 6-8 | 200 | 6245 |
I do see a constant Offset in readings (an overflow also near the boundary conditions)
Above data is captured again with optimisation changes and shifting relevant code into RAM
Hello Dheeraj,
Thank you for the additional data and SysConfig screenshots. Looking at your table more carefully, there are actually two separate issues present: a constant capture offset and a boundary overflow condition. I want to address each one individually.
Issue 1: Constant Capture Offset
Your data shows a consistent offset on both Cap1 and Cap2 regardless of duty cycle:
Expected Cap1 = tick_high_pulse + fixed_offset
212 = 200 + 12 (consistent across all rows)
This offset is a fixed pipeline and routing delay composed of three contributors:
1. INPUTXBAR signal routing latency from PWM1A to the ECAP input
2. SyncIn-to-counter-load pipeline delay internal to the ECAP hardware
3. ECAP event detection pipeline, typically 2 to 3 clock cycles
Because the offset is constant and independent of duty cycle, this is not a configuration error. At your 200 MHz clock, 12 to 14 counts corresponds to approximately 60 to 70 ns, which is consistent with the expected INPUTXBAR routing latency on this device.
Issue 2: Boundary Overflow Near Full Period
Your data shows Cap2 wrapping to a small value when tick_low_pulse approaches the PWM period. The following timing reconstruction explains why this occurs.
With tick_low_pulse = 6240 and the routing delay of 12 counts:
TBCTR = 0 : SyncOut fires, ECAP counter resets
ECAP_CTR = 12 : PWM1A goes high, Cap1 captured (~212)
ECAP_CTR = 212 : PWM1A goes low, Cap2 should be ~6452
ECAP_CTR = 6237 : TBCTR reaches 6249 (PRD), rolls to 0, new SyncOut fires
ECAP counter resets before the falling edge is captured
Cap2 captured : 2 to 4 counts (the remaining low pulse after reset)
The overflow threshold can be verified directly:
tick_high_pulse + routing_delay + tick_low_pulse > PWM_PERIOD
200 + 12 + 6240 = 6452 > 6249 -- overflow confirmed
Recommended Solution
Since synchronization is required in your application, I recommend the following combined approach.
Step 1: Set the ECAP Phase Register to compensate for routing delay
This causes the ECAP counter to start at the measured offset value when the SyncIn arrives, aligning it with the actual PWM counter state and eliminating the Cap1 offset.
DL_ECAP_setCounterPhaseValue(APP_ECAP0_INST, 12U);
The value 12 should match your measured Cap1 offset. If that offset varies slightly across builds or devices, measure it once at startup and store it as a calibration constant.
Step 2: Add boundary detection and wrap correction in the ISR
When the ECAP counter is reset by SyncIn between Event 1 and Event 2, Cap2 will be smaller than Cap1. Detect this condition and reconstruct the correct low pulse width using the known period.
void APP_ECAP0_INT_Handler(void)
{
uint32_t cap1 = DL_ECAP_getCaptureData(APP_ECAP0_INST, DL_ECAP_INPUT_CHAN_1);
uint32_t cap2 = DL_ECAP_getCaptureData(APP_ECAP0_INST, DL_ECAP_INPUT_CHAN_2);
uint32_t high_ticks;
uint32_t low_ticks;
if (cap2 < cap1)
{
/* SyncIn reset the counter between Event 1 and Event 2.
Reconstruct the full low pulse from the two partial segments. */
low_ticks = (APP_MCPWM_4_PERIOD - cap1) + cap2;
}
else
{
low_ticks = cap2 - cap1;
}
high_ticks = cap1;
}
Step 3: Apply software offset subtraction if residual error remains
If a small residual offset persists after setting the phase register, subtract the calibrated offset values directly:
#define ECAP_CAP1_OFFSET 12U high_ticks = (high_ticks >= ECAP_CAP1_OFFSET) ? high_ticks - ECAP_CAP1_OFFSET : 0U;
Summary
|
Issue
|
Root Cause
|
Resolution
|
|---|---|---|
|
Cap1 offset (~12 counts)
|
INPUTXBAR routing and ECAP pipeline delay
|
Set phase register to measured offset value
|
|
Cap2 offset (~14 counts)
|
Same as Cap1 plus one additional capture pipeline stage
|
Software offset subtraction after phase correction
|
|
Cap2 overflow near period boundary
|
SyncIn resets counter before falling edge is captured
|
Boundary detection with period-wrap reconstruction in ISR
|
Please try these changes and let me know if the behavior improves or if any questions come up.
Best Regards,
Zackary Fleenor