在ART-Pi H750上移植TouchGFX(一)——使用STM32CUBMX生成TouchGFX工程
在ART-Pi H750上移植TouchGFX(二)——制做MDK的外部QSPI-FLASH烧录算法
在ART-Pi H750上移植TouchGFX(三)——移植TouchGFX到RT-Thread系统
在ART-Pi H750上移植TouchGFX(四)——使用RT-Thread Studio移植TouchGFX
在ART-Pi H750上移植TouchGFX(五)——制做ST-LINK的外部QSPI-FLASH烧录算法html
硬件: RT-Thread官方ART-PI H750开发版,正点原子4.3寸RGBLCD屏(800*480)
软件: 最新版本的STM32CubeH7固件库,TouchGFXDesigner v4.14和 STM32CubeMX V6.0.1,开发环境MDK v5.29
git
待公布github
关注公众号,免费查看,回复“加群”,加入技术交流群
web
RT-Thread 是一个集实时操做系统(RTOS)内核、中间件组件和开发者社区于一体的技术平台,由熊谱翔先生带领并集合开源社区力量开发而成,RT-Thread 也是一个组件完整丰富、高度可伸缩、简易开发、超低功耗、高安全性的物联网操做系统。RT-Thread 具有一个 IoT OS 平台所需的全部关键组件,例如GUI、网络协议栈、安全传输、低功耗组件等等。通过11年的累积发展,RT-Thread 已经拥有一个国内最大的嵌入式开源社区,同时被普遍应用于能源、车载、医疗、消费电子等多个行业,累积装机量超过 6亿 台,成为国人自主开发、国内最成熟稳定和装机量最大的开源 RTOS。算法
自2006年发布源码并开源,RT-Thread坚持“开源、开放”的理念,贴近开发者知足市场需求,坚持作小而美的物联网操做系统,当前已可完美覆盖面向嵌入式及IoT不一样应用场景:安全
github地址:https://github.com/RT-Thread/rt-thread
gitee地址:https://gitee.com/rtthread/rt-thread网络
STM32CubeMX默认支持的操做系统为FreeRTOS,TouchGFX能够运行在带操做系统和不带操做系统的应用中,用户想要更换操做系统,只须要从新实现OSWrappers类,即可以切换不一样的RTOS。
app
1.从新实现OSWrappers类:electron
/** ****************************************************************************** * File Name : OSWrappers.cpp ****************************************************************************** * @attention * * <h2><center>© Copyright (c) 2020 STMicroelectronics. * All rights reserved.</center></h2> * * This software component is licensed by ST under Ultimate Liberty license * SLA0044, the "License"; You may not use this file except in compliance with * the License. You may obtain a copy of the License at: * www.st.com/SLA0044 * ****************************************************************************** */ #include <touchgfx/hal/OSWrappers.hpp> #include <stm32h7xx_hal.h> #include <touchgfx/hal/GPIO.hpp> #include <touchgfx/hal/HAL.hpp> #include <rtthread.h> #include <rtdevice.h> #include <board.h> #include <rthw.h> static rt_sem_t frame_buffer_sem; static rt_mq_t vsync_q = 0; using namespace touchgfx; // Just a dummy value to insert in the VSYNC queue. static uint8_t dummy = 0x5a; /* * Initialize frame buffer semaphore and queue/mutex for VSYNC signal. */ void OSWrappers::initialize() { frame_buffer_sem = rt_sem_create("gfx_sem", 1, RT_IPC_FLAG_PRIO); // Create a queue of length 1 vsync_q = rt_mq_create("gfx_mq", 1, 1, RT_IPC_FLAG_PRIO); } /* * Take the frame buffer semaphore. Blocks until semaphore is available. */ void OSWrappers::takeFrameBufferSemaphore() { rt_sem_take(frame_buffer_sem, RT_WAITING_FOREVER); } /* * Release the frame buffer semaphore. */ void OSWrappers::giveFrameBufferSemaphore() { rt_sem_release(frame_buffer_sem); } /* * Attempt to obtain the frame buffer semaphore. If semaphore is not available, do * nothing. * * Note must return immediately! This function does not care who has the taken the semaphore, * it only serves to make sure that the semaphore is taken by someone. */ void OSWrappers::tryTakeFrameBufferSemaphore() { rt_sem_trytake(frame_buffer_sem); } /* * Release the frame buffer semaphore in a way that is safe in interrupt context. Called * from ISR. * * Release the frame buffer semaphore in a way that is safe in interrupt context. * Called from ISR. */ void OSWrappers::giveFrameBufferSemaphoreFromISR() { // Since this is called from an interrupt, FreeRTOS requires special handling to trigger a // re-scheduling. May be applicable for other OSes as well. rt_sem_release(frame_buffer_sem); } /* * Signal that a VSYNC has occurred. Should make the vsync queue/mutex available. * * Note This function is called from an ISR, and should (depending on OS) trigger a * scheduling. */ void OSWrappers::signalVSync() { if (vsync_q) { rt_mq_send(vsync_q, &dummy, 1); } } /* * This function blocks until a VSYNC occurs. * * Note This function must first clear the mutex/queue and then wait for the next one to * occur. */ void OSWrappers::waitForVSync() { // First make sure the queue is empty, by trying to remove an element with 0 timeout. rt_mq_recv(vsync_q, &dummy, 1, 0); // Then, wait for next VSYNC to occur. rt_mq_recv(vsync_q, &dummy, 1, RT_WAITING_FOREVER); } /* * A function that causes executing task to sleep for a number of milliseconds. * * A function that causes executing task to sleep for a number of milliseconds. * This function is OPTIONAL. It is only used by the TouchGFX in the case of * a specific frame refresh strategy (REFRESH_STRATEGY_OPTIM_SINGLE_BUFFER_TFT_CTRL). * Due to backwards compatibility, in order for this function to be useable by the HAL * the function must be explicitly registered: * hal.registerTaskDelayFunction(&OSWrappers::taskDelay) * * see HAL::setFrameRefreshStrategy(FrameRefreshStrategy s) * see HAL::registerTaskDelayFunction(void (*delayF)(uint16_t)) */ void OSWrappers::taskDelay(uint16_t ms) { rt_thread_mdelay(ms); } /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
2. 在rtthread中添加touchgfx须要的外设
移植思路:回顾一下touchgfx须要的组件构成,只须要在rtthread中按需添加便可,详细步骤能够参考此教程:使用RTThread和TouchGFX实现DIY数字仪表(二)——把TouchGFX移植到RTThread系统
svg
1.打开上一节的工程,导入一个游戏例程
因为此工程比较大,除了图片和字体,代码量已经超过了128k,因此不能像上一个工程那样直接下载代码了。这种状况,能够参考ST官方开发板的作法,把全部的代码都放到外部flash的空间,内部的128k空间,用来制做bootloader,bootloader上电后对qspi地址映射,而后跳转到qspi flash的地址运行程序。
2.制做bootloader
#include <rtthread.h> #include <rtdevice.h> #include <board.h> #include <drv_common.h> #include "w25qxx.h" #define DBG_TAG "main" #define DBG_LVL DBG_LOG #include <rtdbg.h> /* defined the LED0 pin: PB1 */ #define LED0_PIN GET_PIN(I, 8) #define VECT_TAB_OFFSET 0x00000000UL #define APPLICATION_ADDRESS (uint32_t)0x90000000 typedef void (*pFunction)(void); pFunction JumpToApplication; int main(void) { /* set LED0 pin mode to output */ rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT); W25QXX_Init(); W25Q_Memory_Mapped_Enable();//地址映射 SCB_DisableICache(); SCB_DisableDCache(); SysTick->CTRL = 0; JumpToApplication = (pFunction)(*(__IO uint32_t *)(APPLICATION_ADDRESS + 4)); __set_MSP(*(__IO uint32_t *)APPLICATION_ADDRESS); JumpToApplication();//跳转 return RT_EOK; }
3.制做APP
修改分散加载文件,使代码所有放到外部flash
添加中断重映射
static int vtor_config(void) { /* Vector Table Relocation in Internal QSPI_FLASH */ SCB->VTOR = QSPI_BASE; return 0; } INIT_BOARD_EXPORT(vtor_config);
4.添加触摸gt9147软件包
而后在STM32TouchController.cpp中给touchgfx赋值xy坐标
bool STM32TouchController::sampleTouch(int32_t& x, int32_t& y) { /** * By default sampleTouch returns false, * return true if a touch has been detected, otherwise false. * * Coordinates are passed to the caller by reference by x and y. * * This function is called by the TouchGFX framework. * By default sampleTouch is called every tick, this can be adjusted by HAL::setTouchSampleRate(int8_t); * */ struct rt_touch_data *read_data; read_data = read_coordinate(); if (read_data->event == RT_TOUCH_EVENT_DOWN || read_data->event == RT_TOUCH_EVENT_MOVE) { x = read_data->x_coordinate; y = read_data->y_coordinate; return true; } else { return false; } }