315 views
in System Integration by

Hello,

I have created some variables structures to handle data like input status, output status and device status.

These have different data type inside and are like:

typedef struct _input{
	//Ingressi  sulla Lizard
	bool b_input1;
	bool b_input2;
    ...
	bool b_inputN;
	uint16_t an_value1;
	uint16_t an_value2;
    ..
	uint16_t an_valueM;
	//Contatori ingresso fronti salita/discesa
} input_t;

typedef struct _output{
	bool b_out1;
	bool b_out2;
    ...
	bool b_outN;
	uint16_t an_out1;
	uint16_t an_out2;
    ..
	uint16_t an_outM;
}

typedef struct _device{
    int32_t status;
    int32_t mode;
    ...
} device_t

I have declared one global varaible for each structure in EW in the /Inline code:

input_t In;
output_t Out;
io_exp_t OutIOExp;
device_t Device;

I use these variables to "syncronize" input, output and device status from GUI to device board. To do this, in the Application::Device class, I have created some method like UpdateInput, UpdateOutput and UpdateStatus.

As in your DeviceIntegration example, I use threads and manage Input, Output and Status syncronization:

In your expamples, you use the function EwInvokeCopy to schedule the update of the GUI from the thread. I did the same, but the difference is that I don't pass a single variable value, but the entire structure. To explain better, in the input update thread I pass the input structure, for the state the state structure, and for the outputs the output structure.

To explain better, this is part of the code of the input thread:

static void ReadInputThread(const void* arg)
{
	while (Threads_Initialized)
	{
      In.input1 = HAL_GPIO_ReadPin(INPUT1_GPIO_Port, INPUT1_Pin);
      In.input2 = HAL_GPIO_ReadPin(INPUT2_GPIO_Port, INPUT1_Pin);
      ...
      In.inputN = HAL_GPIO_ReadPin(INPUTN_GPIO_Port, INPUTN_Pin);

      EwInvokeCopy(GUI_UpdateInput, &In, sizeof(input_t));

      EwBspOsDelay(THREAD_WAIT_TIME);
	}
  //Terminazione thread 
  ReadInput_Thread_Active = 0;
  EwBspOsThreadDestroy(EwBspOsThreadGetHandle());
}

I notice that only the function that updates the input GUI is executed. Using the EwIvoke function instead of the EwInvokeCopy function executes all three update functions.
Could it be that I'm already exhausting the internal queue with the first function? If so, is it possible to find out how large the internal queue is? Can I change the size of it?
If I understand correctly, the EwInwokeCopy function, in my specific case, creates a copy of the structure I pass (in this case, the input_t structure) in the internal queue, while the EwInwoke function does not? Since the variables are global and my goal is to always keep the GUI updated based on these variables, can I safely use the EwInvoke function and avoid creating a "useless" copy?

Nicola

1 Answer

0 votes
by

Hello Nicola,

Could it be that I'm already exhausting the internal queue with the first function?

Yes, this can occur. In such case the function EwInvokeCopy() returns 0 to indicate the error case. More details are found in our documentation. The size of the queue is confuguzred through the macto EW_INVOCATION_QUEUE_SIZE. See also Caches and Buffers Configuration.

... can I safely use the EwInvoke function and avoid creating a "useless" copy?

Doing that will theoretically provoke an incoherence when the GUI thread accesses the data structure while the worker thread is modifying this structure at the same time.

I hope adjusting the queue size solves the issue.

Best regards

Paul Banach

by

Hello Paul,

thank you for the answer.

Can you please give also a feedback about my consideration of using command EwInvoke intead of EwInvokeCopy to pass global variables?

I mean this quetion:

If I understand correctly, the EwInwokeCopy function, in my specific case, creates a copy of the structure I pass (in this case, the input_t structure) in the internal queue, while the EwInwoke function does not? Since the variables are global and my goal is to always keep the GUI updated based on these variables, can I safely use the EwInvoke function and avoid creating a "useless" copy?

If I understand correctly, the InvokeCopy command is used to prevent the variable pointer passed to the function from pointing to something that no longer exists once the function is executed. So, for "safety," a copy of the variable is made, and the passed pointer points to this copy.
In the case of global variables, the pointer should always point to valid data (global variables are not deleted). Is this consideration true or am I wrong?

If using EwInvoke function can be a solution, I will use it and I would avoid changing the queue size.

by

Can you please give also a feedback about my consideration of using command EwInvoke intead of EwInvokeCopy to pass global variables?

See my answer above mentioning the possibility of incoherence.

by

Sorry, I din't realize that you already answered me!

Ok, understood.

Just one more question to determinate the queue size: if the same command EwInvokeCopy(for example EwInvokeCopy(GUI_UpdateInput, &In, sizeof(input_t));) is executed more than once before the next iteration through Embedded Wizard application's main loop, the data structure (in this case input_t) is copied again in the queue or there is some kind of check and overwrite of the same structure in queue?

This because I have more than one thread that are executed with a 10 to 100ms timer that execute the EwInvokeCopy command and I don't know the application main loop excecution time (I guess it depends on the complexity of the project).

by

Hello Nicola,

if you invoke the function twice, then two copies of the data structure are stored. There is no check to detect duplicates. It is also not intended. From technical point of view, each copy is an individual version of the data corresponding to the message.

This because I have more than one thread that are executed with a 10 to 100ms timer that execute the EwInvokeCopy command and I don't know the application main loop excecution time (I guess it depends on the complexity of the project).

Note the return value of the EwInvokeCopy() function. If there is no space in the queue, the function returns 0. Therefore test the return value. Usually when you observe such situation you would adjust the configuration of the queue size to avoid it in the future. Alternative approach: when EwInvokeCopy() returns 0, sleep in the thread few milliseconds and then repeat the operation again. The GUI thread may process the contents from the queue in the meantime and the queue is empty then.

I hope it helps you further.

Best regards

Paul Banach

 

Ask Embedded Wizard - Archive

Welcome to the Ask Embedded Wizard archive. This community forum served us well for many years, but we've evolved our support approach!

Your resources:

The Embedded Wizard Online Documentation provides comprehensive documentation, tutorials, examples and ready-to-use software packages.

For dedicated assistance, explore our Embedded Wizard Product Support.

You can still browse the valuable discussions from our community history here.

Embedded Wizard Website | Privacy Policy | Imprint

...