Implementing a Read Timeout in MQXIO driver

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Implementing a Read Timeout in MQXIO driver

Jump to solution
1,806 Views
Cdn_aye
Senior Contributor I

Hi

We are using the rs485 serial driver. We do a read and it all works correctly but I want to create a timeout in the driver should the device hang or fail to respond. This is a normal function in most (non MQX) drivers. Does anyone know of anyway to implement a timeout in the read portion of the driver? I realize we could hack the driver and pass a timeout value, but this seems a bit unprofessional, and further on for other releases unsupported. Or is there another way apart from a timeout you could recommend?

Thanks

Robert

Tags (5)
1 Solution
952 Views
GottiLuca
Contributor IV

Dear Robert,

fread() ALWAYS complete since it's a non-blocking function ; read() , instead, waits for chars  and blocks the task char will be received.

fread() return the number of chars readen from the last time it was invoked ...

If the number of chars is 0 that means that, in the last period (i.e. : 15 ms initial timeout in my example ) , there weren't any response and this is a clear indication of timeout ..

View solution in original post

0 Kudos
6 Replies
952 Views
GottiLuca
Contributor IV

Dear Robert,

I've written a 485 driver and i've had to solve your same issue ( implementing a timeout ).

First of all, i've setup my serial channel in non blocking mode ( ie : use "ittyd:" instead of "ttyd:" ).

Then the timeout function is quite simple , just use _time_delay() function and then fread() to read the data received in the last delay time   ( in the code below the initial timeout is 15 ms ):

  /* half duplex, two wire */
    /* if receiver was disabled before, enable receiver again */ 
    disable_rx = FALSE;
    ioctl( rs485_dev, IO_IOCTL_SERIAL_DISABLE_RX, &disable_rx ) ;
  
        /* Read the data(s) in non blocking mode .. */    
        _time_delay( 15 );
        result = fread( cmdptr->rbuf_ptr, 1, 60 , rs485_dev);
      
        if ( result == 0 ) {
            result = TIMEOUT_ERR;
        }
       

else {

/* receive all the other chars .. */

              }

I believe this can be useful.

952 Views
Cdn_aye
Senior Contributor I

Hi Luca

What I was also concerned about was that the fread(...) might not complete and would just hang if there were no input? For example we have a BT module that could need reset, if we do not receive an response we would reset the device. I suppose I could implement this as two tasks, one with a read the other with a watch dog that spawns the read. If the watch dog times out then terminate the task, but I hoped for another solution.

Thank you for replying and the suggestion.

Robert

0 Kudos
953 Views
GottiLuca
Contributor IV

Dear Robert,

fread() ALWAYS complete since it's a non-blocking function ; read() , instead, waits for chars  and blocks the task char will be received.

fread() return the number of chars readen from the last time it was invoked ...

If the number of chars is 0 that means that, in the last period (i.e. : 15 ms initial timeout in my example ) , there weren't any response and this is a clear indication of timeout ..

0 Kudos
952 Views
DaveTonyCook
Contributor IV

Hi,

fread() is a blocking function if I use your example the only way I can get fread() to not block is by using ittyc (ittycin my case)

however it doesn't receive the character that I send to it and it stops my transmit task from working. Also the documentation isnt very helpful. Pleas help Thanks

#define TIMEOUT_ERR false;

void receive_task(uint32_t initial_data )

{

    MQX_FILE_PTR rs232_dev = NULL;

  char  data_buffer[5] = {0};

    uint32_t num_chars;

    bool timed_out;

  //rs232_dev  = fopen( "ttyc:", ( char const * ) IO_SERIAL_NON_BLOCKING ); // receives characters okay but blocks. Note                                                                                                                                   //IO_SERIAL_NON_BLOCKING has no effect?

  rs232_dev  = fopen( "ittyc:", ( char const * ) IO_SERIAL_NON_BLOCKING ); // does not block with or without                                                                                                                                  // IO_SERIAL_NON_BLOCKING. doent receive                                                                                                                                   // character sent to it

   

  while(TRUE)

  {

        // printf("\n receive task blocked - debug\n");

        //_task_block();

       

        /* Read the data(s) in non blocking mode .. */   

        _time_delay(150);

       

        num_chars = fread( data_buffer, 1, 2 , rs232_dev);

           

        if (num_chars)

        {

           if(data_buffer[0] == 'r' )

           {

                /* receive all the other chars .. */

                // post data to callee task - TBD

                data_buffer[0] = 0;

           }

        }

        else

        {           

             timed_out = TIMEOUT_ERR;

            //post timout event to callee - TBD

        }

  };

}

Transmit Task disabled. and code commented out

Has anyone solved this problem?

Thanks

0 Kudos
952 Views
kubiznak_petr
Contributor V

That doesn't sound correct to me, as both read() and fread() are just mappings to the same mqx function _io_read(), as you can see in mqx/source/include/fio.h.

Whether the file will be read using blocking or non-blocking access is specified by giving IO_SERIAL_NON_BLOCKING flag argument to the fopen() function.

I'm speaking about MQX 4.0.2, but I don't expect such a fundamental thing to be so different in the older versions of MQX.

952 Views
Cdn_aye
Senior Contributor I

Hi Luca

I misunderstood the fread, your code will be very helpful. This will do exactly what I need. Thank you.

Robert

0 Kudos