Line data Source code
1 : /********************************************************************************
2 : * Copyright (c) 2024 Accenture
3 : *
4 : * This program and the accompanying materials are made available under the
5 : * terms of the Apache License Version 2.0 which is available at
6 : * https://www.apache.org/licenses/LICENSE-2.0
7 : *
8 : * SPDX-License-Identifier: Apache-2.0
9 : ********************************************************************************/
10 :
11 : /**
12 : * Contains class AbstractCANTransceiver.
13 : * \file AbstractCANTransceiver.h
14 : * \ingroup transceiver
15 : */
16 : #pragma once
17 :
18 : #include "can/canframes/CANFrame.h"
19 : #include "can/framemgmt/AbstractBitFieldFilteredCANFrameListener.h"
20 : #include "can/framemgmt/AbstractIntervalFilteredCANFrameListener.h"
21 : #include "can/framemgmt/IFilteredCANFrameSentListener.h"
22 : #include "can/transceiver/ICANTransceiverStateListener.h"
23 : #include "can/transceiver/ICanTransceiver.h"
24 :
25 : #include <etl/intrusive_forward_list.h>
26 : #include <etl/intrusive_list.h>
27 :
28 : #include <platform/estdint.h>
29 :
30 : namespace can
31 : {
32 : class ICANFrameSentListener;
33 : class IFilteredCANFrameSentListener;
34 : class FrameDispatcher;
35 : class CanTransportLayer;
36 :
37 : /**
38 : * Cpp2CAN AbstractCANTransceiver
39 : * \class AbstractCANTransceiver
40 : *
41 : *
42 : * An AbstractCANTransceiver is the common hardware independent base class for
43 : * CAN Transceiver classes. This base implementation or the ICanTransceiver interface
44 : * shall be used in all applications to avoid HW dependencies.
45 : *
46 : * This abstract class implements the HW independent methods.
47 : *
48 : * \section Reception
49 : * An implementation of AbstractCANTransceiver has to fill a CANFrame object
50 : * with the data of the received can frame and then call
51 : * notifyListeners() with the received CANFrame which distributes it to all
52 : * listeners, i.e. to all listeners whose filter match the id of fRxFrame.
53 : *
54 : */
55 : class AbstractCANTransceiver : public ICanTransceiver
56 : {
57 : public:
58 : /**
59 : * constructor
60 : * \param busId busId of MultiChannelCanTransceiver
61 : * \post getState() == CLOSED
62 : */
63 : explicit AbstractCANTransceiver(uint8_t busId);
64 :
65 : /**
66 : * \return internal state of transceiver
67 : * \see State
68 : */
69 : State getState() const override;
70 :
71 : /**
72 : * adds an ICANFrameListener to listener list
73 : * \param canFrameListener listener to register
74 : *
75 : * This method contains a critical section and uses Suspend-/ResumeOSInterrupts.
76 : *
77 : * \attention
78 : * The filter of canFrameListener is merged into the transceivers rx-filter.
79 : * It must be configured before adding the listener!
80 : */
81 : void addCANFrameListener(ICANFrameListener& listener) override;
82 :
83 : /**
84 : * Adds a listener to the front of the receiver list.
85 : * \see addCANFrameListener
86 : * Using this method makes sure that the added listener is notified first
87 : * of a incoming CANFrame.
88 : */
89 : void addVIPCANFrameListener(ICANFrameListener& listener) override;
90 :
91 : /**
92 : * removes an ICANFrameListener from listener list
93 : * \param canFrameListener listener to remove
94 : *
95 : * This method contains a critical section and uses Suspend-/ResumeOSInterrupts.
96 : *
97 : * \note
98 : * The elements of canFrameListeners filter will not be removed from
99 : * the transceivers rx-filter.
100 : */
101 : void removeCANFrameListener(ICANFrameListener& listener) override;
102 :
103 : /**
104 : * adds an addCANFrameSentListener to listener list
105 : * \param listener listener to register
106 : *
107 : * This method contains a critical section and uses Suspend-/ResumeOSInterrupts.
108 : *
109 : * \attention
110 : * The filter of listener is merged into the transceivers rx-filter.
111 : * It must be configured before adding the listener!
112 : */
113 : void addCANFrameSentListener(IFilteredCANFrameSentListener& listener) override;
114 :
115 : /**
116 : * removes an ICANFrameListener from listener list
117 : * \param listener listener to remove
118 : *
119 : * This method contains a critical section and uses Suspend-/ResumeOSInterrupts.
120 : *
121 : * \note
122 : * The elements of listener filter will not be removed from
123 : * the transceivers rx-filter.
124 : */
125 : void removeCANFrameSentListener(IFilteredCANFrameSentListener& listener) override;
126 :
127 : /**
128 : * \return busId of transceiver
129 : */
130 1 : uint8_t getBusId() const override { return _busId; }
131 :
132 : /**
133 : * Get the hardware state of the CAN transceiver.
134 : * \return state hardware state of the CAN transceiver
135 : */
136 1 : ICANTransceiverStateListener::CANTransceiverState getCANTransceiverState() const override
137 : {
138 1 : return _transceiverState;
139 : }
140 :
141 : /**
142 : * Sets the transceivers ICANTransceiverStateListener.
143 : * \param pListener ICANTransceiverStateListener to notify when an error
144 : * occurs. 0L if no class needs to be notified.
145 : */
146 1 : void setStateListener(ICANTransceiverStateListener& listener) override
147 : {
148 1 : _stateListener = &listener;
149 1 : }
150 :
151 1 : void removeStateListener() override { _stateListener = nullptr; }
152 :
153 : protected:
154 : void setState(State newState);
155 :
156 : bool isInState(State state) const;
157 :
158 : /**
159 : * Notifies all appropriate listeners about the reception of a CANFrame.
160 : * \param frame CANFrame that will be passed to all listeners
161 : */
162 : void notifyListeners(CANFrame const& frame);
163 :
164 : void notifySentListeners(can::CANFrame const& frame);
165 :
166 : /**
167 : * Notifies the attached ICANTransceiverStateListener that a phy error occurred
168 : */
169 3 : void notifyStateListenerWithPhyError()
170 : {
171 3 : if (_stateListener != nullptr)
172 : {
173 1 : _stateListener->phyErrorOccurred(*this);
174 : }
175 3 : }
176 :
177 : /**
178 : * Notifies the attached ICANTransceiverStateListener with a given
179 : * state
180 : * \param state new can transceiver state.
181 : */
182 : void notifyStateListenerWithState(ICANTransceiverStateListener::CANTransceiverState state);
183 :
184 : protected:
185 : BitFieldFilter _filter;
186 : ::etl::intrusive_list<ICANFrameListener, ::etl::bidirectional_link<0>> _listeners;
187 : IFilteredCANFrameSentListener* _sentListener;
188 : ::etl::intrusive_forward_list<IFilteredCANFrameSentListener, ::etl::forward_link<0>>
189 : _sentListeners;
190 : /** baudrate of transceiver */
191 : uint32_t _baudrate;
192 : /** internal State */
193 : State _state;
194 : uint8_t _busId;
195 : ICANTransceiverStateListener* _stateListener;
196 : ICANTransceiverStateListener::CANTransceiverState _transceiverState;
197 : };
198 :
199 6 : inline ICanTransceiver::State AbstractCANTransceiver::getState() const { return _state; }
200 :
201 2 : inline void AbstractCANTransceiver::setState(ICanTransceiver::State const newState)
202 : {
203 2 : _state = newState;
204 2 : }
205 :
206 2 : inline bool AbstractCANTransceiver::isInState(ICanTransceiver::State const state) const
207 : {
208 2 : return (_state == state);
209 : }
210 :
211 6 : inline void AbstractCANTransceiver::notifyStateListenerWithState(
212 : ICANTransceiverStateListener::CANTransceiverState const state)
213 : {
214 6 : if (_stateListener != nullptr)
215 : {
216 1 : _stateListener->canTransceiverStateChanged(*this, state);
217 : }
218 6 : }
219 :
220 : } // namespace can
|