stm32duino / Arduino_Core_STM32

STM32 core support for Arduino
https://github.com/stm32duino/Arduino_Core_STM32/wiki
Other
2.85k stars 977 forks source link

Problem with STM32H743VIT6 and XPT2046 Touchpad #1380

Closed pacman1945 closed 3 years ago

pacman1945 commented 3 years ago

Describe the bug When using STM32H743VIT6 (or STM32H750VBT6) with XPT2046 touchpad via PaulStoffregen's XPT2046_Touchscreen library, SPI data will be corrupted. Everything worked if I replaced the STM32H7 board with a STM32F407VET6.

To Reproduce

  1. Install the latest version of PaulStoffregen's XPT2046_Touchscreen library (v1.3.0) using Arduino library manager.
  2. Choose example "TouchTestIRQ", modify the CS_PIN & TIRQ_PIN to the proper pins used for XPT2046 touchpad connection.
  3. Open the serial monitor, it will report pressure & x, y coordinates even without touching the touchpad.

Desktop (please complete the following information):

Board (please complete the following information): Tried both of the below boards and have the same problem. https://www.aliexpress.com/item/4000295397211.html?spm=a2g0o.productlist.0.0.637d1d300fFQ5d&algo_pvid=b237e656-d04b-422e-84af-8be8ed4042d9&algo_expid=b237e656-d04b-422e-84af-8be8ed4042d9-34&btsid=0bb0624116200479098028721ef47f&ws_ab_test=searchweb0_0,searchweb201602_,searchweb201603_ https://www.aliexpress.com/item/1005001683272407.html?spm=a2g0o.productlist.0.0.637d1d300fFQ5d&algo_pvid=b237e656-d04b-422e-84af-8be8ed4042d9&algo_expid=b237e656-d04b-422e-84af-8be8ed4042d9-0&btsid=0bb0624116200479098028721ef47f&ws_ab_test=searchweb0_0,searchweb201602_,searchweb201603_

fpistm commented 3 years ago

Hi @pacman1945

Maybe related to #1294 but it seems SPI clock is 2 MHZ anyway you could give a try to the workaround. If it's not work we will not be able to help you as we do not have Touchpad and this is related to third party library usage. You will be on your own for this. If you can reproduce with a simple SPI sketch we could probably help. H7 runs at very high speed it is also possible that library do not handle this properly (already saw that). You can try to disable ICACHE and DCACHE using build_opt.h

-DI_CACHE_DISABLED -DD_CACHE_DISABLED

Edit: other examples failed too (without irq pin)?

pacman1945 commented 3 years ago

Thank you so much for the help. I've tested the #1294 suggestion, but it didn't help. I've also tried to disable ICACHE & DCACHE, the problem still persisted.

I've located a simply sketch using SPI to directly communicates with the XPT2046 touchpad without using any specific touchpad library, it also exhibits the same SPI corruption problem. BTW, this sketch doesn't use IRQ pin.

fpistm commented 3 years ago

Ok thank you. Could you share the sketch please?

JiriBilek commented 3 years ago

It would also be quite helpful if you can capure the SPI traffic using a logic analyzer, if you have any.

pacman1945 commented 3 years ago

Sorry, I don't have access to a logic analyzer.

Below is a simple sketch that I downloaded.

/**
 * XPT2046 Touch Screen Controller example.
 * 
 * Copyright (c) 02 Dec 2015 by Vassilis Serasidis
 * Home: http://www.serasidis.gr
 * email: avrsite@yahoo.gr
 * 
 * The sketch example has been created for using it with STM32Duino (http://stm32duinoforum.com/forum)
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include <SPI.h>
#define csPin PA4
#define Z_THRESHOLD   3500

int xy[2];
int z;
void setup() {
  delay(5000);
  SPI.setMOSI(PA7);
  SPI.setMISO(PA6);
  SPI.setSCLK(PA5);
  Serial.begin(115200);
  Serial.println("-------------------------------------------------");
  Serial.println("XPT2046 example sketch");
  Serial.println("Copyright (c) 02 Dec 2015 by Vassilis Serasidis");
  Serial.println("Home: http://www.serasidis.gr");
  Serial.println("-------------------------------------------------");
  SPI.begin(); //Initiallize the SPI1 port.
  pinMode(csPin, OUTPUT);
  digitalWrite(csPin, HIGH);
}
//-----------------------------------------------------
//
//-----------------------------------------------------
void loop() {
  if(read_XY(xy, &z)){     //Read the X,Y coordinates (12 bits, values 0-4095)
    Serial.print("Pressure: ");
    Serial.print(z, HEX);
    Serial.print("\tX: ");
    Serial.print(xy[0], HEX); //Print X value
    Serial.print("\tY: ");
    Serial.print(xy[1], HEX); //Print Y value
    Serial.println();
    delay(10);
  }
}
//-----------------------------------------------------
//
//-----------------------------------------------------
boolean read_XY(int *xy, int *z){
  int z1, z2, tmpH, tmpL;
  digitalWrite(csPin, LOW);
  //Check if touch screen is pressed.
  SPI.transfer(B10110001); // Z1 (Also tried with value B10110011, same result)
  tmpH = (SPI.transfer(0) << 5);
  tmpL = (SPI.transfer(0) >> 3);
  z1 = tmpH | tmpL;
  SPI.transfer(B11000001); // Z2 ((Also tried with value B11000011, same result)
  tmpH = (SPI.transfer(0) << 5);
  tmpL = (SPI.transfer(0) >> 3);
  z2 = tmpH | tmpL;
  *z = z2 - z1;
  if((z2 - z1) < Z_THRESHOLD){ //If the touch screen is pressed, read the X,Y  coordinates from XPT2046.
    SPI.transfer(B11010001); // X
    tmpH = (SPI.transfer(0) << 5);
    tmpL = (SPI.transfer(0) >> 3);
    xy[0] =  tmpH | tmpL;
    SPI.transfer(B10010001); // Y
    tmpH = (SPI.transfer(0) << 5);
    tmpL = (SPI.transfer(0) >> 3);
    xy[1] =  tmpH | tmpL;
    digitalWrite(csPin, HIGH);
    return true;
  }
  digitalWrite(csPin, HIGH);
  return false;
}

When running the above sketch on a STM32F407VET6, below is part of the output. The results are normal.

Pressure: 7B7   X: 3CF  Y: 24C
Pressure: 7B8   X: 3CF  Y: 24C
Pressure: 7B4   X: 3D2  Y: 24C
Pressure: 7B5   X: 3D3  Y: 250
Pressure: 7B5   X: 3D3  Y: 250
Pressure: 7B3   X: 3D2  Y: 24D
Pressure: 7B2   X: 3CF  Y: 250
Pressure: 7BA   X: 3D2  Y: 24C
Pressure: 7B7   X: 3D4  Y: 24C
Pressure: 7B4   X: 3D3  Y: 24C
Pressure: 7B7   X: 3CF  Y: 24C
Pressure: 7B8   X: 3CF  Y: 250
Pressure: 7B7   X: 3CF  Y: 24C

When running the same sketch on a STM32H743VIT6, below is part of the output. The fields X & Y are corrupted. If you look at bit 12 of X & Y, they're always on (0x1XXX). These are impossible values as they shouldn't be larger than 0xFFF.

Pressure: 737   X: 13FF Y: 11FF
Pressure: 74D   X: 13FF Y: 11FF
Pressure: 741   X: 13FF Y: 11FF
Pressure: 7C0   X: 17D4 Y: 11FF
Pressure: 7B7   X: 17FF Y: 11FF
Pressure: 7C0   X: 1850 Y: 11FF
Pressure: 7AF   X: 187F Y: 11FF
Pressure: 7A1   X: 18C2 Y: 11FF
Pressure: 7B0   X: 18FF Y: 11FF
Pressure: 790   X: 18FF Y: 11FF
Pressure: 770   X: 18FF Y: 11FF
Pressure: 764   X: 18FF Y: 11FF
Pressure: 750   X: 18FF Y: 11FF
Pressure: 766   X: 18FF Y: 13E2
Pressure: 754   X: 18FF Y: 13E4
Pressure: 740   X: 18FF Y: 13F0
Pressure: 7E0   X: 19C0 Y: 13FF
Pressure: 7E0   X: 19C4 Y: 13FF
Pressure: 7DD   X: 19C5 Y: 13FF
pacman1945 commented 3 years ago

I've just replaced the hardware SPI with a Software SPI library (SoftSPI from the below github repo). The STM32H7 is now working properly with XPT2046 touchpad using SoftSPI.

https://github.com/MajenkoLibraries/SoftSPI

fpistm commented 3 years ago

Hi @pacman1945 There is an issue with the default system core clock config. SPI clock sources are too high (480MHz), I've made a PR #1393 to fix this. Please, could you test with your setup?

image

One note about the T_IRQ, it uses the EXTI line so pay attention to not use a GPIO pin number used by another pins. Due to the GPIO EXTI line mapping, for example all Px0 pins used will raised the EXTI 0 interrupt.: image

Moreover some EXTI IRQn are grouped so if you used PA5, PA6 and PA7 for SPI you should not use an IRQ pin Px5 to Px9 as they are all linked to the same EXTI9_5_IRQn .

Here the list of grouped IRQn line: https://github.com/stm32duino/Arduino_Core_STM32/blob/655587065fbdd6324655fee0b13d268507e23a40/libraries/SrcWrapper/src/stm32/interrupt.cpp#L90-L105

pacman1945 commented 3 years ago

I've tested with your updated generic_clock.c. Unfortunately, same problem still occurred with the new HSI clock setting. In order to avoid the IRQ issue that you mentioned, all my testings were now done without using T_IRQ pin.

fpistm commented 3 years ago

Hi @pacman1945 Thank you for the test. I was able to get a Touchscreen with XPT2046 and made some tests. So I've found an issue related to the SPI clock frequencies computation. Function to get the current peripheral source frequency was not correct and now fixed by #1393.

Anyway, H7 runs too quickly and so value read is not correct as the XPT does not have time to made the conversion. I added a small delay to the XPT2046 Touchsrceen btw 2 reads: https://github.com/PaulStoffregen/XPT2046_Touchscreen/blob/aef8ec703e2a04617a331e127d441b58e549c01a/XPT2046_Touchscreen.cpp#L132-L133

        z = z1 + 4095;
+       delayMicroseconds(2);
        int16_t z2 = _pspi->transfer16(0x91 /* X */) >> 3;

The delay allows to get the correct conversion result. Then the default TouchTestIRQ example works fine. This is only a workaround for the library as it does not ensure minimum timing between acquisition request + conversion time. I've check with a logical analyzer and adding the small timing ensure this minimum time.