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

yoogx's avatar
yoogx committed
253
254
   cfmakeraw (&newtio);

255
256
257
258
259
260
261
262
   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");
  }
263

264
265
266
  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");
  }
267

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