Open PaulZC opened 3 years ago
The problem is related to MBED - ownership check.
Step 1: When you call begin() it will create a new mbed-SPI environment that initializes the different variables, IOM and the pins. In my mind it SHOULD update the MBED-owner (_peripheral->owner) to "this" but it does not, that field continues to be a nullptr.
Step 2: When de first time you call SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0)), in the Sparkfun library it will check whether these SPISettings are different than the previous set or default. By default the speed is zero, so it will call dev->format() and dev->frequency() in Mbed-os. These functions are in drivers/SPI.cpp.
Step 3: In Mbed-os either in dev->format() or dev->frequency() it will check whether the owner is "this". Somehow that seems to be important. The first time around it will NOT be (see step 1) and then it calls acquire() to update BOTH SPI-format and SPI-frequency, but NOT before doing a re-init with the call _init_func(this_); This will cause a complete init, same like calling begin() including resetting the pins to what is default defined in g_AM_BSP_GPIO_IOM0_MISO. After doing this, it will finally update _peripheral->owner. So now the pull-up is gone as it is not part of the default definition.
Step 4: Next time you call SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0)), the setting might be same, but even if not, you are now the owner and thus a change (like the pull-up) done to the pin will NOT be reset again.
Either MBED should change (add setting ownership is step 1) or add a 24K pull up on MISO / CIPO (new terminology). Needed for some SD card readers to work correctly. Or do as PaulZC did..
regards, Paul
Background
I’m upgrading the OpenLog Artemis to v2.1 of the core. I need to be able to manually configure the pull-ups on the “qwiic” SCL and SDA pins (D8 and D9) and the SPI CIPO pin (D6).
In v1.2.1 we could call
padMode
to manually set the pull-up on D6 and that worked just fine. But in v2.1padMode
is no longer supported. I've switched topin_config
and that works, but switching has revealed an interesting feature in v2.1.0 of the core:This did not happen in v1.2.1…
This feature took a while to pin down and, once you know it is there, is straightforward to work around. I’ve included my detective work below in case anyone finds it useful.
Anyone wanting to jump straight to the work around for OpenLog Artemis will find:
enableCIPOpullUp
hereProof that pin_config works on D8 and D9
In v1.2.1 we could change the I2C pull-ups by calling (e.g.)
qwiic.setPullups()
. But in v2.1setPullups
is no longer supported.Just to prove that
pin_config
does work as a replacement, try this example:Apollo3 v2.1.0 RedBoard Artemis ATP Connect an oscilloscope to pins D8 and D9 Run this sketch:
You should see this (note the sharp rising edges on both signals):
Change the code to:
And you should see this. Note the slow rising edges (as expected with the larger pull-up).
Interestingly, also note the slower clock speed! That’s a separate issue which has always been there. There is something in the Apollo3 hardware which monitors (probably) the clock to ensure that the clock signal is actually high for the correct period.
Right. OK. Excellent.
pin_config
works.Now let’s look at CIPO (D6)
Using pin_config on CIPO (D6)
OpenLog Artemis has a 1.8V level shifter circuit on the SPI bus to connect it to the ICM-20948 IMU. The bus is shared with the microSD card. On the earliest SparkX hardware, we noticed that there was current leaking through the CIPO level-shifter pull-up resistor into the SD card when the Artemis was in deep sleep. This increased the stand-by current dramatically. So, we removed the external resistor and instead used the internal pull-up on the Artemis pin. We could disable the pull-up to drop the stand-by current. Perfect. Except we did that using
padMode
and padMode ain’t supported no more…So, can we use
pin_config
? Yes, but there is an unexpected feature you need to be aware of...To replicate:
Apollo3 v2.1.0 RedBoard Artemis ATP Connect an oscilloscope to the CIPO pin D6 Run this sketch:
Use a jumper wire to briefly short CIPO to GND. When you remove the jumper CIPO is pulled up quickly:
Now change the sketch to:
Note the slower rise time:
So,
pin_config
looks like it is working.OK. Now change the code to:
And this is what we see when the code starts:
The pull-up on D6 is there initially, but then gets disabled by the SPI transaction. There must be something in the SPI transaction that overrides the pin configuration and disables the pull-up…
Let’s prove that by changing the code to:
And this is what we get:
So, the first transaction resets the pin configuration and disables the pull-up. But only the first one. Subsequent transactions do not re-disable the pull-up.
We can live with this, but it's something that anyone playing with CIPO pull-ups needs to be aware of…
For OpenLog Artemis:
enableCIPOpullUp
is here