Hi,
Is there any known issue, related to noise for example, that might lead the KV58F1M0VLQ24 MCU HSADC to freeze?
I have a custom board designed for ACIM FOC. My development references were:
DRM150 - Sensorless ACIM Field-Oriented Control
Document Number: HVPMC3PHUG
Document Number: HVPKV58F220MUG
At certain conditions, that seems to be related to noise, the HSADC conversion returns the same number from the last valid conversion, and remains on that state until a power reset. The issue happens with both HSADC modules in a random manner, but not necessarily at the same time. Sometimes one module continues to operate and the other freezes. This is very critical for power converter applications since the freeze reading is a valid value.
Commments/sugestions would be very welcome.
Best regards,
Rafael
HSADC configuration:
void init_hsadc(void)
{
hsadc_config_t hsadcConfigStruct;
hsadc_converter_config_t hsadc_converter_config;
hsadc_sample_config_t hsadcSampleConfigStruct;
uint16_t sampleMask;
hsadcConfigStruct.dualConverterScanMode = kHSADC_DualConverterWorkAsTriggeredSequential;
hsadcConfigStruct.enableSimultaneousMode = false;
hsadcConfigStruct.resolution = kHSADC_Resolution12Bit;
hsadcConfigStruct.DMATriggerSoruce = kHSADC_DMATriggerSourceAsEndOfScan;
hsadcConfigStruct.idleWorkMode = kHSADC_IdleKeepNormal;
hsadcConfigStruct.powerUpDelayCount = 18U;
// Initialize each converter
HSADC_Init(HSADC0, &hsadcConfigStruct);
HSADC_Init(HSADC1, &hsadcConfigStruct);
// Configure each converter
hsadc_converter_config.clockDivisor = 4;
hsadc_converter_config.samplingTimeCount = 50;
hsadc_converter_config.powerUpCalibrationModeMask = kHSADC_CalibrationModeSingleEnded;
HSADC_SetConverterConfig(HSADC0, kHSADC_ConverterA|kHSADC_ConverterB, &hsadc_converter_config);
HSADC_SetConverterConfig(HSADC1, kHSADC_ConverterA|kHSADC_ConverterB, &hsadc_converter_config);
// Enable the power for each converter.
HSADC_EnableConverterPower(HSADC0, kHSADC_ConverterA | kHSADC_ConverterB, true);
while ( (kHSADC_ConverterAPowerDownFlag | kHSADC_ConverterBPowerDownFlag)
== ((kHSADC_ConverterAPowerDownFlag | kHSADC_ConverterBPowerDownFlag) & HSADC_GetStatusFlags(HSADC0)) )
{}
HSADC_EnableConverterPower(HSADC1, kHSADC_ConverterA | kHSADC_ConverterB, true);
while ( (kHSADC_ConverterAPowerDownFlag | kHSADC_ConverterBPowerDownFlag)
== ((kHSADC_ConverterAPowerDownFlag | kHSADC_ConverterBPowerDownFlag) & HSADC_GetStatusFlags(HSADC1)) )
{}
// Conversion channel setting.
hsadcSampleConfigStruct.channel67MuxNumber = 0;
hsadcSampleConfigStruct.enableDifferentialPair = false;
hsadcSampleConfigStruct.zeroCrossingMode = kHSADC_ZeroCorssingDisabled;
hsadcSampleConfigStruct.highLimitValue = 0x7FF8U;
hsadcSampleConfigStruct.lowLimitValue = 0U;
hsadcSampleConfigStruct.offsetValue = 0U;
hsadcSampleConfigStruct.enableWaitSync = false;
// HSADC0
hsadcSampleConfigStruct.channelNumber = 4U|HSACD_A_MASK;
HSADC_SetSampleConfig(HSADC0, 0U, &hsadcSampleConfigStruct);
hsadcSampleConfigStruct.channelNumber = 2U|HSACD_A_MASK;
HSADC_SetSampleConfig(HSADC0, 1U, &hsadcSampleConfigStruct);
hsadcSampleConfigStruct.channelNumber = 3U|HSACD_A_MASK;
HSADC_SetSampleConfig(HSADC0, 2U, &hsadcSampleConfigStruct);
/*hsadcSampleConfigStruct.channelNumber = 6U|HSACD_A_MASK;
hsadcSampleConfigStruct.channel67MuxNumber = 0;// Use ch6
HSADC_SetSampleConfig(HSADC0, 3U, &hsadcSampleConfigStruct);
hsadcSampleConfigStruct.channelNumber = 7U|HSACD_A_MASK;
hsadcSampleConfigStruct.channel67MuxNumber = 0;// Use ch7
HSADC_SetSampleConfig(HSADC0, 4U, &hsadcSampleConfigStruct);*/
hsadcSampleConfigStruct.channelNumber = 5U|HSACD_A_MASK;
HSADC_SetSampleConfig(HSADC0, 3U, &hsadcSampleConfigStruct);
hsadcSampleConfigStruct.channelNumber = 0U|HSACD_A_MASK;
HSADC_SetSampleConfig(HSADC0, 4U, &hsadcSampleConfigStruct);
// HSADC1
hsadcSampleConfigStruct.channelNumber = 3U|HSACD_B_MASK;
HSADC_SetSampleConfig(HSADC1, 0U, &hsadcSampleConfigStruct);
hsadcSampleConfigStruct.channelNumber = 7U|HSACD_B_MASK;
hsadcSampleConfigStruct.channel67MuxNumber = 2;// Use ch11
HSADC_SetSampleConfig(HSADC1, 1U, &hsadcSampleConfigStruct);
// Enable the sample slot.
sampleMask = HSADC_SAMPLE_MASK(0U)
| HSADC_SAMPLE_MASK(1U)
| HSADC_SAMPLE_MASK(2U)
| HSADC_SAMPLE_MASK(3U)
| HSADC_SAMPLE_MASK(4U);
HSADC_EnableSample(HSADC0, sampleMask, true);
HSADC_EnableSample(HSADC0, (uint16_t)(~sampleMask), false);// Disable other sample slot.
// Enable the sample slot.
sampleMask = HSADC_SAMPLE_MASK(0U)
| HSADC_SAMPLE_MASK(1U);
HSADC_EnableSample(HSADC1, sampleMask, true);
HSADC_EnableSample(HSADC1, (uint16_t)(~sampleMask), false);// Disable other sample slot.
// Enable synch input to start the ADC conversion
HSADC_EnableConverterSyncInput(HSADC0, kHSADC_ConverterA | kHSADC_ConverterB, true);
HSADC_EnableConverterSyncInput(HSADC1, kHSADC_ConverterA | kHSADC_ConverterB, true);
//Select TIMER0_trig source
SIM->SOPT7 = (SIM->SOPT7 & ~SIM_SOPT7_HSADC0AALTTRGEN_MASK) | SIM_SOPT7_HSADC0AALTTRGEN(0x03) | SIM_SOPT7_HSADC0ATRGSEL(0x09);
SIM->SOPT7 = (SIM->SOPT7 & ~SIM_SOPT7_HSADC0BALTTRGEN_MASK) | SIM_SOPT7_HSADC0BALTTRGEN(0x03) | SIM_SOPT7_HSADC0BTRGSEL(0x09);
SIM->SOPT7 = (SIM->SOPT7 & ~SIM_SOPT7_HSADC1AALTTRGEN_MASK) | SIM_SOPT7_HSADC1AALTTRGEN(0x03) | SIM_SOPT7_HSADC1ATRGSEL(0x09);
SIM->SOPT7 = (SIM->SOPT7 & ~SIM_SOPT7_HSADC1BALTTRGEN_MASK) | SIM_SOPT7_HSADC1BALTTRGEN(0x03) | SIM_SOPT7_HSADC1BTRGSEL(0x09);
SIM->ADCOPT |= (SIM_ADCOPT_ADC0ALTTRGEN_MASK | SIM_ADCOPT_ADC0TRGSEL(0x09));
// Configure HSADC calibration process
// Single-ended input calibration
// Run auto calibration
HSADC_DoAutoCalibration(HSADC0,kHSADC_ConverterA | kHSADC_ConverterB,kHSADC_CalibrationModeSingleEnded);
HSADC_DoAutoCalibration(HSADC1,kHSADC_ConverterA | kHSADC_ConverterB,kHSADC_CalibrationModeSingleEnded);
// Wait until calibration is completed
while (!(HSADC0->STAT & HSADC_STAT_EOCALIA_MASK)){}
while (!(HSADC0->STAT & HSADC_STAT_EOCALIB_MASK)){}
while (!(HSADC1->STAT & HSADC_STAT_EOCALIA_MASK)){}
while (!(HSADC1->STAT & HSADC_STAT_EOCALIB_MASK)){}
// Enable de converter
HSADC_EnableConverter(HSADC0, kHSADC_ConverterA | kHSADC_ConverterB,true);
HSADC_EnableConverter(HSADC1, kHSADC_ConverterA | kHSADC_ConverterB,true);
// Enable & setup interrupt from ADC
HSADC_EnableInterrupts(HSADC0, kHSADC_ConverterAEndOfScanInterruptEnable);
HSADC_EnableInterrupts(HSADC1, kHSADC_ConverterAEndOfScanInterruptEnable);
EnableIRQ(HSADC0_CCA_IRQn); // Enable interrupt
//EnableIRQ(HSADC0_CCB_IRQn); // Enable interrupt
EnableIRQ(HSADC1_CCA_IRQn); // Enable interrupt
//EnableIRQ(HSADC1_CCB_IRQn); // Enable interrupt
NVIC_SetPriority(HSADC0_CCA_IRQn, 1); // Set priority to interrupt
//NVIC_SetPriority(HSADC0_CCB_IRQn, 1); // Set priority to interrupt
NVIC_SetPriority(HSADC1_CCA_IRQn, 1); // Set priority to interrupt
//NVIC_SetPriority(HSADC1_CCB_IRQn, 1); // Set priority to interrupt
}
Hi,
I have check the errata of KV58, I have not seen any item which mentions the ADC hardware bugs.
https://www.nxp.com.cn/docs/en/errata/KINETIS_V_1N86P.pdf
Based on my experience, maybe there is issue if you clear the SIMULT bit in the HSADCx_CTRL2 register.
Pls use the following configuration and have a try.
hsadcConfigStruct.dualConverterScanMode = kHSADC_DualConverterWorkAsTriggeredSequential;
hsadcConfigStruct.enableSimultaneousMode = true; //Rong write, set SIMULT bit
hsadcConfigStruct.resolution = kHSADC_Resolution12Bit;
hsadcConfigStruct.DMATriggerSoruce = kHSADC_DMATriggerSourceAsEndOfScan;
hsadcConfigStruct.idleWorkMode = kHSADC_IdleKeepNormal;
hsadcConfigStruct.powerUpDelayCount = 18U;
// Initialize each converter
HSADC_Init(HSADC0, &hsadcConfigStruct);
HSADC_Init(HSADC1, &hsadcConfigStruct);
If you change the code and the ADC will sample in parallel mode, so the ADC triggering signal has to change, pls check the code yourself.
I suggest you separate the motor for safety, and only test the ADC, you can sample the ADC to a big array and check if the phenomenon happens or not.
I do not guarantee it solve your problem, anyway, pls have a try.
BR
XiangJun Rong
Hi,
For the HSADC module, each hsadc has two adc converters: HSADCxA and HSADCxB, if the HSADCx_CTRL2[SIMULT]=0, the HSADCxA and HSADCxB work independently, each converter requires respective triggering source, per my support experience, only HSADCxB has issue, the HSADCxA does NOT has issue. Pls check if your phenomenon matches what I said.
BR
XiangJun Rong