报错信息

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
[LVGL LOG] [Error]	(59.136, +180)	 _lv_inv_area: detected modifying dirty areas in render 	(in lv_refr.c line #213)

[LVGL LOG] [Error]	(59.241, +105)	 _lv_inv_area: detected modifying dirty areas in render 	(in lv_refr.c line #213)

[LVGL LOG] [Error]	(59.361, +120)	 _lv_inv_area: detected modifying dirty areas in render 	(in lv_refr.c line #213)

[LVGL LOG] [Error]	(59.468, +107)	 _lv_inv_area: detected modifying dirty areas in render 	(in lv_refr.c line #213)

[LVGL LOG] [Error]	(59.588, +120)	 _lv_inv_area: detected modifying dirty areas in render 	(in lv_refr.c line #213)

[LVGL LOG] [Error]	(59.702, +114)	 _lv_inv_area: detected modifying dirty areas in render 	(in lv_refr.c line #213)

错误 “_lv_inv_area: detected modifying dirty areas in render” 通常表示在 LVGL 中检测到试图在渲染期间修改脏区域的情况。这个错误可能是由于不正确的 LVGL API 使用、内存破坏或其他潜在的问题导致的。

以下是一些可能导致这个错误的常见原因:

在渲染期间修改对象属性: LVGL 在渲染期间会对脏区域进行优化处理,如果在渲染期间试图修改对象的属性,可能导致错误。确保对象属性的修改是在渲染之前或之后进行的。

内存破坏: 如果发生内存破坏,可能会导致 LVGL 的内部数据结构被破坏,从而引发此错误。请确保没有越界访问数组、释放已释放的内存等问题。

多线程问题: 如果在多线程环境中使用 LVGL,确保对 LVGL 的访问是线程安全的。在多线程环境中,对 LVGL 的访问应该是同步的,以防止竞争条件。

要解决这个问题,你可以:

检查你的代码,确保没有在渲染期间修改对象属性。

检查内存访问是否正确,防止内存破坏。

如果是多线程环境,确保对 LVGL 的访问是线程安全的。

LVGL的任务处理函数加互斥锁

如果需要使用实际的任务或线程,则需要一个互斥锁,该互斥锁应在调用 lv_task_handler 之前被调用,并在其之后释放

同样,必须在与每个 lv_开头的函数 相关的函数调用和代码周围的其他任务和线程中使用相同的互斥锁

1
2
3
4
5
  /* 获得互斥量: 上锁 */
  xSemaphoreTake(xMutex, portMAX_DELAY);
  lv_task_handler ();
  /* 释放互斥量: 开锁 */
  xSemaphoreGive(xMutex);

FreeRTOS使用互斥锁简单介绍

互斥量函数

创建

互斥量是一种特殊的二进制信号量。

使用互斥量时,先创建、然后去获得、释放它。使用句柄来表示一个互斥量。

创建互斥量的函数有2种:动态分配内存,静态分配内存,函数原型如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12

/* 创建一个互斥量,返回它的句柄。
 * 此函数内部会分配互斥量结构体 
 * 返回值: 返回句柄,非NULL表示成功
 */
SemaphoreHandle_t xSemaphoreCreateMutex( void );

/* 创建一个互斥量,返回它的句柄。
 * 此函数无需动态分配内存,所以需要先有一个StaticSemaphore_t结构体,并传入它的指针
 * 返回值: 返回句柄,非NULL表示成功
 */
SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t *pxMutexBuffer );

要想使用互斥量,需要在配置文件FreeRTOSConfig.h中定义:

1
#define configUSE_MUTEXES 1

其他函数

要注意的是,互斥量不能在ISR中使用。

各类操作函数,比如删除、give/take,跟一般是信号量是一样的。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*
 * xSemaphore: 信号量句柄,你要删除哪个信号量, 互斥量也是一种信号量
 */
void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );

/* 释放 */
BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore );

/* 释放(ISR版本) */
BaseType_t xSemaphoreGiveFromISR(
                       SemaphoreHandle_t xSemaphore,
                       BaseType_t *pxHigherPriorityTaskWoken
                   );

/* 获得 */
BaseType_t xSemaphoreTake(
                   SemaphoreHandle_t xSemaphore,
                   TickType_t xTicksToWait
               );
/* 获得(ISR版本) */
xSemaphoreGiveFromISR(
                       SemaphoreHandle_t xSemaphore,
                       BaseType_t *pxHigherPriorityTaskWoken
                   );

互斥量基本使用 示例

使用互斥量时有如下特点:

刚创建的互斥量可以被成功"take" “take"互斥量成功的任务,被称为"holder”,只能由它"give"互斥量;别的任务"give"不成功 在ISR中不能使用互斥量

本程序创建2个发送任务:故意发送大量的字符。可以做2个实验:

使用互斥量:可以看到任务1、任务2打印的字符串没有混杂在一起 不使用互斥量:任务1、任务2打印的字符串混杂在一起

main函数代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/* 互斥量句柄 */
SemaphoreHandle_t xMutex;

int main( void )
{
	prvSetupHardware();
	
    /* 创建互斥量 */
    xMutex = xSemaphoreCreateMutex( );


	if( xMutex != NULL )
	{
		/* 创建2个任务: 都是打印
		 * 优先级相同
		 */
		xTaskCreate( vSenderTask, "Sender1", 1000, (void *)1, 1, NULL );
		xTaskCreate( vSenderTask, "Sender2", 1000, (void *)2, 1, NULL );

		/* 启动调度器 */
		vTaskStartScheduler();
	}
	else
	{
		/* 无法创建互斥量 */
	}

	/* 如果程序运行到了这里就表示出错了, 一般是内存不足 */
	return 0;
}

发送任务的函数如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
static void vSenderTask( void *pvParameters )
{
	const TickType_t xTicksToWait = pdMS_TO_TICKS( 10UL );	
	int cnt = 0;
	int task = (int)pvParameters;
	int i;
	char c;
	
	/* 无限循环 */
	for( ;; )
	{	
		/* 获得互斥量: 上锁 */
		xSemaphoreTake(xMutex, portMAX_DELAY);
		
		printf("Task %d use UART count: %d, ", task, cnt++);
		c = (task == 1 ) ? 'a' : 'A';
		for (i = 0; i < 26; i++)
			printf("%c", c + i);
		printf("\r\n");
		
		/* 释放互斥量: 开锁 */
		xSemaphoreGive(xMutex);
		
		vTaskDelay(xTicksToWait);
	}
}