po_hi_driver_rtems_drvmgr_serial.c 9.85 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * This is a part of PolyORB-HI-C distribution, a minimal
 * middleware written for generated code from AADL models.
 * You should use it with the Ocarina toolsuite.
 *
 * For more informations, please visit http://taste.tuxfamily.org/wiki
 *
 * Copyright (C) 2018 ESA & ISAE.
 */

#include <deployment.h>
/* Generated code header */

#include <activity.h>
#include <marshallers.h>

#include <po_hi_debug.h>
#include <po_hi_transport.h>
#include <po_hi_gqueue.h>
#include <po_hi_messages.h>
21
#include <po_hi_protected.h>
22
#include <po_hi_returns.h>
23

24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
#include <po_hi_utils.h>
#include <drivers/po_hi_rtems_utils.h>

#include <po_hi_driver_drvmgr_common.h>
/* Common drvmgr initialization */

#include <drivers/po_hi_driver_serial_common.h>

#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <termios.h>
/* POSIX-style files */

#include <drivers/configuration/serial.h>

int po_hi_c_driver_rtems_drvmgr_serial_fd_read[__PO_HI_NB_DEVICES];
int po_hi_c_driver_rtems_drvmgr_serial_fd_write[__PO_HI_NB_DEVICES];

__po_hi_request_t    __po_hi_c_driver_rtems_drvmgr_serial_request;
__po_hi_msg_t        __po_hi_c_driver_rtems_drvmgr_serial_poller_msg;
46
__po_hi_mutex_t      __po_hi_c_rtems_serial_send_mutex;
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70

/*!
 * \fn void __po_hi_c_driver_rtems_drvmgr_serial_poller (const __po_hi_device_id dev_id)
 * \brief Polling function for the RTEMS DRVMGR SERIAL.
 *
 * This function is the poller for the serial interface of the RTEMS DRVMGR SERIAL board.
 * It is supposed to be called by the underlying AADL code at a given period/rate.
 * The argument dev_id is the device_id handled by the device driver. By using
 * such an argument, we can use this function on a single node that uses several
 * driver instances (several serial interfaces connected to different serial buses).
 */

void __po_hi_c_driver_rtems_drvmgr_serial_poller (const __po_hi_device_id dev_id)
{
   int                  n;
   int                  ts;
   uint8_t*             ptr;

   ts = __PO_HI_MESSAGES_MAX_SIZE;
   ptr = &(__po_hi_c_driver_rtems_drvmgr_serial_poller_msg.content[0]);
   __po_hi_msg_reallocate (&__po_hi_c_driver_rtems_drvmgr_serial_poller_msg);
   while (ts > 0) {
     __PO_HI_DEBUG_DEBUG
       ("[DRVMGR SERIAL] Poller waits for incoming message (%d bytes are required)!\n", ts);
71
     n = read (po_hi_c_driver_rtems_drvmgr_serial_fd_read[dev_id], ptr, ts);
72 73

     __PO_HI_DEBUG_DEBUG ("[DRVMGR SERIAL] read() %d returns %d!\n",
74
                          po_hi_c_driver_rtems_drvmgr_serial_fd_read[dev_id], n);
75 76 77 78 79 80 81 82 83 84
     if (n == -1) {
       __PO_HI_DEBUG_DEBUG ("[DRVMGR SERIAL] Cannot read on socket !\n");
       return;
     } else {
       ptr += n;
       ts -= n;
     }
   }

   __po_hi_c_driver_rtems_drvmgr_serial_poller_msg.length = __PO_HI_MESSAGES_MAX_SIZE;
85

86 87
   __po_hi_unmarshall_request (&__po_hi_c_driver_rtems_drvmgr_serial_request,
                               &__po_hi_c_driver_rtems_drvmgr_serial_poller_msg);
88

89 90
   if (__po_hi_c_driver_rtems_drvmgr_serial_request.port > __PO_HI_NB_PORTS) {
     __PO_HI_DEBUG_DEBUG ("[DRVMGR SERIAL] Invalid port number (%d), will not deliver",
91
                          __po_hi_c_driver_rtems_drvmgr_serial_request.port);
92 93 94 95 96 97 98 99 100 101 102
   }
   __po_hi_main_deliver (&__po_hi_c_driver_rtems_drvmgr_serial_request);
}

__po_hi_msg_t           __po_hi_c_driver_rtems_drvmgr_serial_sender_msg;

/*!
 * \fn int __po_hi_c_driver_rtems_drvmgr_serial_sender (const __po_hi_task_id task_id, const __po_hi_port_t port)
 * \brief Function related to the RTEMS DRVMGR SERIAL serial driver - sender function.
 *
 * This function implements the sender function to send bytes through the serial line using
103
 * the RTEMS DRVMGR SERIAL device.
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
 * There are the description of the arguments used by the function:
 *   - task_id: task that actually sends the data (emitter/producer task)
 *   - port   : (global) port that contains the data
 * It returns the following possible values :
 *   - __PO_HI_UNAVAILABLE : the driver does not handle the device connected to argument port.
 *   - __PO_HI_SUCCESS     : either no value was available to be sent or the function
 *                           send the message successfully over the network.
 */
int __po_hi_c_driver_rtems_drvmgr_serial_sender (const __po_hi_task_id task_id, const __po_hi_port_t port)
{
   int                     n;
   int                     ts;
   __po_hi_local_port_t    local_port;
   __po_hi_request_t*      request;
   __po_hi_port_t          destination_port;
   __po_hi_device_id       dev_id;

   dev_id = __po_hi_get_device_from_port (port);

   if (dev_id == invalid_device_id) {
     __PO_HI_DEBUG_DEBUG ("[DRVMGR SERIAL] Invalid device id for sending\n");
     return __PO_HI_UNAVAILABLE;
   }

   local_port = __po_hi_get_local_port_from_global_port (port);
129

130
   request = __po_hi_gqueue_get_most_recent_value (task_id, local_port);
131

132 133 134
   if (request->port == -1)
     {
       __PO_HI_DEBUG_DEBUG
135 136
         ("[DRVMGR SERIAL] Send output task %d, port %d (local_port=%d): no value to send\n",
          task_id, port, local_port);
137 138 139 140
      return __PO_HI_SUCCESS;
   }

   destination_port     = __po_hi_gqueue_get_destination (task_id, local_port, 0);
141
   __po_hi_mutex_lock (&__po_hi_c_rtems_serial_send_mutex);
142 143 144 145 146 147 148 149 150
   __po_hi_msg_reallocate (&__po_hi_c_driver_rtems_drvmgr_serial_sender_msg);

   request->port = destination_port;
   __po_hi_marshall_request (request, &__po_hi_c_driver_rtems_drvmgr_serial_sender_msg);

   __PO_HI_DEBUG_DEBUG
     ("[DRVMGR SERIAL] Destination port= %d, msg size %d send through device %d (fd=%d)\n",
      destination_port,
      __po_hi_c_driver_rtems_drvmgr_serial_sender_msg.length,
151 152
      dev_id, po_hi_c_driver_rtems_drvmgr_serial_fd_write[dev_id]);

153
   n = write (po_hi_c_driver_rtems_drvmgr_serial_fd_write[dev_id],
154 155 156
              &__po_hi_c_driver_rtems_drvmgr_serial_sender_msg,
              __PO_HI_MESSAGES_MAX_SIZE);

157
   __PO_HI_DEBUG_DEBUG ("[DRVMGR SERIAL] write() returns %d\n", n);
158
   __po_hi_mutex_unlock (&__po_hi_c_rtems_serial_send_mutex);
159 160 161 162 163 164 165 166 167 168 169
   request->port = __PO_HI_GQUEUE_INVALID_PORT;

   return 1;
}

/*!
 * \fn void __po_hi_c_driver_rtems_drvmgr_serial_init (__po_hi_device_id id)
 * \brief Initialization function for the RTEMS DRVMGR SERIAL serial driver.
 *
 * This function  is used to initialize the device driver connected to the
 * serial interface to a RTEMS DRVMGR SERIAL board. It uses the configuration properties
170
 * from its associated configuration parameters (using the
171 172 173 174 175 176 177 178 179 180 181 182 183
 * __po_hi_get_device_configuration function).
 */

void __po_hi_c_driver_rtems_drvmgr_serial_init (__po_hi_device_id id)
{
   uint32_t max_size;
   struct termios             oldtio,newtio;

   __po_hi_c_serial_conf_t* serialconf;

   /* Initializes drvmgr subsystem */

   __po_hi_c_driver_drvmgr_init ();
184

185 186 187 188 189 190
   serialconf = (__po_hi_c_serial_conf_t*)__po_hi_get_device_configuration (id);

   if (serialconf == NULL) {
     __PO_HI_DEBUG_INFO ("[DRVMGR SERIAL] Cannot get the name of the device !\n");
     return;
   }
191
   __po_hi_mutex_init (&__po_hi_c_rtems_serial_send_mutex,__PO_HI_MUTEX_REGULAR, 0);
192
   __po_hi_transport_set_sending_func (id, __po_hi_c_driver_rtems_drvmgr_serial_sender);
193

194 195 196
   /* provide the spacewire driver with AMBA Plug&Play
    * info so that it can find the GRSPW cores.
    */
197

198
   __PO_HI_DEBUG_INFO ("[DRVMGR SERIAL] Initialization starts !\n");
199 200

   po_hi_c_driver_rtems_drvmgr_serial_fd_write[id] =
201
     po_hi_c_driver_rtems_drvmgr_serial_fd_read[id] = open (serialconf->devname, O_RDWR);
202

203 204
   if (po_hi_c_driver_rtems_drvmgr_serial_fd_read[id] < 0) {
     __PO_HI_DEBUG_CRITICAL ("[DRVMGR SERIAL] Error while opening device %s for reading\n",
205
                             serialconf->devname);
206 207 208
   }
   if (po_hi_c_driver_rtems_drvmgr_serial_fd_write[id] < 0) {
     __PO_HI_DEBUG_CRITICAL ("[DRVMGR SERIAL] Error while opening device %s for writing\n",
209
                             serialconf->devname);
210
   }
211

212
   __PO_HI_DEBUG_DEBUG ("[DRVMGR SERIAL] Device opened for read (%s), fd=%d\n",
213
                        serialconf->devname , po_hi_c_driver_rtems_drvmgr_serial_fd_read[id]);
214
   __PO_HI_DEBUG_DEBUG ("[DRVMGR SERIAL] Device opened for write (%s), fd=%d\n",
215
                        serialconf->devname , po_hi_c_driver_rtems_drvmgr_serial_fd_write[id]);
216 217 218

   tcgetattr (po_hi_c_driver_rtems_drvmgr_serial_fd_read[id], &oldtio);  /* save current serial port settings */
   tcgetattr (po_hi_c_driver_rtems_drvmgr_serial_fd_read[id], &newtio);  /* save current serial port settings */
219

220 221 222 223 224 225 226 227 228 229 230 231
   newtio.c_cflag |= CREAD ;
   newtio.c_iflag = IGNPAR | IGNBRK;
   newtio.c_lflag |= ICANON;
   newtio.c_cc[VMIN]=1;
   newtio.c_cc[VTIME]=0;

   switch (__po_hi_c_driver_serial_common_get_speed (id))
     {
     case __PO_HI_DRIVER_SERIAL_COMMON_SPEED_19200:
       newtio.c_cflag |= B19200;
       __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] Set speed to 19200\n");
       break;
232

233 234 235 236
     case __PO_HI_DRIVER_SERIAL_COMMON_SPEED_38400:
       newtio.c_cflag |= B38400;
       __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] Set speed to 38400\n");
       break;
237

238 239 240 241
     case __PO_HI_DRIVER_SERIAL_COMMON_SPEED_57600:
       newtio.c_cflag |= B57600;
       __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] Set speed to 57600\n");
       break;
242

243 244 245 246
     case __PO_HI_DRIVER_SERIAL_COMMON_SPEED_115200:
       __PO_HI_DEBUG_DEBUG ("[LINUX SERIAL] Set speed to 115200\n");
       newtio.c_cflag |= B115200;
       break;
247

248
      case __PO_HI_DRIVER_SERIAL_COMMON_SPEED_UNKNWON:
249 250
        __PO_HI_DEBUG_INFO ("[LINUX SERIAL] Unknwon speed for the serial line\n");
        break;
251
     }
252
   cfmakeraw (&newtio);
253

254 255 256 257 258 259 260 261
   max_size = 1024;
#ifdef __PO_HI_MESSAGES_MAX_SIZE
   max_size = 4 * __PO_HI_MESSAGES_MAX_SIZE;
#endif

  if (tcflush (po_hi_c_driver_rtems_drvmgr_serial_fd_read[id], TCIOFLUSH) != 0) {
    __PO_HI_DEBUG_DEBUG ("[DRVMGR SERIAL] Error when trying to flush read part\n");
  }
262

263 264 265
  if (tcflush (po_hi_c_driver_rtems_drvmgr_serial_fd_write[id], TCIOFLUSH) != 0) {
    __PO_HI_DEBUG_DEBUG ("[DRVMGR SERIAL] Error when trying to flush write part\n");
  }
266

267 268
  __PO_HI_DEBUG_DEBUG ("[DRVMGR SERIAL] Initialization complete !\n");
}