Ok, an update on my progress on this undocumented feature set:
So I think I have figured out what chains and triggers are: basically, you can setup up to 8 "triggerGroups". Each of these triggerGroups need to be XBARA connected to a trigger and you can control the order in which these triggerGroups go by modifying their priorities. Within each triggerGroup, you can set up a chain of up to 8 ADC reads. Each of these chains links can have an interrupt or you can just set up an interrupt on the last link in the chain and read all the ADC values at that point. The only real limitation is that you only have 3 interrupts for the entire ADC_ETC. Below is most of my code that was used to set up 2 trigger groups with chains of 4 and 2 ADC reads. Ignore all the stuff with QS or QK; those are RTOS functions for QPC.
#define DEMO_ADC_BASE ADC1
#define DEMO_ADC_CHANNEL_GROUP0 0U
#define DEMO_ADC_CHANNEL_GROUP1 1U
#define DEMO_ADC_CHANNEL_GROUP2 2U
#define DEMO_ADC_CHANNEL_GROUP3 3U
#define DEMO_ADC_ETC_CHANNEL0 15U
#define DEMO_ADC_ETC_CHANNEL1 0U
#define DEMO_ADC_ETC_CHANNEL2 5U
#define DEMO_ADC_ETC_CHANNEL3 6U
#define ADC_NUM_READS 6
#define DEMO_ADC_ETC_CHANNEL4 7U
#define DEMO_ADC_ETC_CHANNEL5 8U
#define DEMO_ADC_ETC_BASE ADC_ETC
#define ADC_ETC_TRIG_GRP0_CHAIN_LENGTH 3U
#define ADC_ETC_TRIG_GRP1_CHAIN_LENGTH 1U
void BSP_init( void )
{
BOARD_BootClockRUN();
CLOCK_EnableClock(kCLOCK_Iomuxc);
if (QS_INIT((void *)0) == 0) {
Q_ERROR();
}
QS_OBJ_DICTIONARY(&l_SysTick_Handler);
QS_USR_DICTIONARY(PHILO_STAT);
QS_USR_DICTIONARY(COMMAND_STAT);
IOMUXC_SetPinMux(
IOMUXC_GPIO_AD_B1_10_GPIO1_IO26,
0U
);
IOMUXC_SetPinConfig(
IOMUXC_GPIO_AD_B1_10_GPIO1_IO26,
IOMUXC_SW_PAD_CTL_PAD_SRE(GPIO_SlowSlewRate) |
IOMUXC_SW_PAD_CTL_PAD_DSE(GPIO_R0DivBy6) |
IOMUXC_SW_PAD_CTL_PAD_SPEED(GPIO_SpeedMed) |
IOMUXC_SW_PAD_CTL_PAD_ODE(0) |
IOMUXC_SW_PAD_CTL_PAD_PKE(0) |
IOMUXC_SW_PAD_CTL_PAD_PUE(0) |
IOMUXC_SW_PAD_CTL_PAD_PUS(GPIO_PullDown100Kohm) |
IOMUXC_SW_PAD_CTL_PAD_HYS(0)
);
IOMUXC_SetPinMux(
IOMUXC_GPIO_AD_B1_11_GPIO1_IO27,
0U
);
IOMUXC_SetPinConfig(
IOMUXC_GPIO_AD_B1_11_GPIO1_IO27,
IOMUXC_SW_PAD_CTL_PAD_SRE(GPIO_SlowSlewRate) |
IOMUXC_SW_PAD_CTL_PAD_DSE(GPIO_R0DivBy6) |
IOMUXC_SW_PAD_CTL_PAD_SPEED(GPIO_SpeedMed) |
IOMUXC_SW_PAD_CTL_PAD_ODE(0) |
IOMUXC_SW_PAD_CTL_PAD_PKE(0) |
IOMUXC_SW_PAD_CTL_PAD_PUE(0) |
IOMUXC_SW_PAD_CTL_PAD_PUS(GPIO_PullDown100Kohm) |
IOMUXC_SW_PAD_CTL_PAD_HYS(0)
);
IOMUXC_SetPinMux(
IOMUXC_GPIO_AD_B1_00_GPIO1_IO16,
0U
);
IOMUXC_SetPinConfig(
IOMUXC_GPIO_AD_B1_00_GPIO1_IO16,
IOMUXC_SW_PAD_CTL_PAD_SRE(GPIO_SlowSlewRate) |
IOMUXC_SW_PAD_CTL_PAD_DSE(GPIO_R0DivBy6) |
IOMUXC_SW_PAD_CTL_PAD_SPEED(GPIO_SpeedMed) |
IOMUXC_SW_PAD_CTL_PAD_ODE(0) |
IOMUXC_SW_PAD_CTL_PAD_PKE(0) |
IOMUXC_SW_PAD_CTL_PAD_PUE(0) |
IOMUXC_SW_PAD_CTL_PAD_PUS(GPIO_PullDown100Kohm) |
IOMUXC_SW_PAD_CTL_PAD_HYS(0)
);
IOMUXC_SetPinMux(
IOMUXC_GPIO_AD_B1_01_GPIO1_IO17,
0U
);
IOMUXC_SetPinConfig(
IOMUXC_GPIO_AD_B1_01_GPIO1_IO17,
IOMUXC_SW_PAD_CTL_PAD_SRE(GPIO_SlowSlewRate) |
IOMUXC_SW_PAD_CTL_PAD_DSE(GPIO_R0DivBy6) |
IOMUXC_SW_PAD_CTL_PAD_SPEED(GPIO_SpeedMed) |
IOMUXC_SW_PAD_CTL_PAD_ODE(0) |
IOMUXC_SW_PAD_CTL_PAD_PKE(0) |
IOMUXC_SW_PAD_CTL_PAD_PUE(0) |
IOMUXC_SW_PAD_CTL_PAD_PUS(GPIO_PullDown100Kohm) |
IOMUXC_SW_PAD_CTL_PAD_HYS(0)
);
IOMUXC_SetPinMux(
IOMUXC_GPIO_AD_B1_02_GPIO1_IO18,
0U
);
IOMUXC_SetPinConfig(
IOMUXC_GPIO_AD_B1_02_GPIO1_IO18,
IOMUXC_SW_PAD_CTL_PAD_SRE(GPIO_SlowSlewRate) |
IOMUXC_SW_PAD_CTL_PAD_DSE(GPIO_R0DivBy6) |
IOMUXC_SW_PAD_CTL_PAD_SPEED(GPIO_SpeedMed) |
IOMUXC_SW_PAD_CTL_PAD_ODE(0) |
IOMUXC_SW_PAD_CTL_PAD_PKE(0) |
IOMUXC_SW_PAD_CTL_PAD_PUE(0) |
IOMUXC_SW_PAD_CTL_PAD_PUS(GPIO_PullDown100Kohm) |
IOMUXC_SW_PAD_CTL_PAD_HYS(0)
);
IOMUXC_SetPinMux(
IOMUXC_GPIO_AD_B1_03_GPIO1_IO19,
0U
);
IOMUXC_SetPinConfig(
IOMUXC_GPIO_AD_B1_03_GPIO1_IO19,
IOMUXC_SW_PAD_CTL_PAD_SRE(GPIO_SlowSlewRate) |
IOMUXC_SW_PAD_CTL_PAD_DSE(GPIO_R0DivBy6) |
IOMUXC_SW_PAD_CTL_PAD_SPEED(GPIO_SpeedMed) |
IOMUXC_SW_PAD_CTL_PAD_ODE(0) |
IOMUXC_SW_PAD_CTL_PAD_PKE(0) |
IOMUXC_SW_PAD_CTL_PAD_PUE(0) |
IOMUXC_SW_PAD_CTL_PAD_PUS(GPIO_PullDown100Kohm) |
IOMUXC_SW_PAD_CTL_PAD_HYS(0)
);
CLOCK_SetMux(kCLOCK_PerclkMux, 1U);
CLOCK_SetDiv(kCLOCK_PerclkDiv, 0U);
adc_config_t k_adcConfig;
ADC_GetDefaultConfig( &k_adcConfig );
ADC_Init( ADC1, &k_adcConfig);
ADC_EnableHardwareTrigger( ADC1, true);
adc_channel_config_t adcChannelConfigStruct;
adcChannelConfigStruct.channelNumber = 16U;
adcChannelConfigStruct.enableInterruptOnConversionCompleted = false;
ADC_SetChannelConfig(ADC1, 0, &adcChannelConfigStruct);
ADC_SetChannelConfig(ADC1, 1, &adcChannelConfigStruct);
ADC_SetChannelConfig(ADC1, 2, &adcChannelConfigStruct);
ADC_SetChannelConfig(ADC1, 3, &adcChannelConfigStruct);
ADC_SetChannelConfig(ADC1, 4, &adcChannelConfigStruct);
ADC_SetChannelConfig(ADC1, 5, &adcChannelConfigStruct);
if( kStatus_Success == ADC_DoAutoCalibration( ADC1 ) ) {
QS_BEGIN(HAT_DBG, 0) QS_STR("ADC Cal Done"); QS_END()
} else {
QS_BEGIN(HAT_ERR, 0) QS_STR("ADC Cal Failed"); QS_END()
}
XBARA_Init(XBARA1);
XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputPitTrigger0, kXBARA1_OutputAdcEtcXbar0Trig0);
XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputPitTrigger0, kXBARA1_OutputAdcEtcXbar0Trig1);
pit_config_t pitConfig;
PIT_GetDefaultConfig(&pitConfig);
PIT_Init(PIT, &pitConfig);
PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, USEC_TO_COUNT(1000000U, CLOCK_GetFreq(kCLOCK_OscClk)));
adc_etc_config_t adcEtcConfig;
ADC_ETC_GetDefaultConfig(&adcEtcConfig);
adcEtcConfig.XBARtriggerMask = 3U;
ADC_ETC_Init(ADC_ETC, &adcEtcConfig);
adc_etc_trigger_config_t adcEtcTriggerConfig;
adcEtcTriggerConfig.enableSyncMode = false;
adcEtcTriggerConfig.enableSWTriggerMode = false;
adcEtcTriggerConfig.triggerChainLength = ADC_ETC_TRIG_GRP0_CHAIN_LENGTH;
adcEtcTriggerConfig.triggerPriority = 1U;
adcEtcTriggerConfig.sampleIntervalDelay = 0U;
adcEtcTriggerConfig.initialDelay = 0U;
ADC_ETC_SetTriggerConfig(ADC_ETC, 0U, &adcEtcTriggerConfig);
adcEtcTriggerConfig.triggerChainLength = ADC_ETC_TRIG_GRP1_CHAIN_LENGTH;
adcEtcTriggerConfig.triggerPriority = 0U;
ADC_ETC_SetTriggerConfig(ADC_ETC, 1U, &adcEtcTriggerConfig);
adc_etc_trigger_chain_config_t adcEtcTriggerChainConfig;
adcEtcTriggerChainConfig.enableB2BMode = true;
adcEtcTriggerChainConfig.ADCHCRegisterSelect = 1U << DEMO_ADC_CHANNEL_GROUP0;
adcEtcTriggerChainConfig.ADCChannelSelect = DEMO_ADC_ETC_CHANNEL0;
adcEtcTriggerChainConfig.InterruptEnable = kADC_ETC_InterruptDisable;
ADC_ETC_SetTriggerChainConfig(ADC_ETC, 0U, DEMO_ADC_CHANNEL_GROUP0, &adcEtcTriggerChainConfig);
adcEtcTriggerChainConfig.ADCHCRegisterSelect = 1U << DEMO_ADC_CHANNEL_GROUP1;
adcEtcTriggerChainConfig.ADCChannelSelect = DEMO_ADC_ETC_CHANNEL1;
adcEtcTriggerChainConfig.InterruptEnable = kADC_ETC_InterruptDisable;
ADC_ETC_SetTriggerChainConfig(ADC_ETC, 0U, DEMO_ADC_CHANNEL_GROUP1, &adcEtcTriggerChainConfig);
adcEtcTriggerChainConfig.ADCHCRegisterSelect = 1U << DEMO_ADC_CHANNEL_GROUP2;
adcEtcTriggerChainConfig.ADCChannelSelect = DEMO_ADC_ETC_CHANNEL2;
adcEtcTriggerChainConfig.InterruptEnable = kADC_ETC_InterruptDisable;
ADC_ETC_SetTriggerChainConfig(ADC_ETC, 0U, DEMO_ADC_CHANNEL_GROUP2, &adcEtcTriggerChainConfig);
adcEtcTriggerChainConfig.ADCHCRegisterSelect = 1U << DEMO_ADC_CHANNEL_GROUP3;
adcEtcTriggerChainConfig.ADCChannelSelect = DEMO_ADC_ETC_CHANNEL3;
adcEtcTriggerChainConfig.InterruptEnable = kADC_ETC_InterruptDisable;
ADC_ETC_SetTriggerChainConfig(ADC_ETC, 0U, DEMO_ADC_CHANNEL_GROUP3, &adcEtcTriggerChainConfig);
adcEtcTriggerChainConfig.ADCHCRegisterSelect = 1U << DEMO_ADC_CHANNEL_GROUP0;
adcEtcTriggerChainConfig.ADCChannelSelect = DEMO_ADC_ETC_CHANNEL4;
adcEtcTriggerChainConfig.InterruptEnable = kADC_ETC_InterruptDisable;
ADC_ETC_SetTriggerChainConfig(ADC_ETC, 1U, DEMO_ADC_CHANNEL_GROUP0, &adcEtcTriggerChainConfig);
adcEtcTriggerChainConfig.ADCHCRegisterSelect = 1U << DEMO_ADC_CHANNEL_GROUP1;
adcEtcTriggerChainConfig.ADCChannelSelect = DEMO_ADC_ETC_CHANNEL5;
adcEtcTriggerChainConfig.InterruptEnable = kADC_ETC_Done1InterruptEnable;
ADC_ETC_SetTriggerChainConfig(ADC_ETC, 1U, DEMO_ADC_CHANNEL_GROUP1, &adcEtcTriggerChainConfig);
EnableIRQ(ADC_ETC_IRQ0_IRQn);
EnableIRQ(ADC_ETC_IRQ1_IRQn);
EnableIRQ(ADC_ETC_IRQ2_IRQn);
EnableIRQ(ADC_ETC_ERROR_IRQ_IRQn);
PIT_StartTimer(PIT, kPIT_Chnl_0);
}
void BSP_AdcEtcIrq1Handler( void )
{
QK_ISR_ENTRY();
volatile uint32_t intFlags0 = ADC_ETC_GetInterruptStatusFlags( DEMO_ADC_ETC_BASE, kADC_ETC_Trg0TriggerSource);
if( intFlags0 & kADC_ETC_Done1StatusFlagMask ) {
ADC_ETC_ClearInterruptStatusFlags( DEMO_ADC_ETC_BASE,
kADC_ETC_Trg0TriggerSource, kADC_ETC_Done1StatusFlagMask );
}
volatile uint32_t intFlags1 = ADC_ETC_GetInterruptStatusFlags( DEMO_ADC_ETC_BASE, kADC_ETC_Trg1TriggerSource);
if( intFlags1 & kADC_ETC_Done1StatusFlagMask ) {
ADC_ETC_ClearInterruptStatusFlags( DEMO_ADC_ETC_BASE,
kADC_ETC_Trg1TriggerSource, kADC_ETC_Done1StatusFlagMask );
}
volatile uint32_t adcValues[ADC_NUM_READS] = {0};
adcValues[0] = ADC_ETC_GetADCConversionValue(
DEMO_ADC_ETC_BASE, 0U, 0U );
adcValues[1] = ADC_ETC_GetADCConversionValue(
DEMO_ADC_ETC_BASE, 0U, 1U );
adcValues[2] = ADC_ETC_GetADCConversionValue(
DEMO_ADC_ETC_BASE, 0U, 2U );
adcValues[3] = ADC_ETC_GetADCConversionValue(
DEMO_ADC_ETC_BASE, 0U, 3U );
adcValues[4] = ADC_ETC_GetADCConversionValue(
DEMO_ADC_ETC_BASE, 1U, 0U );
adcValues[5] = ADC_ETC_GetADCConversionValue(
DEMO_ADC_ETC_BASE, 1U, 1U );
QS_BEGIN(HAT_DBG, 0)
for( uint16_t i = 0; i < ADC_NUM_READS; i++ ) {
QS_STR("ADC"); QS_U32( 1, i); QS_U32( 4, adcValues[i]);
}
QS_END()
QK_ISR_EXIT();
}