Trigger DSD Integrator from CCU8

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
User12130
Level 1
Level 1
Hi All,

im trying to implement a dsd sampling in sync with the pwm of several already synced ccu8 slices.

The ccu8 slice 0 generates an event for period match and upcounting 1 which i use to triggern an interrupt.
The dsd is configured with additional integrator with 1 blanking sample and as a start 2 integration samples. If i set it to trigger allways every thing works as expected.

What i do not get from the dsd app note and the rm is how to route the CCU8 interrupt event to the dsd integrators trigger input. Does any one have an XMC Lib example for this?

I tryed to use CCU80 ST0 status routed by the ERU to the dsd integrator but i seem to miss something. Please see the code below.

pwm init code:

const XMC_SCU_CLOCK_CONFIG_t clock_config =
{
.syspll_config.n_div = 80U,
.syspll_config.p_div = 2U,
.syspll_config.k_div = 4U,
.syspll_config.mode = XMC_SCU_CLOCK_SYSPLL_MODE_NORMAL,
.syspll_config.clksrc = XMC_SCU_CLOCK_SYSPLLCLKSRC_OSCHP,
.enable_oschp = true,
.enable_osculp = false,
.calibration_mode = XMC_SCU_CLOCK_FOFI_CALIBRATION_MODE_FACTORY,
.fstdby_clksrc = XMC_SCU_HIB_STDBYCLKSRC_OSI,
.fsys_clksrc = XMC_SCU_CLOCK_SYSCLKSRC_PLL,
.fsys_clkdiv = 1U,
.fcpu_clkdiv = 1U,
.fccu_clkdiv = 1U,
.fperipheral_clkdiv = 1U
};

const XMC_CCU8_SLICE_COMPARE_CONFIG_t slice_config =
{
.timer_mode = (uint32_t)XMC_CCU8_SLICE_TIMER_COUNT_MODE_CA,
.monoshot = (uint32_t)XMC_CCU8_SLICE_TIMER_REPEAT_MODE_REPEAT,
.shadow_xfer_clear = 0U,
.dither_timer_period = 0U,
.dither_duty_cycle = 0U,
.prescaler_mode = (uint32_t)XMC_CCU8_SLICE_PRESCALER_MODE_NORMAL,
.mcm_ch1_enable = 0U,
.mcm_ch2_enable = 0U,
.slice_status = (uint32_t)XMC_CCU8_SLICE_STATUS_CHANNEL_1,
.passive_level_out0 = (uint32_t)XMC_CCU8_SLICE_OUTPUT_PASSIVE_LEVEL_LOW,
.passive_level_out1 = (uint32_t)XMC_CCU8_SLICE_OUTPUT_PASSIVE_LEVEL_LOW,
.passive_level_out2 = (uint32_t)XMC_CCU8_SLICE_OUTPUT_PASSIVE_LEVEL_LOW,
.passive_level_out3 = (uint32_t)XMC_CCU8_SLICE_OUTPUT_PASSIVE_LEVEL_LOW,
.asymmetric_pwm = 0U,
.invert_out0 = 0U,
.invert_out1 = 1U,
.invert_out2 = 0U,
.invert_out3 = 1U,
.prescaler_initval = 0U,
.float_limit = 0U,
.dither_limit = 0U,
.timer_concatenation = 0U,
};

const XMC_CCU8_SLICE_EVENT_CONFIG_t slice_event0_config =
{
.mapped_input = XMC_CCU8_SLICE_INPUT_H, //Connected to SCU.GSC80
.edge = XMC_CCU8_SLICE_EVENT_EDGE_SENSITIVITY_RISING_EDGE,
.level = XMC_CCU8_SLICE_EVENT_LEVEL_SENSITIVITY_ACTIVE_LOW,
.duration = XMC_CCU8_SLICE_EVENT_FILTER_DISABLED,
};

void initialize(void)
{
XMC_GPIO_CONFIG_t config;

/* Ensure clock frequency is set at 120 MHz */
XMC_SCU_CLOCK_Init(&clock_config);

/* Enable CCU8 module */
XMC_CCU8_Init(CCU80, XMC_CCU8_SLICE_MCMS_ACTION_TRANSFER_PR_CR);

/* Start the prescaler */
XMC_CCU8_StartPrescaler(CCU80);

/* Ensure fCCU reaches CCU80 */
XMC_CCU8_SetModuleClock(CCU80, XMC_CCU8_CLOCK_SCU);

/* Configure CCU8x_CC8y slice as timer */
XMC_CCU8_SLICE_CompareInit(CCU80_CC80, &slice_config);
XMC_CCU8_SLICE_CompareInit(CCU80_CC82, &slice_config);
XMC_CCU8_SLICE_CompareInit(CCU80_CC83, &slice_config);

/* Set period match value of the timer */
XMC_CCU8_SLICE_SetTimerPeriodMatch(CCU80_CC80, 1249U);
XMC_CCU8_SLICE_SetTimerPeriodMatch(CCU80_CC82, 1249U);
XMC_CCU8_SLICE_SetTimerPeriodMatch(CCU80_CC83, 1249U);

/* Set timer compare match valuew for channel 1 Duty Cycle */
XMC_CCU8_SLICE_SetTimerCompareMatch(CCU80_CC80,XMC_CCU8_SLICE_COMPARE_CHANNEL_1, 750U);
XMC_CCU8_SLICE_SetTimerCompareMatch(CCU80_CC82,XMC_CCU8_SLICE_COMPARE_CHANNEL_1, 750U);
XMC_CCU8_SLICE_SetTimerCompareMatch(CCU80_CC83,XMC_CCU8_SLICE_COMPARE_CHANNEL_1, 750U);

/* Transfer value from shadow timer registers to actual timer registers */
XMC_CCU8_EnableShadowTransfer(CCU80, XMC_CCU8_SHADOW_TRANSFER_SLICE_0);
XMC_CCU8_EnableShadowTransfer(CCU80, XMC_CCU8_SHADOW_TRANSFER_SLICE_2);
XMC_CCU8_EnableShadowTransfer(CCU80, XMC_CCU8_SHADOW_TRANSFER_SLICE_3);

/* Configure events */
XMC_CCU8_SLICE_ConfigureEvent(CCU80_CC80, XMC_CCU8_SLICE_EVENT_0, &slice_event0_config);
XMC_CCU8_SLICE_ConfigureEvent(CCU80_CC82, XMC_CCU8_SLICE_EVENT_0, &slice_event0_config);
XMC_CCU8_SLICE_ConfigureEvent(CCU80_CC83, XMC_CCU8_SLICE_EVENT_0, &slice_event0_config);

XMC_CCU8_SLICE_StartConfig(CCU80_CC80, XMC_CCU8_SLICE_EVENT_0, XMC_CCU8_SLICE_START_MODE_TIMER_START_CLEAR);
XMC_CCU8_SLICE_StartConfig(CCU80_CC82, XMC_CCU8_SLICE_EVENT_0, XMC_CCU8_SLICE_START_MODE_TIMER_START_CLEAR);
XMC_CCU8_SLICE_StartConfig(CCU80_CC83, XMC_CCU8_SLICE_EVENT_0, XMC_CCU8_SLICE_START_MODE_TIMER_START_CLEAR);

/* Enable events */
XMC_CCU8_SLICE_EnableEvent(CCU80_CC80, XMC_CCU8_SLICE_IRQ_ID_PERIOD_MATCH);
XMC_CCU8_SLICE_EnableEvent(CCU80_CC80, XMC_CCU8_SLICE_IRQ_ID_ONE_MATCH);

/* Connect period match and one match event to SR0 */
XMC_CCU8_SLICE_SetInterruptNode(CCU80_CC80, XMC_CCU8_SLICE_IRQ_ID_PERIOD_MATCH, XMC_CCU8_SLICE_SR_ID_0);
XMC_CCU8_SLICE_SetInterruptNode(CCU80_CC80, XMC_CCU8_SLICE_IRQ_ID_ONE_MATCH, XMC_CCU8_SLICE_SR_ID_0);
/* Set NVIC priority */
NVIC_SetPriority(CCU80_0_IRQn, 63U);
/* Enable IRQ */
NVIC_EnableIRQ(CCU80_0_IRQn);

/* Get the slice out of idle mode */
XMC_CCU8_EnableClock(CCU80, 0U);
XMC_CCU8_EnableClock(CCU80, 2U);
XMC_CCU8_EnableClock(CCU80, 3U);

/* Start the PWM on a rising edge on SCU.GSC80 */
XMC_SCU_SetCcuTriggerHigh(XMC_SCU_CCU_TRIGGER_CCU80);


dsd init code:

const XMC_DSD_CH_FILTER_CONFIG_t filter_config0 = {
.clock_divider = XMC_DSD_CH_CLK_DIV_2,
.clock_source = XMC_DSD_CH_CLOCK_SOURCE_A,
.data_source = XMC_DSD_CH_DATA_SOURCE_A_DIRECT,
.decimation_factor = 32U,
.filter_start_value = 32U,
.filter_type = XMC_DSD_CH_FILTER_TYPE_CIC3,
.offset = 0U,
.result_event = XMC_DSD_CH_RESULT_EVENT_DISABLE,
.strobe = XMC_DSD_CH_STROBE_DIRECT_CLOCK_RISE,
};

const XMC_DSD_CH_FILTER_CONFIG_t filter_config1 = {
.clock_divider = XMC_DSD_CH_CLK_DIV_2,
.clock_source = XMC_DSD_CH_CLOCK_SOURCE_B,
.data_source = XMC_DSD_CH_DATA_SOURCE_B_DIRECT,
.decimation_factor = 32U,
.filter_start_value = 32U,
.filter_type = XMC_DSD_CH_FILTER_TYPE_CIC3,
.offset = 0U,
.result_event = XMC_DSD_CH_RESULT_EVENT_DISABLE,
.strobe = XMC_DSD_CH_STROBE_DIRECT_CLOCK_RISE,
};

const XMC_DSD_CH_FILTER_CONFIG_t filter_config2 = {
.clock_divider = XMC_DSD_CH_CLK_DIV_2,
.clock_source = XMC_DSD_CH_CLOCK_SOURCE_A,
.data_source = XMC_DSD_CH_DATA_SOURCE_A_DIRECT,
.decimation_factor = 32U,
.filter_start_value = 32U,
.filter_type = XMC_DSD_CH_FILTER_TYPE_CIC3,
.offset = 0U,
.result_event = XMC_DSD_CH_RESULT_EVENT_DISABLE,
.strobe = XMC_DSD_CH_STROBE_DIRECT_CLOCK_RISE,
};

const XMC_DSD_CH_INTEGRATOR_CONFIG_t integrator_config = {
.counted_values = 2,
.discarded_values = 1,
.integration_loop = 1,
.integrator_trigger = XMC_DSD_CH_TRIGGER_SOURCE_B,
.start_condition = XMC_DSD_CH_INTEGRATOR_START_TRIGGER_RISE,
.stop_condition = XMC_DSD_CH_INTEGRATOR_STOP_END_OF_LOOPS,
};



XMC_ERU_ETL_CONFIG_t pwm_event_generator =
{
.input = ERU1_ETL0_INPUTB_CCU80_ST0,
.source = XMC_ERU_ETL_SOURCE_B,
.edge_detection = XMC_ERU_ETL_EDGE_DETECTION_RISING,
.status_flag_mode = XMC_ERU_ETL_STATUS_FLAG_MODE_HWCTRL,
.enable_output_trigger = true,
.output_trigger_channel = XMC_ERU_ETL_OUTPUT_TRIGGER_CHANNEL1
};

void initialize(void)
{
XMC_DSD_Enable(DSD);
XMC_DSD_EnableClock(DSD);

XMC_DSD_CH_MainFilter_Init(DSD_CH0, &filter_config0);
XMC_DSD_CH_MainFilter_Init(DSD_CH1, &filter_config1);
XMC_DSD_CH_MainFilter_Init(DSD_CH2, &filter_config2);

XMC_DSD_CH_Integrator_Init(DSD_CH0, &integrator_config);
XMC_DSD_CH_Integrator_Init(DSD_CH1, &integrator_config);
XMC_DSD_CH_Integrator_Init(DSD_CH2, &integrator_config);

XMC_ERU_ETL_Init(ERU0_ETL1, &pwm_event_generator);


XMC_DSD_Start(DSD, XMC_DSD_CH_ID_0 | XMC_DSD_CH_ID_1 | XMC_DSD_CH_ID_2);

}


regards

Alex
0 Likes
1 Reply
User12130
Level 1
Level 1
In the DSD app note section 6.2 Use case: Periodic measurement with fixed window exactly describes what i want to achieve but the sample code is missing in the app note, Does any one know where this code can be found?
0 Likes