Skip to content

SPI commands hang on SPI_PARAM_LOCK() #7556

Closed
@stuartpittaway

Description

@stuartpittaway

Board

ESP32 DEVKITC

Device Description

DevKITC ESP32 module running on custom PCB for DIYBMS controller.

Hardware Configuration

VSPI port being used on pins GPIO18(CLK), GPIO19(MISO), GPIO23 (MOSI) and GPIO4 CS

This communicates with XPT2046 touch screen controller.

Version

v2.0.5

IDE Name

PlatformIO

Operating System

Windows 10

Flash frequency

40M

PSRAM enabled

yes

Upload speed

921000

Description

This is existing code which has worked (and still works) on v2.0.3 Arduino ESP32 framework.

On 2.0.4 and 2.0.5, the code hangs when calling beginTransaction on the VSPI bus.

This appears to be caused by an infinite loop when calling the macro SPI_PARAM_LOCK() which attempts to obtain a semaphore (xSemaphoreTake)

If I add #define CONFIG_DISABLE_HAL_LOCKS 1 to the top of the debug sketch provided - the code works as expected, and no longer hangs.

This appears to be related to the code added in issue #6425

I'm using this framework library reference in my platformio.ini file

platform_packages =
   framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#2.0.5

Sketch

#define USE_ESP_IDF_LOG 1
static constexpr const char *const TAG = "vspi";
#include <Arduino.h>
#include <SPI.h>
#include "esp_log.h"

SPIClass vspi;

#define TOUCH_CHIPSELECT GPIO_NUM_4

struct TouchScreenValues
{
  bool touched;
  uint8_t pressure;
  uint16_t X;
  uint16_t Y;
};


void setup()
{
  esp_log_level_set(TAG, esp_log_level_t::ESP_LOG_DEBUG);
  Serial.begin(115200, SERIAL_8N1);
  ESP_LOGD(TAG, "Configure VSPI");
  vspi = SPIClass(VSPI);

  // Don't use hardware chip selects on VSPI
  vspi.setHwCs(false);
  vspi.setBitOrder(MSBFIRST);
  vspi.setDataMode(SPI_MODE0);
  // 10mhz
  vspi.setFrequency(10000000);

  // GPIO18(CLK), GPIO19(MISO), GPIO23 (MOSI)
  // and normally GPIO5 (CS) - although not used on my board replaced with GPIO4
  vspi.begin(GPIO_NUM_18, GPIO_NUM_19, GPIO_NUM_23, TOUCH_CHIPSELECT);

  pinMode(TOUCH_CHIPSELECT,OUTPUT);

  ESP_LOGD(TAG, "end of setup");
}
TouchScreenValues TouchScreenUpdate()
{
  /*
      Features and Specification of XPT2046
      https://components101.com/admin/sites/default/files/component_datasheet/XPT2046-Datasheet.pdf
  */
  // Z is touch (depth)
  const uint8_t ADD_Z1 = 0B00110000;
  const uint8_t ADD_Z2 = 0B01000000;
  const uint8_t ADD_X = 0B00010000;
  const uint8_t ADD_Y = 0B01010000;
  const uint8_t STARTBIT = 0B10000000;
  const uint8_t PWR_ALLOFF = 0B00000000;
  const uint8_t PWR_REFOFF_ADCON = 0B00000001;
  const uint8_t ADC_DIFFERENTIAL = 0B00000000;

  const uint8_t ADC_8BIT = 0B00001000;
  const uint8_t ADC_12BIT = 0B00000000;

  TouchScreenValues reply;
  reply.touched = false;
  reply.pressure = 0;
  reply.X = 0;
  reply.Y = 0;

  ESP_LOGD(TAG, "1");
  // *** CODE HANGS ON THIS CALL ****
  vspi.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0));
  ESP_LOGD(TAG, "2");

  digitalWrite(TOUCH_CHIPSELECT, LOW);
  ESP_LOGD(TAG, "3");

  // We don't need accurate touch pressure for this application, so
  // only read Z2 register, we just want a boolean value at the end of the day

  // The transfers are always a step behind, so the transfer reads the previous value/command
  vspi.write(STARTBIT | PWR_REFOFF_ADCON | ADC_8BIT | ADC_DIFFERENTIAL | ADD_Z1);
  ESP_LOGD(TAG, "4");

  // Read Z2 (1 byte) and request X
  reply.pressure = vspi.transfer(STARTBIT | PWR_REFOFF_ADCON | ADC_12BIT | ADC_DIFFERENTIAL | ADD_X);
  ESP_LOGD(TAG, "5");

  // Read X (2 bytes) and request Y
  reply.X = vspi.transfer16(STARTBIT | PWR_REFOFF_ADCON | ADC_12BIT | ADC_DIFFERENTIAL | ADD_Y) >> 3;
  ESP_LOGD(TAG, "6");
  // Take Y reading, then power down after this sample
  reply.Y = vspi.transfer16(STARTBIT | PWR_ALLOFF | ADC_8BIT | ADC_DIFFERENTIAL | ADD_Z2) >> 3;
  ESP_LOGD(TAG, "7");

  // Final transfer to ensure device goes into sleep
  // In order to turn the reference off, an additional write to the XPT2046 is required after the channel has been converted.  Page 24 datasheet
  // uint16_t Z2 =
  vspi.transfer(0);
  ESP_LOGD(TAG, "8");

  digitalWrite(TOUCH_CHIPSELECT, HIGH);
  vspi.endTransaction();

  reply.touched = reply.pressure > 135 && reply.X > 0;
  ESP_LOGI(TAG, "Touch = touch=%i pressure=%u x=%u y=%u", reply.touched, reply.pressure, reply.X, reply.Y);
  return reply;
}

void loop()
{
  ESP_LOGD(TAG, "Loop");
  TouchScreenUpdate();
  delay(5000);
}

Debug Message

No error message - code hangs.

The debug output gets as far as outputting "1" to console.

Other Steps to Reproduce

Tested 2.0.4 and 2.0.5 both fail. 2.0.3 works.

I have checked existing issues, online documentation and the Troubleshooting Guide

  • I confirm I have checked existing issues, online documentation and Troubleshooting guide.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions