Closed Spaceballs3000 closed 5 months ago
Thanks for the question, I will dive into this asap but it might take a few days.
Please give this a try Code compiles for ESP32 but it is not tested with hardware yet Please let me know the results.
//
// FILE: MCP23S17_test_connection_ESP32.ino
// AUTHOR: Rob Tillaart
// PURPOSE: test MCP23S17 library
// URL: https://github.com/RobTillaart/MCP23S17
//
// see issue #42 library
#include "MCP23S17.h"
const int selectPin = 10;
SPIClass * myspi = new SPIClass(FSPI);
MCP23S17 MCP(selectPin, myspi); // HW SPI address 0x00
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.print("MCP23S17_LIB_VERSION: ");
Serial.println(MCP23S17_LIB_VERSION);
Serial.println();
delay(100);
myspi->begin();
bool b = MCP.begin();
Serial.println(b?"true":"false");
int c = testConnection(MCP);
Serial.print("connection: ");
Serial.println(c);
}
void loop()
{
}
int testConnection(MCP23S17 & mcp)
{
uint16_t magic_test_number = 0xABCD;
// Read the current polarity configuration to restore later
uint16_t old_value;
if (! mcp.getPolarity16(old_value)) return -1;
// Write the magic number to polarity register
if (! mcp.setPolarity16(magic_test_number)) return -2;
// Read back the magic number from polarity register
uint16_t temp;
if (! mcp.getPolarity16(temp)) return -3;
// Write old configuration to polarity register
if (! mcp.setPolarity16(old_value)) return -4;
// Check the magic connection test
if (temp != magic_test_number) return -5;
return 0; // OK
}
// -- END OF FILE --
Running that code as is outputs this, over and over.
00:40:30.940 -> Rebooting...
00:40:30.940 -> ESP-ROM:esp32s3-20210327
00:40:30.940 -> Build:Mar 27 2021
00:40:30.940 -> rst:0xc (RTC_SW_CPU_RST),boot:0x8 (SPI_FAST_FLASH_BOOT)
00:40:30.940 -> Saved PC:0x403797d2
00:40:30.940 -> SPIWP:0xee
00:40:30.940 -> mode:DIO, clock div:1
00:40:30.940 -> load:0x3fce3818,len:0x508
00:40:30.940 -> load:0x403c9700,len:0x4
00:40:30.940 -> load:0x403c9704,len:0xad0
00:40:30.940 -> load:0x403cc700,len:0x29e4
00:40:30.940 -> entry 0x403c9880
00:40:31.072 ->
00:40:31.072 -> MCP23S17_LIB_VERSION: 0.5.2
00:40:31.072 ->
00:40:31.207 -> Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
00:40:31.207 ->
00:40:31.207 -> Core 1 register dump:
00:40:31.207 -> PC : 0x42002016 PS : 0x00060a30 A0 : 0x82001de8 A1 : 0x3fcec130
00:40:31.207 -> A2 : 0x00000000 A3 : 0x007a1200 A4 : 0x007a1200 A5 : 0xffffffff
00:40:31.207 -> A6 : 0x000000ff A7 : 0x3fc95a6c A8 : 0x82002ea5 A9 : 0x3fcec110
00:40:31.207 -> A10 : 0x00000000 A11 : 0x00000000 A12 : 0x3fc95a6c A13 : 0x00000000
00:40:31.207 -> A14 : 0x000000ff A15 : 0x3fc95a6c SAR : 0x00000020 EXCCAUSE: 0x0000001c
00:40:31.207 -> EXCVADDR: 0x0000001c LBEG : 0x420040e4 LEND : 0x420040f1 LCOUNT : 0x00000000
00:40:31.207 ->
00:40:31.207 ->
00:40:31.207 -> Backtrace: 0x42002013:0x3fcec130 0x42001de5:0x3fcec160 0x42001eb2:0x3fcec180 0x42001aa9:0x3fcec1a0 0x42004eda:0x3fcec1c0
00:40:31.207 ->
00:40:31.207 ->
00:40:31.207 ->
00:40:31.207 ->
00:40:31.207 -> ELF file SHA256: 71f48bab4ab95527
00:40:31.207 ->
00:40:31.207 -> Rebooting...
Mmm not expected that,
Replace FSPI with VSPI or HSPI? Does it give same crash?
Using VSPI it crashes (note added in #include
1:39:42.708 -> Rebooting...
01:39:42.708 -> ESP-ROM:esp32s3-20210327
01:39:42.708 -> Build:Mar 27 2021
01:39:42.708 -> rst:0xc (RTC_SW_CPU_RST),boot:0x8 (SPI_FAST_FLASH_BOOT)
01:39:42.708 -> Saved PC:0x403797d2
01:39:42.708 -> SPIWP:0xee
01:39:42.708 -> mode:DIO, clock div:1
01:39:42.708 -> load:0x3fce3818,len:0x508
01:39:42.708 -> load:0x403c9700,len:0x4
01:39:42.708 -> load:0x403c9704,len:0xad0
01:39:42.708 -> load:0x403cc700,len:0x29e4
01:39:42.708 -> entry 0x403c9880
01:39:42.836 ->
01:39:42.836 -> MCP23S17_LIB_VERSION: 0.5.2
01:39:42.836 ->
01:39:43.006 -> Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
01:39:43.006 ->
01:39:43.006 -> Core 1 register dump:
01:39:43.006 -> PC : 0x42002016 PS : 0x00060a30 A0 : 0x82001de8 A1 : 0x3fcec130
01:39:43.006 -> A2 : 0x00000000 A3 : 0x007a1200 A4 : 0x007a1200 A5 : 0xffffffff
01:39:43.006 -> A6 : 0x000000ff A7 : 0x3fc95a6c A8 : 0x82002ea5 A9 : 0x3fcec110
01:39:43.006 -> A10 : 0x00000000 A11 : 0x00000000 A12 : 0x3fc95a6c A13 : 0x00000000
01:39:43.006 -> A14 : 0x00000000 A15 : 0x00000000 SAR : 0x00000020 EXCCAUSE: 0x0000001c
01:39:43.006 -> EXCVADDR: 0x0000001c LBEG : 0x420040e4 LEND : 0x420040f1 LCOUNT : 0x00000000
01:39:43.006 ->
01:39:43.006 ->
01:39:43.006 -> Backtrace: 0x42002013:0x3fcec130 0x42001de5:0x3fcec160 0x42001eb2:0x3fcec180 0x42001aa9:0x3fcec1a0 0x42004eda:0x3fcec1c0
01:39:43.006 ->
01:39:43.006 ->
01:39:43.006 ->
01:39:43.006 ->
01:39:43.006 -> ELF file SHA256: f0a696c5210ed340
01:39:43.006 ->
01:39:43.006 -> Rebooting...
mmm, no hardware setup to test (too busy with my own project deadlines coming weeks)
Just a guess - add SPI.begin(); before myspi->begin() , might be some initialization missing.
From: https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/fatal-errors.html#id4
01:39:43.006 -> Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
LoadProhibited, StoreProhibited link These CPU exceptions happen when an application attempts to read from or write to an invalid memory location. The address which has been written/read is found in the EXCVADDR register in the register dump. If this address is zero, it usually means that the application has attempted to dereference a NULL pointer. If this address is close to zero, it usually means that the application has attempted to access a member of a structure, but the pointer to the structure is NULL. If this address is something else (garbage value, not in 0x3fxxxxxx - 0x6xxxxxxx range), it likely means that the pointer used to access the data is either not initialized or has been corrupted.
The EXCVADDR is not zero, so not a NULL pointer problem.
If this address is close to zero, it usually means that the application has attempted to access a member of a structure, but the pointer to the structure is NULL.
The EXCVADDR is 0x0000001c == 28 which is close enough to zero to be the issue.
to be continued.
mmmm
try
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.print("MCP23S17_LIB_VERSION: ");
Serial.println(MCP23S17_LIB_VERSION);
Serial.println();
delay(100);
if (myspi == NULL)
{
Serial.println("NULL pointer problem");
while(1);
}
myspi->begin();
...
adding SPI.begin(); before myspi->begin(); still crashes on either FSPI or VSPI
Crashes using
` void setup() { Serial.begin(115200); Serial.println(); Serial.print("MCP23S17_LIB_VERSION: "); Serial.println(MCP23S17_LIB_VERSION); Serial.println(); delay(100);
if (myspi == NULL) { Serial.println("NULL pointer problem"); while(1); } myspi->begin();
...
`
A minimalistic test
//
// FILE: MCP23S17_minimal_test_ESP32.ino
// AUTHOR: Rob Tillaart
// PURPOSE: test MCP23S17 library
// URL: https://github.com/RobTillaart/MCP23S17
//
// see issue #42 library
#include "MCP23S17.h"
const int selectPin = 10;
void setup()
{
Serial.begin(115200);
Serial.println(MCP23S17_LIB_VERSION);
Serial.println();
delay(100);
SPIClass * myspi = new SPIClass(FSPI); // HSPI, VSPI ...
if (myspi == NULL)
{
Serial.println("NULL pointer problem");
while(1);
}
delay(100);
MCP23S17 MCP(selectPin, myspi);
myspi->begin();
bool b = MCP.begin();
Serial.println(b?"true":"false");
}
void loop()
{
}
// -- END OF FILE --
By having all code in setup, the initialization of the MCP23S17 object is explicit after the first print.
Pasted it as is, still crashes.
03:11:09.923 -> ESP-ROM:esp32s3-20210327
03:11:09.923 -> Build:Mar 27 2021
03:11:09.970 -> rst:0xc (RTC_SW_CPU_RST),boot:0x8 (SPI_FAST_FLASH_BOOT)
03:11:09.970 -> Saved PC:0x403797d2
03:11:09.970 -> SPIWP:0xee
03:11:09.970 -> mode:DIO, clock div:1
03:11:09.970 -> load:0x3fce3818,len:0x508
03:11:09.970 -> load:0x403c9700,len:0x4
03:11:09.970 -> load:0x403c9704,len:0xad0
03:11:09.970 -> load:0x403cc700,len:0x29e4
03:11:09.970 -> entry 0x403c9880
03:11:10.048 -> 0.5.2
03:11:10.048 ->
03:11:10.308 -> Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
03:11:10.308 ->
03:11:10.308 -> Core 1 register dump:
03:11:10.308 -> PC : 0x42001d6e PS : 0x00060a30 A0 : 0x82001b40 A1 : 0x3fcec110
03:11:10.308 -> A2 : 0x00000000 A3 : 0x007a1200 A4 : 0x007a1200 A5 : 0xffffffff
03:11:10.308 -> A6 : 0x000000ff A7 : 0x3fc95a50 A8 : 0x82002b39 A9 : 0x3fcec0f0
03:11:10.308 -> A10 : 0x00000000 A11 : 0x00000000 A12 : 0x3fc95a50 A13 : 0x00000000
03:11:10.308 -> A14 : 0x000000ff A15 : 0x3fc95a50 SAR : 0x00000020 EXCCAUSE: 0x0000001c
03:11:10.308 -> EXCVADDR: 0x0000001c LBEG : 0x42003d78 LEND : 0x42003d85 LCOUNT : 0x00000000
03:11:10.308 ->
03:11:10.308 ->
03:11:10.308 -> Backtrace: 0x42001d6b:0x3fcec110 0x42001b3d:0x3fcec140 0x42001c0a:0x3fcec160 0x42001a71:0x3fcec180 0x42004b6e:0x3fcec1c0
03:11:10.308 ->
03:11:10.308 ->
03:11:10.308 ->
03:11:10.308 ->
03:11:10.308 -> ELF file SHA256: 2f32fde9d2d7e1e8
03:11:10.308 ->
03:11:10.308 -> Rebooting...
It looks like the same crash, so we must close in on the constructor. Time to think...
Found this snippet about the ESP32-S3 in my MCP_DAC lib, which relates to the HSPI etc.
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
#define FSPI 0
#define HSPI 1
#else
#define FSPI 1 //SPI bus attached to the flash (can use the same data lines but different SS)
#define HSPI 2 //SPI bus normally mapped to pins 12 - 15, but can be matrixed to any pins
#if CONFIG_IDF_TARGET_ESP32
#define VSPI 3 //SPI bus normally attached to pins 5, 18, 19 and 23, but can be matrixed to any pins
#endif
#endif
Can you run this sketch?
//
// FILE: ESP32_S3_SPI_test.ino
// AUTHOR: Rob Tillaart
// PURPOSE: test
// URL: https://github.com/RobTillaart/MCP23S17/issues/42
#include "SPI.h"
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
#define FSPI 0
#define HSPI 1
#else
#define FSPI 1 //SPI bus attached to the flash (can use the same data lines but different SS)
#define HSPI 2 //SPI bus normally mapped to pins 12 - 15, but can be matrixed to any pins
#if CONFIG_IDF_TARGET_ESP32
#define VSPI 3 //SPI bus normally attached to pins 5, 18, 19 and 23, but can be matrixed to any pins
#endif
#endif
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.println();
delay(100);
Serial.print("FSPI: \t");
Serial.println(FSPI);
Serial.print("HSPI: \t");
Serial.println(HSPI);
Serial.print("VSPI: \t");
Serial.println(VSPI);
}
void loop()
{
}
// -- END OF FILE --
VSPI doesn't work because CONFIG_IDF_TARGET_ESP32 isn't set. I commented the printf out, output is this.
12:50:04.511 -> C:\Users\
From: http://wiki.fluidnc.com/en/hardware/ESP32-S3_Pin_Reference
SPI The ESP32 S3 has four SPI interfaces which are:
The SPI2 (FSPI) default pins are:
SPI3 does not have default pin mappings because it can be mapped to any available gpio pins
Does it help if you
SPIClass * myspi = new SPIClass(SPI2); // or SPI3
MCP23S17 MCP(selectPin, myspi); // HW SPI address 0x00
----
myspi->begin(); // optional add pins to begin (SCK, MISO, MOSI, SS)
Another line of thought is that the new SPIClass() call behaves not as expected (do not have an S3 to verify)
So a variation that does not use a pointer to the SPIClass object
SPIClass myspi = new SPIClass(HSPI); // or FSPI
MCP23S17 MCP(selectPin, &myspi); // use the & address of myspi.
in setup() one line should change
myspi.begin(); // optional add pins to begin (SCK, MISO, MOSI, SS)
Tried SPI2, but compile error error: 'SPI2' was not declared in this scope; did you mean 'SPI'? 18 | myspi = new SPIClass(SPI2);
Tried SPI3, but compile error error: 'SPI3' was not declared in this scope; did you mean 'SPI'?
Tried SPI, it compiles, but then crashes.
"So a variation that does not use a pointer to the SPIClass object" Compilation error: invalid user-defined conversion from 'SPIClass*' to 'const SPIClass&' [-fpermissive]
I don't think this is a library issue. There is no VSPI or HSPI on the S3, at least it's not mentioned in the data sheet.
I have no issues running HW-SPI with the example sketches "as is" on my ESP-S3-WROOM. Just set the CS pin and leave out the spi pointer from the constructor like this: MCP23S17 MCP(10);
and it should work. The SPI pin mapping may vary on different boards, if you're not sure you can run this code in setup()
after SPI.begin():
Serial.print("MOSI: ");
Serial.println(MOSI);
Serial.print("MISO: ");
Serial.println(MISO);
Serial.print("SCK: ");
Serial.println(SCK);
Just using "MCP23S17 MCP(7);" does enable hardware SPI! checked with MCP.usesHWSPI() and oscilloscope. But then I can't remap these pins that I assigned on my PCB. MOSI=9; MISO=10; SCK=8;
Just using "MCP23S17 MCP(7);" does enable hardware SPI! checked with MCP.usesHWSPI() and oscilloscope. But then I can't remap these pins that I assigned on my PCB. MOSI=9; MISO=10; SCK=8;
Those pins could be configurable with SPI.begin(), did you try?
SPI.begin(SCK, MISO, MOSI, 7);
Optional leave out the last parameter (Select pin = 7) as that is already passed to the MCP object.
Tried this code, the IO expander doesn't respond, and SCK, MISO, MOSI still look wrong. Also tried SPI.begin(8,10,9);
#include "MCP23S17.h"
void setup() {
delay(3100);
Serial.begin(115200);
Serial.println();
Serial.print("MCP23S17_LIB_VERSION: ");
Serial.println(MCP23S17_LIB_VERSION);
delay(100);
MCP23S17 MCP(7);
MCP.setSPIspeed(1000000);
SPI.begin(8,10,9,7); //MOSI=9; MISO=10; SCK=8; SS=7;
Serial.print("getSPIspeed: ");
Serial.println(MCP.getSPIspeed());
Serial.print("usesHWSPI: ");
Serial.println(MCP.usesHWSPI());
Serial.print("MOSI: ");
Serial.println(MOSI);
Serial.print("MISO: ");
Serial.println(MISO);
Serial.print("SCK: ");
Serial.println(SCK);
while (1)
{
MCP.pinMode16(0);
MCP.pinMode16(0xffff);
}
}
void loop() {}
Outputs MCP23S17_LIB_VERSION: 0.5.2 getSPIspeed: 1000000 usesHWSPI: 1 MOSI: 11 MISO: 13 SCK: 12
Serial.print("MOSI: ");
Serial.println(MOSI);
Serial.print("MISO: ");
Serial.println(MISO);
Serial.print("SCK: ");
Serial.println(SCK);
These are hard coded constants in some header file, so they will always be the same,
the IO expander doesn't respond
The above code does only change the mode of the pins from input to output and back in a very tight loop. What response did you expect here?
try replace
while (1)
{
MCP.pinMode16(0);
MCP.pinMode16(0xffff);
}
with
MCP.pinMode16(0); // set all pins output
while (1)
{
MCP.write16(0xF00F);
delay(1000);
MCP.write16(0x0FF0);
delay(1000);
}
If the MCP works it should show pulses on every line.
I edited the default board pinouts to match my PCB and it seems to be working now!
C:\Users\
It now prints out the correct MOSI/MISO/SCK/SS pins, and says usesHWSPI=1.
But I think I hit a new problem, the problem is that I have two IO expanders at address 0 and 1, but i can't talk to the IO expander at address 1, i.e. I can't set MCP23S17 MCP_B(11,10,9,8,1); and if I mix and match the two the CPU hangs.
Serial.print("MOSI: "); Serial.println(MOSI); Serial.print("MISO: "); Serial.println(MISO); Serial.print("SCK: "); Serial.println(SCK);
These are hard coded constants in some header file, so they will always be the same,
the IO expander doesn't respond
The above code does only change the mode of the pins from input to output and back in a very tight loop. What response did you expect here?
try replace
while (1) { MCP.pinMode16(0); MCP.pinMode16(0xffff); }
with
MCP.pinMode16(0); // set all pins output while (1) { MCP.write16(0xF00F); delay(1000); MCP.write16(0x0FF0); delay(1000); }
If the MCP works it should show pulses on every line.
Yeah I saw my mistake earlier and wasn't actually setting the output of the pins.
@Spaceballs3000
But I think I hit a new problem, the problem is that I have two IO expanders with address 0 and 1.. but i can't talk to the IO expander at address 1, i.e. I can't set MCP23S17 MCP_B(11,10,9,8,1); and if I mix and match the two the CPU hangs.
If you have 2 MCP23S17's you must create two MCP23S17 objects, one for each expander. They may be connected on the same SPI bus and use the same SelectPin.
#include "MCP23S17.h"
void setup()
{
delay(3100);
Serial.begin(115200);
Serial.println(MCP23S17_LIB_VERSION);
delay(100);
MCP23S17 MCP_A(7, 0); // set address 0 explicitly
MCP23S17 MCP_B(7, 1); // set address 1 explicitly
MCP_A.setSPIspeed(1000000);
MCP_B.setSPIspeed(1000000);
SPI.begin(8,10,9,7); //MOSI=9; MISO=10; SCK=8; SS=7;
MCP_A.begin();
MCP_B.begin();
etc...
That did it! Adding MCP_A(11, 1) works.
Thank you for your patience in helping me!
Code below that works for me with two IO expanders.
#include "MCP23S17.h"
void setup() {
delay(3100);
Serial.begin(115200);
Serial.println();
Serial.print("MCP23S17_LIB_VERSION: ");
Serial.println(MCP23S17_LIB_VERSION);
pinMode(12, OUTPUT); // RESET pin on IO-EXPANDER (set to output)
digitalWrite(12,HIGH); //Disable Reset on IO-EXPANDERs
MCP23S17 MCP_A(7,0); //SS=7, Address = 0
MCP23S17 MCP_B(11,1); //SS=11, Address = 1
MCP_A.setSPIspeed(4000000);
MCP_B.setSPIspeed(4000000);
SPI.begin(8,10,9); //MOSI=9; MISO=10; SCK=8; SS=7;
MCP_A.begin();
MCP_B.begin();
MCP_A.enableHardwareAddress();
MCP_B.enableHardwareAddress();
Serial.print("getSPIspeed: ");
Serial.println(MCP_A.getSPIspeed());
Serial.print("usesHWSPI: ");
Serial.println(MCP_A.usesHWSPI());
// test connection
int c = testConnection(MCP_A);
Serial.print("Connect A: ");
Serial.println(c);
c = testConnection(MCP_B);
Serial.print("Connect B: ");
Serial.println(c);
MCP_A.pinMode16(0);
MCP_B.pinMode16(0);
while (1)
{
MCP_A.write16(0x0000);
MCP_B.write16(0x0000);
delay(100);
MCP_A.write16(0xffff);
MCP_B.write16(0xffff);
delay(100);
}
}
void loop() {}
//
// the connection test tries to write a magic number to a register
// and read it back. If it is the same it is assumed to be connected
//
int testConnection(MCP23S17 & mcp)
{
uint16_t magic_test_number = 0xABCD;
// Read the current polarity config to restore later
uint16_t old_value;
if (! mcp.getPolarity16(old_value)) return -1;
// Write the magic number to polarity register
if (! mcp.setPolarity16(magic_test_number)) return -2;
// Read back the magic number from polarity register
uint16_t temp;
if (! mcp.getPolarity16(temp)) return -3;
// Write old config to polarity register
if (! mcp.setPolarity16(old_value)) return -4;
// Check the magic connection test
if (temp != magic_test_number) return -5;
return 0; // OK
}
Output is
MCP23S17_LIB_VERSION: 0.5.2 getSPIspeed: 4000000 usesHWSPI: 1 Connect A: 0 Connect B: 0
Good to hear your project works!
Today a new version 0.5.3 is released with ~30% faster 16 bit interface, might be interesting to verify.
If no further questions remain, you may close the issue
Good to hear your project works!
Today a new version 0.5.3 is released with ~30% faster 16 bit interface, might be interesting to verify.
Before 0.5.2 just running this, would get me 60khz on the Select pin.
MCP_A.setSPIspeed(4000000);
while (1)
{
MCP_A.write16(0x0000);
MCP_A.write16(0xffff);
}
Running 0.5.3 I'm now getting 39.5khz on the Select pin, so slower.
Correction about it being slower, I didn't actually probe the IO Expander output itself, on 0.5.3 I get 19.77khz, on 0.5.2 I get 14.94khz! So looks like less traffic to the IO Expander, (I guessing less register chatter) and more setting pin outputs per sec!
Closing, as all my issue's were solved! Again thanks!
Indeed the 16 bit interface only uses 4 bytes instead of 6 to read/ write two 8 bit registers. So communication time is ~30% down and thus The IO lines are ~30% faster.
Can you compare the SW SPI with the HW SPI for 0.5.3 in your setup?
Sure no problem! Running same program earlier but using SW SPI.
MCP23S17_LIB_VERSION: 0.5.2 getSPIspeed: 4000000 usesHWSPI: 0 4.8khz
MCP23S17_LIB_VERSION: 0.5.3 getSPIspeed: 4000000 usesHWSPI: 0 7.3khz
Thanks for the quick test! so we know the optimization works for both HW and SW SPI.
Seeing your numbers, there is still a factor ~2.5 difference between the HW SPI and SW SPI.
FYI, I am working on an AVR optimization of SW SPI - same I used in https://github.com/RobTillaart/FastShiftOut - which would improve the SW SPI for AVR (UNO and MEGA) about a factor 2 (result of first tests). Note that on AVR the "portable" SW SPI is very slow, and even after optimization it is not as fast as HW SPI. When AVR works I might have a look into the optimization of SW SPI for ESP32.
I can get this library to work with SW SPI, but not HW SPI, i.e. MCP23S17 MCP(7,10,9,8,0); // <-- Works but software SPI.
But when I try with hardware vspi it doesn't work i.e. MCP23S17 MCP(10, &vspi); // <-- compiler doesn't like & MCP23S17 MCP(10, vspi); // <-- compiles, but crashes.
Here is the example HW SPI that sends bits out, but I'm not sure how to connect this to the MCP23S17 library.
(updated syntax highlight for readability)