The purpose of this forum post is to figure out why the internal temperature sensor on my STM32L0 processor is reading all 1’s (0x7FF) after a power cycle or software reset. I will try to include as much information as I can about my setup, the way I reproduce the problem, and all the different things I have tried to fix the problem so that anyone reading this can jump in at the same place I am in this investigation.
I will start by describing the device I am using, all the debugging tools I have available, and the STMCubeMX settings for the internal temperature channel of the ADC.
Debugger: ST-Link/V2 (B 2018 15)
Power Supply: Variable Voltage Supply
Debug Equipment: Oscilloscope, DMM, Soldering Iron, Spare Wire (for snooping), Access to lab
IDE: System Workbench
Cube MX Settings:
Use Of Temperature Sensor In Code:
‘HAL-generated’ initialization of the adc
My code that reads temperature calibration points(defined in datasheet) from device ROM.
My code that triggers an ADC conversion, throws that first conversion away (per suggestion from device errata), performs a second conversion, then calculates temperature from that second conversion.
Reproducing The Error
Launching a debug session, flashing a release build of the firmware to the processor with system workbench, and using the ST-Link programming utility to flash the processor all allow the code to work correctly and convert temperature in the way I would expect. I get counts that make sense and convert them to roughly 25 degrees c which is reasonable for my room temperature.
The problem occurs if I power cycle the processor or perform a software reset after flashing the processor or launching a debug session. After either of these reset methods, my temperature calculation is always 601 degrees c which converts to 0x7FF in adc counts. As this is all ones, it seems like there is a problem with the ADC after a power cycle or software reset.
My Investigation So Far
Any time you power cycle the stm32, all three temp sensors flash.
Go grab battery circuit board from the office.
Power cycle it with the power supply.
Debug and see what is causing all three leds to flash.
I was able to reproduce the problem.
flash release fw
It seems like the stm32l0 is not able to run a debug session without resetting the chip.
I tried the method described in this forum post https://www.openstm32.org/forumthread1967
I followed all the instructions, and was able to get the debugger attached to another project running on an STM32f4, but was unable to attach the debugger to the STM32L0 I am using without resetting the processor.
This is the error I kept getting when trying this.
I tried seeing if the problem was the eeprom reading the temp calibration points and it was not that.
I tried hard coding the temperature to 20c and the problem went away.
This tells me that the problem is how the counts are being read from the adc
I tried recompiling the hal with the newest version of the cubeMX firmware and that didn’t fix the problem.
I will now google problems with the adc on the stm32l0
Josh suggested I read from the adc twice and ignore the first read.
I did this and the problem is still happening.
He also suggested that I replace one of the values in the lin bus message with the temperature.
I can’t really do that because the circuit board doesn’t have any ability to hook up to the lin bus of the Hercules.
I could light up one of the three leds when I read in the temperature to see what it is showing up as...
I figured out that the temperature is between 40c and 80 c, now I will zoom in more to figure out what the temp is reading in more detail.
I used the led’s and a ternary search method to measure that the temperature is 601 when the failure happens.
I want to verify one more time that the temp is repeatable at 601, then I want to calculate what 601 means in counts.
I verified the temperature is reading 601.
What is this in counts?
The counts are 7FF (all ones)
I wanted to look on the scope at this signal, but it comes from the internal adc, so I can’t.
Check the processor errata do this first**
Chris would put a long wait before the initialization code (5-10 seconds)
For loop for wait
Try moving the wait around
Start in the user code begin 2 and get the timing for the for loop wait with leds.
I tried this and it did not seem to fix the problem.
The above method checks if the internal adc is taking too long to power up on power cycles.
I checked the errata and am just waiting to hear back from James about one entry.
It looks like it will be good to keep the “double read” because it prevents bad reads due to inactivity, but the double read will not solve the problem I am investigating.
James suggests I set up a spare io pin to trigger when the battery starts an adc transaction and another scope probe on the vref if we are using an external reference.
I don’t think this is possible as the temperature sensor (adc channel 18) is internal to the processor.
Try adding a software reset to where the temperature is read only if the temp is above 500c
It appears that the issue persists even if the processor is reset.
I gather this because the processor reset I set up seemed to have happened twice..
This means that it reset because the temp was 601, got back to the step where it reads the temp, and the temp was 601 again.
Yup, it just happened again.. Stuck in a loop..
So, the issue happens on both a software reset and a power on reset.
That means it is probably not an issue with the adc starting up fast enough.
It could be an issue with how the adc is being initialized.
I am not sure where to look to figure this out.
I could read through the adc init function and try to understand it better.
I could look at every place in the code where the adc is referenced and see if anything sticks out or is obviously missing.
Look for array that’s being written out of bounds.. or uninitialized variables.
I used cpp check to do a static code analysis and it does not appear that there are any uninitialized variables.
MAIN QUESTION: What is different about running a debug session from running the code after a power cycle or software reset.
Ok I have a PLANNNN!
I will check every register address for the adc on startup and blink an led if they are the right value.
I will need to hard code each of these checks.
If the “failed” blink happens, I will make custom blink codes in between each register value to see which changed.
Once I find which one changed, I will figure out a way to tell what it changed to and go from there.
I defined the above function by launching a debug session, stepping past the adc init hal function, and writing down the values of all the adc registers and adc instance memory values.
Ok my led investigation function works!
I tried it before the adc init hal function and it blinked twice red/twice green to indicate that both the hadc variable and the adc’s registers were not set to the right values.
I then had the function call again after the setup and got a single long red then green blink meaning that the hadc var was good and so were all the adc registers.
Now, I’ll run the test with the led diagnostic function call right after the adc init hal function, induce the error state by power cycling, and see what happens.
Looks like the red then green leds only flashed once after the power cycle telling me that the registers are being set up correctly.
Maybe james is right and I should set up a second check right before the first adc read to see if the registers have changed..
Now we know that the adc registers are the same before and after a power cycle, but the temperature is being read out as 0x7FF counts (601 degrees c).
Is that the only adc channel that has a temp sensor on it
It looks like adc channel 18 is the only channel with a temperature sensor
It looks like the voltage reference is on channel 17.
It looks like the TSEN control bit needs to be set (I am assuming to 1) to enable conversions on the temperature sensor.
Maybe the tsen bit is getting set to 0 somehow...
It does not look like the tsen bit is getting set to 0.
I confirmed this using my led diagnostic function at the beginning of the code right after the adc init hal function gets called and in between the two adc reads.
Both of these functions blinked once signaling that the registers and variable memory matched.
I think this is a valid test, because the registers I am ignoring change in the debug session where the temperature gets read correctly, so I can ignore them in the case where the temperature gets read incorrectly.
The adc registers and variable memory do not seem to be the problem.
Some Areas I Haven’t Investigated Yet
Look at whatever clock source is driving the adc and see if any of its registers are different pre/post power cycle.
Is there a filter on the adc
Check if the chip has any brown-out conditions that we don’t know about