• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #pragma once
16 
17 #ifdef __cplusplus
18 extern "C" {
19 #endif
20 
21 #include "soc/soc_caps.h"
22 #if SOC_TWAI_SUPPORTED
23 
24 #include "esp_osal/esp_osal.h"
25 #include "esp_types.h"
26 #include "esp_intr_alloc.h"
27 #include "esp_err.h"
28 #include "gpio.h"
29 #include "hal/twai_types.h"
30 
31 /* -------------------- Default initializers and flags ---------------------- */
32 /** @cond */    //Doxy command to hide preprocessor definitions from docs
33 /**
34  * @brief Initializer macro for general configuration structure.
35  *
36  * This initializer macros allows the TX GPIO, RX GPIO, and operating mode to be
37  * configured. The other members of the general configuration structure are
38  * assigned default values.
39  */
40 #define TWAI_GENERAL_CONFIG_DEFAULT(tx_io_num, rx_io_num, op_mode) {.mode = op_mode, .tx_io = tx_io_num, .rx_io = rx_io_num,        \
41                                                                     .clkout_io = TWAI_IO_UNUSED, .bus_off_io = TWAI_IO_UNUSED,      \
42                                                                     .tx_queue_len = 5, .rx_queue_len = 5,                           \
43                                                                     .alerts_enabled = TWAI_ALERT_NONE,  .clkout_divider = 0,        \
44                                                                     .intr_flags = ESP_INTR_FLAG_LEVEL1}
45 
46 /**
47  * @brief   Alert flags
48  *
49  * The following flags represents the various kind of alerts available in
50  * the TWAI driver. These flags can be used when configuring/reconfiguring
51  * alerts, or when calling twai_read_alerts().
52  *
53  * @note    The TWAI_ALERT_AND_LOG flag is not an actual alert, but will configure
54  *          the TWAI driver to log to UART when an enabled alert occurs.
55  */
56 #define TWAI_ALERT_TX_IDLE                  0x00000001  /**< Alert(1): No more messages to transmit */
57 #define TWAI_ALERT_TX_SUCCESS               0x00000002  /**< Alert(2): The previous transmission was successful */
58 #define TWAI_ALERT_BELOW_ERR_WARN           0x00000004  /**< Alert(4): Both error counters have dropped below error warning limit */
59 #define TWAI_ALERT_ERR_ACTIVE               0x00000008  /**< Alert(8): TWAI controller has become error active */
60 #define TWAI_ALERT_RECOVERY_IN_PROGRESS     0x00000010  /**< Alert(16): TWAI controller is undergoing bus recovery */
61 #define TWAI_ALERT_BUS_RECOVERED            0x00000020  /**< Alert(32): TWAI controller has successfully completed bus recovery */
62 #define TWAI_ALERT_ARB_LOST                 0x00000040  /**< Alert(64): The previous transmission lost arbitration */
63 #define TWAI_ALERT_ABOVE_ERR_WARN           0x00000080  /**< Alert(128): One of the error counters have exceeded the error warning limit */
64 #define TWAI_ALERT_BUS_ERROR                0x00000100  /**< Alert(256): A (Bit, Stuff, CRC, Form, ACK) error has occurred on the bus */
65 #define TWAI_ALERT_TX_FAILED                0x00000200  /**< Alert(512): The previous transmission has failed (for single shot transmission) */
66 #define TWAI_ALERT_RX_QUEUE_FULL            0x00000400  /**< Alert(1024): The RX queue is full causing a frame to be lost */
67 #define TWAI_ALERT_ERR_PASS                 0x00000800  /**< Alert(2048): TWAI controller has become error passive */
68 #define TWAI_ALERT_BUS_OFF                  0x00001000  /**< Alert(4096): Bus-off condition occurred. TWAI controller can no longer influence bus */
69 #define TWAI_ALERT_RX_FIFO_OVERRUN          0x00002000  /**< Alert(8192): An RX FIFO overrun has occurred */
70 #define TWAI_ALERT_TX_RETRIED               0x00004000  /**< Alert(16384): An message transmission was cancelled and retried due to an errata workaround */
71 #define TWAI_ALERT_PERIPH_RESET             0x00008000  /**< Alert(32768): The TWAI controller was reset */
72 #define TWAI_ALERT_ALL                      0x0000FFFF  /**< Bit mask to enable all alerts during configuration */
73 #define TWAI_ALERT_NONE                     0x00000000  /**< Bit mask to disable all alerts during configuration */
74 #define TWAI_ALERT_AND_LOG                  0x00010000  /**< Bit mask to enable alerts to also be logged when they occur. Note that logging from the ISR is disabled if CONFIG_TWAI_ISR_IN_IRAM is enabled (see docs). */
75 
76 /** @endcond */
77 
78 #define TWAI_IO_UNUSED                   ((gpio_num_t) -1)   /**< Marks GPIO as unused in TWAI configuration */
79 
80 /* ----------------------- Enum and Struct Definitions ---------------------- */
81 
82 /**
83  * @brief   TWAI driver states
84  */
85 typedef enum {
86     TWAI_STATE_STOPPED,             /**< Stopped state. The TWAI controller will not participate in any TWAI bus activities */
87     TWAI_STATE_RUNNING,             /**< Running state. The TWAI controller can transmit and receive messages */
88     TWAI_STATE_BUS_OFF,             /**< Bus-off state. The TWAI controller cannot participate in bus activities until it has recovered */
89     TWAI_STATE_RECOVERING,          /**< Recovering state. The TWAI controller is undergoing bus recovery */
90 } twai_state_t;
91 
92 /**
93  * @brief   Structure for general configuration of the TWAI driver
94  *
95  * @note    Macro initializers are available for this structure
96  */
97 typedef struct {
98     twai_mode_t mode;               /**< Mode of TWAI controller */
99     gpio_num_t tx_io;               /**< Transmit GPIO number */
100     gpio_num_t rx_io;               /**< Receive GPIO number */
101     gpio_num_t clkout_io;           /**< CLKOUT GPIO number (optional, set to -1 if unused) */
102     gpio_num_t bus_off_io;          /**< Bus off indicator GPIO number (optional, set to -1 if unused) */
103     uint32_t tx_queue_len;          /**< Number of messages TX queue can hold (set to 0 to disable TX Queue) */
104     uint32_t rx_queue_len;          /**< Number of messages RX queue can hold */
105     uint32_t alerts_enabled;        /**< Bit field of alerts to enable (see documentation) */
106     uint32_t clkout_divider;        /**< CLKOUT divider. Can be 1 or any even number from 2 to 14 (optional, set to 0 if unused) */
107     int intr_flags;                 /**< Interrupt flags to set the priority of the driver's ISR. Note that to use the ESP_INTR_FLAG_IRAM, the CONFIG_TWAI_ISR_IN_IRAM option should be enabled first. */
108 } twai_general_config_t;
109 
110 /**
111  * @brief   Structure to store status information of TWAI driver
112  */
113 typedef struct {
114     twai_state_t state;             /**< Current state of TWAI controller (Stopped/Running/Bus-Off/Recovery) */
115     uint32_t msgs_to_tx;            /**< Number of messages queued for transmission or awaiting transmission completion */
116     uint32_t msgs_to_rx;            /**< Number of messages in RX queue waiting to be read */
117     uint32_t tx_error_counter;      /**< Current value of Transmit Error Counter */
118     uint32_t rx_error_counter;      /**< Current value of Receive Error Counter */
119     uint32_t tx_failed_count;       /**< Number of messages that failed transmissions */
120     uint32_t rx_missed_count;       /**< Number of messages that were lost due to a full RX queue (or errata workaround if enabled) */
121     uint32_t rx_overrun_count;      /**< Number of messages that were lost due to a RX FIFO overrun */
122     uint32_t arb_lost_count;        /**< Number of instances arbitration was lost */
123     uint32_t bus_error_count;       /**< Number of instances a bus error has occurred */
124 } twai_status_info_t;
125 
126 /* ------------------------------ Public API -------------------------------- */
127 
128 /**
129  * @brief   Install TWAI driver
130  *
131  * This function installs the TWAI driver using three configuration structures.
132  * The required memory is allocated and the TWAI driver is placed in the stopped
133  * state after running this function.
134  *
135  * @param[in]   g_config    General configuration structure
136  * @param[in]   t_config    Timing configuration structure
137  * @param[in]   f_config    Filter configuration structure
138  *
139  * @note    Macro initializers are available for the configuration structures (see documentation)
140  *
141  * @note    To reinstall the TWAI driver, call twai_driver_uninstall() first
142  *
143  * @return
144  *      - ESP_OK: Successfully installed TWAI driver
145  *      - ESP_ERR_INVALID_ARG: Arguments are invalid
146  *      - ESP_ERR_NO_MEM: Insufficient memory
147  *      - ESP_ERR_INVALID_STATE: Driver is already installed
148  */
149 esp_err_t twai_driver_install(const twai_general_config_t *g_config, const twai_timing_config_t *t_config, const twai_filter_config_t *f_config);
150 
151 /**
152  * @brief   Uninstall the TWAI driver
153  *
154  * This function uninstalls the TWAI driver, freeing the memory utilized by the
155  * driver. This function can only be called when the driver is in the stopped
156  * state or the bus-off state.
157  *
158  * @warning The application must ensure that no tasks are blocked on TX/RX
159  *          queues or alerts when this function is called.
160  *
161  * @return
162  *      - ESP_OK: Successfully uninstalled TWAI driver
163  *      - ESP_ERR_INVALID_STATE: Driver is not in stopped/bus-off state, or is not installed
164  */
165 esp_err_t twai_driver_uninstall(void);
166 
167 /**
168  * @brief   Start the TWAI driver
169  *
170  * This function starts the TWAI driver, putting the TWAI driver into the running
171  * state. This allows the TWAI driver to participate in TWAI bus activities such
172  * as transmitting/receiving messages. The TX and RX queue are reset in this function,
173  * clearing any messages that are unread or pending transmission. This function
174  * can only be called when the TWAI driver is in the stopped state.
175  *
176  * @return
177  *      - ESP_OK: TWAI driver is now running
178  *      - ESP_ERR_INVALID_STATE: Driver is not in stopped state, or is not installed
179  */
180 esp_err_t twai_start(void);
181 
182 /**
183  * @brief   Stop the TWAI driver
184  *
185  * This function stops the TWAI driver, preventing any further message from being
186  * transmitted or received until twai_start() is called. Any messages in the TX
187  * queue are cleared. Any messages in the RX queue should be read by the
188  * application after this function is called. This function can only be called
189  * when the TWAI driver is in the running state.
190  *
191  * @warning A message currently being transmitted/received on the TWAI bus will
192  *          be ceased immediately. This may lead to other TWAI nodes interpreting
193  *          the unfinished message as an error.
194  *
195  * @return
196  *      - ESP_OK: TWAI driver is now Stopped
197  *      - ESP_ERR_INVALID_STATE: Driver is not in running state, or is not installed
198  */
199 esp_err_t twai_stop(void);
200 
201 /**
202  * @brief   Transmit a TWAI message
203  *
204  * This function queues a TWAI message for transmission. Transmission will start
205  * immediately if no other messages are queued for transmission. If the TX queue
206  * is full, this function will block until more space becomes available or until
207  * it times out. If the TX queue is disabled (TX queue length = 0 in configuration),
208  * this function will return immediately if another message is undergoing
209  * transmission. This function can only be called when the TWAI driver is in the
210  * running state and cannot be called under Listen Only Mode.
211  *
212  * @param[in]   message         Message to transmit
213  * @param[in]   ticks_to_wait   Number of FreeRTOS ticks to block on the TX queue
214  *
215  * @note    This function does not guarantee that the transmission is successful.
216  *          The TX_SUCCESS/TX_FAILED alert can be enabled to alert the application
217  *          upon the success/failure of a transmission.
218  *
219  * @note    The TX_IDLE alert can be used to alert the application when no other
220  *          messages are awaiting transmission.
221  *
222  * @return
223  *      - ESP_OK: Transmission successfully queued/initiated
224  *      - ESP_ERR_INVALID_ARG: Arguments are invalid
225  *      - ESP_ERR_TIMEOUT: Timed out waiting for space on TX queue
226  *      - ESP_FAIL: TX queue is disabled and another message is currently transmitting
227  *      - ESP_ERR_INVALID_STATE: TWAI driver is not in running state, or is not installed
228  *      - ESP_ERR_NOT_SUPPORTED: Listen Only Mode does not support transmissions
229  */
230 esp_err_t twai_transmit(const twai_message_t *message, TickType_t ticks_to_wait);
231 
232 /**
233  * @brief   Receive a TWAI message
234  *
235  * This function receives a message from the RX queue. The flags field of the
236  * message structure will indicate the type of message received. This function
237  * will block if there are no messages in the RX queue
238  *
239  * @param[out]  message         Received message
240  * @param[in]   ticks_to_wait   Number of FreeRTOS ticks to block on RX queue
241  *
242  * @warning The flags field of the received message should be checked to determine
243  *          if the received message contains any data bytes.
244  *
245  * @return
246  *      - ESP_OK: Message successfully received from RX queue
247  *      - ESP_ERR_TIMEOUT: Timed out waiting for message
248  *      - ESP_ERR_INVALID_ARG: Arguments are invalid
249  *      - ESP_ERR_INVALID_STATE: TWAI driver is not installed
250  */
251 esp_err_t twai_receive(twai_message_t *message, TickType_t ticks_to_wait);
252 
253 /**
254  * @brief   Read TWAI driver alerts
255  *
256  * This function will read the alerts raised by the TWAI driver. If no alert has
257  * been issued when this function is called, this function will block until an alert
258  * occurs or until it timeouts.
259  *
260  * @param[out]  alerts          Bit field of raised alerts (see documentation for alert flags)
261  * @param[in]   ticks_to_wait   Number of FreeRTOS ticks to block for alert
262  *
263  * @note    Multiple alerts can be raised simultaneously. The application should
264  *          check for all alerts that have been enabled.
265  *
266  * @return
267  *      - ESP_OK: Alerts read
268  *      - ESP_ERR_TIMEOUT: Timed out waiting for alerts
269  *      - ESP_ERR_INVALID_ARG: Arguments are invalid
270  *      - ESP_ERR_INVALID_STATE: TWAI driver is not installed
271  */
272 esp_err_t twai_read_alerts(uint32_t *alerts, TickType_t ticks_to_wait);
273 
274 /**
275  * @brief   Reconfigure which alerts are enabled
276  *
277  * This function reconfigures which alerts are enabled. If there are alerts
278  * which have not been read whilst reconfiguring, this function can read those
279  * alerts.
280  *
281  * @param[in]   alerts_enabled  Bit field of alerts to enable (see documentation for alert flags)
282  * @param[out]  current_alerts  Bit field of currently raised alerts. Set to NULL if unused
283  *
284  * @return
285  *      - ESP_OK: Alerts reconfigured
286  *      - ESP_ERR_INVALID_STATE: TWAI driver is not installed
287  */
288 esp_err_t twai_reconfigure_alerts(uint32_t alerts_enabled, uint32_t *current_alerts);
289 
290 /**
291  * @brief   Start the bus recovery process
292  *
293  * This function initiates the bus recovery process when the TWAI driver is in
294  * the bus-off state. Once initiated, the TWAI driver will enter the recovering
295  * state and wait for 128 occurrences of the bus-free signal on the TWAI bus
296  * before returning to the stopped state. This function will reset the TX queue,
297  * clearing any messages pending transmission.
298  *
299  * @note    The BUS_RECOVERED alert can be enabled to alert the application when
300  *          the bus recovery process completes.
301  *
302  * @return
303  *      - ESP_OK: Bus recovery started
304  *      - ESP_ERR_INVALID_STATE: TWAI driver is not in the bus-off state, or is not installed
305  */
306 esp_err_t twai_initiate_recovery(void);
307 
308 /**
309  * @brief   Get current status information of the TWAI driver
310  *
311  * @param[out]  status_info     Status information
312  *
313  * @return
314  *      - ESP_OK: Status information retrieved
315  *      - ESP_ERR_INVALID_ARG: Arguments are invalid
316  *      - ESP_ERR_INVALID_STATE: TWAI driver is not installed
317  */
318 esp_err_t twai_get_status_info(twai_status_info_t *status_info);
319 
320 /**
321  * @brief   Clear the transmit queue
322  *
323  * This function will clear the transmit queue of all messages.
324  *
325  * @note    The transmit queue is automatically cleared when twai_stop() or
326  *          twai_initiate_recovery() is called.
327  *
328  * @return
329  *      - ESP_OK: Transmit queue cleared
330  *      - ESP_ERR_INVALID_STATE: TWAI driver is not installed or TX queue is disabled
331  */
332 esp_err_t twai_clear_transmit_queue(void);
333 
334 /**
335  * @brief   Clear the receive queue
336  *
337  * This function will clear the receive queue of all messages.
338  *
339  * @note    The receive queue is automatically cleared when twai_start() is
340  *          called.
341  *
342  * @return
343  *      - ESP_OK: Transmit queue cleared
344  *      - ESP_ERR_INVALID_STATE: TWAI driver is not installed
345  */
346 esp_err_t twai_clear_receive_queue(void);
347 
348 #ifdef __cplusplus
349 }
350 #endif
351 
352 #endif //SOC_TWAI_SUPPORTED
353