STM32F429IGT6(RTスレッドバージョン)へのTouchGFXの移植

目次

序文

1.新しいBSP

2.CubeMXを使用してTouchGFXプロジェクトを作成します

1. FMC(SDRAM)を構成します

2. DMA2Dを構成し、DMA2D割り込みを有効にします

3. LTDCを構成し、LTDC割り込みを有効にします

4.CRCをオンにします

5.TouchGFXを構成します

6. TouchGFXDesignerを実行します

6.1、TouchGFXDesignerインターフェイス

6.2、GUIアプリケーションを追加します

6.3、コードを生成する

3.TouchGFXをRTスレッドに移植する

1.オペレーティングシステムのインターフェイスファイルを変更します

2.touchgfxの新しいアプリケーションサンプルファイルを作成します

3.プロジェクトにファイルを追加します

3.1、\ board \ KConfigを変更します

3.2。\ libraries \ STM32F4xx_HAL \ SConscriptを変更します

3.3、\ board \ SConscriptを変更します

3.4。\ board \ CubeMX_Config \ SConscriptを追加しました

4.タッチドライバーを追加します

4.1TOUCHドライバーファイルを追加する

4.2STM32TouchController.cppを改善する

第四に、オフチップのSPIFLASHに画像を配置します

1. STM32F429 SPIFLASHダウンロードアルゴリズムを作成します

2.プロジェクトテンプレートtemplate.uvprojxを変更します

3.リンクファイルを変更します

4.ビットマップデータを外部FLASHからキャッシュにコピーします

4.1、オープンアナログSPI

4.2、SFUDコンポーネントを開く

4.3、デバイスの初期初期化

4.4、FALソフトウェアパッケージを選択

4.5、TouchGFXドライバーを変更します

第4に、フォントをオフチップSPIFLASHに配置します

5、移植時に注意が必要な事項


序文

移植する前に、rt-threadに精通し、rtthreadのENVツールを使用する必要があります。

1.新しいBSP

rtthreadには、STM32シリーズの詳細なBSP作成チュートリアルがあり、独自のボードに従って独自のBSPを作成できるため、ここでは繰り返しません。公式Webサイトのドキュメントを参照しください。

2.CubeMXを使用してTouchGFXプロジェクトを作成します

作成したBSPで、.. \ board \ CubeMX_Config.iocをダブルクリックしてCubeMXを開き、関連する周辺機器を構成し、初期化コードを生成します。これは、後でtouchgfxサンプルファイルで使用されます。

1. FMC(SDRAM)を構成します

構成されたGPIOは、ご使用のハードウェアと一致している必要があることに注意してください。SDRAMの一部のピンは複数のGPIOで多重化できるためです。生成されたプロジェクトにはSDRAM初期化プログラムはありません

2. DMA2Dを構成し、DMA2D割り込みを有効にします

3. LTDCを構成し、LTDC割り込みを有効にします

構成されたGPIOは、ご使用のハードウェアと一致している必要があることに注意してください。

4.CRCをオンにします

5.TouchGFXを構成します

TouchGFXソフトウェアパッケージを開きます

TouchGFXを構成する

6. TouchGFXDesignerを実行します

CubeMXを使用してプロジェクトを生成した後、最初にIARプロジェクトを開かないでください。また、Touch Designerを実行して、UIパーツを設計し、プロジェクトを改善する必要があります。SrcディレクトリにApplicationTemplate.touchgfx.partがあります。このリンクをクリックして、TouchGFXDesignerを開きます。

6.1、TouchGFXDesignerインターフェイス

6.2、GUIアプリケーションを追加します

以前にTouchGFXDesignerを使用してUIを設計したことがある場合は、関連するファイルを直接コピーするだけです。UIを設計するために以下の手順を実行する必要はありません。[コードの生成]をクリックしてコードを生成し、次のファイルをコピーします。

最初のステップ:screen1を作成し、BoxコントロールとButtonコントロールを配置し、Boxの座標を(0、0)と800x480のサイズに設定し、ボタンを押して放したときのボタンと背景画像の座標を設定します。画像は、Alibaba Vector IconLibraryから取得できます。ダウンロードして…\ Src \ assets \ imagesディレクトリに配置します。インタラクションを追加して、ボタンをクリックしてscreen2に切り替える機能を実現します。

ステップ2:screen2を作成します。ステップは最初のステップと似ていますが、7色を表示するラインコントロールがさらに7つあり、ボタンをクリックしてscreen3に切り替える機能が実現されている点が異なります。

3番目のステップ:screen3を作成し、主に、固定時間に画像を動的に切り替えるために使用されるAnimated Imageコントロールを追加し、ボタンをクリックしてscreen1に戻ります。

6.3、コードを生成する

[コードの生成]をクリックしてコードを生成します。同時に、Srcディレクトリに追加の「xxxx.touchgfx」ファイルがあり、このファイルを直接開くことで、引き続きTouchGFXDesignerを使用してUIを設計できます。

3.TouchGFXをRTスレッドに移植する

1.オペレーティングシステムのインターフェイスファイルを変更します

OSWrappers.cppをコピーし、名前をOSWrappers_rtt.cppに変更し、コードを変更します

#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>
#include <touchgfx/hal/GPIO.hpp>
#include <touchgfx/hal/HAL.hpp>
#include <touchgfx/hal/OSWrappers.hpp>

using namespace touchgfx;

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);
}

static rt_base_t IdleTaskHook(void* p)
{
    if ((int)p) //idle task sched out
    {
        touchgfx::HAL::getInstance()->setMCUActive(true);
    }
    else //idle task sched in
    {
        touchgfx::HAL::getInstance()->setMCUActive(false);
    }
    return RT_TRUE;
}

2.touchgfxの新しいアプリケーションサンプルファイルを作成します

このファイルは、TouchGFXを初期化し、TouchGFXを実行するタスクを作成するために使用されます

3.プロジェクトにファイルを追加します

3.1、\ board \ KConfigを変更します

BSP_USING_LCD、BSP_USING_LTDC、BSP_USING_SDRAM、RT_TOUCHGFXの構成アイテムをファイルに追加して、menuconfigでTouchGFXオンにするかどうかを選択できるようにします。

menu "Onboard Peripheral Drivers"
	...
	config BSP_USING_LCD
        bool "Enable RGB-LCD"
        select BSP_USING_LTDC
        select BSP_USING_SDRAM
        default n
endmenu

menu "On-chip Peripheral Drivers"
	...	
	config BSP_USING_LTDC
        bool
        default n
endmenu

menu "Board extended module Drivers"
    menuconfig RT_STEMWIN
        bool "Enable STemWin"
        default n
        if RT_STEMWIN
            config RT_STEMWIN_DEMO
            bool "Enable STemWin Demo"
            default n
        endif
    
    menuconfig RT_TOUCHGFX
        bool "Enable TouchGFX"
        default n
endmenu

オンにする前にRT_TOUCHGFX、あなたがオンにする必要がありBSP_USING_LCD

RT_TOUCHGFXをオンにします

3.2。\ libraries \ STM32F4xx_HAL \ SConscriptを変更します

次のコンテンツをファイルに追加して、BSP_USING_LTDCの定義後にHALドライバーの関連ファイルをプロジェクトに追加できるようにします。

if GetDepend(['BSP_USING_LTDC']):
    src += ['STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_ltdc.c']
    src += ['STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_ltdc_ex.c']
    src += ['STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma2d.c']
    src += ['STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dma2d.c']
    src += ['STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dsi.c']
	src += ['STM32F4xx_HAL_Driver/Src/stm32f4xx_ltdc.c']

3.3、\ board \ SConscriptを変更します

ファイルの最後に次のコンテンツを追加して、RT_TOUCHGFXがオンになっている場合、\ board \ CubeMX_ConfigディレクトリにSConscriptファイルが含まれるようにします。

if GetDepend(['RT_TOUCHGFX']):
	group = group + SConscript(cwd + '/CubeMX_Config/SConscript')

3.4。\ board \ CubeMX_Config \ SConscriptを追加しました

TouchGFX関連グループをプロジェクトに追加し、関連するソースファイルとヘッダーファイルを含めます

import os
import rtconfig
from building import *

cwd = GetCurrentDir()

# add general drivers
src = Split('''
Src/touchgfx_sample.c
Src/OSWrappers-rtt.cpp
Src/STM32DMA.cpp
Src/STM32TouchController.cpp
Src/TouchGFXGPIO.cpp
Src/TouchGFXConfiguration.cpp
Src/TouchGFXGeneratedHAL.cpp
Src/TouchGFXHAL.cpp
Src/app_touchgfx.c
''')

path =  [cwd + '/Src']
path += [cwd + '/Middlewares/ST/touchgfx/framework/include']


if rtconfig.CROSS_TOOL == 'gcc':
    src += [cwd + '/Middlewares/ST/touchgfx/lib/core/cortex_m4f/gcc/libtouchgfx.a']
elif rtconfig.CROSS_TOOL == 'keil':
    src += [cwd + '/Middlewares/ST/touchgfx/lib/core/cortex_m4f/Keil/touchgfx_core.lib']
elif rtconfig.CROSS_TOOL == 'iar':
    src += [cwd + '/Middlewares/ST/touchgfx/lib/core/cortex_m4f/IAR8.x/touchgfx_core.a']

group = DefineGroup('TouchGFX_app', src, depend = [''], CPPPATH = path)

# add TouchGFX generated
genSrc = Glob('./Src/generated/fonts/src/*.cpp')
genSrc += Glob('./Src/generated/gui_generated/src/*/*.cpp')
genSrc += Glob('./Src/generated/images/src/*.cpp')
genSrc += Glob('./Src/generated/texts/src/*.cpp')
genPath = [cwd + '/Src/generated/fonts/include']
genPath += [cwd + '/Src/generated/gui_generated/include']
genPath += [cwd + '/Src/generated/images/include']
genPath += [cwd + '/Src/generated/texts/include']
group = group + DefineGroup('TouchGFX_generated', genSrc, depend = [''], CPPPATH = genPath)

# add TouchGFX resource
resSrc = Glob('./Src/generated/images/src/*/*.cpp')
group = group + DefineGroup('TouchGFX_resource', resSrc, depend = [''])

# add TouchGFX gui
guiSrc = Glob('./Src/gui/src/*/*.cpp')
guiPath = [cwd + '/Src/gui/include']
group = group + DefineGroup('TouchGFX_gui', guiSrc, depend = [''], CPPPATH = guiPath)

Return('group')

最終的に生成されるプロジェクトは次のとおりです。

4.タッチドライバーを追加します

上記の設定が完了すると、LCD画面は点灯しますが、タッチスクリーンはまだ使用できず、タッチドライバーを追加する必要があります。タッチドライバーの追加も比較的簡単です。まず、ボードのタッチチップに応じてドライバーコードを追加します。

4.1TOUCHドライバーファイルを追加する

新しいdrv_touch.c / hドライバーファイルを作成します。..\ board \ Kconfigを変更して、BSP_USING_TOUCHの構成アイテムを追加します。

menu "Onboard Peripheral Drivers"
    ...
	config BSP_USING_TOUCH
        bool "Enable TOUCH Driver(TSC2046)"
        default n
		
endmenu

.. \ libraries \ HAL_Drivers \ SConscriptを変更し、drv_touch.cを追加して、プロジェクトに自動的に追加します

if GetDepend(['BSP_USING_TOUCH']):
	src += ['drv_touch.c']

4.2STM32TouchController.cppを改善する

タッチドライバファイルを追加したら、STM32TouchController.cppの2つの関数を完了します。注意!ここで得られる座標は、(0,0)から(800,480)までの論理座標です。

第四に、オフチップのSPIFLASHに画像を配置します

1. STM32F429 SPIFLASHダウンロードアルゴリズムを作成します

このアルゴリズムにより、プロジェクトで生成された画像データとフォントデータを外部FLASHに保存できます。

https://blog.csdn.net/sinat_31039061/article/details/107220994

https://blog.csdn.net/Ningjianwen/article/details/100151158

2.プロジェクトテンプレートtemplate.uvprojxを変更します

3.リンクファイルを変更します

リンカーはビットマップのアドレスを選択します。デフォルトでは、TouchGFXのすべてのビットマップはExtFlashSectionに配置され、変更後、画像をオフチップFLASHにリンクできます。

LR_IROM1 0x08000000 0x00100000  {    ; load region size_region
  ER_IROM1 0x08000000 0x00100000  {  ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
  }
  RW_IRAM1 0x20000000 0x00020000  {  ; RW data
   .ANY (+RW +ZI)
  }
}

LR_EROM1 0x90000000 0x00800000  {    ; load region size_region
  ER_EROM1 0x90000000 0x00800000  {  ; load address = execution address
   *.o (ExtFlashSection)
  }
}

4.ビットマップデータを外部FLASHからキャッシュにコピーします

4.1、オープンアナログSPI

4.2、SFUDコンポーネントを開く

4.3、デバイスの初期初期化

次のコンテンツspi_flash_init.cに追加し、softspi1バスを登録し、softspi10デバイスを登録して、softspi1バスにマウントします。SFUDがW25Q64ブロックデバイスを駆動できるようにします。

#include <rtthread.h>
#include "spi_flash.h"
#include "spi_flash_sfud.h"
#include "drv_soft_spi.h"

#if defined(BSP_USING_SPI_FLASH)
static int rt_hw_spi_flash_init(void)
{
    __HAL_RCC_GPIOG_CLK_ENABLE();
    rt_soft_spi_device_attach("softspi1", "softspi10", GPIOG, GPIO_PIN_10);

    if (RT_NULL == rt_sfud_flash_probe("W25Q64", "softspi10"))
    {
        return -RT_ERROR;
    }

    return RT_EOK;
}
INIT_COMPONENT_EXPORT(rt_hw_spi_flash_init);
#endif

4.4、FALソフトウェアパッケージを選択

外部SPIFLASHを操作するために、ENVFALソフトウェアパッケージを開きます

fal_cfg.hを構成します。Tgfxパーティションは、touchgfxのリソースストレージに使用されます

#ifndef _FAL_CFG_H_
#define _FAL_CFG_H_

#include <rtthread.h>
#include <board.h>

#define FLASH_SIZE_GRANULARITY_16K   (4 * 16 * 1024)
#define FLASH_SIZE_GRANULARITY_64K   (64 * 1024)
#define FLASH_SIZE_GRANULARITY_128K  (7 * 128 * 1024)

#define STM32_FLASH_START_ADRESS_16K  STM32_FLASH_START_ADRESS
#define STM32_FLASH_START_ADRESS_64K  (STM32_FLASH_START_ADRESS_16K + FLASH_SIZE_GRANULARITY_16K)
#define STM32_FLASH_START_ADRESS_128K (STM32_FLASH_START_ADRESS_64K + FLASH_SIZE_GRANULARITY_64K)

extern const struct fal_flash_dev stm32_onchip_flash_16k;
extern const struct fal_flash_dev stm32_onchip_flash_64k;
extern const struct fal_flash_dev stm32_onchip_flash_128k;
extern struct fal_flash_dev nor_flash0;

/* flash device table */
#define FAL_FLASH_DEV_TABLE                              \
{                                                        \
	&stm32_onchip_flash_16k,                                         \
    &stm32_onchip_flash_64k,                                         \
    &stm32_onchip_flash_128k,                                        \
    &nor_flash0,                                         \
}
/* ====================== Partition Configuration ========================== */
#ifdef FAL_PART_HAS_TABLE_CFG

/* partition table */
#define FAL_PART_TABLE                                                                                                     \
{                                                                                                                          \
    {FAL_PART_MAGIC_WROD, "bootloader", "onchip_flash_16k",  0 , FLASH_SIZE_GRANULARITY_16K , 0}, \
    {FAL_PART_MAGIC_WROD, "param",      "onchip_flash_64k",  0 , FLASH_SIZE_GRANULARITY_64K , 0}, \
    {FAL_PART_MAGIC_WROD, "app",        "onchip_flash_128k", 0 , FLASH_SIZE_GRANULARITY_128K, 0}, \
	{FAL_PART_MAGIC_WROD, "tgfx",       FAL_USING_NOR_FLASH_DEV_NAME,  0 , 4 * 1024 * 1024, 0}, \
}

#endif /* FAL_PART_HAS_TABLE_CFG */
#endif /* _FAL_CFG_H_ */

ファルを初期化する

#include "fal.h"

int fs_init(void)
{
    /* partition initialized */
    fal_init();
	return 0;
}
INIT_COMPONENT_EXPORT(fs_init);

4.5、TouchGFXドライバーを変更します

ビットマップがキャッシュされると、TouchGFXはピクセルを元の場所からビットマップキャッシュにコピーします。このコピーはHALクラスのメソッドを呼び出すことによって行われるため、画像などのデータが外部FLASHにキャッシュされている場合は、外部FLASHの読み取りをサポートするようにこの関数を変更する必要があります。この関数はTouchGFXHAL.cppで定義されています

#include <fal.h>

bool TouchGFXHAL::blockCopy(void* RESTRICT dest, const void* RESTRICT src, uint32_t numBytes)
{
	uint32_t dataOffset = (uint32_t)src;
	if (dataOffset >= 0x90000000 && dataOffset < 0x92000000)
	{
		const struct fal_partition *part;
		part = fal_partition_find("tgfx");

		dataOffset =  dataOffset - 0x90000000;
		// for copying data from there.
		if (part != RT_NULL)
		{
			fal_partition_read(part, dataOffset, (uint8_t *)dest, numBytes);
		}
		return true;
	}	
	else
	{
		// For all other addresses, just use the default implementation.
		// This is important, as blockCopy is also used for other things in the core framework.
		return HAL::blockCopy(dest, src, numBytes);
	}	
}

blockCopy機能を変更した後、外部SPI FLASHから読み取ることができるのは画像データのみですが、読み取った後はどこに置くべきですか?つまり、読み取った画像データを保存するために、画像キャッシュアドレスも設定する必要があります!!!!!ここではSDRAMに設定しました

void touchgfx_init()
{
    ...
	Bitmap::setCache((uint16_t *)0xC0300000,0x400000,128);
	Bitmap::cacheAll();
}

第4に、フォントをオフチップSPIFLASHに配置します

4.14バージョンのTouchGFXは解決されていません

TouchGFX公式ウェブサイトの4.15バージョンにはドキュメントがあります。可能であるはずです。検証はありません。

5、移植時に注意が必要な事項

1.コンパイル中に多数のエラーが報告された場合は、IARでC ++コンパイルが有効になっているかどうかを確認してください

2. SDRAMとLTDCのピン構成は、ハードウェアに対応している必要があります。これは非常に重要です。

 

 

おすすめ

転載: blog.csdn.net/m0_37845735/article/details/109301620