2 * @file frescan_hw_buffer.c
4 * @brief functions to manage the hw transmission buffer
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.
22 //----------------------------------------------------------------------
23 // Copyright (C) 2006 - 2009 by the FRESCOR consortium:
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
32 // Thales Communication S.A. FRANCE
33 // Visual Tools S.A. SPAIN
34 // Rapita Systems Ltd UK
37 // See http://www.frescor.org
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
45 // based on previous work (FSF) done in the FIRST project
47 // Copyright (C) 2005 Mälardalen University, SWEDEN
48 // Scuola Superiore S.Anna, ITALY
49 // Universidad de Cantabria, SPAIN
50 // University of York, UK
52 // This file is part of FNA (Frescor Network Adaptation)
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.
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 // -----------------------------------------------------------------------
76 #include "frescan_hw_buffer.h"
78 #include <string.h> // memcpy
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
88 * frescan_hw_buffer_abort - abort the packet in the hw tx buffer
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.
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.
99 int frescan_hw_buffer_abort(frescan_network_t net)
103 ret = ioctl(frescan_data[net].fd, CAN_IOCTL_ABORT_FRAME, NULL);
105 FRESCAN_ERROR ("could not abort the frame\n");
113 * frescan_hw_buffer_update - update the hw tx buffer
115 * This function updates the hw tx buffer with the packet with highest
116 * priority (including fp packets and server packets).
118 * TODO: use copy of pointer
121 int frescan_hw_buffer_update(frescan_network_t net)
124 bool is_frame_in_chip, is_fp_highest_prio;
126 frescan_packet_t *packet;
127 frescan_prio_queue_t *pqueue;
128 frescan_prio_t fprio, sprio, prio;
131 ret = frescan_servers_get_highest_prio(net, &id, &sprio);
134 pqueue = frescan_data[net].queues.tx_fp_queue;
136 ret = frescan_pqueue_get_highest_prio(pqueue, &packet, &fprio);
139 if ((id == FRESCAN_MX_IDS) && (packet == NULL)) {
140 DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG, "(ss:0 fp:0)\n");
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;
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;
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);
159 prio = (is_fp_highest_prio) ? fprio : sprio;
160 is_frame_in_chip = (frescan_data[net].last_packet != NULL);
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);
170 DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG,
171 "frame in chip with highest or equal prio\n");
176 if (is_fp_highest_prio) {
177 ret = frescan_pqueue_dequeue(pqueue, &packet, &prio, 0);
180 ret = frescan_servers_dequeue(net, id, &packet, &prio);
183 frescan_id_set_field(&packet->frame->id,
188 if (packet->buffer_pending_bytes > 8) {
189 packet->frame->dlc = 8;
191 packet->frame->dlc = packet->buffer_pending_bytes;
194 memcpy(packet->frame->data,
195 packet->buffer_read_pointer,
198 packet->buffer_pending_bytes -= packet->frame->dlc;
199 packet->buffer_read_pointer += packet->frame->dlc;
201 frag_flag = (packet->buffer_pending_bytes > 0) ? 1 : 0;
203 (&packet->frame->id, FRESCAN_FIELD_FRAG_FLAG, frag_flag);
205 frescan_data[net].last_packet = packet;
206 frescan_data[net].last_packet_prio = prio;
208 DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG,
209 "frame->id:0x%X pend_bytes:%u dlc:%u fflag:%u\n",
211 packet->buffer_pending_bytes,
215 ret = write(frescan_data[net].fd,
216 (void *)packet->frame,
217 sizeof(struct can_frame_t));
219 if (ret != sizeof(struct can_frame_t)) {
220 FRESCAN_ERROR ("could not send frame\n");