Using VREFBUF (analog internal reference) on STM32 G431RB

We have a board with an STM32G431RB MCU, which uses the MCU’s voltage reference buffer (VREFBUF) to produce the voltage reference for the ADCs.

There is no option to enable the voltage reference buffer under Coder Options > Target. Am I looking in the wrong place, or does Plecs not support this?

Without this support, our board has 0 volt on the VREF+ pin, which results in all ADC sampled values returning the maximum value, which is interpreted as 3.3v on the ADC.

If this is not (yet) supported, it should be possible to add a native code block to directly initialize this peripheral. How can we add a native code block which is run once, after Plecs initialization of the hardware has been completed?

Thank you for posting your question! May I ask you to post or send me a minimal example that exemplifies the issue you are experiencing in order for me to reproduce it?

In general, it is possible to add code that is run once, after the initialization of the hardware is complete, by adding a Native Code block to the PLECS model and inserting code in the “Post-init” section.

Hi Jeroen, thanks for looking into this.

You could use a Nucleo-G431RB board to reproduce this issue. The G474RE should also work, as it is almost identical.
Remove jumper JP8. The middle pin of JP8 is connected to the MCU VREF+ pin. Our board needs the MCU to output the 2.9V reference on that pin. This is done using the MCU’s VREFBUF feature. So if everything is configured correctly, you should measure 2.9V on JP8, middle pin.

When generating code using Plecs, the pin measures basically 0V. I could not find a way to configure the VREFBUF feature on the MCU in Plecs Coder Options. (I think there is no real use to sending an example, as any code generated will show the same issue)

We got the VREFBUF to work using the Native Code block as you suggested. This code was taken from the HAL_MspInit() function generated by STM32CubeMX.


/* Configure MCU to output 2.9V reference voltage on VREF+ pin 28 */
{
	// Enable clocks/power, not certain which are required
	__HAL_RCC_SYSCFG_CLK_ENABLE();
	__HAL_RCC_PWR_CLK_ENABLE();

	/** Configure the internal voltage reference buffer voltage scale
	*/
	HAL_SYSCFG_VREFBUF_VoltageScalingConfig(SYSCFG_VREFBUF_VOLTAGE_SCALE2);

	/** Enable the Internal Voltage Reference buffer
	*/
	HAL_SYSCFG_EnableVREFBUF();

	/** Configure the internal voltage reference buffer high impedance mode
	*/
	HAL_SYSCFG_VREFBUF_HighImpedanceConfig(SYSCFG_VREFBUF_HIGH_IMPEDANCE_DISABLE);
}

This produces the desired 2.9V on the pin. So that part is working now.

In the CubeMX generated code, this is done before the ADC is initialized and calibrated. The Post-Init and Init blocks are executed later in the initialization process, probably even after the ADC calibration is performed, which is likely done in PLX_ADC_setup(). I don’t expect this to work correctly, as the ADC is calibrated before the reference is enabled, but I will have to test this on hardware when I get into the office.

Is there a way to get the Native Code block to execute earlier in the initialization process?

Our preferred solution would be if Plecs would implement VREFBUF support into the target configuration, but I understand if you did not make this your top priority.

Thanks for the help!

Hi Mr. Jacobs,

Thank you for providing a detailed description! I am able to reproduce the ADC measurements you observed.

I have attached a PLECS model with an ADC and a Native Code block. I inserted the code that you provided in the “Init” section in the Native Code block and specified 2.9 [V] for the external ADC reference (Vref+) in the coder options. If I supply 1 [V] to the ADC pin, I read a value close to 1 [V].

Please let me know if this already satisfies your requirements, or if the small offset I observe is caused by a problem with the initialization!

We will add this to our queue of requested features, but I cannot promise that this feature will make it into the next release.

Kind regards,
Jeroen Buitendijk

vrefbuf.plecs (10.2 KB)

EDIT: Saved model using STM32 TSP version 1.4.3.

Hi Jeroen,

Testing this here on the Nucleo board we see a 0.970 V measurement in Plecs, while the applied voltage on PA0 is 1.000V (Precision supply and recently calibrated multimeter)

This is close enough that I can say your model has the issue solved! Ours sadly does not. The order of initialization does matter.

In your model the Native Code Init block is placed before the ADC initialization (PLX_ADC_setup() in vrefbuf_initHal()), while in our model the same block ends up much later, after the ADC initialization. Why would the order be so different? Perhaps the presence of other blocks influences the order? We do use the triggered ADC block, could be relevant.

I have attached a stripped version of our model, leaving the hardware initialization in place.

We have devised a temporary workaround; after Build we edit the generated code, re-compile and manually write to the target. Tedious, but it works for now. (And if it starts bothering me too much, I may have to automate the editing, time to break the Python out)

Best regards,
Rob Jacobs

ADC_VREFBUF_Issue_G431RB.plecs (45.7 KB)

Hi Rob,

Thank you for testing the workaround!

Both the initialization code generated by the ADC blocks and the code inserted by the Native Code block are written to the init code section. Because these pieces of code are inserted in the same section, their order is determined by the order in which the blocks are placed in the PLECS model. For this workaround, that means that the Native Code block must be placed in the model before the ADC blocks. I have attached the model you sent me with a different block order, and as far as I can tell it behaves as desired.

Kind regards,
Jeroen

ADC_VREFBUF_Issue_G431RB_Native_Code_block_first.plecs (45.8 KB)