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