Конфликт библиотек на ESP32 S3

Здравствуйте уважаемые форумчане, столкнулся со следующей проблемой:
Использую модуль: ESP32-S3-Touch-LCD-4.3


Документация:

У данного модуля есть сенсор реагирующий на 5 одновременных касаний на контроллере GT911 и разъём под SD карту.
По отдельности они работают исправно, а при совместной работе модуль просто не видит SD карту, при чём я испробовал все библиотеки которые смог найти в интернете, результат у всех одинаковый - вместе не работаю.

В какую сторону мне копать?

Мой код:

#include <GT911.h>
#include <Arduino_GFX_Library.h>
#include <INA226_WE.h>
#include <RTClib.h>
#include <EEPROM.h>
#include <CRC8.h>
#include <CRC.h>
#include "waveshare_sd_card.h"

INA226_WE INA226_CH1 = INA226_WE(0x40);
INA226_WE INA226_CH2 = INA226_WE(0x44);
INA226_WE INA226_CH3 = INA226_WE(0x45);

RTC_DS3231 RTC;
GT911 TOUCH;
Arduino_ESP32RGBPanel* rgbpanel = new Arduino_ESP32RGBPanel(
  5 /* DE */,  3 /* VSYNC */,  46 /* HSYNC */,  7 /* PCLK */,
  1 /* R0 */,  2 /* R1 */,  42 /* R2 */,  41 /* R3 */,  40 /* R4 */,
  39 /* G0 */,  0 /* G1 */,  45 /* G2 */,  48 /* G3 */,  47 /* G4 */,  21 /* G5 */,
  14 /* B0 */,  38 /* B1 */,  18 /* B2 */,  17 /* B3 */,  10 /* B4 */,
  0 /* hsync_polarity */, 40 /* hsync_front_porch */, 48 /* hsync_pulse_width */, 88 /* hsync_back_porch */,
  0 /* vsync_polarity */, 13 /* vsync_front_porch */, 3 /* vsync_pulse_width */, 32 /* vsync_back_porch */,
  1 /* pclk_active_neg */, 16000000 /* prefer_speed */
);


Arduino_RGB_Display* GFX = new Arduino_RGB_Display(
  800 /* width */,  480 /* height */,  rgbpanel,  0 /* rotation */,  true /* auto_flush */
);

Arduino_Canvas_Indexed *CANVAS = new Arduino_Canvas_Indexed(720, 480, GFX, 0, 0, 0, 0);

esp_expander::CH422G *expander = NULL;

// Initial Setup
void setup(){
    Serial.begin(115200);

    Serial.println("Initialize IO expander");
    /* Initialize IO expander */
    const __FlashStringHelper* OK = F("OK");                      //Экономим оперативную память и сохраняем во флеш память
  const __FlashStringHelper* NO = F("NO");                      //Экономим оперативную память и сохраняем во флеш память
  
  GFX->begin();
  CANVAS->begin(GFX_SKIP_OUTPUT_BEGIN);
  
  GFX->fillScreen(0x0000);
  GFX->setTextColor(0xffff);
  GFX->setCursor(200, 10);
  GFX->print(F("Display..............................................................."));
  GFX->println(OK);
  
  GFX->print(F("SD..............................................................."));
  expander = new esp_expander::CH422G(EXAMPLE_I2C_SCL_PIN, EXAMPLE_I2C_SDA_PIN, EXAMPLE_I2C_ADDR);
  expander->init();
  expander->begin();
  expander->enableAllIO_Output();
  expander->digitalWrite(TP_RST , HIGH);
  expander->digitalWrite(LCD_RST , HIGH);
  expander->digitalWrite(LCD_BL , HIGH);
  expander->digitalWrite(SD_CS, LOW);
  expander->digitalWrite(USB_SEL, LOW);

  SPI.setHwCs(false);
  SPI.begin(SD_CLK, SD_MISO, SD_MOSI, SD_SS);
  if (!SD.begin(SD_SS)) {
    GFX->println(NO);
  }
  else
    GFX->println(OK);
  uint8_t cardType = SD.cardType();


  GFX->print(F("CARD..............................................................."));
  if(cardType == CARD_NONE)
    GFX->println("NONE");
  else if(cardType == CARD_MMC)
    GFX->println("MMC");
  else if(cardType == CARD_SD)
    GFX->println("SDSC");
  else if(cardType == CARD_SDHC)
    GFX->println("SDHC");
  else
    GFX->println("UNKNOWN");

  GFX->print(F("TOUCH..............................................................."));
  if (!TOUCH.begin(-1, -1, GT911_I2C_ADDR_28, 400000))
  {
    if (!TOUCH.begin(-1, -1, GT911_I2C_ADDR_BA, 400000))
    {
      GFX->println(NO);
    }
    else
      GFX->println(OK);
  }
  else
    GFX->println(OK);
}

// Main Loop
void loop() {
    
}

Библиотека waveshare_sd_card.h (взята из документации к данному модулю)
Файл waveshare_sd_card.h:

#include "SD.h"
#include "SPI.h"
#include <esp_io_expander.hpp>

// Extension IO pin definition
#define TP_RST 1      // Touch screen reset pin
#define LCD_BL 2      // LCD backlight pinout
#define LCD_RST 3     // LCD reset pin
#define SD_CS 4       // SD card select pin
#define USB_SEL 5     // USB select pin

// I2C pin definitions
#define EXAMPLE_I2C_ADDR    (ESP_IO_EXPANDER_I2C_CH422G_ADDRESS)
#define EXAMPLE_I2C_SDA_PIN 8         // I2C data line pins
#define EXAMPLE_I2C_SCL_PIN 9         // I2C clock line pin

#define SD_MOSI 11    // SD card master output slave input pin
#define SD_CLK  12    // SD card clock pin
#define SD_MISO 13    // SD card master input slave output pin
#define SD_SS -1      // SD card select pin (not used)

void listDir(fs::FS &fs, const char * dirname, uint8_t levels);
void createDir(fs::FS &fs, const char * path);
void removeDir(fs::FS &fs, const char * path);
void writeFile(fs::FS &fs, const char * path, const char * message);
void appendFile(fs::FS &fs, const char * path, const char * message);
void readFile(fs::FS &fs, const char * path);
void deleteFile(fs::FS &fs, const char * path);
void renameFile(fs::FS &fs, const char * path1, const char * path2);
void testFileIO(fs::FS &fs, const char * path);

#endif

Файл waveshare_sd_card.cpp:

/*
 * Connect the SD card to the following pins:
 *
 * SD Card |   ESP32
 *    D2       - (Not connected)
 *    D3       SS (Chip Select)
 *    CMD      MOSI (Master output slave input)
 *    VSS      GND (Ground)
 *    VDD      3.3V (Power supply)
 *    CLK      SCK (Clock)
 *    VSS      GND (Ground)
 *    D0       MISO (Master Input Slave Output)
 *    D1       - (Not connected)
 */

#include "waveshare_sd_card.h"

// List files and subdirectories in a directory
void listDir(fs::FS &fs, const char * dirname, uint8_t levels) {
    Serial.printf("Listing directory: %s\n", dirname); 
    // Listing Directories
    File root = fs.open(dirname);
    if (!root) {
        Serial.println("Failed to open directory");
        return;
    }
    if (!root.isDirectory()) {
        Serial.println("Not a directory");
        return;
    }

    File file = root.openNextFile();
    while (file) {
        if (file.isDirectory()) {
            Serial.print("  DIR : ");
            Serial.println(file.name());
            if (levels) {
                listDir(fs, file.path(), levels - 1);
            }
        } else {
            Serial.print("  FILE: ");
            Serial.print(file.name());
            Serial.print("  SIZE: ");
            Serial.println(file.size());
        }
        file = root.openNextFile();
    }
}

// Creating Dir
void createDir(fs::FS &fs, const char * path) {
    Serial.printf("Creating Dir: %s\n", path);
    if (fs.mkdir(path)) {
        Serial.println("Dir created");
    } else {
        Serial.println("mkdir failed");
    }
}

// Remove a directory
void removeDir(fs::FS &fs, const char * path) {
    Serial.printf("Removing Dir: %s\n", path);
    if (fs.rmdir(path)) {
        Serial.println("Dir removed");
    } else {
        Serial.println("rmdir failed");
    }
}

// Reading a file
void readFile(fs::FS &fs, const char * path) {
    Serial.printf("Reading file: %s\n", path);

    File file = fs.open(path);
    if (!file) {
        Serial.println("Failed to open file for reading");
        return;
    }

    Serial.print("Read from file: ");
    while (file.available()) {
        Serial.write(file.read());
    }
    file.close();
}

// Writing to a File
void writeFile(fs::FS &fs, const char * path, const char * message) {
    Serial.printf("Writing file: %s\n", path);

    File file = fs.open(path, FILE_WRITE);
    if (!file) {
        Serial.println("Failed to open file for writing");
        return;
    }
    if (file.print(message)) {
        Serial.println("File written");
    } else {
        Serial.println("Write failed");
    }
    file.close();
}

// Append to file
void appendFile(fs::FS &fs, const char * path, const char * message) {
    Serial.printf("Appending to file: %s\n", path);

    File file = fs.open(path, FILE_APPEND);
    if (!file) {
        Serial.println("Failed to open file for appending");
        return;
    }
    if (file.print(message)) {
        Serial.println("Message appended");
    } else {
        Serial.println("Append failed");
    }
    file.close();
}

// Rename a file
void renameFile(fs::FS &fs, const char * path1, const char * path2) {
    Serial.printf("Renaming file %s to %s\n", path1, path2);
    if (fs.rename(path1, path2)) {
        Serial.println("File renamed");
    } else {
        Serial.println("Rename failed");
    }
}

// Deleting files
void deleteFile(fs::FS &fs, const char * path) {
    Serial.printf("Deleting file: %s\n", path);
    if (fs.remove(path)) {
        Serial.println("File deleted");
    } else {
        Serial.println("Delete failed");
    }
}

// Test file IO performance
void testFileIO(fs::FS &fs, const char * path) {
    File file = fs.open(path);
    static uint8_t buf[512];  // Buffer
    size_t len = 0;
    uint32_t start = millis();
    uint32_t end = start;
    if (file) {
        len = file.size();
        size_t flen = len;
        start = millis();
        while (len) {
            size_t toRead = len;
            if (toRead > 512) {
                toRead = 512;
            }
            file.read(buf, toRead);
            len -= toRead;
        }
        end = millis() - start;
        Serial.printf(" %u bytes read for %u ms\n", flen, end);
        file.close();
    } else {
        Serial.println("Failed to open file for reading");
    }

    // Write test
    file = fs.open(path, FILE_WRITE);
    if (!file) {
        Serial.println("Failed to open file for writing");
        return;
    }

    size_t i;
    start = millis();
    for (i = 0; i < 2048; i++) {
        file.write(buf, 512);
    }
    end = millis() - start;
    Serial.printf("%u bytes written for %u ms\n", 2048 * 512, end);
    file.close();
}

Библиотека GT911
Файл GT911.h

#ifndef GT911_H
#define GT911_H

#include <Arduino.h>
#include <Wire.h>
#include "GT911_Structs.h"

// 0x28/0x29 (0x14 7bit)
#define GT911_I2C_ADDR_28  0x14
// 0xBA/0xBB (0x5D 7bit)
#define GT911_I2C_ADDR_BA  0x5D

#define GT911_MAX_CONTACTS 5

#define GT911_REG_CFG 0x8047
#define GT911_REG_CHECKSUM 0x80FF
#define GT911_REG_DATA 0x8140
#define GT911_REG_ID 0x8140
#define GT911_REG_COORD_ADDR 0x814E

enum : uint8_t {
  GT911_MODE_INTERRUPT,
  GT911_MODE_POLLING
};

class GT911 {
  public:
    enum class Rotate {
      _0,
      _90,
      _180,
      _270,
    };
  private:
    TwoWire *_wire;
    int8_t _intPin;
    int8_t _rstPin;
    uint8_t _addr;

    bool _configLoaded = false;
    GTConfig _config;
    GTInfo _info;
    GTPoint _points[GT911_MAX_CONTACTS];

    Rotate _rotation = Rotate::_0;

    void reset();
    void i2cStart(uint16_t reg);
    bool write(uint16_t reg, uint8_t data);
    uint8_t read(uint16_t reg);
    bool writeBytes(uint16_t reg, uint8_t *data, uint16_t size);
    bool readBytes(uint16_t reg, uint8_t *data, uint16_t size);
    uint8_t calcChecksum(uint8_t *buf, uint8_t len);
    uint8_t readChecksum();
    int8_t readTouches();
    bool readTouchPoints();
  public:
    GT911(TwoWire *twi = &Wire);
    bool begin(int8_t intPin = -1, int8_t rstPin = -1, uint8_t addr = GT911_I2C_ADDR_BA,
               uint32_t clk = 400000);
    bool productID(uint8_t *buf, uint8_t len);
    GTConfig* readConfig();
    bool writeConfig();
    GTInfo* readInfo();

    uint8_t touched(uint8_t mode = GT911_MODE_INTERRUPT);
    GTPoint getPoint(uint8_t num);
    GTPoint *getPoints();

    void setRotation(Rotate rotation);
};

#endif

Файл GT911_Structs.h

struct __attribute__((packed)) GTInfo {
  char productId[4]; // 0x8140 - 0x8143 
  uint16_t fwId; // 0x8144 - 0x8145 
  uint16_t xResolution; // 0x8146 - 0x8147
  uint16_t yResolution; // 0x8148 - 0x8149
  uint8_t vendorId; // 0x814A
};

struct __attribute__((packed)) GTPoint {
  // 0x814F-0x8156, ... 0x8176 (5 points) 
  uint8_t trackId;
  uint16_t x;
  uint16_t y;
  uint16_t area;
  uint8_t reserved;
};

struct __attribute__((packed)) GTConfig {
  uint8_t configVersion; // 0x8047
  uint16_t xResolution; // 0x8048 - 0x8049
  uint16_t yResolution; // 0x804A - 0x804B
  uint8_t touchNumber; // 0x804C
  uint8_t moduleSwitch1; // 0x804D
  uint8_t moduleSwitch2; // 0x804E
  uint8_t shakeCount; // 0x804F
  uint8_t filter; // 0x8050
  uint8_t largeTouch; // 0x8051
  uint8_t noiseReduction; // 0x8052
  uint8_t screenTouchLevel; // 0x8053
  uint8_t screenLeaveLevel; // 0x8054
  uint8_t lowPowerControl; // 0x8055
  uint8_t refreshRate; // 0x8056
  uint8_t xThreshold; // 0x8057
  uint8_t yThreshold; // 0x8058
  uint8_t xSpeedLimit; // 0x8059 - reserved
  uint8_t ySpeedLimit; // 0x805A - reserved
  uint8_t vSpace; // 0x805B
  uint8_t hSpace; // 0x805C
  uint8_t miniFilter; // 0x805D
  uint8_t stretchR0; // 0x805E
  uint8_t stretchR1; // 0x805F
  uint8_t stretchR2; // 0x8060
  uint8_t stretchRM; // 0x8061
  uint8_t drvGroupANum; // 0x8062 
  uint8_t drvGroupBNum; // 0x8063
  uint8_t sensorNum; // 0x8064
  uint8_t freqAFactor; // 0x8065
  uint8_t freqBFactor; // 0x8066
  uint16_t pannelBitFreq; // 0x8067 - 0x8068
  uint16_t pannelSensorTime; // 0x8069 - 0x806A
  uint8_t pannelTxGain; // 0x806B
  uint8_t pannelRxGain; // 0x806C
  uint8_t pannelDumpShift; // 0x806D
  uint8_t drvFrameControl; // 0x806E
  uint8_t chargingLevelUp; // 0x806F
  uint8_t moduleSwitch3; // 0x8070
  uint8_t gestureDis; // 0x8071
  uint8_t gestureLongPressTime; // 0x8072
  uint8_t xySlopeAdjust; // 0x8073
  uint8_t gestureControl; // 0x8074
  uint8_t gestureSwitch1; // 0x8075
  uint8_t gestureSwitch2; // 0x8076
  uint8_t gestureRefreshRate; // 0x8077
  uint8_t gestureTouchLevel; // 0x8078
  uint8_t newGreenWakeUpLevel; // 0x8079
  uint8_t freqHoppingStart; // 0x807A
  uint8_t freqHoppingEnd; // 0x807B
  uint8_t noiseDetectTimes; // 0x807C
  uint8_t hoppingFlag; // 0x807D
  uint8_t hoppingThreshold; // 0x807E
  uint8_t noiseThreshold; // 0x807F
  uint8_t noiseMinThreshold; // 0x8080
  uint8_t NC_1; // 0x8081
  uint8_t hoppingSensorGroup; // 0x8082
  uint8_t hoppingSeg1Normalize; // 0x8083
  uint8_t hoppingSeg1Factor; // 0x8084
  uint8_t mainClockAjdust; // 0x8085
  uint8_t hoppingSeg2Normalize; // 0x8086
  uint8_t hoppingSeg2Factor; // 0x8087
  uint8_t NC_2; // 0x8088
  uint8_t hoppingSeg3Normalize; // 0x8089
  uint8_t hoppingSeg3Factor; // 0x808A
  uint8_t NC_3; // 0x808B
  uint8_t hoppingSeg4Normalize; // 0x808C
  uint8_t hoppingSeg4Factor; // 0x808D
  uint8_t NC_4; // 0x808E
  uint8_t hoppingSeg5Normalize; // 0x808F
  uint8_t hoppingSeg5Factor; // 0x8090
  uint8_t NC_5; // 0x8091
  uint8_t hoppingSeg6Normalize; // 0x8092
  uint8_t key[4]; // 0x8093 - 0x8096
  uint8_t keyArea; // 0x8097
  uint8_t keyTouchLevel; // 0x8098
  uint8_t keyLeaveLevel; // 0x8099
  uint8_t keySens[2]; // 0x809A - 0x809B
  uint8_t keyRestrain; // 0x809C
  uint8_t keyRestrainTime; // 0x809D
  uint8_t gestureLargeTouch; // 0x809E
  uint8_t NC_6[2]; // 0x809F - 0x80A0
  uint8_t hotknotNoiseMap; // 0x80A1
  uint8_t linkThreshold; // 0x80A2
  uint8_t pxyThreshold; // 0x80A3
  uint8_t gHotDumpShift; // 0x80A4
  uint8_t gHotRxGain; // 0x80A5
  uint8_t freqGain[4]; // 0x80A6 - 0x80A9
  uint8_t NC_7[9]; // 0x80AA - 0x80B2
  uint8_t combineDis; // 0x80B3
  uint8_t splitSet; // 0x80B4
  uint8_t NC_8[2]; // 0x80B5 - 0x80B6
  uint8_t sensorCH[14]; // 0x80B7 - 0x80C4
  uint8_t NC_9[16]; // 0x80C5 - 0x80D4
  uint8_t driverCH[26]; // 0x80D5 - 0x80EE
  uint8_t NC_10[16]; // 0x80EF - 0x80FE
};

Файл GT911.cpp:

#include "GT911.h"
#include <Wire.h>

#ifndef ICACHE_RAM_ATTR
#define ICACHE_RAM_ATTR
#endif

// Interrupt handling
volatile bool gt911IRQ = false;

void IRAM_ATTR _gt911_irq_handler() {
  noInterrupts();
  gt911IRQ = true;
  interrupts();
}


GT911::GT911(TwoWire *twi) : _wire(twi ? twi : &Wire) {

}

void GT911::reset() {
  delay(1);

  pinMode(_intPin, OUTPUT);
  pinMode(_rstPin, OUTPUT);

  digitalWrite(_intPin, LOW);
  digitalWrite(_rstPin, LOW);

  delay(11);

  digitalWrite(_intPin, _addr == GT911_I2C_ADDR_28);

  delayMicroseconds(110);
  pinMode(_rstPin, INPUT);

  delay(6);
  digitalWrite(_intPin, LOW);

  delay(51);
}

void GT911::i2cStart(uint16_t reg) {
  _wire->beginTransmission(_addr);
  _wire->write(reg >> 8);
  _wire->write(reg & 0xFF);
}

bool GT911::write(uint16_t reg, uint8_t data) {
  i2cStart(reg);
  _wire->write(data);
  return _wire->endTransmission() == 0;
}

uint8_t GT911::read(uint16_t reg) {
  i2cStart(reg);
  _wire->endTransmission();
  _wire->requestFrom(_addr, (uint8_t)1);
  while (_wire->available()) {
    return _wire->read();
  }
  return 0;
}

bool GT911::writeBytes(uint16_t reg, uint8_t *data, uint16_t size) {
  i2cStart(reg);
  for (uint16_t i = 0; i < size; i++) {
    _wire->write(data[i]);
  }
  return _wire->endTransmission() == 0;
}

bool GT911::readBytes(uint16_t reg, uint8_t *data, uint16_t size) {
  i2cStart(reg);
  _wire->endTransmission();

  uint16_t index = 0;
  while (index < size) {
    uint8_t req = _min(size - index, I2C_BUFFER_LENGTH);
    _wire->requestFrom(_addr, req);
    while (_wire->available()) {
      data[index++] = _wire->read();
    }
    index++;
  }

  return size == index - 1;
}

uint8_t GT911::calcChecksum(uint8_t *buf, uint8_t len) {
  uint8_t ccsum = 0;
  for (uint8_t i = 0; i < len; i++) {
    ccsum += buf[i];
  }

  return (~ccsum) + 1;
}

uint8_t GT911::readChecksum() {
  return read(GT911_REG_CHECKSUM);
}

int8_t GT911::readTouches() {
  uint32_t timeout = millis() + 20;
  do {
    uint8_t flag = read(GT911_REG_COORD_ADDR);
    if ((flag & 0x80) && ((flag & 0x0F) < GT911_MAX_CONTACTS)) {
      write(GT911_REG_COORD_ADDR, 0);
      return flag & 0x0F;
    }
    delay(1);
  } while (millis() < timeout);

  return 0;
}

bool GT911::readTouchPoints() {
  bool result = readBytes(GT911_REG_COORD_ADDR + 1, (uint8_t*)_points, sizeof(GTPoint) * GT911_MAX_CONTACTS);

  if (result && _rotation != Rotate::_0) {
    for (uint8_t i = 0; i < GT911_MAX_CONTACTS; i++) {
      if (_rotation == Rotate::_180) {
        _points[i].x = _info.xResolution - _points[i].x;
        _points[i].y = _info.yResolution - _points[i].y;
      }
    }
  }

  return result;
}

bool GT911::begin(int8_t intPin, int8_t rstPin, uint8_t addr, uint32_t clk) {
  _intPin = intPin;
  _rstPin = rstPin;
  _addr = addr;

  if (_rstPin > 0) {
    delay(300);
    reset();
    delay(200);
  }

  if (intPin > 0) {
    pinMode(_intPin, INPUT);
    attachInterrupt(_intPin, _gt911_irq_handler, FALLING);
  }

  _wire->begin();
  _wire->setClock(clk);
  _wire->beginTransmission(_addr);
  if (_wire->endTransmission() == 0) {
    readInfo(); // Need to get resolution to use rotation
    return true;
  }
  return false;
}

bool GT911::productID(uint8_t *buf, uint8_t len) {
  if (len < 4) {
    return false;
  }

  memset(buf, 0, 4);
  return readBytes(GT911_REG_ID, buf, 4);
}

GTConfig* GT911::readConfig() {
  readBytes(GT911_REG_CFG, (uint8_t*)&_config, sizeof(_config));

  if (readChecksum() == calcChecksum((uint8_t*)&_config, sizeof(_config))) {
    _configLoaded = true;
    return &_config;
  }
  return nullptr;
}

bool GT911::writeConfig() {
  uint8_t checksum = calcChecksum((uint8_t*)&_config, sizeof(_config));
  if (_configLoaded && readChecksum() != checksum) { // Config is different
    writeBytes(GT911_REG_CFG, (uint8_t*)&_config, sizeof(_config));

    uint8_t buf[2] = { checksum, 1 };
    writeBytes(GT911_REG_CHECKSUM, buf, sizeof(buf));
    return true;
  }
  return false;
}

GTInfo* GT911::readInfo() {
  readBytes(GT911_REG_DATA, (uint8_t*)&_info, sizeof(_info));
  return &_info;
}

uint8_t GT911::touched(uint8_t mode) {
  bool irq = false;
  if (mode == GT911_MODE_INTERRUPT) {
    noInterrupts();
    irq = gt911IRQ;
    gt911IRQ = false;
    interrupts();
  } else if (mode == GT911_MODE_POLLING) {
    irq = true;
  }

  uint8_t contacts = 0;
  if (irq) {
    contacts = readTouches();

    if (contacts > 0) {
      readTouchPoints();
    }
  }

  return contacts;
}

GTPoint GT911::getPoint(uint8_t num) {
  return _points[num];
}

GTPoint *GT911::getPoints() {
  return _points;
}

void GT911::setRotation(Rotate rotation) {
  _rotation = rotation;
}

В сторону примеров от производителя.

The TF card uses SPI/MMC to communicate, note that the SD_CS pin needs to be driven by the EXIO4 of the CH422G

Так код выше и из примеров от производителя.

Так разве я не передаю управление, или я что-то не понимаю?

#define SD_CS 4       // SD card select pin

 expander = new esp_expander::CH422G(EXAMPLE_I2C_SCL_PIN, EXAMPLE_I2C_SDA_PIN, EXAMPLE_I2C_ADDR);
 expander->digitalWrite(SD_CS, LOW);

Если Вы про, что последний пин указан SD_SS, а не SD_CS, то это код из примера производителя, который работает, если из кода удалить строчку:

if (!TOUCH.begin(-1, -1, GT911_I2C_ADDR_28, 400000))
  {
    if (!TOUCH.begin(-1, -1, GT911_I2C_ADDR_BA, 400000))
    {

    }
  }

Я пробовал менять, на SPI.begin(SD_CLK, SD_MISO, SD_MOSI, SD_CS); но это не даёт результата.

Таймаут пробовали увеличить?(gt911.cpp стр.113)

Я в ESP32 вообще зелёный, но вроде, как у всех, при входе в обработчик запрет на прерывания автоматом должен быть

В RTOS можно и без прерываний обойтись, по задачам и ядрам раскидать. Как-то игрался в WOKWI…

Ну попробуй на другой SPI повесить свою карту памяти, например.
Используй HSPI, например:

SPIClass MySPI(HSPI);

Проблема не в SPI, проблема в I2C (у модуля 2 USB через оба можно залить прошивку, но получить ошибки можно через один), в итоге я получил ошибку:

ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce2820,len:0x1188
load:0x403c8700,len:0x4
load:0x403c8704,len:0xbf0
load:0x403cb700,len:0x30e4
entry 0x403c88ac
E (85) i2c: i2c driver install error
[E][Expander][esp_expander_base.cpp:0142](init): I2C driver install failed [ESP_FAIL]
E (86) i2c: i2c driver install error
[E][Expander][esp_expander_base.cpp:0142](init): I2C driver install failed [ESP_FAIL]
[E][Expander][esp_expander_ch422g.cpp:0030](begin): Init failed
[E][Expander][esp_expander_ch422g.cpp:0096](enableAllIO_Output): Not begun
[E][Expander][esp_expander_base.cpp:0213](digitalWrite): Not begun
[E][Expander][esp_expander_base.cpp:0213](digitalWrite): Not begun
[E][Expander][esp_expander_base.cpp:0213](digitalWrite): Not begun
[E][Expander][esp_expander_base.cpp:0213](digitalWrite): Not begun
[E][Expander][esp_expander_base.cpp:0213](digitalWrite): Not begun

Конфликтуют эти строчки:

TOUCH.begin(-1, -1, GT911_I2C_ADDR_28, 400000)
expander = new esp_expander::CH422G(EXAMPLE_I2C_SCL_PIN, EXAMPLE_I2C_SDA_PIN, EXAMPLE_I2C_ADDR);

Обе сидят на шине I2C и тот кто второй, тот и не работает.
Если поменять строчки местами, то получаю такую ошибку:

ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce2820,len:0x1188
load:0x403c8700,len:0x4
load:0x403c8704,len:0xbf0
load:0x403cb700,len:0x30e4
entry 0x403c88ac
[I][Expander][esp_io_expander_ch422g.c:0075](esp_io_expander_new_i2c_ch422g): version: 0.1.0
E (1091) i2c: i2c driver install error

Всем спасибо, нашёл ответ, изучив весь код библиотеки ESP32_IO_Expander.
После инициализации SD нужно уничтожить объект командой expander->del();
Код выглядит так:

  expander = new esp_expander::CH422G(EXAMPLE_I2C_SCL_PIN, EXAMPLE_I2C_SDA_PIN, EXAMPLE_I2C_ADDR);
  expander->init();
  expander->begin();
  expander->enableAllIO_Output();
  expander->digitalWrite(TP_RST , HIGH);
  expander->digitalWrite(LCD_RST , HIGH);
  expander->digitalWrite(LCD_BL , HIGH);
  expander->digitalWrite(SD_CS, LOW);
  expander->digitalWrite(USB_SEL, LOW);
  SPI.setHwCs(false);
  SPI.begin(SD_CLK, SD_MISO, SD_MOSI, SD_SS);
  if (!SD.begin(SD_SS)) {
    GFX->println(NO);
  }
  else
    GFX->println(OK);
  expander->del();

В противном случае I2C на модуле не заработает, так как будет конфликтовать с I2C созданным командой expander->init();

Код функции init() в библиотеке ESP32_IO_Expander:

bool Base::init(void)
{
    ESP_UTILS_LOG_TRACE_ENTER_WITH_THIS();

    ESP_UTILS_CHECK_FALSE_RETURN(!isOverState(State::INIT), false, "Already initialized");

    // Convert the partial configuration to full configuration
    _config.convertPartialToFull();
#if ESP_UTILS_CONF_LOG_LEVEL == ESP_UTILS_LOG_LEVEL_DEBUG
    _config.printHostConfig();
    _config.printDeviceConfig();
#endif // ESP_UTILS_LOG_LEVEL_DEBUG

    // Initialize the I2C host if not skipped
    if (!isHostSkipInit()) {
        i2c_port_t host_id = static_cast<i2c_port_t>(getConfig().host_id);
        ESP_UTILS_CHECK_ERROR_RETURN(
            i2c_param_config(host_id, getHostFullConfig()), false, "I2C param config failed"
        );
        ESP_UTILS_CHECK_ERROR_RETURN(
            i2c_driver_install(host_id, getHostFullConfig()->mode, 0, 0, 0), false, "I2C driver install failed"
        );
        ESP_UTILS_LOGD("Init I2C host(%d)", static_cast<int>(host_id));
    }

    setState(State::INIT);

    ESP_UTILS_LOG_TRACE_EXIT_WITH_THIS();

    return true;
}

Почему об этом ни чего не сказано в документации, я хз.