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.
43 * NOTE: if the frame is already being transmitted it won't abort it. In both
44 * cases a IRQ will be raised and either 'frescan_hook_frame_sent' or
45 * 'frescan_hook_frame_aborted' will be called.
48 int frescan_hw_buffer_abort(frescan_network_t net)
52 ret = ioctl(the_networks[net].fd, CAN_IOCTL_ABORT_FRAME, NULL);
54 ERROR ("could not abort the frame\n");
62 * frescan_hw_buffer_update - update the hw tx buffer
64 * This function updates the hw tx buffer with the packet with highest
65 * priority (including fp packets and server packets).
67 * TODO: use copy of pointer
70 int frescan_hw_buffer_update(frescan_network_t net)
73 bool is_frame_in_chip, is_fp_highest_prio;
75 frescan_packet_t *packet;
76 frescan_prio_queue_t *pqueue;
77 frescan_prio_t fprio, sprio, prio;
80 ret = frescan_servers_get_highest_prio(net, &id, &sprio);
81 if (ret != 0) return ret;
83 pqueue = the_networks[net].queues.tx_fp_queue;
85 ret = frescan_pqueue_get_highest_prio(pqueue, &packet, &fprio);
86 if (ret != 0) return ret;
88 if ((id == FRESCAN_MX_IDS) && (packet == NULL)) {
89 DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG, "(ss:0 fp:0)\n");
93 if ((id != FRESCAN_MX_IDS) && (packet == NULL)) {
94 DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG, "(ss:1 fp:0)\n");
95 is_fp_highest_prio = false;
98 if ((id == FRESCAN_MX_IDS) && (packet != NULL)) {
99 DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG, "(ss:0 fp:1)\n");
100 is_fp_highest_prio = true;
103 if ((id != FRESCAN_MX_IDS) && (packet != NULL)) {
104 DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG, "(ss:1 fp:1)\n");
105 is_fp_highest_prio = (fprio > sprio);
108 prio = (is_fp_highest_prio) ? fprio : sprio;
109 is_frame_in_chip = (the_networks[net].last_packet != NULL);
111 if (is_frame_in_chip &&
112 (prio > the_networks[net].last_packet_prio)) {
113 DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG,"abort frame\n");
114 ret = frescan_hw_buffer_abort(net);
116 ERROR ("could not abort frame\n");
122 if (is_fp_highest_prio) {
123 ret = frescan_pqueue_dequeue(pqueue, &packet, &prio, 0);
124 if (ret != 0) return ret;
126 ret = frescan_servers_dequeue(net, id, &packet, &prio);
127 if (ret != 0) return ret;
129 frescan_id_set_field(&packet->frame->id,
134 if (packet->buffer_pending_bytes > 8) {
135 packet->frame->dlc = 8;
137 packet->frame->dlc = packet->buffer_pending_bytes;
140 memcpy(packet->frame->data,
141 packet->buffer_read_pointer,
144 packet->buffer_pending_bytes -= packet->frame->dlc;
145 packet->buffer_read_pointer += packet->frame->dlc;
147 frag_flag = (packet->buffer_pending_bytes > 0) ? 1 : 0;
149 (&packet->frame->id, FRESCAN_FIELD_FRAG_FLAG, frag_flag);
151 the_networks[net].last_packet = packet;
152 the_networks[net].last_packet_prio = prio;
154 DEBUG(FRESCAN_HW_BUFFER_ENABLE_DEBUG,
155 "frame->id:0x%X pend_bytes:%u dlc:%u fflag:%u\n",
157 packet->buffer_pending_bytes,
161 ret = write(the_networks[net].fd,
162 (void *)packet->frame,
163 sizeof(struct can_frame_t));
165 if (ret != sizeof(struct can_frame_t)) {
166 ERROR ("could not send frame\n");