STM32H735G-DK based TouchGFX project with custom display/touchscreen driver
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-05-30 11:38 AM
I have a STM32H73G-DK developement kit and I want to interface a custom 7" touchscreen/display with it using TouchGFX to create a basic menu structure. I was able to get the display to show static images by following the guide in these youtube videos (from STMicro):
Following these videos I was able to get a static image to display perfectly however I also need to get the touchscreen functionality to work as well. The development kit comes with a smaller display that uses the FT5336 touchscreen controller but my display uses the GT911. One of the steps in the first video is the comment out the touch screen "sampleTouch" code in STM32TouchController.cpp and type in "return true;" as the only code to execute there. This effectively disables the touchscreen functionality, and if you don't do it the whole project will fail and you get gibberish on the screen. Since my screen uses the GT911 I searched for drivers for this and I found that STMicro actually wrote an entire driver for that chip and has it up on the Github here:
https://github.com/STMicroelectronics/stm32-gt911
I brought these files into my project in the same location as the corresponding driver files for the FT5336 and changed all mentions of FT5336 to GT911 in stm32h735g_discovery_ts.h and stm32h735g_discovery.c. I also had to change some other define statements in the .c file due to them not lining up exactly with the naming convention that is more or less shared between the two driver sets. Once I did this I also noticed in the .h file that there are define statements for width, height, and I2C address...I changed these to 800x480 with an I2C address of 0xBA to match the GT911 and the size of my touch panel. I returned the sampleTouch "function" to it's original un-commented state and built/ran the program. When I do this my screen now shows mostly gibberish with an old image that must not have been cleared from memory from a previous attempt at getting the display working. when I stop my program the program counter is stuck in the MemManage_Handler.
I know from previous tests using TouchGFX with all the stock hardware from ST that projects using the touchscreen work just fine as long as you're using the stock display with the FT5336 controller. Since both the FT5336 and GT911 drivers were written by ST with nearly identical function calls and define statements (except the values stored being changed) I thought this would be a relatively simple change. What else do I need to change in my project to switch over from the FT5336 to GT911 controller? Are there other Discovery Kits that happen to use the GT911 that I can look at their code and see what they did?
Solved! Go to Solution.
- Labels:
-
TouchGFX
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-06-12 12:03 PM
After a lot of experimentation I was able to fix my issues. There were several things going on to cause this not to work.
- The GT911 library was for some reason written to utilize 8bit register addresses. The GT911 has 16bit register addresses. I had to change the function calls for I2C memory write and read functions to 16 bit
- The adapter I rigged up to connect my custom display (ZIF Connector) to the Discovery board (1.27mm pitch breakaway header) was an absolute mess with a 50 pin ribbon cable pealed back and stripped back and soldered to individual points on a universal ZIF to DIP adapter PCB. This was introducing a ton of noise into the I2C_SDA trace. On a logic analyzer this looked perfectly fine except the I2C Bus kept locking up. Once I used an oscilloscope I could see how bad it actually was. I went back and designed a tiny custom adapter PCB (2"x1" rectangle) that made the necessary connections and added filtering components and hardware pull-up resistors that the Discovery board lacks (it uses the internal pull-ups that are very weak compared to what is recommended). Using this new adapter board (even without the filtering components) greatly reduced the length and messiness of the cable. This almost entirely fixed the problem. The I2C bus no longer locks up at all...not even once.
- The GT911 library seems to be written so that the "x" direction is the short length of the display and the "y" is the long length. So my 800x480 screen had to be described as a 480x800 in the GT911_conf.h file. I could not find a "rotation" setting...so I'm assuming this is the correct way to adjust this.
Once all of these changes were made the touch functionality of the display seems to work perfectly.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-05-31 4:15 AM
The MemManage_Handler implies invalid memory access. In your sampleTouch implementation, verify:
if (GT911_TS_GetState(0, &TS_State) == TS_OK) {
if (TS_State.TouchDetected) {
// Ensure you access the correct coordinates safely
x = TS_State.TouchX[0];
y = TS_State.TouchY[0];
updateTouch(x, y); // or however you pass it to TouchGFX
return true;
}
}
return false;
Make sure TS_State is a global/static variable and not stack-based if you’re calling it repeatedly.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-06-02 5:31 AM
Thank you, I started working through this problem on Friday afternoon with our software engineer and this is exactly where we tracked the issue to, though it was getting late and we had to put it down for the weekend. We found that in stm32h7335g_discovery_ts.c when we reached line 344:
/* Get each touch coordinates */
if(Ts_Drv->GetState(Ts_CompObj[Instance], &state) < 0)
{
ret = BSP_ERROR_COMPONENT_FAILURE;
}/* Check and update the number of touches active detected */
this if statement "passes" and the code drops into it, appears this means it's detecting a failure of some kind. It totally skips the following else if and else statements where it actually reads a touch's position.
else if(state.TouchDetected != 0U)
{
x_oriented = state.TouchX;
y_oriented = state.TouchY;
if((Ts_Ctx[Instance].Orientation & TS_SWAP_XY) == TS_SWAP_XY)
{
x_oriented = state.TouchY;
y_oriented = state.TouchX;
}
if((Ts_Ctx[Instance].Orientation & TS_SWAP_X) == TS_SWAP_X)
{
x_oriented = Ts_Ctx[Instance].MaxX - state.TouchX - 1UL;
}
if((Ts_Ctx[Instance].Orientation & TS_SWAP_Y) == TS_SWAP_Y)
{
y_oriented = Ts_Ctx[Instance].MaxY - state.TouchY;
}
/* Apply boundary */
TS_State->TouchX = (x_oriented * Ts_Ctx[Instance].Width) / Ts_Ctx[Instance].MaxX;
TS_State->TouchY = (y_oriented * Ts_Ctx[Instance].Height) / Ts_Ctx[Instance].MaxY;
/* Store Current TS state */
TS_State->TouchDetected = state.TouchDetected;
/* Check accuracy */
x_diff = (TS_State->TouchX > Ts_Ctx[Instance].PreviousX[0])?
(TS_State->TouchX - Ts_Ctx[Instance].PreviousX[0]):
(Ts_Ctx[Instance].PreviousX[0] - TS_State->TouchX);
y_diff = (TS_State->TouchY > Ts_Ctx[Instance].PreviousY[0])?
(TS_State->TouchY - Ts_Ctx[Instance].PreviousY[0]):
(Ts_Ctx[Instance].PreviousY[0] - TS_State->TouchY);
if ((x_diff > Ts_Ctx[Instance].Accuracy) || (y_diff > Ts_Ctx[Instance].Accuracy))
{
/* New touch detected */
Ts_Ctx[Instance].PreviousX[0] = TS_State->TouchX;
Ts_Ctx[Instance].PreviousY[0] = TS_State->TouchY;
}
else
{
TS_State->TouchX = Ts_Ctx[Instance].PreviousX[0];
TS_State->TouchY = Ts_Ctx[Instance].PreviousY[0];
}
}
else
{
TS_State->TouchDetected = 0U;
TS_State->TouchX = Ts_Ctx[Instance].PreviousX[0];
TS_State->TouchY = Ts_Ctx[Instance].PreviousY[0];
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-06-02 5:32 AM
We have yet to actually solve the issue though. So any further insight would be appreciated.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-06-02 1:56 PM
OK, so took a deep dive into the I2C communications between the TS Controller (GT911) and the STM32H735G-DK Discovery Board. Using a logic analyzer I was able to see that during the initialization stage the MCU was sending only byte size register addresses. The GT911 addresses are Word size (0x8140 - 0x8143 = Product ID). I tracked this down to line 363 in stm32h735g_discovery_bus.c (line 8 below):
int32_t BSP_I2C4_ReadReg(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t Length)
{
int32_t ret;
#if defined(BSP_USE_CMSIS_OS)
/* Get semaphore to prevent multiple I2C access */
osSemaphoreWait(BspI2cSemaphore, osWaitForever);
#endif
if(I2C4_ReadReg(DevAddr, Reg, I2C_MEMADD_SIZE_16BIT, pData, Length) == 0)
{
ret = BSP_ERROR_NONE;
}
else
{
if( HAL_I2C_GetError(&hbus_i2c4) == HAL_I2C_ERROR_AF)
{
ret = BSP_ERROR_BUS_ACKNOWLEDGE_FAILURE;
}
else
{
ret = BSP_ERROR_PERIPH_FAILURE;
}
}
#if defined(BSP_USE_CMSIS_OS)
/* Release semaphore to prevent multiple I2C access */
osSemaphoreRelease(BspI2cSemaphore);
#endif
return ret;
}
I changed this to 16 bit and re ran the code and now I am getting proper responses from the GT911 chip. However now when I run the code, sometimes it runs just fine and gets through this with the proper information coming back from the GT911 and sometimes it errors out. Sometimes when it errors out it locks the I2C_SDA line low for some reason. When that happens I have to power cycle the test setup before I can get it to work at all again. I don't know what side is locking up...if it's the GT911 SDA pin or if it's the MCU SDA pin. Since resetting the MCU code and starting over doesn't unlock it I'm guessing it's the GT911. Any ideas why this would happen?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-06-12 12:03 PM
After a lot of experimentation I was able to fix my issues. There were several things going on to cause this not to work.
- The GT911 library was for some reason written to utilize 8bit register addresses. The GT911 has 16bit register addresses. I had to change the function calls for I2C memory write and read functions to 16 bit
- The adapter I rigged up to connect my custom display (ZIF Connector) to the Discovery board (1.27mm pitch breakaway header) was an absolute mess with a 50 pin ribbon cable pealed back and stripped back and soldered to individual points on a universal ZIF to DIP adapter PCB. This was introducing a ton of noise into the I2C_SDA trace. On a logic analyzer this looked perfectly fine except the I2C Bus kept locking up. Once I used an oscilloscope I could see how bad it actually was. I went back and designed a tiny custom adapter PCB (2"x1" rectangle) that made the necessary connections and added filtering components and hardware pull-up resistors that the Discovery board lacks (it uses the internal pull-ups that are very weak compared to what is recommended). Using this new adapter board (even without the filtering components) greatly reduced the length and messiness of the cable. This almost entirely fixed the problem. The I2C bus no longer locks up at all...not even once.
- The GT911 library seems to be written so that the "x" direction is the short length of the display and the "y" is the long length. So my 800x480 screen had to be described as a 480x800 in the GT911_conf.h file. I could not find a "rotation" setting...so I'm assuming this is the correct way to adjust this.
Once all of these changes were made the touch functionality of the display seems to work perfectly.
