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 * See MaRTE OS license
26 #include "frescan_hw_buffer.h"
28 #include <string.h> // memcpy
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
37 * frescan_hw_buffer_abort - abort the packet in the hw tx buffer
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.
46 int frescan_hw_buffer_abort(frescan_network_t net)
50 // ret = ioctl(the_networks[net].fd,
51 // CAN_IOCTL_ABORT_FRAME, NULL);
53 // ERROR ("could not abort the frame\n");
56 ERROR ("NOT IMPLEMENTED\n");
61 * frescan_hw_buffer_update - update the hw tx buffer
63 * This function updates the hw tx buffer with the packet with highest
64 * priority (including fp packets and server packets).
66 * TODO: use copy of pointer
69 int frescan_hw_buffer_update(frescan_network_t net)
72 bool is_frame_in_chip, is_fp_highest_prio;
74 frescan_packet_t *packet;
75 frescan_prio_queue_t *pqueue;
76 frescan_prio_t fprio, sprio, prio;
79 ret = frescan_servers_get_highest_prio(net, &id, &sprio);
80 if (ret != 0) return ret;
82 pqueue = the_networks[net].queues.tx_fp_queue;
84 ret = frescan_pqueue_get_highest_prio(pqueue, &packet, &fprio);
85 if (ret != 0) return ret;
87 if ((id == FRESCAN_MX_IDS) && (packet == NULL)) {
88 DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG, "(ss:0 fp:0)\n");
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;
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;
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);
107 prio = (is_fp_highest_prio) ? fprio : sprio;
108 is_frame_in_chip = (the_networks[net].last_packet != NULL);
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);
115 ERROR ("could not abort frame\n");
121 if (is_fp_highest_prio) {
122 ret = frescan_pqueue_dequeue(pqueue, &packet, &prio, 0);
123 if (ret != 0) return ret;
125 ret = frescan_servers_dequeue(net, id, &packet, &prio);
126 if (ret != 0) return ret;
128 frescan_id_set_field(&packet->frame->id,
133 if (packet->buffer_pending_bytes > 8) {
134 packet->frame->dlc = 8;
136 packet->frame->dlc = packet->buffer_pending_bytes;
139 memcpy(packet->frame->data,
140 packet->buffer_read_pointer,
143 packet->buffer_pending_bytes -= packet->frame->dlc;
144 packet->buffer_read_pointer += packet->frame->dlc;
146 frag_flag = (packet->buffer_pending_bytes > 0) ? 1 : 0;
148 (&packet->frame->id, FRESCAN_FIELD_FRAG_FLAG, frag_flag);
150 the_networks[net].last_packet = packet;
151 the_networks[net].last_packet_prio = prio;
153 DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG,
154 "frame->id:0x%X pend_bytes:%u dlc:%u fflag:%u\n",
156 packet->buffer_pending_bytes,
160 ret = write(the_networks[net].fd,
161 (void *)packet->frame,
162 sizeof(struct can_frame_t));
164 if (ret != sizeof(struct can_frame_t)) {
165 ERROR ("could not send frame\n");