What is the correct way to override and initialise io_serial driver in MQX

cancel
Showing results for 
Search instead for 
Did you mean: 

What is the correct way to override and initialise io_serial driver in MQX

Jump to solution
399 Views
DaveTonyCook
Contributor IV

Hi,

I cant get my receive_task to open the serial device in non-blocking mode.  This is what I have found:-

MQX calls _io_serial_default_init(); from init_bsp.c during system initialisation which leaves the driver open and sets the default kernel_data->INIT.IO_OPEN_MODE = BSP_DEFAULT_IO_OPEN_MODE (Note This is auto generated during the MQX bsp lib build)

where BSP_DEFAULT_IO_OPEN_MODE is defined as #define BSP_DEFAULT_IO_OPEN_MODE (void *) (IO_SERIAL_XON_XOFF | IO_SERIAL_TRANSLATION | IO_SERIAL_ECHO)

_io_serial_default_init() call kernel_data->PROCESSOR_STDIN = _io_fopen((char *)kernel_data->INIT.IO_CHANNEL,(char *)kernel_data->INIT.IO_OPEN_MODE);

Which at line 61 (below) opens the device in the default mode.  When my receive_task makes a call to fopen in non-blocking mode (shown below at line 84) it calls _mqx_int _io_serial_polled_open where at line 136 it reports that the device is already open and returns leaving the open mode unchanged. Please advise the correct way to override this behaviour rather than me just hack it. Thanks

MQX_FILE_PTR _io_fopen(const char  *open_type_ptr,const char  *open_mode_ptr )

{ /* Body */

   KERNEL_DATA_STRUCT_PTR kernel_data;

   MQX_FILE_PTR           file_ptr;

   IO_DEVICE_STRUCT_PTR   dev_ptr;

   char                  *dev_name_ptr;

   char                  *tmp_ptr;

   _mqx_int                result;

   _GET_KERNEL_DATA(kernel_data);

   _lwsem_wait((LWSEM_STRUCT_PTR)&kernel_data->IO_LWSEM);

   dev_ptr = (IO_DEVICE_STRUCT_PTR)((void *)kernel_data->IO_DEVICES.NEXT);

   while (dev_ptr != (void *)&kernel_data->IO_DEVICES.NEXT) {

      dev_name_ptr = dev_ptr->IDENTIFIER;

      tmp_ptr      = (char *)open_type_ptr;

      while (*tmp_ptr && *dev_name_ptr &&

         (*tmp_ptr == *dev_name_ptr))

      {

         ++tmp_ptr;

         ++dev_name_ptr;

      } /* Endwhile */

      if (*dev_name_ptr == '\0') {

         /* Match */

         break;

      } /* Endif */

      dev_ptr = (IO_DEVICE_STRUCT_PTR)((void *)dev_ptr->QUEUE_ELEMENT.NEXT);

   } /* Endwhile */

 

   _lwsem_post((LWSEM_STRUCT_PTR)&kernel_data->IO_LWSEM);

 

   if (dev_ptr == (void *)&kernel_data->IO_DEVICES.NEXT) {

      return(NULL);

   } /* Endif */

   file_ptr = (MQX_FILE_PTR)_mem_alloc_system_zero((_mem_size)sizeof(MQX_FILE));

#if MQX_CHECK_MEMORY_ALLOCATION_ERRORS

   if (file_ptr == NULL) {

      return(NULL);

   } /* Endif */

#endif

   _mem_set_type(file_ptr, MEM_TYPE_FILE_PTR);

 

   file_ptr->DEV_PTR = dev_ptr;

   if (dev_ptr->IO_OPEN != NULL) {

     result = (*dev_ptr->IO_OPEN)(file_ptr, (char *)open_type_ptr, (char *)open_mode_ptr); //Line 61

      if (result != MQX_OK) {

         _task_set_error(result);

         _mem_free(file_ptr);

         return(NULL);

      } /* Endif */

   } /* Endif */

   return(file_ptr);

} /* Endbody */

#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;

 

   // receives characters okay but blocks.  Note IO_SERIAL_NON_BLOCKING has no effect?

   rs232_dev  = fopen( "ttyc:", ( char const * ) IO_SERIAL_NON_BLOCKING );  // Line84

  

  while(TRUE)

  {

        /* 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

        }

  };

}

_mqx_int _io_serial_polled_open

    (

        /* [IN] the file handle for the device being opened */

        MQX_FILE_PTR fd_ptr,

        /* [IN] the remaining portion of the name of the device */

        char        *open_name_ptr,

        /* [IN] the flags to be used during operation:

        ** echo, translation, xon/xoff, encoded into a pointer.

        */

        char        *flags

    )

{

    IO_DEVICE_STRUCT_PTR               io_dev_ptr;

    IO_SERIAL_POLLED_DEVICE_STRUCT_PTR polled_dev_ptr;

    _mqx_uint                          result = MQX_OK;

    _mqx_uint                          ioctl_val;

    io_dev_ptr     = fd_ptr->DEV_PTR;

    polled_dev_ptr = (void *)io_dev_ptr->DRIVER_INIT_PTR;

    if (polled_dev_ptr->COUNT) {          // Line 136

        /* Device is already opened */

        polled_dev_ptr->COUNT++;

        fd_ptr->FLAGS = polled_dev_ptr->FLAGS;

        return (_mqx_int)(result);

    }

    polled_dev_ptr->CHARQ = (CHARQ_STRUCT_PTR)_mem_alloc_system((_mem_size)(

      sizeof(CHARQ_STRUCT) - (4 * sizeof(char)) + polled_dev_ptr->QUEUE_SIZE

    ));

#if MQX_CHECK_MEMORY_ALLOCATION_ERRORS

    if (polled_dev_ptr->CHARQ == NULL) {

        return(MQX_OUT_OF_MEMORY);

    }

#endif

    _mem_set_type(polled_dev_ptr->CHARQ,MEM_TYPE_IO_SERIAL_CHARQ);  

    _CHARQ_INIT(polled_dev_ptr->CHARQ, polled_dev_ptr->QUEUE_SIZE);

    polled_dev_ptr->FLAGS = (_mqx_uint)flags;

    fd_ptr->FLAGS = (_mqx_uint)flags;

#if MQX_ENABLE_LOW_POWER        

    _lwsem_wait (&(polled_dev_ptr->LPM_INFO.LOCK));

#endif

    result = (*polled_dev_ptr->DEV_INIT)(

        polled_dev_ptr->DEV_INIT_DATA_PTR, &polled_dev_ptr->DEV_INFO_PTR, open_name_ptr

    );

#if MQX_ENABLE_LOW_POWER        

    _lwsem_post (&(polled_dev_ptr->LPM_INFO.LOCK));

#endif

    if (result == MQX_OK) {

        if ((polled_dev_ptr->DEV_IOCTL) != NULL) {

            ioctl_val = (_mqx_uint)flags;

            (*polled_dev_ptr->DEV_IOCTL)(polled_dev_ptr->DEV_INFO_PTR, IO_IOCTL_SERIAL_SET_FLAGS, &ioctl_val);

        }

        if ((_mqx_uint)flags & IO_SERIAL_NON_BLOCKING) {

            if ((_mqx_uint)flags & (IO_SERIAL_TRANSLATION | IO_SERIAL_ECHO | IO_SERIAL_XON_XOFF)) {

                result = MQX_INVALID_PARAMETER;

            } else {

                if ((polled_dev_ptr->DEV_IOCTL) != NULL) {

                    result = (*polled_dev_ptr->DEV_IOCTL)(polled_dev_ptr->DEV_INFO_PTR,                                                                  IO_IOCTL_SERIAL_CAN_TRANSMIT, &ioctl_val);    

                }

            }

        }

    }

    if (result != MQX_OK) {

        _mem_free(polled_dev_ptr->CHARQ);

        return (_mqx_int)(result);

    }

    polled_dev_ptr->COUNT    = 1;

    return (_mqx_int)(result);

}

0 Kudos
1 Solution
144 Views
danielchen
NXP TechSupport
NXP TechSupport

Hi Dave:

I suggest you try to use IO control command to override the default settings

Please refer to the MQX_IO_User_Guide.pdf for more details.  In section 6.7  IO Control Commands

Below is an example to do this.

   _mqx_uint param = 0;

    fptr = _io_fopen(BSP_DEFAULT_IO_CHANNEL, NULL);

    /* device uses default flags. this task needs non-blocking mode */  

    if (IO_OK != ioctl(fptr, IO_IOCTL_SERIAL_GET_FLAGS, &param))

    {

printf("MyTask error ioctl getflags!\n");

      _task_block();

    }

   

    param |= IO_SERIAL_NON_BLOCKING;

    if (IO_OK != ioctl(fptr, IO_IOCTL_SERIAL_SET_FLAGS, &param))

    {

printf("MyTask error ioctl set flags!\n");

      _task_block();

    }

Regards

Daniel

View solution in original post

2 Replies
144 Views
DaveTonyCook
Contributor IV

I have found the following solution.  If anyone thinks this is incorrect then please let me know.  As far as I can see its still a bit of a hack.  I havnt been able to find any description of this process in the MQX documentation. If it exist please let me know

Thanks

_mqx_init_task() called from mqx.c by _mqx_init_kernel_data_internal() where _mqx_init_task() is placed in the task template task_template_ptr->TASK_ADDRESS = _mqx_init_task

_bsp_init() Called from inittask.c by _mqx_init_task()

_io_serial_default_init() Called from init_bsp.c by _bsp_init()

    /* Initialize the default serial I/O */

    _io_serial_default_init();

this call initialises the installed driver with the default values specified by BSP_DEFAULT_IO_OPEN_MODE.  Calling _io_serial_default_init() opens the io device, further calls to fopen() only return the handle to the device that has been opened by _io_serial_default_init().  Any parameters passed to fopen() on subsequent call do not have any effect.

To override this action over ride the default BSP_DEFAULT_IO_OPEN_MODE with your own BSP_USER_DEFINED_IO_OPEN_MODE in the MQX_INITIALIZATION_STRUCT  MQX_init_struct found in mqx_init.c 

const MQX_INITIALIZATION_STRUCT  MQX_init_struct =

{

   /* PROCESSOR_NUMBER                */  BSP_DEFAULT_PROCESSOR_NUMBER,

   /* START_OF_KERNEL_MEMORY          */  BSP_DEFAULT_START_OF_KERNEL_MEMORY,

   /* END_OF_KERNEL_MEMORY            */  BSP_DEFAULT_END_OF_KERNEL_MEMORY,

   /* INTERRUPT_STACK_SIZE            */  BSP_DEFAULT_INTERRUPT_STACK_SIZE,

   /* TASK_TEMPLATE_LIST              */  MQX_template_list,

   /* MQX_HARDWARE_INTERRUPT_LEVEL_MAX*/  BSP_DEFAULT_MQX_HARDWARE_INTERRUPT_LEVEL_MAX,

   /* MAX_MSGPOOLS                    */  BSP_DEFAULT_MAX_MSGPOOLS,

   /* MAX_MSGQS                       */  BSP_DEFAULT_MAX_MSGQS,

   /* IO_CHANNEL                      */  BSP_DEFAULT_IO_CHANNEL,

   /* IO_OPEN_MODE                    */  BSP_DEFAULT_IO_OPEN_MODE,

You need to create a BSP_USER_DEFINED_IO_OPEN_MODE in twrk70f120m.h found in the mqx project workspace and rebuild bsp library. 

e.g.

Overide:

#ifndef BSP_DEFAULT_IO_OPEN_MODE

    #define BSP_DEFAULT_IO_OPEN_MODE  (void *) (IO_SERIAL_XON_XOFF | IO_SERIAL_TRANSLATION | IO_SERIAL_ECHO)

#endif

with:

#define BSP_USER_DEFINED_IO_OPEN_MODE // comment out if default settings are required

#ifdef BSP_USER_DEFINED_IO_OPEN_MODE

    #define BSP_DEFAULT_IO_OPEN_MODE    (void *) (IO_SERIAL_NON_BLOCKING)

#endif

note if using IAR tools then pass BSP_USER_DEFINED_IO_OPEN_MODE in the preprocessor for cleaner control.

The following task now works:

#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_rx;

    bool timed_out;

   rs232_dev  = fopen( "ttyc:", NULL );

  

while(TRUE)

  {

        /* synchronise to transmit task */

          // wait on event from tx task

      

        /* Read a character in non-blocking mode every 150ms */  

        _time_delay( 150 );

      

        num_chars_rx = fread( data_buffer, 1, 1 , rs232_dev);

      

        /*  any characters received ? */

        if (num_chars_rx == 0)

        {

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

           {

                /* receive all the other chars .. Looking for ETX */

                // post data to callee task - TBD

           }

        }

        else

        {          

             timed_out = TIMEOUT_ERR;

            //post timout event to callee - TBD

        }

  };

}

0 Kudos
145 Views
danielchen
NXP TechSupport
NXP TechSupport

Hi Dave:

I suggest you try to use IO control command to override the default settings

Please refer to the MQX_IO_User_Guide.pdf for more details.  In section 6.7  IO Control Commands

Below is an example to do this.

   _mqx_uint param = 0;

    fptr = _io_fopen(BSP_DEFAULT_IO_CHANNEL, NULL);

    /* device uses default flags. this task needs non-blocking mode */  

    if (IO_OK != ioctl(fptr, IO_IOCTL_SERIAL_GET_FLAGS, &param))

    {

printf("MyTask error ioctl getflags!\n");

      _task_block();

    }

   

    param |= IO_SERIAL_NON_BLOCKING;

    if (IO_OK != ioctl(fptr, IO_IOCTL_SERIAL_SET_FLAGS, &param))

    {

printf("MyTask error ioctl set flags!\n");

      _task_block();

    }

Regards

Daniel

View solution in original post