]> rtime.felk.cvut.cz Git - frescor/fna.git/blob - src_frescan/frescan_hw_buffer.c
BUG corrected: when sending two packets one after the other very fast, the second...
[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 - 2008 FRESCOR consortium partners:
24  *
25  *    Universidad de Cantabria,              SPAIN
26  *    University of York,                    UK
27  *    Scuola Superiore Sant'Anna,            ITALY
28  *    Kaiserslautern University,             GERMANY
29  *    Univ. Politécnica  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 for a link to partners' websites
38  *
39  *           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  *  This file is part of FRESCAN
45  *
46  *  FRESCAN is free software; you can  redistribute it and/or  modify
47  *  it under the terms of  the GNU General Public License as published by
48  *  the Free Software Foundation;  either  version 2, or (at  your option)
49  *  any later version.
50  *
51  *  FRESCAN  is distributed  in  the hope  that  it  will  be useful,  but
52  *  WITHOUT  ANY  WARRANTY;     without  even the   implied   warranty  of
53  *  MERCHANTABILITY  or  FITNESS FOR  A  PARTICULAR PURPOSE. See  the  GNU
54  *  General Public License for more details.
55  *
56  *  You should have  received a  copy of  the  GNU  General Public License
57  *  distributed  with  FRESCAN;  see file COPYING.   If not,  write to the
58  *  Free Software  Foundation,  59 Temple Place  -  Suite 330,  Boston, MA
59  *  02111-1307, USA.
60  *
61  * As a special exception, including FRESCAN header files in a file,
62  * instantiating FRESCAN generics or templates, or linking other files
63  * with FRESCAN objects to produce an executable application, does not
64  * by itself cause the resulting executable application to be covered
65  * by the GNU General Public License. This exception does not
66  * however invalidate any other reasons why the executable file might be
67  * covered by the GNU Public License.
68  * -----------------------------------------------------------------------
69  *
70  */
71
72 #include "frescan_hw_buffer.h"
73
74 #include <string.h> // memcpy
75 #include <assert.h>
76
77 #include "frescan_data.h"    // frescan_data
78 #include "frescan_debug.h"   // DEBUG, FRESCAN_ERROR
79 #include "frescan_servers.h" // frescan_servers_get_highest_prio
80 #include "frescan_queues.h"  // frescan_pqueue_xxx, frescan_servers_dequeue
81 #include "frescan_id.h"      // frescan_id_set_field
82
83 /**
84  * frescan_hw_buffer_abort - abort the packet in the hw tx buffer
85  *
86  * This function aborts the packet that is currently in the hw transmission
87  * buffer of the chip. It is useful to prevent priority inversion when there
88  * is another packet with highest priority waiting in the frescan queues.
89  *
90  * NOTE: if the frame is already being transmitted it won't abort it. In both
91  * cases a IRQ will be raised and either 'frescan_hook_frame_sent' or
92  * 'frescan_hook_frame_aborted' will be called.
93  */
94
95 int frescan_hw_buffer_abort(frescan_network_t net)
96 {
97         int ret;
98
99         ret = ioctl(frescan_data[net].fd, CAN_IOCTL_ABORT_FRAME, NULL);
100         if (ret == -1) {
101                 FRESCAN_ERROR ("could not abort the frame\n");
102                 return -1;
103         }
104
105         return 0;
106 }
107
108 /**
109  * frescan_hw_buffer_update - update the hw tx buffer
110  *
111  * This function updates the hw tx buffer with the packet with highest
112  * priority (including fp packets and server packets).
113  *
114  * TODO: use copy of pointer
115  */
116
117 int frescan_hw_buffer_update(frescan_network_t net)
118 {
119         int ret;
120         bool is_frame_in_chip, is_fp_highest_prio;
121         uint32_t frag_flag;
122         frescan_packet_t *packet;
123         frescan_prio_queue_t *pqueue;
124         frescan_prio_t fprio, sprio, prio;
125         frescan_ss_t id;
126
127         ret = frescan_servers_get_highest_prio(net, &id, &sprio);
128         assert(ret == 0);
129
130         pqueue = frescan_data[net].queues.tx_fp_queue;
131
132         ret = frescan_pqueue_get_highest_prio(pqueue, &packet, &fprio);
133         assert(ret == 0);
134
135         if ((id == FRESCAN_MX_IDS) && (packet == NULL)) {
136                 DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG, "(ss:0 fp:0)\n");
137                 return 0;
138         }
139
140         if ((id != FRESCAN_MX_IDS) && (packet == NULL)) {
141                 DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG, "(ss:1 fp:0)\n");
142                 is_fp_highest_prio = false;
143         }
144
145         if ((id == FRESCAN_MX_IDS) && (packet != NULL)) {
146                 DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG, "(ss:0 fp:1)\n");
147                 is_fp_highest_prio = true;
148         }
149
150         if ((id != FRESCAN_MX_IDS) && (packet != NULL)) {
151                 DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG, "(ss:1 fp:1)\n");
152                 is_fp_highest_prio = (fprio > sprio);
153         }
154
155         prio = (is_fp_highest_prio) ? fprio : sprio;
156         is_frame_in_chip = (frescan_data[net].last_packet != NULL);
157
158         if (is_frame_in_chip) {
159                 if (prio > frescan_data[net].last_packet_prio) {
160                         // TODO: if same server, dont abort
161                         DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG, "abort frame\n");
162                         ret = frescan_hw_buffer_abort(net);
163                         assert(ret == 0);
164                         return 0;
165                 } else {
166                         DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG,
167                               "frame in chip with highest or equal prio\n");
168                         return 0;
169                 }
170         }
171
172         if (is_fp_highest_prio) {
173                 ret = frescan_pqueue_dequeue(pqueue, &packet, &prio, 0);
174                 assert(ret == 0);
175         } else {
176                 ret = frescan_servers_dequeue(net, id, &packet, &prio);
177                 assert(ret == 0);
178
179                 frescan_id_set_field(&packet->frame->id,
180                                       FRESCAN_FIELD_PRIO,
181                                       (uint32_t)prio);
182         }
183
184         if (packet->buffer_pending_bytes > 8) {
185                 packet->frame->dlc = 8;
186         } else {
187                 packet->frame->dlc = packet->buffer_pending_bytes;
188         }
189
190         memcpy(packet->frame->data,
191                packet->buffer_read_pointer,
192                packet->frame->dlc);
193
194         packet->buffer_pending_bytes -= packet->frame->dlc;
195         packet->buffer_read_pointer  += packet->frame->dlc;
196
197         frag_flag = (packet->buffer_pending_bytes > 0) ? 1 : 0;
198         frescan_id_set_field
199                         (&packet->frame->id, FRESCAN_FIELD_FRAG_FLAG, frag_flag);
200
201         frescan_data[net].last_packet = packet;
202         frescan_data[net].last_packet_prio = prio;
203
204         DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG,
205               "frame->id:0x%X pend_bytes:%u dlc:%u fflag:%u\n",
206               packet->frame->id,
207               packet->buffer_pending_bytes,
208               packet->frame->dlc,
209               frag_flag);
210
211         ret = write(frescan_data[net].fd,
212                     (void *)packet->frame,
213                     sizeof(struct can_frame_t));
214
215         if (ret != sizeof(struct can_frame_t)) {
216                 FRESCAN_ERROR ("could not send frame\n");
217                 return ret;
218         }
219
220         return 0;
221 }