earlephilhower / arduino-pico

Raspberry Pi Pico Arduino core, for all RP2040 and RP2350 boards
GNU Lesser General Public License v2.1
2.09k stars 434 forks source link

RP2350-E9 erratum: input pin can become latched at about ~2V #2380

Closed dhalbert closed 2 months ago

dhalbert commented 3 months ago

There is discussion going on elsewhere about erratum RP2350-E9. It describes a case where GPIO input pins can get latched at slightly above 2V. RP2350-E9 says the internal pull-down has to be enabled for this to happen, but several of us have found that the pull-down does not need to be enabled for the problem to occur.

Background:

Thanks to @DangerousPrototypes for finding the initial problem as described in RP2350-E9. @Gadgetoid and I both found the problem to be more pervasive that RP2350-E9 describes. We have all done additional testing and write-ups.

It is not clear whether a clean software workaround is possible. Such a workaround might go into arduino-pico. In the Raspberry Pi forum thread there's more testing information, speculation and testing of workarounds, and speculation about a chip respin.

I don't think it's worth starting another speculation thread here right now. I think it would be good to wait for more information from Raspberry Pi themselves, and then any potential workaround can be discussed. If you subscribe to the issues and threads above, you can keep up to date.

earlephilhower commented 3 months ago

Good summary. Let's leave the dust settle first and let the folks who do this for a living come up with good solution (that covers the multiple cases I think I'm seeing in the linked discussions) and we can put it in.

pike2k commented 3 months ago

Fixed by documentation according to Raspberry Pi's datasheet. I wonder if they will update E9 soon. So much for Pico2 being 'a drop-in replacement' for Pico.

todbot commented 3 months ago

Except some cases can't be fixed with documentation. Two examples I'm currently aware of are: capacitive touch sensing (which use a 1M pulldown) and low-current buttons (which uses an external 100k pull-down) Both affect me, and yep, make the Pico2 not a drop-in replacement for Pico.

dhalbert commented 2 months ago

The RP2350 datasheet has been updated and the RP2350-E9 erratum has been extensively revised: https://datasheets.raspberrypi.com/rp2350/rp2350-datasheet.pdf#page=1342. The erratum title is now "Increased leakage current on Bank 0 GPIO when pad input is enabled".

The main workaround is to keep the input (GPIO.IE) disabled most of the time and to eable it only temporarily only to read. Alternatively an 8.2kohm or lower can be installed as an external pull-down. PIO can't control GPIO.IE, so if a pull-down is really needed, it needs to be external.

earlephilhower commented 2 months ago

If I understand it correctly, it seems like in this case the core here needs to:

  1. Explicitly disable GPIO.IE on any pinMode(input*) (but PU/PD can still be enabled as needed)
  2. On digitalRead A. Disable interrupts B. Disable FreeRTOS task switching, (maybe swap A/B, need to check) C. Set the IE bit D. Do gpio_read E. Clear IE bit F. Restore task swapping/IRQs

Optimization would be to check only if a PD is used and do all the hoop-jumping.

Does someone reading this have a good way of testing any fix like this if I put it in a PR? I've got a DMM, but no oscilloscope to verify dynamic response...

dhalbert commented 2 months ago

@earlephilhower I am hoping that RPi will offer some sample code or add some support in pico-sdk for pin reading. I was considering about asking about that soon.

When the internal pull-UP is enabled, it may be possible to avoid the rigamarole if you are willing to assume that a logical 0 on the pin will be strong and overcome the leakage current. Perhaps there will be some discussion about this. I think it's worth waiting a bit to see what further info we can glean.

dhalbert commented 2 months ago

I'm not sure you need to disable FreeRTOS task switching explicitly. Disabling interrupts should be the start of a critical section, which should suppress task switching, since that would be done due to an interrupt or event (timer tick or condition).

dhalbert commented 2 months ago
earlephilhower commented 2 months ago

The disable interrupts and disable FreeRTOS task switching is because I thought the issue was leaving .IE on too long would corrupt the data when high impedance sources were read. Enabling it for 2 150MHz clock cycles (7-13ns?) before reading wouldn't let enough charge pass through to do much damage to the Vin, but if you get an IRQ or task switch and IE is set for 1ms+ it could be bad.

But it's uglier that that because this only works for non-IRQ/sleep wakeup pins. For IRQ enabled pins you need to always have IE or you'll never get the signal. And "I'm using this for an IRQ" is known at a separate spot in the code/time than "set this pin to an input" by the SDK (and the app in general).

dhalbert commented 2 months ago

Yup, I agree it needs a critical section. I was just saying that if you disable interrupts explicitly, that should also turn off FREETOS task switching, so I don't think you need to do both explicitly.

One can only hope that any external interrupts are active low, and use a pull-up. Otherwise, yup, a significant problem.

earlephilhower commented 2 months ago

On the ARM (2040 at least), FreeRTOS uses system exceptions which are non maskable. I spent more time than I'd wanted to digging into this to allow flash writes and SMP to work, believe me! 😭

It's a supported SMP call, but it's rather heavy weight vs. just clearing a register for IRQs.

dhalbert commented 2 months ago

Thanks for the correction! I should have looked it up. Our FreeRTOS experience has been on ESP-IDF since only, and we just use the supplied API.

dhalbert commented 2 months ago

@earlephilhower Today we discussed internally what to do about the E9 workaround for CircuitPython.

Without adding additional API specifically to support the RP2350, there is no way to inform CircuitPython in various use cases, "well, yes, this is a weak input signal, so do the workaround". The only hint would be if you enabled the internal pulldown, but there are other cases as well. We do not right now want to make a special-case API for the RP2350.

So our conclusion was to not implement the workaround, at least for now, but simply to document the restrictions that make it unnecessary: don't expect the internal pulldown to work, use an external pulldown 8.2k or lower if you need a pulldown, or make sure your input signal can sink enough current to override the leakage current. This is defining the problem away.

I don't know if you feel this would be satisfactory for your own purposes, but it's one way to deal with it.

earlephilhower commented 2 months ago

Thanks, @dhalbert . Appreciate your update and think that's going to be the solution here as well.

It seems there's just not one safe-and-effective-for-all option other than, "Use external PDs or fully drive input signals" seems to be the only guaranteed way of getting all use cases working.

It's not the end of the world. All chips have errata and if the RPI guys were given a bad SPICE model for the pads or their standard cell supplier dropped the ball it's not their blame. Hopefully a mask rev can get then back and going because there's a lot of awesome new features in the chip!