2023-12-01 02:17 AM
Hello everybody
Unfortunately I'm stuck with the problem when using the ADC4 of the STM32U575 VIT6Q revision 01:
Everything works as with the already implemented ADC1, the initialization, starting conversions, the EOC interrupts and reading the data register (ADC4_DR) but I only get 0 out of it, when reading from GPIOB pins.
I've tested the following configurations on the respective GPIO pins (all configured the same, in analog mode):
By working i mean delivering values other than 0 (when connecting the inputs to GND, the values are around 60...70 out of 4096 resp. 4095 @ 3.3V with the configured 12 bit resolution, so these are plausible values). Not working means the values read from ADC4_DR are constantly 0.
I'm aware of the TZSC feature, whereas "unsecure" peripherals are disconnected by HW when accessing secure GPIOs, according to section "3.13.1 GPIOs TrustZone security" in the "STM32U575xx datasheet" (DS13737 Rev 6), and "Table 10. Non-secure peripheral functions that are not connected to secure I/Os" in the "STM32U575/585 Reference manual" (RM0456 Rev 3). However, the TZSC option bit in FLASH_OPTR is set to zero, meaning that the TrustZone security is disabled. Also, ADC1 and ADC4 are basically working but just not the combination ADC4 with GPIOB.
The "STM32U575xx and STM32U585xx device errata" (ES0499 - Rev 😎 does not mention any problems of this nature regarding ADC4, GPIO or GTZC.
My initialization routine is as follows, using the defined "objects" below:
/**
* @brief Configuration of the motor interface Adc device
*/
static const AdcDevice_members_t tMotorInterfaceAdcMembers = {
.ptRuntimeData = &tMotorInterfaceAdcRuntimeData,
.ptAdcPeripheral = ADC1,
.eAdcIrqN = ADC1_IRQn,
.u32AdcChannel = ADC_CHANNEL_7
};
/**
* @brief Configuration of the force sensor monitoring Adc device
*/
static const AdcDevice_members_t tForceSensorMonitoringAdcMembers = {
.ptRuntimeData = &tForceSensorMonitoringAdcRuntimeData,
.ptAdcPeripheral = ADC4,
.eAdcIrqN = ADC4_IRQn,
.u32AdcChannel = ADC_CHANNEL_19
};
void Adc_vInit (const Adc_device_t ptDevice, const Adc_callbackRoutine_t pxHandler)
{
ASSERT_PTR_NOT_NULL(ptDevice);
AdcDevice_runtimeData_t* const ptRuntimeData = ptDevice->ptRuntimeData;
ADC_HandleTypeDef* const ptAdcHandle = &ptRuntimeData->tAdcHandle;
uint32_t u32SamplingTimeCommon = 0u;
uint32_t u32SamplingTime = 0u;
uint32_t u32SequencerRank = 0u;
// register the specified handler
ptRuntimeData->pxRegisteredHandler = pxHandler;
// initialize the remaining members of the runtime data
ptRuntimeData->u32LatestConversionData = 0;
// enable the VDDA voltage monitor of the associated ADC peripheral
PWR->SVMCR |= PWR_SVMCR_AVM1EN;
// wait until the VDDA voltage is enabled
while ((PWR->SVMSR & PWR_SVMSR_VDDA1RDY) == 0u);
// declare VDDA independent analog supply as valid
PWR->SVMCR |= PWR_SVMCR_ASV;
// enable the clock source of the associated ADC peripheral
switch ((uint32_t)ptDevice->ptAdcPeripheral)
{
case (uint32_t)ADC1:
/**
* @remark 20 ADC clock cycles for 12 bit ADC resolution.
* Refer to section 29.4.22 "Programmable resolution (RES) - fast conversion mode"
* on p.1021 within the "STM32U575/585 Reference manual" (RM0456 Rev 3)
*/
u32SamplingTimeCommon = ADC_SAMPLETIME_20CYCLES;
u32SamplingTime = ADC_SAMPLETIME_20CYCLES;
u32SequencerRank = ADC_REGULAR_RANK_1;
__HAL_RCC_ADC1_CLK_ENABLE();
break;
case (uint32_t)ADC4:
/**
* @remark 12.5 ADC clock cycles for 12 bit ADC resolution.
* Refer to section 30.4.18 "Programmable resolution (RES) - fast conversion mode"
* on p.1101 within the "STM32U575/585 Reference manual" (RM0456 Rev 3)
*/
u32SamplingTimeCommon = ADC4_SAMPLETIME_12CYCLES_5;
u32SamplingTime = ADC4_SAMPLINGTIME_COMMON_1;
u32SequencerRank = ADC4_REGULAR_RANK_1;
__HAL_RCC_ADC4_CLK_ENABLE();
break;
default:
Err_HANDLE_REUSABLE_ERROR((uint32_t)ptDevice->ptAdcPeripheral, "Unsupported ADC peripheral");
break;
}
// initialize the associated ADC peripheral
ptAdcHandle->Instance = ptDevice->ptAdcPeripheral;
ptAdcHandle->Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV4; // clock divider = 4
ptAdcHandle->Init.Resolution = ADC_RESOLUTION_12B; // 12 bit ADC resolution
ptAdcHandle->Init.GainCompensation = 0u;
ptAdcHandle->Init.ScanConvMode = ADC_SCAN_DISABLE;
ptAdcHandle->Init.DataAlign = ADC_DATAALIGN_RIGHT;
ptAdcHandle->Init.EOCSelection = ADC_EOC_SINGLE_CONV; // end of single conversion
ptAdcHandle->Init.LowPowerAutoWait = DISABLE;
ptAdcHandle->Init.LowPowerAutoPowerOff = ADC_LOW_POWER_NONE;
ptAdcHandle->Init.ContinuousConvMode = DISABLE;
ptAdcHandle->Init.NbrOfConversion = 1u;
ptAdcHandle->Init.DiscontinuousConvMode = DISABLE;
ptAdcHandle->Init.NbrOfDiscConversion = 1u;
ptAdcHandle->Init.ExternalTrigConv = ADC_SOFTWARE_START; // software triggered
ptAdcHandle->Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
ptAdcHandle->Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR; // conversion data is stored in DR register
ptAdcHandle->Init.DMAContinuousRequests = DISABLE;
ptAdcHandle->Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; // overwrite obsolete data
ptAdcHandle->Init.SamplingTimeCommon1 = u32SamplingTimeCommon;
ptAdcHandle->Init.SamplingTimeCommon2 = u32SamplingTimeCommon;
ptAdcHandle->Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
ptAdcHandle->Init.OversamplingMode = DISABLE;
ptAdcHandle->Init.Oversampling.Ratio = ADC_OVERSAMPLING_RATIO_2;
ptAdcHandle->Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_NONE;
ptAdcHandle->Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER;
ptAdcHandle->Init.Oversampling.OversamplingStopReset = ADC_REGOVERSAMPLING_CONTINUED_MODE;
ptAdcHandle->Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_LOW;
ptAdcHandle->Init.VrefProtection = ADC_VREF_PPROT_NONE;
ASSERT_TRUE(HAL_ADC_Init(ptAdcHandle) == HAL_OK,
"Failed to initialize Adc");
// wait until the ADC voltage regulator is enabled
while ((ptDevice->ptAdcPeripheral->ISR & ADC_ISR_LDORDY) == 0u);
ADC_ChannelConfTypeDef tAdcChannelConfig = {0};
tAdcChannelConfig.Channel = ptDevice->u32AdcChannel;
tAdcChannelConfig.Rank = u32SequencerRank;
tAdcChannelConfig.SamplingTime = u32SamplingTime;
tAdcChannelConfig.SingleDiff = ADC_SINGLE_ENDED; // single ended (non-differencial)
tAdcChannelConfig.OffsetNumber = ADC_OFFSET_NONE;
tAdcChannelConfig.Offset = 0x000u;
tAdcChannelConfig.OffsetRightShift = DISABLE;
tAdcChannelConfig.OffsetSignedSaturation = DISABLE;
tAdcChannelConfig.OffsetSaturation = DISABLE;
tAdcChannelConfig.OffsetSign = ADC_OFFSET_SIGN_POSITIVE;
ASSERT_TRUE(HAL_ADC_ConfigChannel(ptAdcHandle, &tAdcChannelConfig) == HAL_OK,
"Failed to configure channel of Adc");
}
Does anybody encountered similar problems or has any clue what I'm still missing?
Thanks in advance for the help and best regards
Manuel
Solved! Go to Solution.
2024-02-08 11:29 PM
Nevermind, a colleague found the change that solved the problem:
Instead of
ptAdcHandle->Init.ScanConvMode = ADC_SCAN_DISABLE;
use
ptAdcHandle->Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
cheers
2024-02-08 11:29 PM
Nevermind, a colleague found the change that solved the problem:
Instead of
ptAdcHandle->Init.ScanConvMode = ADC_SCAN_DISABLE;
use
ptAdcHandle->Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
cheers