Questions about define object and effect on memory

Hi @Zebra067 ,

Don’t apologise for your English, I can only speak English lol so I have much respect for people who can speak in multiple languages! :grinning:

I am still not convinced about your file versions, the file I sent was from the SDK installed on my machine. It doesn’t matter though if your up a running and happy with your performance that is all that matters. :slight_smile:

With regard to your touch panel, I have written and used i2c, rs232 and most recently USB touch drivers with LVGL. My usual approach is to use a FreeRTOS queue to collect touch events from with in an interrupt handler for the device. Then have LVGL call a function to read the FreeRTOS queue.

Can you tell me which drivers you are using currently, is it from the NXP SDK?
Can you say which touch screen chip you are using?

I am working on some template code for you if you can answer my questions above I will customise it as much as I can for your application.

Kind Regards,

Pete

1 Like

he @pete-pjb,

Thank you , english is the universal language, it’s important :smiley:

I’am sure that you have modified the file i sent you :stuck_out_tongue: because there’s a macro for my panel that not supported by the demo demo_panel_ampire, yes it doesn’t matter the version, i just wanted to let you know that the file you sent was not the last update

I’am using ILITEK2511, and i didn’t find a driver for this , so i use for now the driver fsl_gt911.c(included in SDK) that i adapted to make it work with my touchpanel for now, (i should write it properly later)

i use a global volatile bool variable that in my IRQ_handler i put it to true, and i wrote a condition in the part of reading data from i2c )driver if this variable is true the MCU send a command to touchpanel for reading data),
i don’t know how to explain this in a good way, but i use a global variable change value by IRQ_handler and i use this variable in my driver, i assume it’s not a good use for organization of code, and i believe that a driver must not be related to global variable of any project to make it easy for porting.

kind regards,

Zebra,

1 Like

Hi @Zebra067 ,

Here is a template which I hope will give you a good performance:

#define THREAD_STACKSIZE	1024					// This is more than enough! 
#define TOUCH_PRIORITY		tskIDLE_PRIORITY + 2	// You probably want to set this the same as LVGL

// Global or Static variables ( I have all these defined in structure to keep them together personally )
lv_indev_drv_t			indev_drv;
lv_indev_data_t			last_state;
QueueHandle_t			touch_state_q;
SemaphoreHandle_t 		TouchTaskSemaphore = NULL;


// Replacement for current lv_port_indev_init() function.
void lv_port_indev_init(void)
{
    static lv_indev_drv_t indev_drv;

    /*------------------
     * Touchpad
     * -----------------*/

    /*Initialize your touchpad */
    DEMO_InitTouch();

    /*Register a touchpad input device*/
    lv_indev_drv_init(&indev_drv);
    indev_drv.type = LV_INDEV_TYPE_POINTER;
    indev_drv.read_cb = &touch_read;         /*This function will be called periodically (by the LVGL) to get the touch position and state*/
    indev_drv.user_data = NULL;
    indev = lv_indev_drv_register(&indev_drv);
	pointer_state_q = xQueueCreate( 256, sizeof( lv_indev_data_t ) );		// We can queue up to 256 touch events!
	TouchTaskSemaphore = xSemaphoreCreateBinary();
    /* Add a line here to attach the receive_touch_isr( ) function to the hardware interrupt */
	xTaskCreate( (TaskFunction_t)sysmsg_task, "Touch Handler", THREAD_STACKSIZE, NULL, TOUCH_PRIORITY, NULL );

}

// Replacemnt for current DEMO_ReadTouch() function
void touch_read(struct _lv_indev_drv_t * indev_drv, lv_indev_data_t * data) {

	static lv_indev_data_t		event_d_q;

	if( xQueueReceive( touch_state_q, &event_d_q, 0 ) ) {
		memcpy( data, &event_d_q, sizeof(lv_indev_data_t) );
		data->continue_reading = (uxQueueMessagesWaiting( touch_state_q ) ? pdTRUE : pdFALSE);	// If more events are available let LVGL know
#ifdef _DEBUG_INDEV_TOUCH_MOUSE_
		printf( "INDEV: %ld, %ld, %s\r\n", data->point.x, data->point.y, data->state ? "PR" : "RL" ) ;
#endif
	}
    return;
}

// Interrupt Service Handler for Ilitek Chip
void receive_touch_isr( ) {			// Attach this  interrupt handler to the hardware interrupt associated with the Ilitek chip

	static BaseType_t 	xHigherPriorityTaskWoken;

    xHigherPriorityTaskWoken = pdFALSE;
    xSemaphoreGiveFromISR( TouchTaskSemaphore, &xHigherPriorityTaskWoken );		// This wakes the touch_task() so it can collect data.

    portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
 
/* This type of task driven approach allows for defered processing of the data so you don't have to do lots of lengthy 
 * i2c processing from an interrupt handler which is obviously not desired and utilises the benefits of having an RTOS */ 
void touch_task( void *p ) {
	
	lv_coord_t		touch_x, touch_y;
	uint8_t			Touched;
	
	while( 1 ) {	// It's a task so it runs for ever...
		if( xSemaphoreTake( TouchTaskSemaphore, portMAX_DELAY ) == pdTRUE ) {
			 
			if (kStatus_Success == GT911_GetSingleTouch(&s_touchHandle, &touch_x, &touch_y)) {
				Touched = LV_INDEV_STATE_PR;
			} else {
				Touched = LV_INDEV_STATE_REL;
			}

			/*Set the last pressed coordinates*/
			last_state.point.x = touch_x * LCD_WIDTH / s_touchResolutionX;
			last_state.point.y = touch_y * LCD_HEIGHT / s_touchResolutionY;
			last_state.state = Touched;
			xQueueSend( touch_state_q, &last_state, 0 );
		 }
	}
}

I have looked at the i2c drivers and I think this will be okay with the NXP code.

They only thing I can’t spot is where the NXP driver sets the interrupt service handler for the touch chip so hopefully you can see that!

Again this code is completely uncompiled and untested as I don’t have the hardware so my apologies in advance if there are any errors!

Let me know if you have any success. Good Luck! :smiley:

Kind Regards,

Pete

1 Like

Hi @pete-pjb,

Thank you for your suggestion, I’ll try to make it work, and see if there’s better performances,
in the DEMO of NXP there’s no ISR for the touch, and it’s working in polling and communication with touchpanel is called periodically (by the LVGL) to get the touch position and state by processing the i2C,
For me i Added an ISR_Handler and all what does is put the g_inputSignal to true, and it’s not processing i2C in isr_handler :

extern volatile bool g_InputSignal;

void GPIO_IRQHandler(void)
{
    /* clear the interrupt status */
    GPIO_PortClearInterruptFlags(BOARD_TOUCH_INT_GPIO, 1U << BOARD_TOUCH_INT_PIN);
    /* Change state of switch. */
    g_InputSignal = true;
    SDK_ISR_EXIT_BARRIER;
}

and in the function called periodically by LVGL GT911_ReadRawTouchData i made a condtition if the g_InputSignal is true we need to read data from touchpanel and put a g_inputSignal to false

static status_t GT911_ReadRawTouchData(gt911_handle_t *handle, uint8_t *touchPointNum)
{
    status_t status;


    if (g_InputSignal)
    {
    status = handle->I2C_ReceiveFunc(handle->i2cAddr, GT911_REG_STAT, GT911_REG_ADDR_SIZE, &gt911Stat, 1);
    if (kStatus_Success != status)
    {
        *touchPointNum = 0;
        return status;
    }

    *touchPointNum = gt911Stat & GT911_STAT_POINT_NUMBER_MASK;

    if (0U != (gt911Stat & GT911_STAT_BUF_MASK))
    {
        if (*touchPointNum > 0U)
        {
            status = handle->I2C_ReceiveFunc(handle->i2cAddr, GT911_REG_FIRST_POINT, GT911_REG_ADDR_SIZE,
                                             (void *)handle->pointReg, (*touchPointNum) * sizeof(gt911_point_reg_t));
        }

        /* Must set the status register to 0 after read. */
        gt911Stat = 0;
        status    = handle->I2C_SendFunc(handle->i2cAddr, GT911_REG_STAT, GT911_REG_ADDR_SIZE, &gt911Stat, 1);
    }


	return status;
}

What do you think about this ?

i would have many tasks to manage later, so i don’t know if it’s good for me to add another task just to handle touchpanel, while i can handle in the same task with LVGL.

I’ll try for sure to use what you suggested,

Thank you so much for your suggestion

Kind regards,

Zerba,

1 Like

Hi @Zebra067 ,

I think your solution should work well also, and if you find it works well right now and you are not missing any touch events, there is probably no need to change it.
The advantage my approach brings is that the events are queued and providing the Ilitek chips hardware FIFO doesn’t overrun you shouldn’t miss any events but if your solution is providing an acceptable performance that’s all good.

The extra task shouldn’t really cause any major issues as it will be sleeping/blocked until such time as there is anything to do so that shouldn’t be a problem.
You can also reduce the stack size for the task if you want to keep resource utilisation down, it should function happily with the same size stack as the idle task as there are few variables declared on the stack. I just popped in some arbitrary value when typing up the code.

Personally I don’t like any code executing from with in LVGLs framework to introduce any delay or blocking if I can help it. So by having the “potentially relatively lengthy” i2c accesses in a separate task it stops them from blocking the rendering of the GUI if that makes sense? You can then use different priorities in the tasks to balance the system to provide the CPU time where it is most needed at any point in time and keep the GUI responsive at all times.

Another way of improving GUI performance I use, is to implement a FreeRTOS task which runs at a lower priority than the GUI with a queue(similar to the touch task above) which contains a case statement for many different background tasks then LVGL can post messages to this queue, so for example if I want to load a file into a text box LVGL will queue a request to the FreeRTOS task which has been triggered by an LVGL event and the task will carry out the slow process of reading from an SD card etc. at a lower priority in the background but throughout the period of the file loading the GUI remains absolutely responsive. If this file handling was called directly from within the event handler which queues the request in LVGL, the GUI would halt completely while the file is loading which personally I don’t like at all. I hope that makes sense.

Kind Regards,

Pete

1 Like

Hi @Zebra067 ,

I need to send you an email with regard to helping you with Eclipse, can you send an email to [email protected] from the address you would like me to send a response to.

Kind Regards,

Pete

1 Like

Hi @pete-pjb ,

Yes, it works for now but I see that your approach is better and it would the two tasks work in same time and datas are protected,

Of course it’s preferable to not having any process making delays that would affect LVGL performances so your approach of using a second task makes sense, Thank you for suggesting me this,

i’m grateful for your support

Kind regards,

Zebra

1 Like

Hi pete-pjb, If use “else lv_disp_flush_ready( disp_drv );”, my programe will block in wait lock, blow “11112” will not print:

task
lock()
lv_task_handler();
unlock()

gui:
printf(“11111\r\n”)
lock()
printf(“11112\r\n”)
gui code
unlock()

If use like this, the area of PERF_MONITOR will twinkle:
if( lv_disp_flush_is_last( disp_drv ) ) {
DCACHE_CleanInvalidateByRange((uint32_t)color_p, DEMO_FB_SIZE);
ELCDIF_SetNextBufferAddr(LCDIF, (uint32_t)color_p);
DEMO_UpdateDualBuffer(disp_drv, area, color_p);
s_framePending = true;
}
lv_disp_flush_ready( disp_drv );

Hi @humphrey ,

I am sorry but I have been away on business for a couple of weeks.

If this is still an issue for you perhaps you can let me know a bit more information?

Sorry but I am not totally certain about what is happening based on what you have posted so far. :slight_smile:

Kind Regards,

Pete

Hi @pete-pjb , thank you very much, I have resolved it by your this code:

1 Like