]> rtime.felk.cvut.cz Git - frescor/fna.git/blob - src_frescan/frescan_hw_buffer.c
Unified header for FNA
[frescor/fna.git] / src_frescan / frescan_hw_buffer.c
1 /*!
2  * @file frescan_hw_buffer.c
3  *
4  * @brief functions to manage the hw transmission buffer
5  *
6  * @version 0.01
7  *
8  * @date 12-Mar-2008
9  *
10  * @author
11  *      Daniel Sangorrin
12  *
13  * @comments
14  *
15  * This file contains the functions needed to manage the hw transmission buffer.
16  * This is needed to update the transmission buffer of the CAN chip with the
17  * message with highest priority. This could involve having to abort the
18  * frame that is currently in the buffer.
19  *
20  * @license
21  *
22 //----------------------------------------------------------------------
23 //  Copyright (C) 2006 - 2009 by the FRESCOR consortium:
24 //
25 //    Universidad de Cantabria,              SPAIN
26 //    University of York,                    UK
27 //    Scuola Superiore Sant'Anna,            ITALY
28 //    Kaiserslautern University,             GERMANY
29 //    Univ. Politecnica  Valencia,           SPAIN
30 //    Czech Technical University in Prague,  CZECH REPUBLIC
31 //    ENEA                                   SWEDEN
32 //    Thales Communication S.A.              FRANCE
33 //    Visual Tools S.A.                      SPAIN
34 //    Rapita Systems Ltd                     UK
35 //    Evidence                               ITALY
36 //
37 //    See http://www.frescor.org
38 //
39 //        The FRESCOR project (FP6/2005/IST/5-034026) is funded
40 //        in part by the European Union Sixth Framework Programme
41 //        The European Union is not liable of any use that may be
42 //        made of this code.
43 //
44 //
45 //  based on previous work (FSF) done in the FIRST project
46 //
47 //   Copyright (C) 2005  Mälardalen University, SWEDEN
48 //                       Scuola Superiore S.Anna, ITALY
49 //                       Universidad de Cantabria, SPAIN
50 //                       University of York, UK
51 //
52 // This file is part of FNA (Frescor Network Adaptation)
53 //
54 // FNA is free software; you can redistribute it and/or modify it
55 // under terms of the GNU General Public License as published by the
56 // Free Software Foundation; either version 2, or (at your option) any
57 // later version.  FNA is distributed in the hope that it will be
58 // useful, but WITHOUT ANY WARRANTY; without even the implied warranty
59 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
60 // General Public License for more details. You should have received a
61 // copy of the GNU General Public License along with FNA; see file
62 // COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,
63 // Cambridge, MA 02139, USA.
64 //
65 // As a special exception, including FNA header files in a file,
66 // instantiating FNA generics or templates, or linking other files
67 // with FNA objects to produce an executable application, does not
68 // by itself cause the resulting executable application to be covered
69 // by the GNU General Public License. This exception does not
70 // however invalidate any other reasons why the executable file might be
71 // covered by the GNU Public License.
72 // -----------------------------------------------------------------------
73  *
74  */
75
76 #include "frescan_hw_buffer.h"
77
78 #include <string.h> // memcpy
79 #include <assert.h>
80
81 #include "frescan_data.h"    // frescan_data
82 #include "frescan_debug.h"   // DEBUG, FRESCAN_ERROR
83 #include "frescan_servers.h" // frescan_servers_get_highest_prio
84 #include "frescan_queues.h"  // frescan_pqueue_xxx, frescan_servers_dequeue
85 #include "frescan_id.h"      // frescan_id_set_field
86
87 /**
88  * frescan_hw_buffer_abort - abort the packet in the hw tx buffer
89  *
90  * This function aborts the packet that is currently in the hw transmission
91  * buffer of the chip. It is useful to prevent priority inversion when there
92  * is another packet with highest priority waiting in the frescan queues.
93  *
94  * NOTE: if the frame is already being transmitted it won't abort it. In both
95  * cases a IRQ will be raised and either 'frescan_hook_frame_sent' or
96  * 'frescan_hook_frame_aborted' will be called.
97  */
98
99 int frescan_hw_buffer_abort(frescan_network_t net)
100 {
101         int ret;
102
103         ret = ioctl(frescan_data[net].fd, CAN_IOCTL_ABORT_FRAME, NULL);
104         if (ret == -1) {
105                 FRESCAN_ERROR ("could not abort the frame\n");
106                 return -1;
107         }
108
109         return 0;
110 }
111
112 /**
113  * frescan_hw_buffer_update - update the hw tx buffer
114  *
115  * This function updates the hw tx buffer with the packet with highest
116  * priority (including fp packets and server packets).
117  *
118  * TODO: use copy of pointer
119  */
120
121 int frescan_hw_buffer_update(frescan_network_t net)
122 {
123         int ret;
124         bool is_frame_in_chip, is_fp_highest_prio;
125         uint32_t frag_flag;
126         frescan_packet_t *packet;
127         frescan_prio_queue_t *pqueue;
128         frescan_prio_t fprio, sprio, prio;
129         frescan_ss_t id;
130
131         ret = frescan_servers_get_highest_prio(net, &id, &sprio);
132         assert(ret == 0);
133
134         pqueue = frescan_data[net].queues.tx_fp_queue;
135
136         ret = frescan_pqueue_get_highest_prio(pqueue, &packet, &fprio);
137         assert(ret == 0);
138
139         if ((id == FRESCAN_MX_IDS) && (packet == NULL)) {
140                 DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG, "(ss:0 fp:0)\n");
141                 return 0;
142         }
143
144         if ((id != FRESCAN_MX_IDS) && (packet == NULL)) {
145                 DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG, "(ss:1 fp:0)\n");
146                 is_fp_highest_prio = false;
147         }
148
149         if ((id == FRESCAN_MX_IDS) && (packet != NULL)) {
150                 DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG, "(ss:0 fp:1)\n");
151                 is_fp_highest_prio = true;
152         }
153
154         if ((id != FRESCAN_MX_IDS) && (packet != NULL)) {
155                 DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG, "(ss:1 fp:1)\n");
156                 is_fp_highest_prio = (fprio > sprio);
157         }
158
159         prio = (is_fp_highest_prio) ? fprio : sprio;
160         is_frame_in_chip = (frescan_data[net].last_packet != NULL);
161
162         if (is_frame_in_chip) {
163                 if (prio > frescan_data[net].last_packet_prio) {
164                         // TODO: if same server, dont abort
165                         DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG, "abort frame\n");
166                         ret = frescan_hw_buffer_abort(net);
167                         assert(ret == 0);
168                         return 0;
169                 } else {
170                         DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG,
171                               "frame in chip with highest or equal prio\n");
172                         return 0;
173                 }
174         }
175
176         if (is_fp_highest_prio) {
177                 ret = frescan_pqueue_dequeue(pqueue, &packet, &prio, 0);
178                 assert(ret == 0);
179         } else {
180                 ret = frescan_servers_dequeue(net, id, &packet, &prio);
181                 assert(ret == 0);
182
183                 frescan_id_set_field(&packet->frame->id,
184                                       FRESCAN_FIELD_PRIO,
185                                       (uint32_t)prio);
186         }
187
188         if (packet->buffer_pending_bytes > 8) {
189                 packet->frame->dlc = 8;
190         } else {
191                 packet->frame->dlc = packet->buffer_pending_bytes;
192         }
193
194         memcpy(packet->frame->data,
195                packet->buffer_read_pointer,
196                packet->frame->dlc);
197
198         packet->buffer_pending_bytes -= packet->frame->dlc;
199         packet->buffer_read_pointer  += packet->frame->dlc;
200
201         frag_flag = (packet->buffer_pending_bytes > 0) ? 1 : 0;
202         frescan_id_set_field
203                         (&packet->frame->id, FRESCAN_FIELD_FRAG_FLAG, frag_flag);
204
205         frescan_data[net].last_packet = packet;
206         frescan_data[net].last_packet_prio = prio;
207
208         DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG,
209               "frame->id:0x%X pend_bytes:%u dlc:%u fflag:%u\n",
210               packet->frame->id,
211               packet->buffer_pending_bytes,
212               packet->frame->dlc,
213               frag_flag);
214
215         ret = write(frescan_data[net].fd,
216                     (void *)packet->frame,
217                     sizeof(struct can_frame_t));
218
219         if (ret != sizeof(struct can_frame_t)) {
220                 FRESCAN_ERROR ("could not send frame\n");
221                 return ret;
222         }
223
224         return 0;
225 }