MarlinFirmware / Marlin

Marlin is an optimized firmware for RepRap 3D printers based on the Arduino platform. Many commercial 3D printers come with Marlin installed. Check with your vendor if you need source code for your specific machine.
https://marlinfw.org
GNU General Public License v3.0
16.14k stars 19.21k forks source link

[Question] Too many SD CS pins? #14492

Closed GMagician closed 5 years ago

GMagician commented 5 years ago

Sorry to continuos bother but there are some thing I don't understand... SOFT_SPI_xx_PINs are defined only in SdFatConfig.h and they seems related to Mega...Shouldn't they be declared in HAL? or pins?

GMagician commented 5 years ago

Another question...always about SD SS_PIN SDSS Why two pins used both for SD CS?

while I understand why SD_SS and LCD_SDSS in case of boards with both onboard SD and a LCD SD, I don't understand why LCD_SD is not defined often since (on all/most avr) SD is ... LCD SD

Grogyan commented 5 years ago

14495 removes a lot of pin declarations.

This may likely affect external SPI enabled devices, such as the MAX31855 and the MAX7219

ManuelMcLure commented 5 years ago

All of the pin definitions removed by #14495 were in a #if 0 block so it is impossible that any other code was using them.

Oops - nevermind - I was only seeing the first diff.

Bob-the-Kuhn commented 5 years ago

SOFT_SPI_xx_PINs are defined only in SdFatConfig.h

The soft SPI pins defined in SdFatConfig.h are only used to access the SD card.

The SdFat library is a general purpose SD card library originally aimed at the Arduino AVR series. In Marlin there is rarely a need to use the library's soft SPI. As far as I know all the 3D printer controllers are designed so that the SD card is tied to a hardware SPI.

I think all the AVR based controllers use the hardware SPI for just the SD card.

There are some 32 bit boards that use the same SPI pins for the SD card and the LCD and even the TMC2130 stepper drivers. Some combinations can use one hardware SPI controller to handle multiple devices. In most combinations the hardware SPI controllers can handle just one device and won't allow the soft SPIs to control the SPI pins which means that all devices must use soft SPIs. The soft SPI for the SD card is usually handled by the HAL. The soft SPI for the LCD is provided by the LCD software.

Why two pins used both for SD CS? SDSS SS_PIN

I think this is because some applications use the hardware SPI controller for the SD card so the select is SDSS. In general the select is called Slave Select or SS for short.

thinkyhead commented 5 years ago

In fact, I know of no instance where someone had to set USE_SOFTWARE_SPI to 1 in SdFatConfig.h. Can you think of any case where we would want this when using typical 3D printer setups?

Bob-the-Kuhn commented 5 years ago

I do not know of any case where this is used on a 3D printer.

I used it a long time ago in the early days of the LPC1768 in some test code. As I remember it, changes to options/defines in 2 or 3 files are required. Much easier now to just use the HAL's softSPI.

GMagician commented 5 years ago

@Bob-the-Kuhn

The soft SPI pins defined in SdFatConfig.h are only used to access the SD card.

Are you sure? I found no evidence of their use in code

There are some 32 bit boards that use the same SPI pins for the SD card and the LCD and even the TMC2130 stepper drivers. Some combinations can use one hardware SPI controller to handle multiple devices. In most combinations the hardware SPI controllers can handle just one device and won't allow the soft SPIs to control the SPI pins which means that all devices must use soft SPIs. The soft SPI for the SD card is usually handled by the HAL. The soft SPI for the LCD is provided by the LCD software.

The SS hardware controlled pin is a processor limit so I think HALs should support soft SPI by their own. One example of "board" specific behaviours is SAMD51. It support H/W spi with just 1 SS, but SS handling may be disabled. This will let us to use H/W spi clock/data control and S/W CS control. Again most (or all) 32 bits HALs have theirs own SOFT SPI handling (some of them simply say 'not available') so why SdFat and lcd need another SPI soft handling? By my spi knowledge, since spi can communicate with just 1 device at time (CS decide witch one), there is no need of "many" spi soft manager (only reason may be code optimization due to different clk freq and or mode, even if latter may be just an xor added to clock control).

I may think as "stupid man" because I don't know all Marlin backstage (and history), but this seems to me a easy to maintain solution

gloomyandy commented 5 years ago

I think the main reason that there are many soft SPI routines in Marlin is because more often than not the code containing that code was imported from another library or project (in some cases it is actually still maintained as an external lib - like TMCStepper). So the code already had the SPI code in it. Changing that code to use some sort of common SPI routine provided by the HAL or whatever would be extra work and makes updating to a newer version of that external code more difficult.

Oh and I'm pretty sure that Marlin always uses S/W chip select, the general rule is that the calling code (SD code, TMC code, LCD code whatever) manages the chip select pin and is responsible for setting it before calling the SPI transfer code. This mean that it is possible to maintain the CS value across multiple SPI transactions (which is needed by some devices). There are downsides to this though, there is no central point tracking CS state and so it is typically not possible to use a shared SPI bus from an interrupt routine etc.

GMagician commented 5 years ago

it is typically not possible to use a shared SPI bus from an interrupt routine etc.

That will be hard even with H/W support on CS, you should need a "transaction" H/W support to achieve that.

From Adafruit Grand Central point of view, there are 2 SPI lines, one on board, dedicated, and other that may be shared with external H/W (LCD, LCD SD, TMC and so on). Now what I need is to decide how HAL_SPI functions have to link with Marlin... Is there in the wild some other board that has separate SPI for SD and TMC/LCD and so on? I think there is, so all "Marlin" core can handle such situation (I don't have to split all thinks in code)

gloomyandy commented 5 years ago

The Marlin HAL really only exports a single SPI device (this is probably another reason for the large number of software SPI implementations). On many of the HALs this will use hardware SPI, but can often be configured to use software SPI, it is typically used by Marlin for access to the SD card and if other hardware shares the same SPI bus for access to that. After that it is pretty much a free for all I think!

On the LPC1768 most boards have two hardware SPI busses in use, one is usually wired to the onboard SD card reader, the other to external devices. The LPC176x HAL will switch which SPI device it exports depending upon the pin configurations (it will also use a software SPI implementation if the configured pins do not match the hardware devices, or if the software option is forced). The LPC176x framework can also export the onboard SD card reader as a USB mass storage device and the framework contains code that uses one of the hardware SPI devices for access to the reader. If Marlin is also configured to use the onboard reader then that hardware SPI device is actually shared between the framework and Marlin. Other HALs may do something similar. but I'm really not sure.

This entire area is a bit of mess really. It would be nice to have better support for multiple SPI busses (both hardware and software) from the HALs.

GMagician commented 5 years ago

It would be nice to have better support for multiple SPI busses (both hardware and software) from the HALs.

That's what I was thinking but it's not something I can manage. I'm in trouble to figure out how Marlin is working to and my SPI... A good solution may be to have SPI class like serial...maybe a template class where you specify pins and depending on them H/W vs S/W spi may be used, but maybe 2 SPI classes are enough.. one for onboard devices and other shared (latest may be soft or H/W since I thing former will be designed to handle H/W spi).

Bob-the-Kuhn commented 5 years ago

SPIs, SPIs, … everywhere you look there are SPIs.

Yes, Marlin assumes the "application" controlls the slave select.

I think the SAM series (used in DUE) is the only CPU that has a hardware SPI that is designed to control multiple slave select pins. It's a neat device but ... since Marlin is meant to run on multiple platforms we try to avoid CPU specific code unless we have no choice.

The HALs provide a single SPI primarily aimed at the SD card. Most can be set to use a hardware SPI controller or a soft SPI. The SD card software is not aware of which implementation is in use.

The LPC1768 boards usually have one hardware SPI controller dedicated to the on board SD card and one tied to the LCD interface. There is at least one where the same hardware SPI controller is tied to both.

LCDs add a layer of complication. The nicest ones have completely seperate SPI busses for the LCD and it's SD card. There is one I know of that has one bus and two slave selects. There is one SOB of a LCD/motherboard combination that has one bus and only one slave select.

Life gets simpler once you get away from the LCD and SD card area. The libraries for some of these devices have a provision to use a hardware controller but I'm not aware of any actually using one. All of these soft SPIs use unique names for the SPI pins.

Since Marlin doesn't (yet) use a real time operating system, all the SPI routines wait for the transmission to complete before proceeding. The use of an interrupt routine to service a hardware SPI controller is just added overhead right now.

I worked on a SPI manager a couple of years ago. I had it working for the LPC1768 SD card and one LCD. I stopped working on it when I realized it would be a maintenance nightmare. Every library that used a SPI would need to be modified to use the interface. Every time one of the libraries changed then the modification would need to be copied forward by the Marlin folks.

GMagician commented 5 years ago

@Bob-the-Kuhn from your statement now I know we are in a nightmare and we have to stay in it. Well I'll do some tryes to integrate SPI and hope to find some light in this dark side of Marlin :-D

Thanks all for your comments

Bob-the-Kuhn commented 5 years ago

Trying to hit the items I missed in my previous post


The soft SPI pins defined in SdFatConfig.h are only used to access the SD card.

Are you sure? I found no evidence of their use in code

Correct - the SD card library's soft SPI is not used. Enabling it is a real pain and requires non-standard methods (can't just modify the configuration or pins files).


Why all the different soft SPI routines? As stated earlier they come as part of the library for the specific device/function. These libraries are usually also used by non-Marlin applications which means they need to provide their own SPI routines for the general case.

Bob-the-Kuhn commented 5 years ago

find some light in this dark side of Marlin

If Marlin were dedicated to a single CPU/hardware configuration then we could make things much simpler.

As I see it we have two main choices:

Both approaches have large drawbacks.

It's well above my paygrade to make an informed decision on what is better in the long run.

GMagician commented 5 years ago

I'm wondering if a Marlin manager with multi point entries to fullfill different libraries requirements...I don't understand why so many different approach to SPI...you can read, write clocking n bits and read back...I think SPI is not more parametrizable than a standard rs232 (modes may be solved with xors). But looking at troubles I have to simply integrate spi in a board, I'm not the right one to find a solution

GMagician commented 5 years ago

@gloomyandy I've some doubt. You said Marlin:

The Marlin HAL really only exports a single SPI device

and that's what I can see, but if this SPI uses internal bus (onboard dedicated pins)...how can you use an LCD or TMC connected other SPI pins (external SPI bus)?

spibegin, init and so on declared in HAL are used by (AFAIK) SD, some strange devices (some ADC?!?) digipots...then?

gloomyandy commented 5 years ago

As I said the HAL only supports a single SPI device, so if the LCD and and/or TMC devices are not on the same SPI bus as the SD card then access to them will be via software SPI and will be using the SPI code built in to those libraries. Remember that on most (all?) systems just because an LCD/TMC is attached to SPI hardware capable pins you do not have to use the hardware SPI, you can also just use the pins as GPIO devices and run software SPI over them. No it's not the best way to do and yes it is a bit of a mess. But it actually works surprisingly well.

If there is code that always uses the HAL supplied SPI routines then I think you may find that they only work if they can use the same bus as the SD card (assuming the SD card is in use). Rem

Bob-the-Kuhn commented 5 years ago

The SPI provided by the HAL is dedicated to the SD card.

Another complication is the SPI mode. The SD cards use SPI mode 0 while most LCDs like SPI mode 3.

If you want a challenge then consider the L6470 family of stepper drivers. They use a SPI daisy chain. This system minimizes hardware by using just one slave select which is tied to every driver. In a three driver system the MOSI of the CPU is tied to the MOSI of the first driver, the MISO of the first driver is tied to the MOSI of the second driver, the MISO of the second driver is tied to the MOSI of the third driver and the MISO of the third driver is tied to the MISO of the CPU. The result is you need to send three bytes of data for every SPI transfer (one command and two NOOPs). If you want to send a command to driver 1 then you set the slave select active, send NOOP, send NOOP, send command and then set the slave select inactive.

I think the digipots are all I2C but I could easily be wrong.

I know there are SPI and I2C based thermal input devices supported by Marlin. I've never looked at the details on these.


Here's an overview of the SPI users that I'm aware of.

SD card on LCD:

SD card on controller:

LCD:

TMC2130 stepper drivers:

L6470 stepper drivers:

Other SPI based stepper drivers: I don't remember

Thermal inputs: Never investigated them.

GMagician commented 5 years ago

Edit: Well I see that some of spi devices below reported are board specific (dac) or use a spi channel that may define which bus to use...proceeding

Original: Well the fact that there is no system wide SPI class similar to what serial does is a bad thing. From what I learned, slave CS is handled by software because of "only one pin supported in H/W" (due is only exception) so, when many slaves share the bus, only soft may/hate to be used (excpection is only samd51, it can disconnect CS from H/W handling so any GPIO pin may be used as CS). @Bob-the-Kuhn different modes and/or daisy are not an issue... Former, H/W speaking, may be handled by spi.begintransaction, soft by xors on clk, some tweak on data read or even change called function (using pointer to functions like c++ does on virtual functions). daisy chain is no an issue...is just who call spi.send that has to call more of such functions with appropriate data.

Moving back to HAL spi that connect to SD is not completely true. I see calls to spiSend in: 'dac_dac084s085.cpp', 'DUE/LPC1768 u8g', 'SpiEeprom.cpp', 'SdCard.cpp', 'usb_host.cpp' then if my hal_spi handles onboard SD, it seems that many other H/W devices will respond to it and, in my personal case all the other should use the shared spi bus (that it's also a H/W spi port) I think that, always for samd51, it will be impossible to use onboard SD without change how Marlin uses SPI.

gloomyandy commented 5 years ago

The SPI provided by the HAL is dedicated to the SD card.

While I'd agree that the primary user of the HAL SPI device is the SD card, it is sometimes used by other devices (and this is the case even if SD support is not enabled).The TMC library can use the HAL supplied SPI interface if it is configured to use "hardware" SPI. Note that sometimes the HAL supplied SPI interface may not use hardware SPI (even though it is attached to SPI capable pins). So for instance on the SKR V1.1 board I've had the LCD, the SD card and 5 TMC drivers all happily using the same SPI bus, (but because the LCD was in use the HAL supplied device was automatically switched to software SPI). If I disabled the LCD then the TMC drivers and SD card happily ran sharing the (now hardware) HAL SPI. It can be very confusing to work out exactly what is going on with SPI with Marlin!

gloomyandy commented 5 years ago

@GMagician different SPI modes certainly are an issue with Marlin as it is at the moment. Many of the SPI users within Marlin (often code that has come from an external library) do not use spi.begintransaction so there is no way to switch the spi mode if the bus is being shared. Then there are the "external" libraries like TMCStepper which also do not use begintransaction, which would need to be be modified. Finally many of the current HALs do not actually implement begintransaction. So at the very least any attempt to use a shared hardware SPI bus with different modes active will need changes to core Marlin code.

As to using the onboard SD reader on your samd51 device I think you may be surprised. The setup you have is very similar to that on say the SKR V1.3 board and there are many users happily using the onboard SD card reader with that board. Although it is far from ideal Marlin is very configurable and many of the other callers to spiSend can be configured to use software SPI and so can use the "other shared SPI bus" rather than the one routed to the onboard reader. Some of the other uses of the HAL supplied SPI device that you have found (like eeprom and dacs etc.) are devices that may only rarely (if ever) be used with a samd51. This is certainly the case with the LPC176x based boards. I suspect that if/when someone wants to use these devices then the code (which is basically making false assumptions about how the device can be attached to a system) will get fixed.

GMagician commented 5 years ago

do not use spi.begintransaction [cut] Then there are the "external" libraries like TMCStepper which also do not use begintransaction, which would need to be be modified.

with this we go back to what @Bob-the-Kuhn said, he tried to uniform calls with a lot of new issues (also related to code maintenance).

While I get more info from you I realize how big is SPI hell in Marlin, due to not standardization in SPI use, this will be ever and ever worst...

I hope to be able to reach the goal

The TMC library can use the HAL supplied SPI interface if it is configured to use "hardware" SPI. Note that sometimes the HAL supplied SPI interface may not use hardware SPI

This will add more confusion to all because, it seems to me, tmc soft mode is: proprietary spi bus, while tmc hard mode is: hal shared spi...then hal_spi may be hard or soft. Or have I misunderstand you?

I don't really know how, you maintainers, can survive to all these ;-)

gloomyandy commented 5 years ago

The TMCStepper library has its own software SPI implementation but I would not say it was any more propriety than any of the other many SPI implementations in Marlin! It should work happily alongside other software SPI modes. When using hard mode the library just makes calls to the HAL for SPI, the actual implementation of that SPI interface is then up to the HAL and can be either software or hardware.

I think with trying to deal with this confusion there are a few things to think about...

  1. You can probably view the various software SPI solutions as a black box, just assume that they work. So long as all users of a bus are using software SPI then everything will probably just work fine. It may not be pretty but it will probably work.
  2. Although it is kind of irritating not using hardware SPI is not that big a deal. Other than the SD card reader most devices do not actually transfer that much data and so do not need high speed transfers. Also because of the way that Marlin uses SPI, hardware SPI is not that much of an advantage (as Marlin will just spin waiting for the transfer to complete, happily wasting cycles). Luckily with a 32bit cpu we have a few more cycles to waste.
  3. Although it kind of makes me groan every time I look at SPI and find yet another SPI implementation, trying to fix that problem is not at all easy. It is also to some extent an "all or nothing" solution, if you want to use hardware SPI on a bus then everything that uses that bus must use that solution, if there is just one software SPI user of the bus then you are screwed. This means that fixing this problem will almost certainly mean modifying a lot of code and pulling what is in effect externally maintained code into Marlin. That may easily end up being a bigger maintenance nightmare then what we have now!
  4. Marlin supports a very wide range of hardware. Sometimes doing that means you have to use less than optimum solutions for some of that hardware.
  5. Marlin is trying to make the move from 8 to 32bit hardware, this is a big step, but we are getting pretty close. "Fixing" the SPI problem is a big change and now is probably not the time to make that change.

Final thoughts on this. Fixing this sort of "architectural problem" is not easy. I've worked for several major software companies (including SCO, Sun Microsystems and Oracle), working on code that ran on many different platforms (but probably not as many as Marlin is trying to support!). Those teams had all of the hardware, test setups, test groups etc. and doing this sort of change would not have been a trivial project. Making these changes with a very part time, distributed team were hardly anyone (probably no-one) has access to all of the different hardware platforms will make it even harder. Good luck to anyone that takes it on!

AnHardt commented 5 years ago

The hardware SPI CS pins get their real power when being a slave (receiving mode). The SPI hardware can sleep, until the pin is going low. The other pins can go tri-state, not loading the bus.

gloomyandy commented 5 years ago

@AnHardt Does anything in Marlin ever run in slave mode?

AnHardt commented 5 years ago

Does anything in Marlin ever run in slave mode?

As long we are talkig about SPI - No. However, what i described are the reasons for the existence of hardware SPI CS pins. For host-mode about every pin can be used. In the future this may be different. For example the temperature controller could be on its own processor communicating as a SPI-slave but part of Marlin.

If we are talking about Marlin in general - Yes. When connected to a host-computer, sending g-code - Marlin is the slave.

thinkyhead commented 5 years ago

I think with trying to deal with this confusion there are a few things to think about...

The thing is that SPI is so darned simple as a protocol — just a glorified shift register. So it's easy to throw a software implementation into a simple loop in a sketch when doing casual coding, but if you want to use more SPI buses, then also a hardware-based bus with asynchronous performance, self-management of CS pins, and so on, then there well be some platform-specific setup and details involved. So, yes, definitely… the "black box" encapsulation is needed for the sake of the application.

We all fully expected the SPI code in the HAL to be a pretty scattered creature to start with. And then the idea would be to wrangle as much into a common class as possible and keep all the shared code together. As usual, Marlin would preserve the behavior where SPI objects are allocated statically at compile-time, initialized at runtime (or any time before use), and there's a common interface at the HAL level.

I think we can take that job in small incremental steps, and we will get there. The first step is actually the easy one, but kind of tedious. And that is to actually list out everything about SPI in Marlin. Everyplace where SPI pins are defined and used - including platform cores. Every point where an SPI class instance is referenced. And of course, all the places where SPI classes, methods, and data members are defined. And then, describe the actual usage of each SPI connection, how often they are called and when, and so on…

Once that process is done, then consolidate a method and/or a class here and there. If needed, use "mixin" classes, where all things possible to make common are in one class, and then platform-specific add-ons are also inherited.

I agree we would want to never touch behavior in this process. If something is using a distinct timing or order-of-operations, then it should be left untouched.

So… small and careful steps are best here, and it will slowly improve.

github-actions[bot] commented 4 years ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.