2

I'm building a battery operated device and must shutoff MOSI pin during sleep because it leaks current through the SD card if I don't (about 400 µA).

Problem is, it won't stay off. I've looked at SPI documentation and as far as I know I just need to call spi.end() then set pinmode to output and finally digitalWrite LOW. I observe with an oscilloscope that it does go low upon my asking it to but only for about 1 µs (actually it goes low twice within a 5 µs time period).

I've also tried manually setting the pin low using the PORT registers and the behavior is the same... see relevant code:

spi.end();  

//pinMode(pin_MOSI, OUTPUT);
//digitalWrite(pin_MOSI, LOW);

//Both above (commented out) and below result in the same behavior -- pin does not stay LOW

DDRB |= B00100000;            //set pin 5 as output
PORTB &= B11011111;           //set output low for pin 5

delay(5000);

...As you can see there is a delay to ensure that it isn't being set high by some other code.

Is there some sort of SPI interrupt that automatically sets the pin high again?

Hardware details:

MCU: ATMEGA1284P; Programmer: Atmel-ICE


UPDATE (13-Mar-2019):

I didn't realize that SPI is implemented by Atmel in hardware directly (see datasheet page 105):

MOSI/PCINT13 – Port B, Bit 5 – MOSI: SPI Master Data output, Slave Data input for SPI channel. When the SPI0 is enabled as a slave, this pin is configured as an input regardless of the setting of DDB5. When the SPI is enabled as a master, the data direction of this pin is controlled by DDB5. When the pin is forced to be an input, the pull-up can still be controlled by the PORTB5 bit.

I am currently chasing down this latest information and will hopefully come to a resolution soon. I will post any progress.

  • is it a SD module with logic level conversion? – Juraj Mar 13 at 5:01
  • @Juraj: No level shifting, straight 3.3 volts to the SD card. – DatuPuti Mar 13 at 15:51
  • I thought you using SPI.begin() and SPI.end() to use the embedded hardware from the Arduino IDE. You are bit-banging instead? – CrossRoads Mar 13 at 17:00
  • @CrossRoads: I'm using SPIClass from <spi.h>. I'm assuming that is part of the Arduino core but I'm not certain. I have successfully gotten it to work by clearing the SPI enable bit (SPE) from the SPCR register so I know the library was not doing it for me. – DatuPuti Mar 13 at 17:05
  • @Juraj: I'm using ATmega1284P which is a 3.3 volt MCU -- doesn't have 5 volts. Thanks! – DatuPuti Mar 13 at 17:46
1

Indeed, SPI is hardware implemented. I was able to get the MOSI pin to operate as intended by clearing the SPI enable bit from the SPCR register as follows:

SPCR &= 0B10111111;  //disable SPI

To re-enable after sleep, I'm assuming I'll just do SPCR |= 0B01000000; ...pretty sure that will work but I'll update here if I have to modify my solution.

.

Perhaps also pertinant information:

I was using an object of SPIClass in SPI.h which is from the Arduino core libraries -- for some reason it wasn't disabling SPI in hardware when calling the spi.end() method, maybe because there was some other SPI object initialized by some other library. Here is the source from SPI.cpp for the end method:

void SPIClass::end() {
  uint8_t sreg = SREG;
  noInterrupts(); // Protect from a scheduler and prevent transactionBegin
  // Decrease the reference counter
  if (initialized)
    initialized--;
  // If there are no more references disable SPI
  if (!initialized) {
    SPCR &= ~_BV(SPE);
    interruptMode = 0;
    #ifdef SPI_TRANSACTION_MISMATCH_LED
    inTransactionFlag = 0;
    #endif
  }
  SREG = sreg;
}

The line SPCR &= ~_BV(SPE); should have done the job for me but I'm guessing it never got there because initialized was probably still non-zero.

  • If you didn't have #include <SPI.h> at the top of your sketch, how were you able to use SPI.begin(), SPI.transfer(); etc? – CrossRoads Mar 13 at 17:39
  • @CrossRoads: I did have SPI.h included -- sorry if that was not clear. – DatuPuti Mar 13 at 17:45
  • I thought I read something about not using the library, but I don't see it now. Perhaps I had two topics confused. Glad you got it sorted. – CrossRoads Mar 13 at 18:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.