Runtime rotation

I see, please send a photo from the messed up screen.

1 Like

O.K, thanks.
Every 5 seconds I rotate the screen so in this video we can see both states:

@kisvegabor so, any idea?:slightly_smiling_face:

Sorry, I messed your reply.

The white lines and flickering screen suggest that it’s not an LVGL issue a driver issue. But your driver seiótings look good.

Can you print the areas from flush_cb when the screen is rotated?
Please also

  • post your flush_cb
  • try with v8
  • in v8 set disp_drv.full_refresh = 1
1 Like

thanks for your answer.:tada:

here it is:

static void ex_disp_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_p)
{
	/*Return if the area is out the screen*/
	if(area->x2 < 0) return;
	if(area->y2 < 0) return;
	if(area->x1 > LV_HOR_RES - 1) return;
	if(area->y1 > LV_VER_RES - 1) return;

	/*Truncate the area to the screen*/
	int32_t act_x1 = area->x1 < 0 ? 0 : area->x1;
	int32_t act_y1 = area->y1 < 0 ? 0 : area->y1;
	int32_t act_x2 = area->x2 > LV_HOR_RES - 1 ? LV_HOR_RES - 1 : area->x2;
	int32_t act_y2 = area->y2 > LV_VER_RES - 1 ? LV_VER_RES - 1 : area->y2;

	x1_flush = act_x1;
	y1_flush = act_y1;
	x2_flush = act_x2;
	y2_fill = act_y2;
	y_fill_act = act_y1;
	buf_to_flush = color_p;

#if 1
		printf("%d, %d, %d, %d - ", act_x1, act_x2, act_y1, act_y2);
#endif

	/*Start the DMA transfer using the interrupt mode */
	HAL_StatusTypeDef err;
	err = HAL_DMA_Start_IT(&DmaHandle, (uint32_t)buf_to_flush, (uint32_t)&my_fb[y_fill_act * LV_HOR_RES + x1_flush],
			(x2_flush - x1_flush + 1));

	if(err != HAL_OK) {
		while(1);	/*Halt on error*/
	}
}

and from the printf I got these:


LV_DISP_ROT_90

0, 49, 0, 399 - 50, 99, 0, 399 - 100, 149, 0, 399 - 150, 199, 0, 399 - 200, 249, 0, 399 - 250, 299, 0, 399 - 300, 349, 0, 399 - 350, 399, 0, 399 - 362, 399, 0, 60 - 362, 399, 0, 69 - 362, 399, 0, 69 - 362, 399, 0, 57 - 362, 399, 0, 60 - 362, 399, 0, 60 - 362, 399, 0, 60 - 362, 399, 0, 60 - 362, 399, 0, 57 - 362, 399, 0, 60 - 362, 399, 0, 60 - 362, 399, 0, 60 - 362, 399, 0, 60 - 362, 399, 0, 57 - 362, 399, 0, 60 - 362, 399, 0, 60 -


LV_DISP_ROT_NONE

0, 399, 0, 159 - 0, 399, 160, 319 - 0, 399, 320, 479 - 0, 399, 480, 639 - 0, 399, 640, 799 - 0, 399, 800, 959 - 0, 399, 960, 1119 - 0, 399, 1120, 1279 - 339, 399, 1242, 1279 - 331, 399, 1242, 1279 - 331, 399, 1242, 1279 - 331, 399, 1242, 1279 - 339, 399, 1242, 1279 - 342, 399, 1242, 1279 - 339, 399, 1242, 1279 - 339, 399, 1242, 1279 - 339, 399, 1242, 1279 - 338, 399, 1242, 1279 - 338, 399, 1242, 1279 - 338, 399, 1242, 1279 - 339, 399, 1242, 1279 - 339, 399, 1242, 1279 - 338, 399, 1242, 1279 - 338, 399, 1242, 1279 -


It is version 8.

No difference😕

Thanks!

I think the “Truncate the area to the screen” causes the problem. How is it work if this section is removed?

1 Like

I removed, but didn’t help. It’s just the same.

It seems “Return if the area is out the screen” should be removed too.

If doesn’t help please post the log again from the flush callback and the new code of the callback.

1 Like

It didn’t work too.
this is the new flush callback:

static void ex_disp_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_p)
{
//	/*Return if the area is out the screen*/
//	if(area->x2 < 0) return;
//	if(area->y2 < 0) return;
//	if(area->x1 > LV_HOR_RES - 1) return;
//	if(area->y1 > LV_VER_RES - 1) return;

	/*Truncate the area to the screen*/
	int32_t act_x1 = area->x1;// < 0 ? 0 : area->x1;
	int32_t act_y1 = area->y1;// < 0 ? 0 : area->y1;
	int32_t act_x2 = area->x2;// > LV_HOR_RES - 1 ? LV_HOR_RES - 1 : area->x2;
	int32_t act_y2 = area->y2;// > LV_VER_RES - 1 ? LV_VER_RES - 1 : area->y2;

	x1_flush = act_x1;
	y1_flush = act_y1;
	x2_flush = act_x2;
	y2_fill = act_y2;
	y_fill_act = act_y1;
	buf_to_flush = color_p;

#if 1
		printf("%d, %d, %d, %d - ", act_x1, act_x2, act_y1, act_y2);
#endif

	/*Start the DMA transfer using the interrupt mode */
	HAL_StatusTypeDef err;
	err = HAL_DMA_Start_IT(&DmaHandle, (uint32_t)buf_to_flush, (uint32_t)&my_fb[y_fill_act * LV_HOR_RES + x1_flush],
			(x2_flush - x1_flush + 1));

	if(err != HAL_OK) {
		while(1);	/*Halt on error*/
	}
}

and here is the logs:


LV_DISP_ROT_90
0, 49, 0, 1279 - 50, 99, 0, 1279 - 100, 149, 0, 1279 - 150, 199, 0, 1279 - 200, 249, 0, 1279 - 250, 299, 0, 1279 - 300, 349, 0, 1279 - 350, 399, 0, 1279 - 362, 399, 0, 60 - 362, 399, 0, 69 - 362, 399, 0, 69 - 362, 399, 0, 60 - 362, 399, 0, 60 - 362, 399, 0, 60 - 362, 399, 0, 57 - 362, 399, 0, 60 - 362, 399, 0, 60 - 362, 399, 0, 60 - 362, 399, 0, 60 - 362, 399, 0, 57 - 362, 399, 0, 60 - 362, 399, 0, 60 - 362, 399, 0, 60 -


LV_DISP_ROT_NONE
0, 399, 0, 159 - 0, 399, 160, 319 - 0, 399, 320, 479 - 0, 399, 480, 639 - 0, 399, 640, 799 - 0, 399, 800, 959 - 0, 399, 960, 1119 - 0, 399, 1120, 1279 - 339, 399, 1242, 1279 - 334, 399, 1242, 1279 - 334, 399, 1242, 1279 - 339, 399, 1242, 1279 - 339, 399, 1242, 1279 - 338, 399, 1242, 1279 - 338, 399, 1242, 1279 - 338, 399, 1242, 1279 - 339, 399, 1242, 1279 - 339, 399, 1242, 1279 - 338, 399, 1242, 1279 - 338, 399, 1242, 1279 - 338, 399, 1242, 1279 - 339, 399, 1242, 1279 - 339, 399, 1242, 1279 - 338, 399, 1242, 1279 -


Great! We are getting closer. Now at least the areas look good.

I’m pretty sure there is only one fix and it will work :slight_smile:

I think the root of the issue was the use of LV_HOR/VER_RES in the flush_cb because with 90-degree rotation they return the opposite resolution. (E.g. LV_HOR_RESlv_disp_get_ver_res())
But you display didn’t change it has 400x1280 resolution.

Long story short

err = HAL_DMA_Start_IT(&DmaHandle, (uint32_t)buf_to_flush, (uint32_t)&my_fb[y_fill_act * LV_HOR_RES + x1_flush], (x2_flush - x1_flush + 1));

should be

err = HAL_DMA_Start_IT(&DmaHandle, (uint32_t)buf_to_flush, (uint32_t)&my_fb[y_fill_act * 400 + x1_flush], (x2_flush - x1_flush + 1));

(LV_HOR_RES → 400)

1 Like

Yes, thanks :tada::pray:. we got so close, but not completely.:thinking:
Look at this:

When it wants to switch to LV_DISP_ROT_90 state, and also after that, we can see some things on the screen. what are these? how can i fix this?

This is the dma callback:

static void DMA_TransferComplete(DMA_HandleTypeDef *han)
{
	y_fill_act ++;

	if(y_fill_act > y2_fill) {
		lv_disp_flush_ready(&disp_drv);
	} else {
		buf_to_flush += (x2_flush - x1_flush + 1);
		/*##-7- Start the DMA transfer using the interrupt mode ####################*/
		/* Configure the source, destination and buffer size DMA fields and Start DMA Stream transfer */
		/* Enable All the DMA interrupts */
		if(HAL_DMA_Start_IT(han,(uint32_t)buf_to_flush, (uint32_t)&my_fb[y_fill_act * 400U + x1_flush],
				(x2_flush - x1_flush + 1)) != HAL_OK) {
			assert_param(false);	/*Halt on error*/
		}
	}
}

I also test it without the dma:

static void ex_disp_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_p)
{
	/*Truncate the area to the screen*/
	int32_t act_x1 = area->x1;
	int32_t act_y1 = area->y1;
	int32_t act_x2 = area->x2;
	int32_t act_y2 = area->y2;

	x1_flush = act_x1;
	y1_flush = act_y1;
	x2_flush = act_x2;
	y2_fill = act_y2;
	y_fill_act = act_y1;
	buf_to_flush = color_p;

	int32_t x, y;
	for(y = area->y1; y <= area->y2; y++) {
		for(x = area->x1; x <= area->x2; x++) {

			my_fb[y * 400 + x] = color_p->full;
			color_p++;
		}
	}

	lv_disp_flush_ready(drv);
}

which worked well, but I want to use the DMA.

It seems like a caching issue. Try adding SCB_CleanInvalidateDCache(); to the beginning of flush_cb.

1 Like

the stm323f429 doesn’t have cach AFAIK.

As far as I know, F4 only has a flash cache, not a full CPU cache.

You could try inserting a DSB instruction (__asm volatile("DSB\n")) before starting the DMA transfer, however, it’s unlikely that it will help.

@kisvegabor Is it just me, or do those artifacts look very reminiscent of the issue with the F746 project on v8?

Ah, true.

Hm, the linked issue was solved for me if not -O3 was selected. @Ali_Rostami Can you test with -O0.

Can you also try lowering the px clock frequency?

I’m compiling with CMake, which uses -O2, and the problem still appears.

Do you know which GCC version you’re using? Maybe it’s an issue with the compiler.

The things listed in this comment suggest somethings very weird.

Do you know which GCC version you’re using? Maybe it’s an issue with the compiler.

arm-none-eabi-gcc --version
arm-none-eabi-gcc (GNU Arm Embedded Toolchain 10-2020-q4-major) 10.2.1 20201103 (release)

And the GCC version:

gcc --version
gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0

with F4 and DMA, you have to take care that the render buffer is not located in the CCM RAM, which has no connection to the DMA. But afaik, an attempt to do this causes a hardfault.
with F7, its more complicated because of cache and different busses for the memory. Using the DTCM for the render buffer is the fastest, this is not cachable and does not need the CleanInvalidateCache(). When the SRAM is used, the cache can be disabled by using the MPU. Then the cache flush is also not necessary, but the SRAM access is slower than the DTCM.

Yes, I tested with other optimization levels too, but no difference.

Yeah, this works. I reduced it 2 times, and the problem vanished, but I have the flickering problem now.