Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
common/Can.cxx
Go to the documentation of this file.
1
34#include <cstdint>
35#include <algorithm>
36#include <fcntl.h>
37#include "Devtab.hxx"
38#include "Can.hxx"
39#include "can_frame.h"
40
41unsigned Can::numReceivedPackets_{0};
42unsigned Can::numTransmittedPackets_{0};
43
47{
48 txBuf->flush();
49 rxBuf->flush();
50}
51
58ssize_t Can::read(File *file, void *buf, size_t count)
59{
60 HASSERT((count % sizeof(struct can_frame)) == 0);
61
62 struct can_frame *data = (struct can_frame*)buf;
63 ssize_t result = 0;
64
65 count /= sizeof(struct can_frame);
66
67 while (count)
68 {
69 portENTER_CRITICAL();
70 /* We limit the amount of bytes we read with each iteration in order
71 * to limit the amount of time that interrupts are disabled and
72 * preserve our real-time performance.
73 */
74 size_t frames_read = rxBuf->get(data, count < 8 ? count : 8);
75 portEXIT_CRITICAL();
76
77 if (frames_read == 0)
78 {
79 /* no more data to receive */
80 if ((file->flags & O_NONBLOCK) || result > 0)
81 {
82 break;
83 }
84 else
85 {
86 /* wait for data to come in */
87 rxBuf->block_until_condition(file, true);
88 }
89 }
90
91 count -= frames_read;
92 result += frames_read;
93 data += frames_read;
94 }
95
96 if (!result && (file->flags & O_NONBLOCK))
97 {
98 return -EAGAIN;
99 }
100
101 return result * sizeof(struct can_frame);
102}
103
110ssize_t Can::write(File *file, const void *buf, size_t count)
111{
112 HASSERT((count % sizeof(struct can_frame)) == 0);
113
114 const struct can_frame *data = (const struct can_frame*)buf;
115 ssize_t result = 0;
116
117 count /= sizeof(struct can_frame);
118
119 while (count)
120 {
121 portENTER_CRITICAL();
122 /* We limit the amount of bytes we write with each iteration in order
123 * to limit the amount of time that interrupts are disabled and
124 * preserve our real-time performance.
125 */
126 size_t frames_written = txBuf->put(data, count < 8 ? count : 8);
127
128 if (frames_written == 0)
129 {
130 portEXIT_CRITICAL();
131 /* no more data to receive */
132 if ((file->flags & O_NONBLOCK) || result > 0)
133 {
134 break;
135 }
136 else
137 {
138 /* wait for space to be available, this call will release the
139 * critical section lock.
140 */
141 txBuf->block_until_condition(file, false);
142 }
143 }
144 else
145 {
146 tx_msg();
147 portEXIT_CRITICAL();
148 result += frames_written;
149 count -= frames_written;
150 data += frames_written;
151 }
152 }
153
154 if (!result && (file->flags & O_NONBLOCK))
155 {
156 return -EAGAIN;
157 }
158
159 return result * sizeof(struct can_frame);
160}
161
168bool Can::select(File* file, int mode)
169{
170 portENTER_CRITICAL();
171 bool retval = false;
172 switch (mode)
173 {
174 case FREAD:
175 if (rxBuf->pending() > 0)
176 {
177 retval = true;
178 }
179 else
180 {
182 }
183 break;
184 case FWRITE:
185 if (txBuf->space() > 0)
186 {
187 retval = true;
188 }
189 else
190 {
192 }
193 break;
194 default:
195 case 0:
196 /* we don't support any exceptions */
197 break;
198 }
199 portEXIT_CRITICAL();
200
201 return retval;
202}
DeviceBuffer< struct can_frame > * txBuf
transmit buffer
int read(struct can_frame *frame)
Read a frame if there is one available.
void flush_buffers() OVERRIDE
called after disable
DeviceBuffer< struct can_frame > * rxBuf
receive buffer
virtual void tx_msg()=0
function to try and transmit a message
bool select(File *file, int mode) OVERRIDE
Device select method.
int write(const struct can_frame *frame)
Send a frame if there is space available.
void flush()
flush all the data out of the buffer and reset the buffer.
size_t space()
Return the number of items for which space is available.
size_t pending()
Return the number of items in the queue.
void select_insert()
Add client to list of clients needing woken.
size_t get(T *buf, size_t items)
remove a number of items from the buffer.
size_t put(const T *buf, size_t items)
Insert a number of items to the buffer.
#define FWRITE
Workaround for missing header defines on some newlib versions.
Definition fcntl.h:58
#define FREAD
Workaround for missing header defines on some newlib versions.
Definition fcntl.h:53
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
Definition macros.h:138
File information.
Definition Devtab.hxx:52
int flags
open flags
Definition Devtab.hxx:63