1 /*
2  * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #pragma once
8 
9 #include <stdint.h>
10 #include <stdbool.h>
11 #include "sdkconfig.h"
12 #include "soc/soc_caps.h"
13 #include "soc/clk_tree_defs.h"
14 
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18 
19 /**
20  * @brief   TWAI Constants
21  */
22 #define TWAI_EXTD_ID_MASK               0x1FFFFFFF  /**< Bit mask for 29 bit Extended Frame Format ID */
23 #define TWAI_STD_ID_MASK                0x7FF       /**< Bit mask for 11 bit Standard Frame Format ID */
24 #define TWAI_FRAME_MAX_DLC              8           /**< Max data bytes allowed in TWAI */
25 #define TWAI_FRAME_EXTD_ID_LEN_BYTES    4           /**< EFF ID requires 4 bytes (29bit) */
26 #define TWAI_FRAME_STD_ID_LEN_BYTES     2           /**< SFF ID requires 2 bytes (11bit) */
27 #define TWAI_ERR_PASS_THRESH            128         /**< Error counter threshold for error passive */
28 
29 /** @cond */    //Doxy command to hide preprocessor definitions from docs
30 /**
31  * @brief   TWAI Message flags
32  *
33  * The message flags are used to indicate the type of message transmitted/received.
34  * Some flags also specify the type of transmission.
35  */
36 #define TWAI_MSG_FLAG_NONE              0x00        /**< No message flags (Standard Frame Format) */
37 #define TWAI_MSG_FLAG_EXTD              0x01        /**< Extended Frame Format (29bit ID) */
38 #define TWAI_MSG_FLAG_RTR               0x02        /**< Message is a Remote Frame */
39 #define TWAI_MSG_FLAG_SS                0x04        /**< Transmit as a Single Shot Transmission. Unused for received. */
40 #define TWAI_MSG_FLAG_SELF              0x08        /**< Transmit as a Self Reception Request. Unused for received. */
41 #define TWAI_MSG_FLAG_DLC_NON_COMP      0x10        /**< Message's Data length code is larger than 8. This will break compliance with TWAI */
42 
43 #define TWAI_BRP_MAX    SOC_TWAI_BRP_MAX    /**< Maximum configurable BRP value */
44 #define TWAI_BRP_MIN    SOC_TWAI_BRP_MIN    /**< Minimum configurable BRP value */
45 
46 
47 /**
48  * @brief Initializer macros for timing configuration structure
49  *
50  * The following initializer macros offer commonly found bit rates. These macros
51  * place the sample point at 80% or 67% of a bit time.
52  *
53  * @note The available bit rates are dependent on the chip target and ECO version.
54  */
55 #if SOC_TWAI_BRP_MAX > 256
56 #define TWAI_TIMING_CONFIG_1KBITS()     {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 20000, .brp = 0, .tseg_1 = 15, .tseg_2 = 4, .sjw = 3, .triple_sampling = false}
57 #define TWAI_TIMING_CONFIG_5KBITS()     {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 100000, .brp = 0, .tseg_1 = 15, .tseg_2 = 4, .sjw = 3, .triple_sampling = false}
58 #define TWAI_TIMING_CONFIG_10KBITS()    {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 200000, .brp = 0, .tseg_1 = 15, .tseg_2 = 4, .sjw = 3, .triple_sampling = false}
59 #endif // SOC_TWAI_BRP_MAX > 256
60 
61 #if (SOC_TWAI_BRP_MAX > 128) || (CONFIG_ESP32_REV_MIN_FULL >= 200)
62 #define TWAI_TIMING_CONFIG_12_5KBITS()  {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 312500, .brp = 0, .tseg_1 = 16, .tseg_2 = 8, .sjw = 3, .triple_sampling = false}
63 #define TWAI_TIMING_CONFIG_16KBITS()    {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 400000, .brp = 0, .tseg_1 = 16, .tseg_2 = 8, .sjw = 3, .triple_sampling = false}
64 #define TWAI_TIMING_CONFIG_20KBITS()    {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 400000, .brp = 0, .tseg_1 = 15, .tseg_2 = 4, .sjw = 3, .triple_sampling = false}
65 #endif // (SOC_TWAI_BRP_MAX > 128) || (CONFIG_ESP32_REV_MIN_FULL >= 200)
66 
67 #if SOC_TWAI_CLK_SUPPORT_XTAL
68 #define TWAI_TIMING_CONFIG_25KBITS()    {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 500000, .brp = 0, .tseg_1 = 15, .tseg_2 = 4, .sjw = 3, .triple_sampling = false}
69 #else   // APB80M
70 #define TWAI_TIMING_CONFIG_25KBITS()    {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 625000, .brp = 0, .tseg_1 = 16, .tseg_2 = 8, .sjw = 3, .triple_sampling = false}
71 #endif
72 #define TWAI_TIMING_CONFIG_50KBITS()    {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 1000000, .brp = 0, .tseg_1 = 15, .tseg_2 = 4, .sjw = 3, .triple_sampling = false}
73 #define TWAI_TIMING_CONFIG_100KBITS()   {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 2000000, .brp = 0, .tseg_1 = 15, .tseg_2 = 4, .sjw = 3, .triple_sampling = false}
74 #define TWAI_TIMING_CONFIG_125KBITS()   {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 2000000, .brp = 0, .tseg_1 = 11, .tseg_2 = 4, .sjw = 3, .triple_sampling = false}
75 #define TWAI_TIMING_CONFIG_250KBITS()   {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 4000000, .brp = 0, .tseg_1 = 11, .tseg_2 = 4, .sjw = 2, .triple_sampling = false}
76 #if SOC_TWAI_CLK_SUPPORT_XTAL && CONFIG_XTAL_FREQ == 40   // TWAI_CLK_SRC_XTAL = 40M
77 #define TWAI_TIMING_CONFIG_500KBITS()   {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 10000000, .brp = 0, .tseg_1 = 15, .tseg_2 = 4, .sjw = 3, .triple_sampling = false}
78 #define TWAI_TIMING_CONFIG_800KBITS()   {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 20000000, .brp = 0, .tseg_1 = 16, .tseg_2 = 8, .sjw = 3, .triple_sampling = false}
79 #define TWAI_TIMING_CONFIG_1MBITS()     {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 20000000, .brp = 0, .tseg_1 = 15, .tseg_2 = 4, .sjw = 3, .triple_sampling = false}
80 #else   // 32M, 48M, APB80M
81 #define TWAI_TIMING_CONFIG_500KBITS()   {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 8000000, .brp = 0, .tseg_1 = 11, .tseg_2 = 4, .sjw = 2, .triple_sampling = false}
82 #define TWAI_TIMING_CONFIG_800KBITS()   {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 8000000, .brp = 0, .tseg_1 = 6, .tseg_2 = 3, .sjw = 1, .triple_sampling = false}
83 #define TWAI_TIMING_CONFIG_1MBITS()     {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 8000000, .brp = 0, .tseg_1 = 5, .tseg_2 = 2, .sjw = 1, .triple_sampling = false}
84 #endif
85 
86 /**
87  * @brief   Initializer macro for filter configuration to accept all IDs
88  */
89 #define TWAI_FILTER_CONFIG_ACCEPT_ALL() {.acceptance_code = 0, .acceptance_mask = 0xFFFFFFFF, .single_filter = true}
90 /** @endcond */
91 
92 /**
93  * @brief   TWAI Controller operating modes
94  */
95 typedef enum {
96     TWAI_MODE_NORMAL,               /**< Normal operating mode where TWAI controller can send/receive/acknowledge messages */
97     TWAI_MODE_NO_ACK,               /**< Transmission does not require acknowledgment. Use this mode for self testing */
98     TWAI_MODE_LISTEN_ONLY,          /**< The TWAI controller will not influence the bus (No transmissions or acknowledgments) but can receive messages */
99 } twai_mode_t;
100 
101 /**
102  * @brief   Structure to store a TWAI message
103  *
104  * @note    The flags member is deprecated
105  */
106 typedef struct {
107     union {
108         struct {
109             //The order of these bits must match deprecated message flags for compatibility reasons
110             uint32_t extd: 1;           /**< Extended Frame Format (29bit ID) */
111             uint32_t rtr: 1;            /**< Message is a Remote Frame */
112             uint32_t ss: 1;             /**< Transmit as a Single Shot Transmission. Unused for received. */
113             uint32_t self: 1;           /**< Transmit as a Self Reception Request. Unused for received. */
114             uint32_t dlc_non_comp: 1;   /**< Message's Data length code is larger than 8. This will break compliance with ISO 11898-1 */
115             uint32_t reserved: 27;      /**< Reserved bits */
116         };
117         //Todo: Deprecate flags
118         uint32_t flags;                 /**< Deprecated: Alternate way to set bits using message flags */
119     };
120     uint32_t identifier;                /**< 11 or 29 bit identifier */
121     uint8_t data_length_code;           /**< Data length code */
122     uint8_t data[TWAI_FRAME_MAX_DLC];    /**< Data bytes (not relevant in RTR frame) */
123 } twai_message_t;
124 
125 /**
126  * @brief RMT group clock source
127  * @note User should select the clock source based on the power and resolution requirement
128  */
129 #if SOC_TWAI_SUPPORTED
130 typedef soc_periph_twai_clk_src_t twai_clock_source_t;
131 #else
132 typedef int twai_clock_source_t;
133 #endif
134 
135 /**
136  * @brief   Structure for bit timing configuration of the TWAI driver
137  *
138  * @note    Macro initializers are available for this structure
139  */
140 typedef struct {
141     twai_clock_source_t clk_src;    /**< Clock source, set to 0 or TWAI_CLK_SRC_DEFAULT if you want a default clock source */
142     uint32_t quanta_resolution_hz;  /**< The resolution of one timing quanta, in Hz.
143                                          Note: the value of `brp` will reflected by this field if it's non-zero, otherwise, `brp` needs to be set manually */
144     uint32_t brp;                   /**< Baudrate prescale (i.e., clock divider). Any even number from 2 to 128 for ESP32, 2 to 32768 for non-ESP32 chip.
145                                          Note: For ESP32 ECO 2 or later, multiples of 4 from 132 to 256 are also supported */
146     uint8_t tseg_1;                 /**< Timing segment 1 (Number of time quanta, between 1 to 16) */
147     uint8_t tseg_2;                 /**< Timing segment 2 (Number of time quanta, 1 to 8) */
148     uint8_t sjw;                    /**< Synchronization Jump Width (Max time quanta jump for synchronize from 1 to 4) */
149     bool triple_sampling;           /**< Enables triple sampling when the TWAI controller samples a bit */
150 } twai_timing_config_t;
151 
152 /**
153  * @brief   Structure for acceptance filter configuration of the TWAI driver (see documentation)
154  *
155  * @note    Macro initializers are available for this structure
156  */
157 typedef struct {
158     uint32_t acceptance_code;       /**< 32-bit acceptance code */
159     uint32_t acceptance_mask;       /**< 32-bit acceptance mask */
160     bool single_filter;             /**< Use Single Filter Mode (see documentation) */
161 } twai_filter_config_t;
162 
163 #ifdef __cplusplus
164 }
165 #endif
166