【ThreadX全家桶】GuiX移植

本文详细介绍了在STM32平台上移植ThreadX GUIX的过程,包括添加GUIX源文件、整合GUIXStudio生成的配置文件、实现显示和触摸驱动,以及设置内存分配和测试函数。通过实例代码展示了LCD驱动和触摸事件处理,为STM32 GUIX应用提供了参考。
摘要由CSDN通过智能技术生成


前言

本篇文章的知识基本全部来源于《安富莱_STM32-V6开发板ThreadX GUIX教程》,有兴趣的同学可以前往学习。
此次GUIX移植未使用DMA2D做加速处理,后期深入了解后再实现DMA2D部分。


一、添加GUIX文件

因为STM32CubeMX没有GuiX包,所以需要从GitHUB下载GuiX源代码,手动将源文件添加到工程。

二、添加GUIX Studio生成的4个文件

GUIX Studio的操作方法参考《安富莱_STM32-V6开发板ThreadX GUIX教程》,将生成的4个文件添加到工程并添加路径。

三、显示驱动分析

LCD驱动的核心工作就是将画布中脏区域的数据更新到显存,该过程可分为两步实现:
①分析比较出画布脏的区域
②将脏区域拷贝到显存上相应的地方
代码如下(示例):

static void stm32f4_24xrgb_buffer_toggle(GX_CANVAS *canvas, GX_RECTANGLE *dirty)
{
	GX_RECTANGLE    Limit;
	GX_RECTANGLE    Copy;
	ULONG           offset;
	INT             copy_width;
	INT             copy_height;

	INT             row;
	INT             src_stride_ulongs;
	INT             dest_stride_ulongs;

	ULONG *get;
	ULONG *put;

	gx_utility_rectangle_define(&Limit, 0, 0, canvas->gx_canvas_x_resolution - 1, canvas->gx_canvas_y_resolution - 1);	//此服务将定义指定的矩形。参数是分辨率

	if (gx_utility_rectangle_overlap_detect(&Limit, &canvas->gx_canvas_dirty_area, &Copy))		//此服务将检测提供的矩形是否有重叠。 如果发现重叠,服务将返回 GX_TRUE 和重叠矩形。
	{
		copy_width = Copy.gx_rectangle_right - Copy.gx_rectangle_left + 1;		//计算矩形脏区域的分辨率
		copy_height = Copy.gx_rectangle_bottom - Copy.gx_rectangle_top + 1;

		/* 从canvas读取更新区 */
		offset = Copy.gx_rectangle_top * canvas->gx_canvas_x_resolution + Copy.gx_rectangle_left;
		get = canvas ->gx_canvas_memory + offset;		//计算脏区域在 画布 上的起始物理地址

		/* 从LCD显存读取要更新的区域,将canvas更新的数据复制进来 */
		put = (ULONG *) FrameBufer;
		offset = (canvas->gx_canvas_display_offset_y + Copy.gx_rectangle_top)* g_LcdWidth;
		offset += canvas->gx_canvas_display_offset_x + Copy.gx_rectangle_left;
		put += offset;				//计算脏区域 映射到 显存 上的起始地址

		src_stride_ulongs = canvas ->gx_canvas_x_resolution;
		dest_stride_ulongs = g_LcdWidth;
		
		for(row = 0; row < copy_height; row++)
		{
			memcpy(put, get, copy_width * 4);
			put += dest_stride_ulongs;
			get += src_stride_ulongs;
		}
	}
}

GUIX 为所有支持颜色深度和格式的每个低级别绘图函数都提供默认软件实现。所以需要将新的驱动进行注册,用于覆盖GUIX的默认驱动。根据自己LCD像素格式选择合适的setup函数,LAYERADDR为显存地址。

代码如下(示例):

UINT stm32f4_graphics_driver_setup_24xrgb(GX_DISPLAY *display)
{	
    _gx_display_driver_32argb_setup(display, (VOID*)LAYERADDR, stm32f4_24xrgb_buffer_toggle);
    return(GX_SUCCESS);
}

四、触摸驱动分析

GuiX是事件驱动模式,所以当发生屏幕触摸时,需要发送相应的事件到GuiX协议栈。触摸事件共分为三类:按压、释放和移动。
代码如下(示例):

void TouchDrive(void)
{
	static uint8_t s_tp_down = 0;
	static GX_EVENT event;
	
	Touch_Scan();	//循环检测,坐标保存在touchInfo结构体
	event.gx_event_payload.gx_event_pointdata.gx_point_x = touchInfo.x[0];
	event.gx_event_payload.gx_event_pointdata.gx_point_y = touchInfo.y[0];
	event.gx_event_sender = 0;
	event.gx_event_target = 0;
	event.gx_event_display_handle = LAYERADDR;
	
	if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_15) == GPIO_PIN_SET)		//松手
	{
		if (s_tp_down == 1)
		{
			s_tp_down = 0;
			event.gx_event_type = GX_EVENT_PEN_UP;
			gx_system_event_send(&event);
		}
	}
	else
	{
		if (s_tp_down == 0)		//按下
		{
			s_tp_down = 1;
			event.gx_event_type = GX_EVENT_PEN_DOWN;
			gx_system_event_send(&event);
		}
		else		//移动
		{
			event.gx_event_type = GX_EVENT_PEN_DRAG;
			gx_system_event_send(&event);
		}
	}
}

五、GUIX测试函数

1.内存分配说明

GUIX项目中,内存需要分为四部分
①显存,LAYER0ADDR(0xD0000000)
②画布,Canvas_Memory 0xD0200000
③GUIX组件等活动所需的动态内存区域,地址0xD0300000,大小8M
④剩余内存,保留

2.动态内存申请与释放函数

1、GUIX的有关活动需要申请与释放内存,使用ThreadX提供的内存分配相关API封装两个内存分配与释放函数,供GUIX调用。
代码如下(示例):

TX_BYTE_POOL  memory_pool;
VOID *memory_allocate(ULONG size)
{
    VOID *memptr;

    if (tx_byte_allocate(&memory_pool, &memptr, size, TX_NO_WAIT) == TX_SUCCESS)
    {
        return memptr;
    }
    return NULL;
}

void memory_free(VOID *mem)
{
    tx_byte_release(mem);
}

3、应用程序

下面提供一个DEMO程序,显示配置与组件创建两个函数由GUIX Studio生成的文件定义,用户只需填好参数即可使用,函数gx_studio_display_configure的参数在xxx_resources.h中定义,函数gx_studio_named_widget_create的第一个参数与结构体xxx_widget_table下结构体window_define的成员保持一致。
代码如下(示例):

uint8_t       *MemoryBlock = (uint8_t *)(0xD0300000); /* 动态内存地址    */
#define 	  GUI_NUMBYTES     1024*1024*8                         /* 设置动态内存大小 */
#define 	  Canvas_Memory    0xD0200000                          /* 设置Canvas地址   */

GX_WINDOW 		*pScreen;
GX_WINDOW_ROOT  *root;
void GuixDemo(void)
{
	Touch_Init();		//触摸IO初始化

	tx_byte_pool_create(&memory_pool, "MemoryBlock",  MemoryBlock,  GUI_NUMBYTES);	/* 初始化内存池 */
	gx_system_memory_allocator_set(memory_allocate, memory_free);		/* 注册动态内存申请和释放函数 */
	gx_system_initialize();		/* 初始化GUIX */
	guiapp_display_table[0].canvas_memory = (GX_COLOR *)Canvas_Memory;	/* 设置画布地址 */
	gx_studio_display_configure(0, stm32f4_graphics_driver_setup_24xrgb, LANGUAGE_ENGLISH, DISPLAY_1_THEME_1, &root);
	gx_studio_named_widget_create("window", (GX_WIDGET *)root, (GX_WIDGET **)&pScreen);
	gx_widget_show(root);
	gx_system_start();
	
	while(1)
	{
		TouchDrive();		//GuiX触摸驱动
		tx_thread_sleep(20);
	}
}

注:
1、LTDC只使用一个层,使用两个层时,画面刷新时会抽搐
2、触摸芯片的检测函数一般使用IO模拟IIC,其延时函数可能会被Keil优化掉,所以需要在延时函数中使用volatile修饰局部变量。


  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值