µTasker Forum

µTasker Forum => µTasker general => Topic started by: hervé on November 28, 2010, 05:43:54 PM

Title: INTERNAL_ROUTE
Post by: hervé on November 28, 2010, 05:43:54 PM
Hello Mark,

When sending a message to a task we can test if it fits the buffer size allocated, by pointing the message to null.
Code: [Select]
fnWrite( TASK_TEST, 0, MSG_LENGTH); // test if we can write
How to do when sending to  INTERNAL_ROUTE, as the message is used to find the correct heap in this case ?

In fact I don't want to start writing a message if I could not complete ( it will be misinterpreted by the listener)

 
                
Title: Re: INTERNAL_ROUTE
Post by: mark on November 29, 2010, 01:29:59 PM
Hi Hervé

This is something that can't be done at the moment but it is quite easy to add:

In the driver function static QUEUE_TRANSFER fnWriteInternal(unsigned char *output_buffer, QUEUE_TRANSFER nr_of_bytes) locate the following code (it is at the end of the subroutine).

        ptQUEQue = (struct stQUEQue *)(que_ids[newDestID - 1].input_buffer_control); // set to input control block - write directly to input
        nr_of_bytes = fnFillBuf(ptQUEQue, output_buffer, nr_of_bytes);
        uTaskerStateChange(NewWakeTask, UTASKER_ACTIVATE);
        return (nr_of_bytes);


Now make the following change:

        ptQUEQue = (struct stQUEQue *)(que_ids[newDestID - 1].input_buffer_control); // set to input control block - write directly to input
        if (output_buffer[MSG_SOURCE_TASK] == 0) {                       // check on destination's queue
            return (ptQUEQue->buf_length - ptQUEQue->chars);             // remaining space in queue (before adding new message)
        }
        nr_of_bytes = fnFillBuf(ptQUEQue, output_buffer, nr_of_bytes);
        uTaskerStateChange(NewWakeTask, UTASKER_ACTIVATE);
        return (nr_of_bytes);


This will allow you to call using something like:


    unsigned char int_message[HEADER_LENGTH];

    int_message[MSG_DESTINATION_NODE] = INTERNAL_ROUTE;
    int_message[MSG_SOURCE_NODE]      = INTERNAL_ROUTE;
    int_message[MSG_DESTINATION_TASK] = TASK_DEBUG;
    int_message[MSG_SOURCE_TASK]      = 0; // setting the source task to zero causes the write to return the available queue size (before any extra data is entered)

    return (fnWrite(INTERNAL_ROUTE, int_message, HEADER_LENGTH));


Also the following can be generally used  to cause the same return value:
fnEventMessage(TASK_DEBUG, 0, 0);

The only thing to bear in mind is the fact that the value returned may not always be correct if an interrupt were to post a message to the same task just after (or during) the call. This is because the interrupt's message would reduce the available space. Either calls can be protected by disabling interrupts (if it is known that interrupts may also be posting messages to the same task) or else the queue can be increased a little in size and the check be made for larger message size to take in account such a possible occurrance.

Regards

Mark


Title: Re: INTERNAL_ROUTE
Post by: hervé on November 29, 2010, 02:50:22 PM
Thank you Mark,

It looks fine.

But as I'm only interested in knowing if I could write or not I will change the test

        if (output_buffer[MSG_SOURCE_TASK] == 0) {                       // check on destination's queue
            return (ptQUEQue->buf_length - ptQUEQue->chars);             // remaining space in queue (before adding new message)
        }

to

        if (output_buffer[MSG_SOURCE_TASK] == 0) {                       // check on destination's queue
            return ((ptQUEQue->buf_length - ptQUEQue->chars)>=nr_of_bytes);             // check remaining space in queue (before adding new message)
        }

Thanks for help again.

Title: Re: INTERNAL_ROUTE
Post by: hervé on November 30, 2010, 03:36:31 PM
Hi Mark,

I made the following changes :

Code: [Select]
#define SIZE_TEST  0xFF
....
        if (output_buffer[MSG_SOURCE_TASK] == SIZE_TEST) {                       // check on destination's queue
            return (ptQUEQue->buf_length - ptQUEQue->chars);             // remaining space in queue (before adding new message)
        }

and also

Code: [Select]
....
    int_message[MSG_SOURCE_TASK]      = SIZE_TEST; // setting the source task to SIZE_TEST causes the write to return the available queue size (before any extra data is entered)

because in fact the function fnWrite( INTERNAL_ROUTE....
is called with ucMessage[ MSG_SOURCE_TASK ] = TIMER_EVENT;
which is defined as null....


Title: Re: INTERNAL_ROUTE
Post by: mark on November 30, 2010, 05:58:07 PM
Hi Hervé

Thanks. I didn't realsie that but you are correct.

However I suggest adding the following to uTasker.h

#define CHECK_QUEUE     0x03                                             // task reference used to check input queues
This is because there are in fact already three task references defined which are handles spcially:

#define TIMER_EVENT     0x00                                             // message from task 0x00 can only be timer
#define INTERRUPT_EVENT 0x01                                             // message from task 0x01 can only be interrupt
#define FUNCTION_EVENT  0x02                                             // message from task 0x02 is a function event, specifying handling by a function rather than a task


This will then keep all of these special task references together.

This means that my reference now looks like this:

        if (output_buffer[MSG_SOURCE_TASK] == CHECK_QUEUE) {             // check on destination's queue
            return (ptQUEQue->buf_length - ptQUEQue->chars);             // remaining space in queue (before adding new message)
        }


Note that I don't return a check with the value because this returns the remaining queue space (rather than a comparison result). This is then compatible with the return value declaration and also its use is more compatible with the fnWrite() call with zero pointer. The caller can simply compare the returned value with the data size that it wants to send to see whether it fits or not.

It also allows the following to work (which is not possible when a comarison is made since it ois always made with a fixed header length):

if (fnEventMessage(TASK_DEBUG, CHECK_QUEUE, 0) >= message_length) { // check that the message will fit in the receiver's input queue
 // send message to task's input queue
}



Regards

Mark





Title: Re: INTERNAL_ROUTE
Post by: hervé on December 01, 2010, 08:14:49 AM
Hi Mark,

In fact :

if (fnEventMessage(TASK_DEBUG,CHECK_QUEUE, 0) >= message_length) { // check that the message will fit in the receiver's input queue
 // send message to task's input queue
}
Title: Re: INTERNAL_ROUTE
Post by: mark on December 01, 2010, 10:10:04 AM
Hi Hervé

Thanks - corrected in the last post.

Regards

Mark
Title: Re: INTERNAL_ROUTE
Post by: timadria on May 03, 2016, 10:12:50 AM
Marc,

I was searching for this solution myself. E need this to check if there is still some space available on my serial port buffer before adding extra messages.
I tried to do this but get not the serial buffer size. This is set to 1024 in the fnOpenUart.
tInterfaceParameters.Rx_tx_sizes.TxQueueSize = 1024;   // output buffer size

I always get 37 back. Is there an other solution to check this for the serial port?

I did the request like this: fnEventMessage(TASK_SERIAL, CHECK_QUEUE, 0);

Thanks, Tim
Title: Re: INTERNAL_ROUTE
Post by: mark on May 03, 2016, 08:31:59 PM
Hi

fnEventMessage(TASK_SERIAL, CHECK_QUEUE, 0); can be used to check the amunt of remaining space in the input queue of the tsk named "TASK_SERIAL".

To check the remaining space in the output buffer of a UART you need to use:

fnWrite(UART_Handle, 0, SIZE_TO_CHECK);
and it will return 0 if SIZE_TO_CHECK would not fit.


Note: See debug.c for some examples of its useage since the command line menu can be generated even if there is quite a small UART output buffer by writing the menu as a series of smaller blocks.


Regards

Mark


Title: Re: INTERNAL_ROUTE
Post by: timadria on May 04, 2016, 12:59:33 PM
Hi Marc,

This works perfect for me.

Thanks
Title: Re: INTERNAL_ROUTE
Post by: mark on May 04, 2016, 01:40:09 PM
Great!
Thanks for the confirmation.

Mark