OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5022|回复: 1

记录在RT-Thread系统上移植TouchGFX的一个小坑

[复制链接]

17

主题

46

帖子

0

精华

初级会员

Rank: 2

积分
196
金钱
196
注册时间
2014-10-5
在线时间
39 小时
发表于 2020-12-19 17:00:37 | 显示全部楼层 |阅读模式
本帖最后由 stm32新人一枚 于 2020-12-19 17:04 编辑





这个帖子主要用来记录自己在RT-Thread上移植TouchGFX的一些坑。

RT-Thread和TouchGFX,以及相关的模块,都是在STM32CubeMx上配置的。

配置好之后,只需要对TouchGFX的“OSWrappers.cpp”文件进行修改,就可以正常使用了。

CSDN网站中有大神做过移植,详情在这里https://blog.csdn.net/sinat_31039061/article/details/105045469
CSDN中这个帖子后来需要付费订阅了,但是百度还是能搜到另外一个网站可以看这个帖子:https://www.freesion.com/article/9090379134/

里边记录了OSWrappers.cpp的修改详细方法。

我自己按照帖子的方法移植之后,也能运行,只是有些小细节有问题。
后边贴的图片,是实拍图,红框里的字符会显示不全。而且经过排查,不是单片机运行速度或者RAM读写速度问题。



之后我又用STM32CubeMx重新配了一个FreeRTOS的工程,显示同样的内容,FreeRTOS的工程就很完美。
然后对比两个工程的OSWrappers.cpp,发现了端倪。
主要问题在于void OSWrappers::takeFrameBufferSemaphore()和void OSWrappers::giveFrameBufferSemaphore()中的信号量处理有问题。



这里贴出我修改后的代码(代码中重点修改的内容简单做了标注。其他部分的代码,也有根据FreeRTOS工程略做调整的部分,这里不再着重标注)

修改之后就可以完美运行了!

  1. /**
  2.   ******************************************************************************
  3.   * File Name          : OSWrappers.cpp
  4.   ******************************************************************************
  5.   * @attention
  6.   *
  7.   * <h2><center>&#169; Copyright (c) 2020 STMicroelectronics.
  8.   * All rights reserved.</center></h2>
  9.   *
  10.   * This software component is licensed by ST under Ultimate Liberty license
  11.   * SLA0044, the "License"; You may not use this file except in compliance with
  12.   * the License. You may obtain a copy of the License at:
  13.   *                             www.st.com/SLA0044
  14.   *
  15.   ******************************************************************************
  16.   */

  17. /* USER CODE BEGIN target/OSWrappers.cpp */

  18. #include <cassert>
  19. #include <touchgfx/hal/HAL.hpp>
  20. #include <touchgfx/hal/OSWrappers.hpp>
  21. #include <rtthread.h>
  22. using namespace touchgfx;
  23. static rt_sem_t frame_buffer_sem;
  24. static rt_sem_t vsync_sem;
  25. /*
  26. * Initialize frame buffer semaphore and queue/mutex for VSYNC signal.
  27. */
  28. void OSWrappers::initialize()
  29. {
  30.   frame_buffer_sem = rt_sem_create("gfx_sem", 1, RT_IPC_FLAG_PRIO);
  31.   vsync_sem = rt_sem_create("vsync_sem", 1, RT_IPC_FLAG_PRIO);
  32. }

  33. /*
  34. * Take the frame buffer semaphore. Blocks until semaphore is available.
  35. */

  36. /////////////////////////////////重点修改的内容/////////////////////////////////

  37. void OSWrappers::takeFrameBufferSemaphore()
  38. {
  39.   rt_sem_take(frame_buffer_sem,RT_WAITING_FOREVER);
  40. }

  41. /*
  42. * Release the frame buffer semaphore.
  43. */

  44. /////////////////////////////////重点修改的内容/////////////////////////////////

  45. void OSWrappers::giveFrameBufferSemaphore()
  46. {
  47.   rt_sem_release(frame_buffer_sem);
  48. }

  49. /*
  50. * Attempt to obtain the frame buffer semaphore. If semaphore is not available, do
  51. * nothing.
  52. *
  53. * Note must return immediately! This function does not care who has the taken the semaphore,
  54. * it only serves to make sure that the semaphore is taken by someone.
  55. */
  56. void OSWrappers::tryTakeFrameBufferSemaphore()
  57. {
  58.   rt_sem_trytake(frame_buffer_sem);
  59. }

  60. /*
  61. * Release the frame buffer semaphore in a way that is safe in interrupt context. Called
  62. * from ISR.
  63. *
  64. * Release the frame buffer semaphore in a way that is safe in interrupt context.
  65. * Called from ISR.
  66. */
  67. void OSWrappers::giveFrameBufferSemaphoreFromISR()
  68. {
  69.   rt_sem_release(frame_buffer_sem);
  70. }

  71. /*
  72. * Signal that a VSYNC has occurred. Should make the vsync queue/mutex available.
  73. *
  74. * Note This function is called from an ISR, and should (depending on OS) trigger a
  75. * scheduling.
  76. */
  77. void OSWrappers::signalVSync()
  78. {
  79.   rt_sem_release(vsync_sem);
  80. }

  81. /*
  82. * This function blocks until a VSYNC occurs.
  83. *
  84. * Note This function must first clear the mutex/queue and then wait for the next one to
  85. * occur.
  86. */
  87. void OSWrappers::waitForVSync()
  88. {
  89.   rt_sem_take(vsync_sem,0);
  90.   rt_sem_take(vsync_sem,RT_WAITING_FOREVER);
  91. }

  92. /*
  93. * A function that causes executing task to sleep for a number of milliseconds.
  94. *
  95. * A function that causes executing task to sleep for a number of milliseconds.
  96. * This function is OPTIONAL. It is only used by the TouchGFX in the case of
  97. * a specific frame refresh strategy (REFRESH_STRATEGY_OPTIM_SINGLE_BUFFER_TFT_CTRL).
  98. * Due to backwards compatibility, in order for this function to be useable by the HAL
  99. * the function must be explicitly registered:
  100. * hal.registerTaskDelayFunction(&OSWrappers::taskDelay)
  101. *
  102. * see HAL::setFrameRefreshStrategy(FrameRefreshStrategy s)
  103. * see HAL::registerTaskDelayFunction(void (*delayF)(uint16_t))
  104. */
  105. void OSWrappers::taskDelay(uint16_t ms)
  106. {
  107.   rt_thread_mdelay(ms);
  108. }

  109. /* USER CODE END target/OSWrappers.cpp */

  110. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
复制代码





异常实拍图

异常实拍图
可能我已经不能算新人了
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

17

主题

46

帖子

0

精华

初级会员

Rank: 2

积分
196
金钱
196
注册时间
2014-10-5
在线时间
39 小时
 楼主| 发表于 2020-12-30 18:19:50 | 显示全部楼层
本帖最后由 stm32新人一枚 于 2020-12-30 18:28 编辑





再补充一个内容:

RT-Thread基础上使用TouchGFX的时候,需要在DMA2D中断和LTDC中断中加入RT-Thread中断管理的两个函数。
进中断的时候加rt_interrupt_enter();
出中断的时候加rt_interrupt_leave();

分别在
1.   TouchGFXGeneratedHAL.cpp文件中重写的void HAL_LTDC_LineEventCallback(LTDC_HandleTypeDef *hltdc)函数里
大概98行加rt_interrupt_enter();
118行,添加   rt_interrupt_leave();
  1. void HAL_LTDC_LineEventCallback(LTDC_HandleTypeDef *hltdc)
  2. {
  3.     rt_interrupt_enter();
  4.     if (LTDC->LIPCR == lcd_int_active_line)
  5.     {
  6.         //entering active area
  7.         HAL_LTDC_ProgramLineEvent(hltdc, lcd_int_porch_line);
  8.         HAL::getInstance()->vSync();
  9.         OSWrappers::signalVSync();
  10.         // Swap frame buffers immediately instead of waiting for the task to be scheduled in.
  11.         // Note: task will also swap when it wakes up, but that operation is guarded and will not have
  12.         // any effect if already swapped.
  13.         HAL::getInstance()->swapFrameBuffers();
  14.         GPIO::set(GPIO::VSYNC_FREQ);
  15.     }
  16.     else
  17.     {
  18.         //exiting active area
  19.         HAL_LTDC_ProgramLineEvent(hltdc, lcd_int_active_line);
  20.         GPIO::clear(GPIO::VSYNC_FREQ);
  21.         HAL::getInstance()->frontPorchEntered();
  22.     }
  23.     rt_interrupt_leave();
  24. }
复制代码



2.   STM32DMA.cpp文件中重写的void DMA2D_XferCpltCallback(DMA2D_HandleTypeDef* handle)函数里
57行,添加   rt_interrupt_enter();
60行,添加   rt_interrupt_leave();

  1. static void DMA2D_XferCpltCallback(DMA2D_HandleTypeDef* handle)
  2. {
  3.     /* USER CODE BEGIN DMA2D_XferCpltCallback */
  4.     // If the framebuffer is placed in Write Through cached memory (e.g. SRAM) then we need
  5.     // to flush the Dcache prior to letting DMA2D accessing it. That's done
  6.     // using SCB_CleanInvalidateDCache().

  7.     // SCB_CleanInvalidateDCache();
  8.     /* USER CODE END DMA2D_XferCpltCallback */
  9.     rt_interrupt_enter();

  10.     touchgfx::HAL::getInstance()->signalDMAInterrupt();
  11.     rt_interrupt_leave();
  12. }
复制代码

在使用RT-Thread的时候,要注意中断函数中,都要添加这两个中断管理函数,不然可能出奇怪的问题。

上边我提到的两个文件里没加中断管理的代码,就会导致触摸屏经常莫名其妙的没反应了,希望看到这个帖子的小伙伴们注意




可能我已经不能算新人了
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-3-1 06:24

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表