1 /**
2  * CAN driver functions.
3  *
4  * Defines functions that must be implemented for each target.
5  *
6  * @file        CO_driver.h
7  * @ingroup     CO_driver
8  * @author      Janez Paternoster
9  * @copyright   2004 - 2020 Janez Paternoster
10  *
11  * This file is part of CANopenNode, an opensource CANopen Stack.
12  * Project home page is <https://github.com/CANopenNode/CANopenNode>.
13  * For more information on CANopen see <http://www.can-cia.org/>.
14  *
15  * Licensed under the Apache License, Version 2.0 (the "License");
16  * you may not use this file except in compliance with the License.
17  * You may obtain a copy of the License at
18  *
19  *     http://www.apache.org/licenses/LICENSE-2.0
20  *
21  * Unless required by applicable law or agreed to in writing, software
22  * distributed under the License is distributed on an "AS IS" BASIS,
23  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24  * See the License for the specific language governing permissions and
25  * limitations under the License.
26  */
27 
28 #ifndef CO_DRIVER_H
29 #define CO_DRIVER_H
30 
31 #ifdef __cplusplus
32 extern "C" {
33 #endif /* __cplusplus */
34 
35 #include "CO_driver_target.h"
36 #include "CO_types.h"
37 
38 /* Include processor header file */
39 #include <stdint.h>         /* for 'int8_t' to 'uint64_t' */
40 
41 /**
42  * @defgroup CO_driver Driver
43  * @ingroup CO_CANopen
44  * @{
45  *
46  * Microcontroller specific code for CANopenNode.
47  *
48  * This file contains type definitions, functions and macros for:
49  *  - Basic data types.
50  *  - Receive and transmit buffers for CANopen messages.
51  *  - Interaction with CAN module on the microcontroller.
52  *  - CAN receive and transmit interrupts.
53  *
54  * This file is not only a CAN driver. There are no classic CAN queues for CAN
55  * messages. This file provides direct connection with other CANopen
56  * objects. It tries to provide fast responses and tries to avoid unnecessary
57  * calculations and memory consumptions.
58  *
59  * CO_CANmodule_t contains an array of _Received message objects_ (of type
60  * CO_CANrx_t) and an array of _Transmit message objects_ (of type CO_CANtx_t).
61  * Each CANopen communication object owns one member in one of the arrays.
62  * For example Heartbeat producer generates one CANopen transmitting object,
63  * so it has reserved one member in CO_CANtx_t array.
64  * SYNC module may produce sync or consume sync, so it has reserved one member
65  * in CO_CANtx_t and one member in CO_CANrx_t array.
66  *
67  * ###Reception of CAN messages.
68  * Before CAN messages can be received, each member in CO_CANrx_t must be
69  * initialized. CO_CANrxBufferInit() is called by CANopen module, which
70  * uses specific member. For example @ref CO_HBconsumer uses multiple members
71  * in CO_CANrx_t array. (It monitors multiple heartbeat messages from remote
72  * nodes.) It must call CO_CANrxBufferInit() multiple times.
73  *
74  * Main arguments to the CO_CANrxBufferInit() function are CAN identifier
75  * and a pointer to callback function. Those two arguments (and some others)
76  * are copied to the member of the CO_CANrx_t array.
77  *
78  * Callback function is a function, specified by specific CANopen module
79  * (for example by @ref CO_HBconsumer). Each CANopen module defines own
80  * callback function. Callback function will process the received CAN message.
81  * It will copy the necessary data from CAN message to proper place. It may
82  * also trigger additional task, which will further process the received message.
83  * Callback function must be fast and must only make the necessary calculations
84  * and copying.
85  *
86  * Received CAN messages are processed by CAN receive interrupt function.
87  * After CAN message is received, function first tries to find matching CAN
88  * identifier from CO_CANrx_t array. If found, then a corresponding callback
89  * function is called.
90  *
91  * Callback function accepts two parameters:
92  *  - object is pointer to object registered by CO_CANrxBufferInit().
93  *  - msg  is pointer to CAN message of type CO_CANrxMsg_t.
94  *
95  * Callback function must return #CO_ReturnError_t: CO_ERROR_NO,
96  * CO_ERROR_RX_OVERFLOW, CO_ERROR_RX_PDO_OVERFLOW, CO_ERROR_RX_MSG_LENGTH or
97  * CO_ERROR_RX_PDO_LENGTH.
98  *
99  *
100  * ###Transmission of CAN messages.
101  * Before CAN messages can be transmitted, each member in CO_CANtx_t must be
102  * initialized. CO_CANtxBufferInit() is called by CANopen module, which
103  * uses specific member. For example Heartbeat producer must initialize it's
104  * member in CO_CANtx_t array.
105  *
106  * CO_CANtxBufferInit() returns a pointer of type CO_CANtx_t, which contains buffer
107  * where CAN message data can be written. CAN message is send with calling
108  * CO_CANsend() function. If at that moment CAN transmit buffer inside
109  * microcontroller's CAN module is free, message is copied directly to CAN module.
110  * Otherwise CO_CANsend() function sets _bufferFull_ flag to true. Message will be
111  * then sent by CAN TX interrupt as soon as CAN module is freed. Until message is
112  * not copied to CAN module, its contents must not change. There may be multiple
113  * _bufferFull_ flags in CO_CANtx_t array set to true. In that case messages with
114  * lower index inside array will be sent first.
115  */
116 
117 /**
118  * Request CAN configuration (stopped) mode and *wait* untill it is set.
119  *
120  * @param CANdriverState User-provided CAN module structure.
121  */
122 void CO_CANsetConfigurationMode(void *CANdriverState);
123 
124 
125 /**
126  * Request CAN normal (opearational) mode and *wait* untill it is set.
127  *
128  * @param CANmodule This object.
129  */
130 void CO_CANsetNormalMode(CO_CANmodule_t *CANmodule);
131 
132 
133 /**
134  * Initialize CAN module object.
135  *
136  * Function must be called in the communication reset section. CAN module must
137  * be in Configuration Mode before.
138  *
139  * @param CANmodule This object will be initialized.
140  * @param CANdriverState User-provided CAN module structure..
141  * @param rxArray Array for handling received CAN messages
142  * @param rxSize Size of the above array. Must be equal to number of receiving CAN objects.
143  * @param txArray Array for handling transmitting CAN messages
144  * @param txSize Size of the above array. Must be equal to number of transmitting CAN objects.
145  * @param CANbitRate Valid values are (in kbps): 10, 20, 50, 125, 250, 500, 800, 1000.
146  * If value is illegal, bitrate defaults to 125.
147  *
148  * Return #CO_ReturnError_t: CO_ERROR_NO or CO_ERROR_ILLEGAL_ARGUMENT.
149  */
150 CO_ReturnError_t CO_CANmodule_init(
151         CO_CANmodule_t         *CANmodule,
152         void                   *CANdriverState,
153         CO_CANrx_t              rxArray[],
154         uint16_t                rxSize,
155         CO_CANtx_t              txArray[],
156         uint16_t                txSize,
157         uint16_t                CANbitRate);
158 
159 
160 /**
161  * Switch off CANmodule. Call at program exit.
162  *
163  * @param CANmodule CAN module object.
164  */
165 void CO_CANmodule_disable(CO_CANmodule_t *CANmodule);
166 
167 
168 /**
169  * Read CAN identifier from received message
170  *
171  * @param rxMsg Pointer to received message
172  * @return 11-bit CAN standard identifier.
173  */
174 uint16_t CO_CANrxMsg_readIdent(const CO_CANrxMsg_t *rxMsg);
175 
176 
177 /**
178  * Configure CAN message receive buffer.
179  *
180  * Function configures specific CAN receive buffer. It sets CAN identifier
181  * and connects buffer with specific object. Function must be called for each
182  * member in _rxArray_ from CO_CANmodule_t.
183  *
184  * @param CANmodule This object.
185  * @param index Index of the specific buffer in _rxArray_.
186  * @param ident 11-bit standard CAN Identifier.
187  * @param mask 11-bit mask for identifier. Most usually set to 0x7FF.
188  * Received message (rcvMsg) will be accepted if the following
189  * condition is true: (((rcvMsgId ^ ident) & mask) == 0).
190  * @param rtr If true, 'Remote Transmit Request' messages will be accepted.
191  * @param object CANopen object, to which buffer is connected. It will be used as
192  * an argument to pFunct. Its type is (void), pFunct will change its
193  * type back to the correct object type.
194  * @param pFunct Pointer to function, which will be called, if received CAN
195  * message matches the identifier. It must be fast function.
196  *
197  * Return #CO_ReturnError_t: CO_ERROR_NO CO_ERROR_ILLEGAL_ARGUMENT or
198  * CO_ERROR_OUT_OF_MEMORY (not enough masks for configuration).
199  */
200 CO_ReturnError_t CO_CANrxBufferInit(
201         CO_CANmodule_t         *CANmodule,
202         uint16_t                index,
203         uint16_t                ident,
204         uint16_t                mask,
205         bool_t                  rtr,
206         void                   *object,
207         void                  (*pFunct)(void *object, const CO_CANrxMsg_t *message));
208 
209 
210 /**
211  * Configure CAN message transmit buffer.
212  *
213  * Function configures specific CAN transmit buffer. Function must be called for
214  * each member in _txArray_ from CO_CANmodule_t.
215  *
216  * @param CANmodule This object.
217  * @param index Index of the specific buffer in _txArray_.
218  * @param ident 11-bit standard CAN Identifier.
219  * @param rtr If true, 'Remote Transmit Request' messages will be transmitted.
220  * @param noOfBytes Length of CAN message in bytes (0 to 8 bytes).
221  * @param syncFlag This flag bit is used for synchronous TPDO messages. If it is set,
222  * message will not be sent, if curent time is outside synchronous window.
223  *
224  * @return Pointer to CAN transmit message buffer. 8 bytes data array inside
225  * buffer should be written, before CO_CANsend() function is called.
226  * Zero is returned in case of wrong arguments.
227  */
228 CO_CANtx_t *CO_CANtxBufferInit(
229         CO_CANmodule_t         *CANmodule,
230         uint16_t                index,
231         uint16_t                ident,
232         bool_t                  rtr,
233         uint8_t                 noOfBytes,
234         bool_t                  syncFlag);
235 
236 
237 /**
238  * Send CAN message.
239  *
240  * @param CANmodule This object.
241  * @param buffer Pointer to transmit buffer, returned by CO_CANtxBufferInit().
242  * Data bytes must be written in buffer before function call.
243  *
244  * @return #CO_ReturnError_t: CO_ERROR_NO, CO_ERROR_TX_OVERFLOW or
245  * CO_ERROR_TX_PDO_WINDOW (Synchronous TPDO is outside window).
246  */
247 CO_ReturnError_t CO_CANsend(CO_CANmodule_t *CANmodule, CO_CANtx_t *buffer);
248 
249 
250 /**
251  * Clear all synchronous TPDOs from CAN module transmit buffers.
252  *
253  * CANopen allows synchronous PDO communication only inside time between SYNC
254  * message and SYNC Window. If time is outside this window, new synchronous PDOs
255  * must not be sent and all pending sync TPDOs, which may be on CAN TX buffers,
256  * must be cleared.
257  *
258  * This function checks (and aborts transmission if necessary) CAN TX buffers
259  * when it is called. Function should be called by the stack in the moment,
260  * when SYNC time was just passed out of synchronous window.
261  *
262  * @param CANmodule This object.
263  */
264 void CO_CANclearPendingSyncPDOs(CO_CANmodule_t *CANmodule);
265 
266 
267 /**
268  * Verify all errors of CAN module.
269  *
270  * Function is called directly from CO_EM_process() function.
271  *
272  * @param CANmodule This object.
273  */
274 void CO_CANverifyErrors(CO_CANmodule_t *CANmodule);
275 
276 #ifdef __cplusplus
277 }
278 #endif /* __cplusplus */
279 
280 /** @} */
281 #endif /* CO_DRIVER_H */
282