TEMU  2
The Terma Emulator
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
Can.h
Go to the documentation of this file.
1 //===------------------------------------------------------------*- C++ -*-===////
2 // T-EMU: The Terma Emulator
3 // (c) Terma 2016
4 // Authors: Mattias Holm <maho (at) terma.com>
5 //
6 //===----------------------------------------------------------------------===//
7 
8 #ifndef TEMU_CAN_H
9 #define TEMU_CAN_H
10 
11 /*
12  The CAN interface is EXPERIMENTAL AND UNSTABLE at present.
13 
14  The CAN bus model consist of two interfaces, firstly a CAN device
15  interface and secondly a CAN bus interface. In addition to these
16  interfaces a bus class is provided that does message routing and
17  some validation of device traffic. This bus class is needed as the
18  CAN (like the 1553) bus is a multi-node bus.
19 
20  The bus interface allows the user to implement their own bus models
21  if needed (e.g. to support connections to legacy models using
22  another device interface).
23 
24  The bundled bus models, allows for the enabling of send events,
25  i.e. an event being issued with whenever a transaction is on the
26  bus. This can be used to inject errors in messages if needed.
27  */
28 
29 #include "temu-c/Support/Objsys.h"
30 
31 #include <assert.h>
32 #include <stdbool.h>
33 #include <string.h>
34 #include <stdint.h>
35 
36 #ifdef __cplusplus
37 extern "C" {
38 #endif
39 
40 
41 // The flags field contain the frame header,
42 // it is constructed as follows:
43 // ACK : 1 / [31]
44 // RTR : 1 / [30]
45 // IDE : 1 / [29]
46 // Ident A: 11 / [28..18]
47 // Ident B: 18: [17..0]
48 // As can be seen, this does not fully reflect a CAN message, but
49 // the critical bits are there. Bits implied by the format are
50 // omitted.
51 // Also, the frame object does not contain CRCs, we do not need
52 // these in the bus model and CRC errors are instead modelled
53 // using the error field.
54 typedef struct {
55  uint8_t Data[8];
56  uint32_t Flags;
57  uint8_t Length;
58  uint8_t Error;
60 
61 static inline int
62 temu_canIsExtendedFrame(temu_CanFrame *Frame)
63 {
64  return (Frame->Flags >> 29) & 1;
65 }
66 static inline int
67 temu_canIsRemoteTransmissionRequest(temu_CanFrame *Frame)
68 {
69  return (Frame->Flags >> 30) & 1;
70 }
71 
72 // User model can call this to set the ack bit
73 static inline void
74 temu_canSetAck(temu_CanFrame *Frame)
75 {
76  Frame->Flags |= (1 << 31);
77 }
78 
79 static inline uint32_t
80 temu_canGetAck(temu_CanFrame *Frame)
81 {
82  return (Frame->Flags >> 31) & 1;
83 }
84 
85 
86 static inline uint32_t
87 temu_canGetIdent(temu_CanFrame *Frame)
88 {
89  if (temu_canIsExtendedFrame(Frame)) {
90  return Frame->Flags & 0x1fffffff;
91  } else {
92  return (Frame->Flags >> 18) & 0x7ff;
93  }
94 }
95 
96 static inline void
97 temu_canMakeBasicFrame(temu_CanFrame *Frame, uint32_t Ident, uint32_t RTR,
98  uint32_t Length, uint8_t *Data)
99 {
100  Frame->Flags = (Ident << 18) | (RTR << 30);
101  Frame->Length = (uint8_t)Length;
102 
103  if (Length && !RTR) {
104  memcpy(Frame->Data, Data, Length > 8 ? 8 : Length);
105  }
106 }
107 
108 static inline void
109 temu_canMakeExtFrame(temu_CanFrame *Frame, uint32_t Ident, uint32_t RTR,
110  uint32_t Length, uint8_t *Data)
111 {
112  Frame->Flags = Ident | (RTR << 30) | (1 << 29);
113  Frame->Length = (uint8_t)Length;
114 
115  if (Length && !RTR) {
116  memcpy(Frame->Data, Data, Length > 8 ? 8 : Length);
117  }
118 }
119 
120 static inline uint32_t
121 temu_canBitsForFrame(temu_CanFrame *Frame)
122 {
123  if (temu_canIsExtendedFrame(Frame)) {
124  uint32_t DataLen = (Frame->Length > 8 ? 8 : Frame->Length) * 8;
125  if (temu_canIsRemoteTransmissionRequest(Frame)) {
126  DataLen = 0;
127  }
128 
129  return 1 + 11 + 1 + 1 + 18 + 1 + 2 + 4 + 15 + 1 + 1 + 1 + 7 + DataLen;
130 
131  } else {
132  uint32_t DataLen = (Frame->Length > 8 ? 8 : Frame->Length) * 8;
133  if (temu_canIsRemoteTransmissionRequest(Frame)) {
134  DataLen = 0;
135  }
136  return 1 + 11 + 1 + 1 + 1 + 4 + 15 + 1 + 1 + 1 + 7 + DataLen;
137  }
138 }
139 
140 typedef struct {
141  uint64_t LastReportSentBits; // Number of bits sent during last report
142  uint64_t SentBits; // Current number of sent bits
144 
145 struct temu_CanDevIface;
147 struct temu_CanBusIface;
149 
150 #define TEMU_CAN_DEV_IFACE_TYPE "CanDevIface"
151 #define TEMU_CAN_BUS_IFACE_TYPE "CanBusIface"
152 
153 TEMU_IFACE_REFERENCE_TYPE(temu_CanDev);
154 TEMU_IFACE_REFERENCE_TYPE(temu_CanBus);
155 
157  void (*connected)(void *Dev, temu_CanBusIfaceRef Bus);
158  void (*disconnected)(void *Dev);
159  void (*receive)(void *Dev, temu_CanFrame *Frame);
160 };
161 
163  void (*connect)(void *Bus, temu_CanDevIfaceRef Dev);
164  void (*disconnect)(void *Bus, temu_CanDevIfaceRef Dev);
165 
166  void (*send)(void *Bus, void *Sender, temu_CanFrame *Frame);
167  void (*enableSendEvents)(void *Bus);
168  void (*disableSendEvents)(void *Bus);
169  void (*reportStats)(void *Bus);
170 
171  // High performance bus models can respond to setFilter to filter
172  // data based on the flags field. The use of a filtering bus model
173  // means that the filtered frames will be targeted at specific devices
174  // attached to the bus. Note that a device model should not assume that
175  // the bus model will filter. Infact, the default bundled bus model
176  // will simply broadcast the messages to all attached devices.
177  // In case the bus has a lot of devices, it may make sense to use
178  // a bus with routing based on filtering. For that reason a device
179  // can request the bus to filter based on a mask and a code, filtering
180  // is done by anding Frame->Flags with Mask and comparing with Code.
181  // Note that a device must still do its own filtering.
182  void (*setFilter)(void *Bus, temu_CanDevIfaceRef Dev, int FilterID,
183  uint32_t Mask, uint32_t Code);
184 };
185 
186 #ifdef __cplusplus
187 }
188 #endif
189 
190 #endif /* !TEMU_CAN_H */
void(* connect)(void *Bus, temu_CanDevIfaceRef Dev)
Definition: Can.h:163
void(* disconnected)(void *Dev)
Definition: Can.h:158
uint8_t Length
Definition: Can.h:57
#define TEMU_IFACE_REFERENCE_TYPE(N)
Definition: Objsys.h:129
uint64_t LastReportSentBits
Definition: Can.h:141
uint32_t Flags
Definition: Can.h:56
void(* reportStats)(void *Bus)
Definition: Can.h:169
uint8_t Data[8]
Definition: Can.h:55
void(* connected)(void *Dev, temu_CanBusIfaceRef Bus)
Definition: Can.h:157
void(* disableSendEvents)(void *Bus)
Definition: Can.h:168
uint64_t SentBits
Definition: Can.h:142
void(* send)(void *Bus, void *Sender, temu_CanFrame *Frame)
Definition: Can.h:166
void(* receive)(void *Dev, temu_CanFrame *Frame)
Definition: Can.h:159
uint8_t Error
Definition: Can.h:58
void(* enableSendEvents)(void *Bus)
Definition: Can.h:167
void(* disconnect)(void *Bus, temu_CanDevIfaceRef Dev)
Definition: Can.h:164
void(* setFilter)(void *Bus, temu_CanDevIfaceRef Dev, int FilterID, uint32_t Mask, uint32_t Code)
Definition: Can.h:182