Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trying to figure out two devices on the SPI bus #504

Open
brightproject opened this issue Dec 29, 2024 · 2 comments
Open

Trying to figure out two devices on the SPI bus #504

brightproject opened this issue Dec 29, 2024 · 2 comments

Comments

@brightproject
Copy link

brightproject commented Dec 29, 2024

Good day @greiman

According to GitHub tradition, I express my gratitude to you for your work🙂

My microcontroller stm32f411ceu6

STM32F411CEU6_WeAct_Black_Pill_V2 0-1 1

I compile the code into vscode + .pio and use the framework

https://github.com/platformio/platform-ststm32

I also have a BNO08x sensor, which is connected via the I2C bus via the library

https://github.com/adafruit/Adafruit_BNO08x

Bus speed is 400 kHz.

I connect two different devices to it via SPI:
CAN bus transceiver

398922519-d7f98f14-8745-4e5d-863a-4c51b6c6bb63

module with microSD

398922643-14263056-a90a-4820-9cbe-5afab92b90f0

Two device boards are connected to one SPI, only different SS contacts.

The connection is very simple, I use standard contacts for the SPI:

MOSI - PA7
MISO - PA6
SCK - PA5
SD_CS/SS - PB0
CAN_CS/SS - PA4

The CAN module works fine, checked in another code.
Now I decided to launch in addition to the CAN module also a module for saving data to the micro SDHC card.
I have three microSD cards - 512 MB(fat16), 8 GB(fat32) and 32 GB(fat32).

398924883-3ca4aacd-cca2-4cc0-82bf-b0635663c3d4

The cards are not of the best quality, the 512 MB card stopped being detected after the first attempt to consider it a SD module, and it can't even be formatted via the program.

https://www.sdcard.org/downloads/formatter/sd-memory-card-formatter-for-windows-download/

The best and fastest working microSD is 8GB, its SdInfo report is below:

sdFat version: 2.2.3

Assuming the SD is the only SPI device.
Edit DISABLE_CS_PIN to disable an SPI device.

Assuming the SD chip select pin is: 200
Edit SD_CS_PIN to change the SD chip select pin.

type any character to start
init time: 2 ms

Card type: SDHC
sdSpecVer: 6.00
HighSpeedMode: true

Manufacturer ID: 0XFE
OEM ID: 4V
Product: ASTC\0
Revision: 1.2
Serial number: 0X7C1
Manufacturing date: 8/2024
CID HEX: FE3456415354430012000007C1018883

cardSize: 7818.18 MB (MB = 1,000,000 bytes)
flashEraseSize: 128 blocks
eraseSingleBlock: true
dataAfterErase: ones
CSD HEX: 400E00325B5900003A3F7F800A400027

OCR: 0XC0FF8000

SD Partition Table
part,boot,bgnCHS[3],type,endCHS[3],start,length
1,0X0,0X82,0X3,0X0,0XB,0X81,0XCB,0XB6,8192,15261696
2,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0,0
3,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0,0
4,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0,0

Scanning FAT, please wait.

Volume is FAT32
sectorsPerCluster: 64
fatStartSector: 12658
dataStartSector: 16384
clusterCount: 238336
freeClusterCount: 238323

All this is just information, for the general picture.
The work of two modules CAN bus transceiver and microSD module on one SPI bus is interesting.
Using a logic analyzer, I measured the speed of one module CAN

can_no_sd

Two simultaneously working modules CAN and microSD

can_yes_sd

Probably screenshots are not as clear as viewing data directly in the analyzer.
As you can see, when

CAN.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ)

is running, the pauses between sending messages to CAN are on average 6 ms.
When

CAN.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ)

and

sd.begin(SD_CS_PIN, SD_SCK_MHZ(20))

are running, the pauses between sending messages to CAN are about 16-20 ms, which significantly affects the external device that receives data via the CAN bus - it begins to noticeably slow down with data display.
But my question is not specifically about this, my question is about how and where does the

SdFat.h

library configure the SPI bus?
The SPI bus for the CAN module is configured as follows

beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE3));

What mode does SdFat use?

Regarding SdFat, I don't understand what mode is needed, I set the speed directly in the Arduino Setup section:

SD_SCK_MHZ(20)

But despite the fact that both devices have a speed of 20 MHz on the SPI bus, the analyzer shows complete nonsense, there is never a stable speed, but the problem is still not in this, as it seems to me, but in the fact that the library for the CAN module closes the SPI connection every transaction

#define MCP2515_UNSELECT() digitalWrite(MCPCS, HIGH)

And the SdFat library does something of its own, and I don't understand it

CAN_FATSD_2

As you can see from the screenshot, the SdFat select pin chip occupies the SPI bus for 7 ms, and the select chip of the CAN module occupies the SPI bus for 1.18 ms.

As far as I understand, the CS pin for the operation of the microSD module begins its cycle by pressing the CS pin to 0 - label 0, then it pulls the CS pin twice and at label 1 it completes the recording cycle and then there is a pause until label 2. The CS pin of the CAN module operates between labels 1 and 2.

can_sd_duration_cs

In general, I am not a big expert in analyzing what is happening on the SPI bus, perhaps the community will help me figure out the issue and make the operation of two devices on the SPI bus correct and coordinated.

@greiman
Copy link
Owner

greiman commented Dec 30, 2024

Sharing an SPI port with an SD and any device that requires quick response is a bad idea.

Run the bench example in shared and dedicated mode to see why.

Here is a quote from the SD standard:

The host should use 100 ms timeout (minimum) for single and multiple read operations
rather than using TAAC and NSAC.

The host should use a fixed timeout for write operations rather than using a timeout calculated from
the R2W_FACTOR parameter.It is strongly recommended for hosts to implement more than 500ms
timeout value even if the card indicates the 250ms maximum busy length.

In general, an SD can have occasional long delays. See the Physical Layer Simplified Specification here.

When I design a time critical app I use a dedicated SPI port for the SD, multiple threads in a RTOS or interrupts to provide fast access for sensors. Also provide sufficient buffer.

But my question is not specifically about this, my question is about how and where does the

SdFat.h

library configure the SPI bus?

Here is where the SPI configuration is set.

beginTransaction() is called here for SD read/write operations. Actually it will be called lower in an activate() function.

@brightproject
Copy link
Author

When I design a time critical app I use a dedicated SPI port for the SD, multiple threads in a RTOS or interrupts to provide fast access for sensors.

I am extremely grateful to you, I will try to allocate a separate SPI for the microSD module.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants