Pages: [1]   Go Down
Author Topic: SPI.end() causes SPI.transfer() to hang even after a new SPI.begin()  (Read 1173 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 9
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It appears that something SPI.end() changes isn't being reset by SPI.begin() on the Due. As a result, if SPI.end() is used to disable SPI, it can't be re-enabled later in the program. A simplified example is shown below.

This sequence works:
Code:
SPI.begin();
SPI.transfer(0);

This sequence hangs on the Due, but works on other Arduino boards:
Code:
SPI.end();
SPI.begin();
SPI.transfer(0);
Logged

Offline Offline
God Member
*****
Karma: 32
Posts: 506
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I can confirm this. (The problem seems to be that SPI.end() calls SPI_Disable(), but SPI.begin doesn't call SPI_Enable() - it's called in the constructor.)

To fix this: open the file hardware/arduino/sam/libraries/SPI/SPI.cpp and at the beginning of the SPIClass::begin() method add the line
SPI_Enable(spi);
The method should now look like this:
Code:
void SPIClass::begin() {
        SPI_Enable(spi);
        // NPCS control is left to the user

        // Default speed set to 4Mhz
        setClockDivider(BOARD_SPI_DEFAULT_SS, 21);
        setDataMode(BOARD_SPI_DEFAULT_SS, SPI_MODE0);
        setBitOrder(BOARD_SPI_DEFAULT_SS, MSBFIRST);
}

I've added this issue to the Arduino github here: https://github.com/arduino/Arduino/issues/1406
« Last Edit: May 09, 2013, 08:52:36 am by stimmer » Logged


0
Offline Offline
Newbie
*
Karma: 0
Posts: 9
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks. That fixes the problem. Is there somewhere else I should be posting this to make sure this fix gets into the SPI release version?
Logged

Offline Offline
God Member
*****
Karma: 32
Posts: 506
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I've already reported the issue in the official place and as it's a simple one-liner I expect it will get fixed pretty soon.
Logged


Offline Offline
Full Member
***
Karma: 9
Posts: 109
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I am using the old AVR compatible api's.
I can confirm the above work around works for me too.

But after calling SPI.end(), I want to tristate SCK and MOSI. How do I do that? I tried adding
Code:
pinMode(MOSI, INPUT);
pinMode(SCK, INPUT);
But after that SPI.begin() does not work anymore.
I dare not configuring them as output before calling SPI.begin() because I noticed that SPIClass::begin() does not have code in it to do so, that is probably done for a reason.
Logged

Offline Offline
God Member
*****
Karma: 32
Posts: 506
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Does it work if you add the line:
Code:
SPI_Configure(spi, id, SPI_MR_MSTR | SPI_MR_PS | SPI_MR_MODFDIS);
immediately before each call to SPI.begin(); ?
Logged


Offline Offline
Full Member
***
Karma: 9
Posts: 109
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Almost, the initcb() (which is SPI_0_Init()) has to be called too.
Thanks!
Logged

Forum Administrator
Milano, Italy
Offline Offline
Sr. Member
*****
Karma: 22
Posts: 292
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Merged the fix upstream:

https://github.com/arduino/Arduino/commit/d101bf51a2c9ebe08be737dd9b5db8b32d64e44a

C
Logged

C.

Pages: [1]   Go Up
Jump to: