po_hi_driver_rasta_serial.c 10.2 KB
Newer Older
1
2
3
4
5
/*
 * 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.
 *
6
7
8
9
10
11
12
13
14
15
16
 * Copyright (C) 2010-2011, European Space Agency
 */

/*! \file po_hi_driver_rasta_serial.c
 *  \brief Driver that interface PolyORB-HI-C and the serial interface of RASTA boards using the RTEMS 4.8 driver.
 *
 *  This driver works ONLY with the RTEMS 4.8 version that was available on GAISLER website
 *  on April 2010. This version is available at:
 *    - http://download.tuxfamily.org/taste/tools/rtems-4.8-gaisler.tgz
 *  However, please note that it is no longer supported by GAISLER and contains
 *  other bugs (such as the serial driver for the LEON that does not work).
17
18
 */

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

22
#ifdef __PO_HI_NEED_DRIVER_SERIAL_RASTA
23

24
#include <activity.h>
25
26
#include <marshallers.h>

27
#include <po_hi_debug.h>
28
29
30
#include <po_hi_transport.h>
#include <po_hi_gqueue.h>
#include <po_hi_messages.h>
31
#include <po_hi_returns.h>
32
#include <po_hi_utils.h>
33
#include <drivers/po_hi_rtems_utils.h>
34
#include <drivers/po_hi_driver_rasta_serial.h>
35
#include <drivers/po_hi_driver_rasta_common.h>
36

37
38
#include <drivers/po_hi_driver_serial_common.h>

39
40
41
42
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
julien.delange's avatar
julien.delange committed
43
#include <termios.h>
44
45
/* POSIX-style files */

46
47
48
49
50
#include <pci.h>
#include <rasta.h>
#include <apbuart_rasta.h>
/* Rasta includes from GAISLER drivers */

51
#include <drivers/configuration/serial.h>
52

53
54
55
int po_hi_c_driver_rasta_serial_fd_read[__PO_HI_NB_DEVICES];
int po_hi_c_driver_rasta_serial_fd_write[__PO_HI_NB_DEVICES];

56

57
58
59
60
61
62
63
64
65
66
/*!
 * \fn void __po_hi_c_driver_serial_rasta_poller (const __po_hi_device_id dev_id)
 * \brief Polling function for the RASTA.
 *
 * This function is the poller for the serial interface of the RASTA 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).
 */
67

68
void __po_hi_c_driver_serial_rasta_poller (const __po_hi_device_id dev_id)
69
{
70
71
72
   int                  n;
   int                  ts;
   uint8_t*             ptr;
jdelange's avatar
jdelange committed
73
74
   __po_hi_request_t    request;
   __po_hi_msg_t        msg;
75

julien.delange's avatar
julien.delange committed
76
   ts = __PO_HI_MESSAGES_MAX_SIZE;
jdelange's avatar
jdelange committed
77
78
   ptr = &(msg.content[0]);
   __po_hi_msg_reallocate (&msg);
julien.delange's avatar
julien.delange committed
79
   while (ts > 0)
80
   {
81
      __PO_HI_DEBUG_DEBUG ("[RASTA SERIAL] Poller waits for incoming message (%d bytes are required)!\n", ts);
82
      n = read (po_hi_c_driver_rasta_serial_fd_read[dev_id], ptr, ts); 
julien.delange's avatar
julien.delange committed
83

84
      __PO_HI_DEBUG_DEBUG ("[RASTA SERIAL] read() %d returns %d!\n", po_hi_c_driver_rasta_serial_fd_read[dev_id], n);
julien.delange's avatar
julien.delange committed
85
86
      if (n == -1)
      {
87
         __PO_HI_DEBUG_DEBUG ("[RASTA SERIAL] Cannot read on socket !\n");
julien.delange's avatar
julien.delange committed
88
89
         return;
      }
90
91
92
93
94
      else
      {
         ptr += n;
         ts -= n;
      }
95
96
   }

jdelange's avatar
jdelange committed
97
   msg.length = __PO_HI_MESSAGES_MAX_SIZE;
98

jdelange's avatar
jdelange committed
99
100
   __po_hi_unmarshall_request (&request,
                               &msg);
101

jdelange's avatar
jdelange committed
102
103
104
105
106
   if (request.port > __PO_HI_NB_PORTS)
   {
      __PO_HI_DEBUG_DEBUG ("[RASTA SERIAL] Invalid port number (%d), will not deliver", request.port);
   }
   __po_hi_main_deliver (&request);
107
108
}

109
110
111
extern amba_confarea_type* __po_hi_driver_rasta_common_get_bus ();
void __po_hi_rasta_interrrupt_register(void *handler, int irqno, void *arg);

112
113
114
115
116
117
118
119
120
121
/*!
 * \fn void __po_hi_c_driver_serial_rasta_init (__po_hi_device_id id)
 * \brief Initialization function for the RASTA serial driver.
 *
 * This function  is used to initialize the device driver connected to the
 * serial interface to a RASTA board. It uses the configuration properties
 * from its associated configuration parameters (using the 
 * __po_hi_get_device_configuration function).
 */

122
void __po_hi_c_driver_serial_rasta_init (__po_hi_device_id id)
123
{
124
125
   __po_hi_c_serial_conf_t* serialconf;

126
   __po_hi_c_driver_rasta_common_init ();
127

128
   serialconf = (__po_hi_c_serial_conf_t*)__po_hi_get_device_configuration (id);
129

130
   if (serialconf == NULL)
131
132
133
134
135
   {
      __PO_HI_DEBUG_INFO ("[RASTA SERIAL] Cannot get the name of the device !\n");
      return;
   }

136
137
138
139
    /* provide the spacewire driver with AMBA Plug&Play
     * info so that it can find the GRSPW cores.
     */

140
   __PO_HI_DEBUG_INFO ("[RASTA SERIAL] Initialization starts !\n");
141

142
143
   po_hi_c_driver_rasta_serial_fd_write[id] = 
   po_hi_c_driver_rasta_serial_fd_read[id] = open (serialconf->devname, O_RDWR);
144
145
146
   /*
   po_hi_c_driver_rasta_serial_fd_write = open (serialconf->devname, O_WRONLY);
   */
147

148
   if (po_hi_c_driver_rasta_serial_fd_read[id] < 0)
149
   {
150
      __PO_HI_DEBUG_CRITICAL ("[RASTA SERIAL] Error while opening device %s for reading\n", serialconf->devname);
151
   }
152
   if (po_hi_c_driver_rasta_serial_fd_write[id] < 0)
153
154
155
156
   {
      __PO_HI_DEBUG_CRITICAL ("[RASTA SERIAL] Error while opening device %s for writing\n", serialconf->devname);
   }

157
158
   __PO_HI_DEBUG_DEBUG ("[RASTA SERIAL] Device opened for read (%s), fd=%d\n", serialconf->devname , po_hi_c_driver_rasta_serial_fd_read[id]);
   __PO_HI_DEBUG_DEBUG ("[RASTA SERIAL] Device opened for write (%s), fd=%d\n", serialconf->devname , po_hi_c_driver_rasta_serial_fd_write[id]);
159

160
161
162
   switch (__po_hi_c_driver_serial_common_get_speed (id))
   {
      case __PO_HI_DRIVER_SERIAL_COMMON_SPEED_19200:
163
164
         __PO_HI_DRIVERS_RTEMS_UTILS_IOCTL(po_hi_c_driver_rasta_serial_fd_read[id], APBUART_SET_BAUDRATE, 19200);
         __PO_HI_DRIVERS_RTEMS_UTILS_IOCTL(po_hi_c_driver_rasta_serial_fd_write[id], APBUART_SET_BAUDRATE, 19200);
165
166
167
         break;

      case __PO_HI_DRIVER_SERIAL_COMMON_SPEED_38400:
168
169
         __PO_HI_DRIVERS_RTEMS_UTILS_IOCTL(po_hi_c_driver_rasta_serial_fd_read[id], APBUART_SET_BAUDRATE, 38400);
         __PO_HI_DRIVERS_RTEMS_UTILS_IOCTL(po_hi_c_driver_rasta_serial_fd_write[id], APBUART_SET_BAUDRATE, 38400);
170
171
172
         break;

      case __PO_HI_DRIVER_SERIAL_COMMON_SPEED_57600:
173
174
         __PO_HI_DRIVERS_RTEMS_UTILS_IOCTL(po_hi_c_driver_rasta_serial_fd_read[id], APBUART_SET_BAUDRATE, 57600);
         __PO_HI_DRIVERS_RTEMS_UTILS_IOCTL(po_hi_c_driver_rasta_serial_fd_write[id], APBUART_SET_BAUDRATE, 57600);
175
176
177
         break;

      case __PO_HI_DRIVER_SERIAL_COMMON_SPEED_115200:
178
179
         __PO_HI_DRIVERS_RTEMS_UTILS_IOCTL(po_hi_c_driver_rasta_serial_fd_read[id], APBUART_SET_BAUDRATE, 115200);
         __PO_HI_DRIVERS_RTEMS_UTILS_IOCTL(po_hi_c_driver_rasta_serial_fd_write[id], APBUART_SET_BAUDRATE, 115200);
180
181
182
183
184
185
186
         break;

      case __PO_HI_DRIVER_SERIAL_COMMON_SPEED_UNKNWON:
         __PO_HI_DEBUG_INFO ("[RASTA SERIAL] Unknwon speed for the serial line\n");
         break;
   }

187
   /*
188
  __PO_HI_DRIVERS_RTEMS_UTILS_IOCTL(po_hi_c_driver_rasta_serial_fd, APBUART_SET_BLOCKING, APBUART_BLK_RX | APBUART_BLK_TX | APBUART_BLK_FLUSH);
189
190
  __PO_HI_DRIVERS_RTEMS_UTILS_IOCTL(po_hi_c_driver_rasta_serial_fd, APBUART_SET_BLOCKING, APBUART_BLK_FLUSH | APBUART_BLK_RX);
  */
191
192
193
194
195
196
  __PO_HI_DRIVERS_RTEMS_UTILS_IOCTL(po_hi_c_driver_rasta_serial_fd_read[id], APBUART_SET_BLOCKING, APBUART_BLK_FLUSH | APBUART_BLK_TX );
  __PO_HI_DRIVERS_RTEMS_UTILS_IOCTL(po_hi_c_driver_rasta_serial_fd_read[id], APBUART_SET_TXFIFO_LEN, 256);  /* Transmitt buffer 64 chars */
  __PO_HI_DRIVERS_RTEMS_UTILS_IOCTL(po_hi_c_driver_rasta_serial_fd_read[id], APBUART_SET_RXFIFO_LEN, 256); /* Receive buffer 256 chars */
  __PO_HI_DRIVERS_RTEMS_UTILS_IOCTL(po_hi_c_driver_rasta_serial_fd_read[id], APBUART_SET_ASCII_MODE, 0); /* Make \n go \n\r or \r\n */
  __PO_HI_DRIVERS_RTEMS_UTILS_IOCTL(po_hi_c_driver_rasta_serial_fd_read[id], APBUART_CLR_STATS, 0);
  __PO_HI_DRIVERS_RTEMS_UTILS_IOCTL(po_hi_c_driver_rasta_serial_fd_read[id], APBUART_START, 0);
julien.delange's avatar
julien.delange committed
197

198

199
  if (tcflush (po_hi_c_driver_rasta_serial_fd_read[id], TCIOFLUSH) != 0)
200
201
202
203
  {
     __PO_HI_DEBUG_DEBUG ("[RASTA SERIAL] Error when trying to flush read part\n");
  }

204
  if (tcflush (po_hi_c_driver_rasta_serial_fd_write[id], TCIOFLUSH) != 0)
julien.delange's avatar
julien.delange committed
205
  {
206
     __PO_HI_DEBUG_DEBUG ("[RASTA SERIAL] Error when trying to flush write part\n");
julien.delange's avatar
julien.delange committed
207
  }
208
209

  __PO_HI_DEBUG_DEBUG ("[RASTA SERIAL] Initialization complete !\n");
210
211
}

212
213
214
215
216
217
218
219
220
221
222
223
224
225
/*!
 * \fn int __po_hi_c_driver_serial_rasta_sender (const __po_hi_task_id task_id, const __po_hi_port_t port)
 * \brief Function related to the RASTA serial driver - sender function.
 *
 * This function implements the sender function to send bytes through the serial line using
 * the RASTA device. 
 * 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.
 */
226
227
int __po_hi_c_driver_serial_rasta_sender (const __po_hi_task_id task_id, const __po_hi_port_t port)
{
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
   int                     n;
   int                     ts;
   __po_hi_local_port_t    local_port;
   __po_hi_request_t*      request;
   __po_hi_msg_t           msg;
   __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 ("[RASTA SERIAL] Invalid device id for sending\n");
      return __PO_HI_UNAVAILABLE;
   }
243
244
245
246
247

   local_port = __po_hi_get_local_port_from_global_port (port);

   request = __po_hi_gqueue_get_most_recent_value (task_id, local_port);

248
249
250
251
252
253
   if (request->port == -1)
   {
      __PO_HI_DEBUG_DEBUG ("[RASTA SERIAL] Send output task %d, port %d (local_port=%d): no value to send\n", task_id, port, local_port);
      return __PO_HI_SUCCESS;
   }

254
255
256
257
258
   destination_port     = __po_hi_gqueue_get_destination (task_id, local_port, 0);

   __po_hi_msg_reallocate (&msg);

   request->port = destination_port;
jdelange's avatar
jdelange committed
259
   __PO_HI_DEBUG_DEBUG ("[RASTA SERIAL] Destination port= %d, send through device %d (fd=%d)\n", destination_port, dev_id, po_hi_c_driver_rasta_serial_fd_write[dev_id]);
260
261
262

   __po_hi_marshall_request (request, &msg);

263
   n = write (po_hi_c_driver_rasta_serial_fd_write[dev_id], &msg, __PO_HI_MESSAGES_MAX_SIZE);
264

265
   __PO_HI_DEBUG_DEBUG ("[RASTA SERIAL] write() returns %d\n", n);
266
267
268

   request->port = __PO_HI_GQUEUE_INVALID_PORT;

269
270
271
   return 1;
}

272
273
#endif