Hello,
I am currently using module of ADC triggering by FTM and PDB,
However,After a period of time, this module will trigger PDB error, which will cause the ADC interrupt to trigger abnormally, and normal sampling cannot be performed.
In addition, The same problem also appears in ADC with PDB and back-to-back triggers,The current measure is to reinitialize
What is the root cause of the problem and how to solve it fundamentally
Same question, when I use the FTM0 to trigger the PDB,ADC interrupt can run in just once. However When I use the soft to trigger PDB , it works normally.
void Mx_ADC_Init(void)
{
module_clk_config_t adc_clk_config={
.gating = 1,
.source = SPLL_CLK,//FIRC_CLK
.mul = 0,
.div = 0
};
const adc_converter_config_t ADC_0_ConvConfig0 = {
.clockDivide = ADC_CLK_DIVIDE_1,
.sampleTime = 80U,
.resolution = ADC_RESOLUTION_12BIT,
.inputClock = ADC_CLK_ALT_1,
.trigger = ADC_TRIGGER_HARDWARE,
.pretriggerSel = ADC_PRETRIGGER_SEL_PDB,
.triggerSel = ADC_TRIGGER_SEL_PDB,
.dmaEnable = false,
.voltageRef = ADC_VOLTAGEREF_VREF,
.continuousConvEnable = false,
.supplyMonitoringEnable = false
};
adc_chan_config_t ADC_0_ChnConfig0 = {
.interruptEnable = false,
.channel = ADC_INPUTCHAN_EXT2
};
adc_chan_config_t ADC_1_ChnConfig0 = {
.interruptEnable = false,
.channel = ADC_INPUTCHAN_EXT2
};
pdb_adc_pretrigger_config_t pdb_1_adcTrigConfig0 = {
.adcPreTriggerIdx = 0U,
.preTriggerEnable = true,
.preTriggerOutputEnable = false,
.preTriggerBackToBackEnable = false
};
/*! @brief PDB timer configurations */
pdb_timer_config_t pdb_1_timerConfig0 = {
.loadValueMode = PDB_LOAD_VAL_IMMEDIATELY,
.seqErrIntEnable = false,
.clkPreDiv = PDB_CLK_PREDIV_BY_1,
.clkPreMultFactor = PDB_CLK_PREMULT_FACT_AS_1,
.triggerInput =PDB_TRIGGER_IN0,//PDB_SOFTWARE_TRIGGER
.continuousModeEnable = false,
.dmaEnable = false,
.intEnable = false,
.instanceBackToBackEnable = false,
};
trgmux_user_config_t trgmuxConfig;
trgmux_inout_mapping_config_t trgmuxInoutMappingConfig[] =
{
{TRGMUX_TRIG_SOURCE_FTM0_INIT_TRIG, TRGMUX_TARGET_MODULE_PDB0_TRG_IN, false},
{TRGMUX_TRIG_SOURCE_FTM0_INIT_TRIG, TRGMUX_TARGET_MODULE_PDB1_TRG_IN, false},
};
trgmuxConfig.numInOutMappingConfigs = 2;
trgmuxConfig.inOutMappingConfig = trgmuxInoutMappingConfig;
CLOCK_DRV_SetModuleClock(ADC0_CLK, &adc_clk_config);
CLOCK_DRV_SetModuleClock(ADC1_CLK, &adc_clk_config);
CLOCK_DRV_SetModuleClock(PDB0_CLK, NULL);
CLOCK_DRV_SetModuleClock(PDB1_CLK, NULL);
ADC_DRV_ConfigConverter(0, &ADC_0_ConvConfig0);
ADC_DRV_ConfigConverter(1, &ADC_0_ConvConfig0);
ADC_DRV_AutoCalibration(0);
ADC_DRV_AutoCalibration(1);
ADC_0_ChnConfig0.interruptEnable = true;
ADC_DRV_ConfigChan(0, 0UL, &ADC_0_ChnConfig0);//V current
ADC_0_ChnConfig0.channel = ADC_INPUTCHAN_EXT3;
ADC_0_ChnConfig0.interruptEnable = false;
ADC_DRV_ConfigChan(0, 1UL, &ADC_0_ChnConfig0);
ADC_0_ChnConfig0.channel = ADC_INPUTCHAN_EXT4;
ADC_DRV_ConfigChan(0, 2UL, &ADC_0_ChnConfig0);
ADC_0_ChnConfig0.channel = ADC_INPUTCHAN_EXT5;
ADC_DRV_ConfigChan(0, 3UL, &ADC_0_ChnConfig0);
ADC_0_ChnConfig0.channel = ADC_INPUTCHAN_EXT6;
ADC_DRV_ConfigChan(0, 4UL, &ADC_0_ChnConfig0);
ADC_0_ChnConfig0.channel = ADC_INPUTCHAN_EXT7;
ADC_0_ChnConfig0.interruptEnable = true;
ADC_DRV_ConfigChan(0, 5UL, &ADC_0_ChnConfig0);
ADC_DRV_ConfigChan(1, 0UL, &ADC_1_ChnConfig0);
ADC_1_ChnConfig0.channel = ADC_INPUTCHAN_EXT3;
ADC_DRV_ConfigChan(1, 1UL, &ADC_1_ChnConfig0);
ADC_1_ChnConfig0.channel = ADC_INPUTCHAN_EXT0;
ADC_DRV_ConfigChan(1, 2UL, &ADC_1_ChnConfig0);
ADC_1_ChnConfig0.channel = ADC_INPUTCHAN_EXT1;
ADC_DRV_ConfigChan(1, 3UL, &ADC_1_ChnConfig0);
ADC_1_ChnConfig0.channel = ADC_INPUTCHAN_EXT10;
ADC_DRV_ConfigChan(1, 4UL, &ADC_1_ChnConfig0);
ADC_1_ChnConfig0.channel = ADC_INPUTCHAN_EXT11;
ADC_DRV_ConfigChan(1, 5UL, &ADC_1_ChnConfig0);
PDB_DRV_Init(0, &pdb_1_timerConfig0);
PDB_DRV_Enable(0);
PDB_DRV_ConfigAdcPreTrigger(0, 0UL, &pdb_1_adcTrigConfig0);
pdb_1_adcTrigConfig0.adcPreTriggerIdx = 1;
pdb_1_adcTrigConfig0.preTriggerBackToBackEnable = true;
PDB_DRV_ConfigAdcPreTrigger(0, 0UL, &pdb_1_adcTrigConfig0);
pdb_1_adcTrigConfig0.adcPreTriggerIdx = 2;
PDB_DRV_ConfigAdcPreTrigger(0, 0UL, &pdb_1_adcTrigConfig0);
pdb_1_adcTrigConfig0.adcPreTriggerIdx = 3;
PDB_DRV_ConfigAdcPreTrigger(0, 0UL, &pdb_1_adcTrigConfig0);
pdb_1_adcTrigConfig0.adcPreTriggerIdx = 4;
PDB_DRV_ConfigAdcPreTrigger(0, 0UL, &pdb_1_adcTrigConfig0);
pdb_1_adcTrigConfig0.adcPreTriggerIdx = 5;
PDB_DRV_ConfigAdcPreTrigger(0, 0UL, &pdb_1_adcTrigConfig0);
PDB_DRV_SetTimerModulusValue(0, 80*50);
PDB_DRV_SetAdcPreTriggerDelayValue(0, 0UL, 0UL,
80*1);//1us
PDB_DRV_LoadValuesCmd(0);
PDB_DRV_Init(1, &pdb_1_timerConfig0);
PDB_DRV_Enable(1);
pdb_1_adcTrigConfig0.adcPreTriggerIdx = 0;
pdb_1_adcTrigConfig0.preTriggerBackToBackEnable = false;
PDB_DRV_ConfigAdcPreTrigger(1, 0UL, &pdb_1_adcTrigConfig0);
pdb_1_adcTrigConfig0.adcPreTriggerIdx = 1;
pdb_1_adcTrigConfig0.preTriggerBackToBackEnable = true;
PDB_DRV_ConfigAdcPreTrigger(1, 0UL, &pdb_1_adcTrigConfig0);
pdb_1_adcTrigConfig0.adcPreTriggerIdx = 2;
PDB_DRV_ConfigAdcPreTrigger(1, 0UL, &pdb_1_adcTrigConfig0);
pdb_1_adcTrigConfig0.adcPreTriggerIdx = 3;
PDB_DRV_ConfigAdcPreTrigger(1, 0UL, &pdb_1_adcTrigConfig0);
pdb_1_adcTrigConfig0.adcPreTriggerIdx = 4;
PDB_DRV_ConfigAdcPreTrigger(1, 0UL, &pdb_1_adcTrigConfig0);
pdb_1_adcTrigConfig0.adcPreTriggerIdx = 5;
PDB_DRV_ConfigAdcPreTrigger(1, 0UL, &pdb_1_adcTrigConfig0);
PDB_DRV_SetTimerModulusValue(1, 80*50);
PDB_DRV_SetAdcPreTriggerDelayValue(1, 0UL, 0UL,
80*1);
PDB_DRV_LoadValuesCmd(1);
TRGMUX_DRV_Init(0, &trgmuxConfig);
INT_SYS_InstallHandler(ADC0_IRQn, &ADC_IRQHandler, (isr_t*) 0);
INT_SYS_SetPriority(ADC0_IRQn,1);
INT_SYS_EnableIRQ(ADC0_IRQn);
}
Hi,
most probably this will be due to missing or incorrect read of ADC result register.
Other issue could be input PDB trigger, which comes earlier than all conversions is done.
Try to refer to simple S32DS "S32K144_Project_PDB" example. It configures PDB for continuous mode SW triggered, but you can test if ADC interrupt is correctly entered with configured period.
BR, Petr
hi,
I read all the result registers in the interrupt, and this phenomenon occurred after running for a period of time. After the PDB error is generated, I will also read all the ADC result registers, but the ADC interrupt still cannot be generated normally.
My configuration code is completely derived from Appendix C. Example code: ADC with PDB and back-to-back triggers in Application Note A12217.
My question is why the trigger period of my PDB is earlier than the conversion period? How to circumvent this problem?
Hello Petrs,
The board I use is my own hardware development board and Following is my Code:
/* SW=3, ADC1 initialized to be triggered by FTM3 Init triggers */
void adc1_ftm_trigger_Init()
{
PCC->PCCn[PCC_ADC1_INDEX] = 0; // Disable clock for ADC1
PCC->PCCn[PCC_ADC1_INDEX] = PCC_PCCn_PCS(3) | PCC_PCCn_CGC_MASK; // Enable clock for ADC1
S32_NVIC->ISER[ADC1_IRQn / 32] |= (1 << (ADC1_IRQn % 32)); // Enable interrupt
/* Set divide ratio to 1 and select 12-bit conversion */
ADC1->CFG1 = ADC_CFG1_ADIV(0) | ADC_CFG1_MODE(1) | ADC_CFG1_ADICLK(0);
/* Select hardware trigger */
ADC1->SC2 = ADC_SC2_ADTRG_MASK;
/* Select channel 1 as an input and enable conversion complete interrupt */
//ADC1->SC1[0] = ADC_SC1_AIEN_MASK | ADC_SC1_ADCH(1);
ADC1->SC1[0] = ADC_SC1_AIEN_MASK | ADC_SC1_ADCH(0);
ADC1->SC1[1] = ADC_SC1_AIEN_MASK | ADC_SC1_ADCH(1);
ADC1->SC1[2] = ADC_SC1_AIEN_MASK | ADC_SC1_ADCH(2);
ADC1->SC1[3] = ADC_SC1_AIEN_MASK | ADC_SC1_ADCH(3);
INT_SYS_SetPriority(ADC1_IRQn, 1);
}
/* SW=3, TRGMUX initialization to route FTM Init trigger signal into PDB0 trigger input */
void TRGMUX_Init()
{
//PCC->PCCn[PCC_TRGMUX_INDEX] = PCC_PCCn_CGC_MASK; // Enable clock for TRGMUX module
TRGMUX->TRGMUXn[TRGMUX_PDB1_INDEX] = TRGMUX_TRGMUXn_SEL0(0x1D); // Set FTM3 as a trigger source for PDB1
}
/* SW=3, PDB1 initialization to trigger ADC0 at the center of PWM by pre-trigger signal */
void pdb1_ftm_trigger_Init()
{
PCC->PCCn[PCC_PDB1_INDEX] = PCC_PCCn_CGC_MASK; // Enable clock for PDB1
S32_NVIC->ISER[PDB1_IRQn / 32] |= (1 << (PDB1_IRQn % 32)); // Enable interrupt
PDB1->MOD = 1000; // Set Modulo
PDB1->CH[0].C1 = PDB_C1_TOS(1) | PDB_C1_EN(1); // Select and enable Channel0
PDB1->CH[0].DLY[0] = 0; // Set delay
PDB1->IDLY = 0; // Set interrupt delay
PDB1->SC = PDB_SC_PRESCALER(0) | PDB_SC_MULT(0); // Select clock prescaler and mult factor
PDB1->SC |= PDB_SC_TRGSEL(0) | PDB_SC_PDBIE_MASK; // Select trigger input source and enable interrupt
PDB1->SC |= PDB_SC_PDBEIE_MASK;
PDB1->SC |= PDB_SC_PDBEN_MASK | PDB_SC_LDOK_MASK; // Enable PDB and update PDB registers
}
/* ADC1 interrupt routine */
void ADC1_IRQHandler()
{
GPIO_LED2_HIGH();
if(adc1_trigger.adc1_trigger_mes == ADC_BY_FTM)
{
uout.val = ADC1->R[0]; // Read ADC result register
iout.val = ADC1->R[1];
iavg_out.val = ADC1->R[2];
uin.val = ADC1->R[3];
}
else if(adc1_trigger.adc1_trigger_mes == ADC_BY_PDB)
{
adc1_results[ADC1_CH_VOUT] = (uint16_t)ADC1->R[4];
adc1_results[ADC1_CH_IOUT] = (uint16_t)ADC1->R[5];
adc1_results[ADC1_CH_IAVG] = (uint16_t)ADC1->R[6];
adc1_results[ADC1_CH_UINH] = (uint16_t)ADC1->R[7];
uout.val = adc1_results[ADC1_CH_VOUT];
iout.val = adc1_results[ADC1_CH_IOUT];
iavg_out.val = adc1_results[ADC1_CH_IAVG];
uin.val = adc1_results[ADC1_CH_UINH];
}
else
{
}
GPIO_LED2_LOW();
}
/* PDB0 interrupt routine */
void PDB1_IRQHandler()
{
PDB1->SC &= ~PDB_SC_PDBIF_MASK; // Clear PDB interrupt flag
if(PDB1->CH[0].S & PDB_S_ERR_MASK)
{
PDB1->CH[0].S &= PDB_S_ERR(0);
if(adc1_trigger.adc1_trigger_mes == ADC_BY_FTM)
{
uout.val = ADC1->R[0]; // Read ADC result register
iout.val = ADC1->R[1];
iavg_out.val = ADC1->R[2];
uin.val = ADC1->R[3];
}
else if(adc1_trigger.adc1_trigger_mes == ADC_BY_PDB)
{
adc1_results[ADC1_CH_VOUT] = (uint16_t)ADC1->R[4];
adc1_results[ADC1_CH_IOUT] = (uint16_t)ADC1->R[5];
adc1_results[ADC1_CH_IAVG] = (uint16_t)ADC1->R[6];
adc1_results[ADC1_CH_UINH] = (uint16_t)ADC1->R[7];
uout.val = adc1_results[ADC1_CH_VOUT];
iout.val = adc1_results[ADC1_CH_IOUT];
iavg_out.val = adc1_results[ADC1_CH_IAVG];
uin.val = adc1_results[ADC1_CH_UINH];
}
else
{
}
adc1_trigger.adc1_trigger_error = 1;
}
}
void adc_ftm_trigger_start(void)
{
TRGMUX_Init();
pdb1_ftm_trigger_Init();
adc1_ftm_trigger_Init();
adc1_trigger.adc1_trigger_mes = ADC_BY_FTM;
adc1_trigger.adc1_trigger_flag = 1;
adc1_trigger.adc1_trigger_error = 0;
}