]> rtime.felk.cvut.cz Git - frescor/fna.git/blob - src_frescan/frescan_hw_buffer.c
add a test to obtain measures of a round trip
[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  * See MaRTE OS license
23  *
24  */
25
26 #include "frescan_hw_buffer.h"
27
28 #include <string.h> // memcpy
29
30 #include "frescan_data.h"    // the_networks
31 #include "frescan_debug.h"   // DEBUG, ERROR
32 #include "frescan_servers.h" // frescan_servers_get_highest_prio
33 #include "frescan_queues.h"  // frescan_pqueue_xxx, frescan_servers_dequeue
34 #include "frescan_id.h"      // frescan_id_set_field
35
36 /**
37  * frescan_hw_buffer_abort - abort the packet in the hw tx buffer
38  *
39  * This function aborts the packet that is currently in the hw transmission
40  * buffer of the chip. It is useful to prevent priority inversion when there
41  * is another packet with highest priority waiting in the frescan queues.
42  *
43  * TODO: implement it
44  */
45
46 int frescan_hw_buffer_abort(frescan_network_t net)
47 {
48 //         int ret;
49 //
50 //         ret = ioctl(the_networks[net].fd,
51 //                     CAN_IOCTL_ABORT_FRAME, NULL);
52 //         if (ret == -1) {
53 //                 ERROR ("could not abort the frame\n");
54 //                 return -1;
55 //         }
56         ERROR ("NOT IMPLEMENTED\n");
57         return -1;
58 }
59
60 /**
61  * frescan_hw_buffer_update - update the hw tx buffer
62  *
63  * This function updates the hw tx buffer with the packet with highest
64  * priority (including fp packets and server packets).
65  *
66  * TODO: use copy of pointer
67  */
68
69 int frescan_hw_buffer_update(frescan_network_t net)
70 {
71         int ret;
72         bool is_frame_in_chip, is_fp_highest_prio;
73         uint32_t frag_flag;
74         frescan_packet_t *packet;
75         frescan_prio_queue_t *pqueue;
76         frescan_prio_t fprio, sprio, prio;
77         frescan_ss_t id;
78
79         ret = frescan_servers_get_highest_prio(net, &id, &sprio);
80         if (ret != 0) return ret;
81
82         pqueue = the_networks[net].queues.tx_fp_queue;
83
84         ret = frescan_pqueue_get_highest_prio(pqueue, &packet, &fprio);
85         if (ret != 0) return ret;
86
87         if ((id == FRESCAN_MX_IDS) && (packet == NULL)) {
88                 DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG, "(ss:0 fp:0)\n");
89                 return 0;
90         }
91
92         if ((id != FRESCAN_MX_IDS) && (packet == NULL)) {
93                 DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG, "(ss:1 fp:0)\n");
94                 is_fp_highest_prio = false;
95         }
96
97         if ((id == FRESCAN_MX_IDS) && (packet != NULL)) {
98                 DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG, "(ss:0 fp:1)\n");
99                 is_fp_highest_prio = true;
100         }
101
102         if ((id != FRESCAN_MX_IDS) && (packet != NULL)) {
103                 DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG, "(ss:1 fp:1)\n");
104                 is_fp_highest_prio = (fprio > sprio);
105         }
106
107         prio = (is_fp_highest_prio) ? fprio : sprio;
108         is_frame_in_chip = (the_networks[net].last_packet != NULL);
109
110         if (is_frame_in_chip &&
111            (prio > the_networks[net].last_packet_prio)) {
112                 DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG,"abort frame\n");
113                 ret = frescan_hw_buffer_abort(net);
114                 if (ret != 0) {
115                         ERROR ("could not abort frame\n");
116                         return ret;
117                 }
118                 return 0;
119         }
120
121         if (is_fp_highest_prio) {
122                 ret = frescan_pqueue_dequeue(pqueue, &packet, &prio, 0);
123                 if (ret != 0) return ret;
124         } else {
125                 ret = frescan_servers_dequeue(net, id, &packet, &prio);
126                 if (ret != 0) return ret;
127
128                 frescan_id_set_field(&packet->frame->id,
129                                       FRESCAN_FIELD_PRIO,
130                                       (uint32_t)prio);
131         }
132
133         if (packet->buffer_pending_bytes > 8) {
134                 packet->frame->dlc = 8;
135         } else {
136                 packet->frame->dlc = packet->buffer_pending_bytes;
137         }
138
139         memcpy(packet->frame->data,
140                packet->buffer_read_pointer,
141                packet->frame->dlc);
142
143         packet->buffer_pending_bytes -= packet->frame->dlc;
144         packet->buffer_read_pointer  += packet->frame->dlc;
145
146         frag_flag = (packet->buffer_pending_bytes > 0) ? 1 : 0;
147         frescan_id_set_field
148                         (&packet->frame->id, FRESCAN_FIELD_FRAG_FLAG, frag_flag);
149
150         the_networks[net].last_packet = packet;
151         the_networks[net].last_packet_prio = prio;
152
153         DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG,
154               "frame->id:0x%X pend_bytes:%u dlc:%u fflag:%u\n",
155               packet->frame->id,
156               packet->buffer_pending_bytes,
157               packet->frame->dlc,
158               frag_flag);
159
160         ret = write(the_networks[net].fd,
161                     (void *)packet->frame,
162                     sizeof(struct can_frame_t));
163
164         if (ret != sizeof(struct can_frame_t)) {
165                 ERROR ("could not send frame\n");
166                 return ret;
167         }
168
169         return 0;
170 }