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