├── .gitignore ├── LICENSE ├── README.md ├── examples ├── esp32can_basic │ └── esp32can_basic.ino ├── esp32can_filter │ └── esp32can_filter.ino └── esp32can_mirror │ └── esp32can_mirror.ino ├── keywords.txt ├── library.properties └── src ├── CAN.c ├── CAN.h ├── CAN_config.h ├── ESP32CAN.cpp ├── ESP32CAN.h └── can_regdef.h /.gitignore: -------------------------------------------------------------------------------- 1 | .pioenvs 2 | .piolibdeps 3 | .vscode/**/* 4 | .travis.yml 5 | platformio.ini 6 | lib/readme.txt -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Michael Wagner 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Arduino Library for the ESP32 CAN Bus (ESP32-Arduino-CAN) 2 | 3 | ## Features 4 | 5 | * Support the CAN Bus from the ESP32 (SJA1000) 6 | * CAN Messages send and receive 7 | * Various Bus speeds 8 | * Standard and Extended Frames 9 | * CAN Message Filter 10 | 11 | 12 | 13 | ## Third Party Components 14 | 15 | - Arduino-ESP32-CAN-Demo 16 | - Arduino CAN Demo from [iotsharing.com - nhatuan84](https://github.com/nhatuan84/arduino-esp32-can-demo) 17 | 18 | - ESPCan Driver 19 | - Base CAN Driver from [Thomas Barth](https://github.com/ThomasBarth/ESP32-CAN-Driver) and [Nayar Systems](https://github.com/nayarsystems/ESP32-CAN-Driver) 20 | - General [Component CAN Driver Pack](https://github.com/ESP32DE/ESP32-CAN-Driver/tree/Component_CAN_Driver_Pack) Work for ESP-IDF with menuconfig from [rudi ;-)](http://esp32.de) 21 | 22 | ## Usage 23 | 24 | See the examples in the [/examples](examples) folder. -------------------------------------------------------------------------------- /examples/esp32can_basic/esp32can_basic.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | CAN_device_t CAN_cfg; // CAN Config 6 | unsigned long previousMillis = 0; // will store last time a CAN Message was send 7 | const int interval = 1000; // interval at which send CAN Messages (milliseconds) 8 | const int rx_queue_size = 10; // Receive Queue size 9 | 10 | void setup() { 11 | Serial.begin(115200); 12 | Serial.println("Basic Demo - ESP32-Arduino-CAN"); 13 | CAN_cfg.speed = CAN_SPEED_125KBPS; 14 | CAN_cfg.tx_pin_id = GPIO_NUM_5; 15 | CAN_cfg.rx_pin_id = GPIO_NUM_4; 16 | CAN_cfg.rx_queue = xQueueCreate(rx_queue_size, sizeof(CAN_frame_t)); 17 | // Init CAN Module 18 | ESP32Can.CANInit(); 19 | } 20 | 21 | void loop() { 22 | 23 | CAN_frame_t rx_frame; 24 | 25 | unsigned long currentMillis = millis(); 26 | 27 | // Receive next CAN frame from queue 28 | if (xQueueReceive(CAN_cfg.rx_queue, &rx_frame, 3 * portTICK_PERIOD_MS) == pdTRUE) { 29 | 30 | if (rx_frame.FIR.B.FF == CAN_frame_std) { 31 | printf("New standard frame"); 32 | } 33 | else { 34 | printf("New extended frame"); 35 | } 36 | 37 | if (rx_frame.FIR.B.RTR == CAN_RTR) { 38 | printf(" RTR from 0x%08X, DLC %d\r\n", rx_frame.MsgID, rx_frame.FIR.B.DLC); 39 | } 40 | else { 41 | printf(" from 0x%08X, DLC %d, Data ", rx_frame.MsgID, rx_frame.FIR.B.DLC); 42 | for (int i = 0; i < rx_frame.FIR.B.DLC; i++) { 43 | printf("0x%02X ", rx_frame.data.u8[i]); 44 | } 45 | printf("\n"); 46 | } 47 | } 48 | // Send CAN Message 49 | if (currentMillis - previousMillis >= interval) { 50 | previousMillis = currentMillis; 51 | CAN_frame_t tx_frame; 52 | tx_frame.FIR.B.FF = CAN_frame_std; 53 | tx_frame.MsgID = 0x001; 54 | tx_frame.FIR.B.DLC = 8; 55 | tx_frame.data.u8[0] = 0x00; 56 | tx_frame.data.u8[1] = 0x01; 57 | tx_frame.data.u8[2] = 0x02; 58 | tx_frame.data.u8[3] = 0x03; 59 | tx_frame.data.u8[4] = 0x04; 60 | tx_frame.data.u8[5] = 0x05; 61 | tx_frame.data.u8[6] = 0x06; 62 | tx_frame.data.u8[7] = 0x07; 63 | ESP32Can.CANWriteFrame(&tx_frame); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /examples/esp32can_filter/esp32can_filter.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | CAN_device_t CAN_cfg; // CAN Config 6 | const int rx_queue_size = 10; // Receive Queue size 7 | 8 | void setup() { 9 | Serial.begin(115200); 10 | Serial.println("Filter Demo - ESP32-Arduino-CAN"); 11 | CAN_cfg.speed = CAN_SPEED_125KBPS; 12 | CAN_cfg.tx_pin_id = GPIO_NUM_5; 13 | CAN_cfg.rx_pin_id = GPIO_NUM_4; 14 | CAN_cfg.rx_queue = xQueueCreate(rx_queue_size, sizeof(CAN_frame_t)); 15 | 16 | // Set CAN Filter 17 | // See in the SJA1000 Datasheet chapter "6.4.15 Acceptance filter" 18 | // and the APPLICATION NOTE AN97076 chapter "4.1.2 Acceptance Filter" 19 | // for PeliCAN Mode 20 | CAN_filter_t p_filter; 21 | p_filter.FM = Single_Mode; 22 | 23 | p_filter.ACR0 = 0x29; 24 | p_filter.ACR1 = 0; 25 | p_filter.ACR2 = 0; 26 | p_filter.ACR3 = 0; 27 | 28 | p_filter.AMR0 = 0; 29 | p_filter.AMR1 = 0xFF; 30 | p_filter.AMR2 = 0xFF; 31 | p_filter.AMR3 = 0xFF; 32 | ESP32Can.CANConfigFilter(&p_filter); 33 | 34 | // Init CAN Module 35 | ESP32Can.CANInit(); 36 | } 37 | 38 | void loop() { 39 | 40 | CAN_frame_t rx_frame; 41 | 42 | unsigned long currentMillis = millis(); 43 | 44 | // Receive next CAN frame from queue 45 | if (xQueueReceive(CAN_cfg.rx_queue, &rx_frame, 3 * portTICK_PERIOD_MS) == pdTRUE) { 46 | 47 | if (rx_frame.FIR.B.FF == CAN_frame_std) { 48 | printf("New standard frame"); 49 | } 50 | else { 51 | printf("New extended frame"); 52 | } 53 | 54 | if (rx_frame.FIR.B.RTR == CAN_RTR) { 55 | printf(" RTR from 0x%08X, DLC %d\r\n", rx_frame.MsgID, rx_frame.FIR.B.DLC); 56 | } 57 | else { 58 | printf(" from 0x%08X, DLC %d, Data ", rx_frame.MsgID, rx_frame.FIR.B.DLC); 59 | for (int i = 0; i < rx_frame.FIR.B.DLC; i++) { 60 | printf("0x%02X ", rx_frame.data.u8[i]); 61 | } 62 | printf("\n"); 63 | } 64 | } 65 | } 66 | 67 | -------------------------------------------------------------------------------- /examples/esp32can_mirror/esp32can_mirror.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | CAN_device_t CAN_cfg; // CAN Config 6 | const int rx_queue_size = 10; // Receive Queue size 7 | 8 | void setup() { 9 | Serial.begin(115200); 10 | Serial.println("Mirror Demo - ESP32-Arduino-CAN"); 11 | CAN_cfg.speed = CAN_SPEED_125KBPS; 12 | CAN_cfg.tx_pin_id = GPIO_NUM_5; 13 | CAN_cfg.rx_pin_id = GPIO_NUM_4; 14 | CAN_cfg.rx_queue = xQueueCreate(rx_queue_size, sizeof(CAN_frame_t)); 15 | // Init CAN Module 16 | ESP32Can.CANInit(); 17 | } 18 | 19 | void loop() { 20 | CAN_frame_t rx_frame; 21 | //receive next CAN frame from queue 22 | if (xQueueReceive(CAN_cfg.rx_queue, &rx_frame, 3 * portTICK_PERIOD_MS) == pdTRUE) { 23 | 24 | if (rx_frame.FIR.B.FF == CAN_frame_std) { 25 | printf("New standard frame"); 26 | } 27 | else { 28 | printf("New extended frame"); 29 | } 30 | 31 | if (rx_frame.FIR.B.RTR == CAN_RTR) { 32 | printf(" RTR from 0x%08X, DLC %d\r\n", rx_frame.MsgID, rx_frame.FIR.B.DLC); 33 | } 34 | else { 35 | printf(" from 0x%08X, DLC %d, Data ", rx_frame.MsgID, rx_frame.FIR.B.DLC); 36 | for (int i = 0; i < rx_frame.FIR.B.DLC; i++) { 37 | printf("0x%02X ", rx_frame.data.u8[i]); 38 | } 39 | printf("\n"); 40 | } 41 | 42 | //respond to sender 43 | ESP32Can.CANWriteFrame(&rx_frame); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map ESP32CAN 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | ESP32CAN KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | CANInit KEYWORD2 15 | CANWriteFrame KEYWORD2 16 | CANStop KEYWORD2 17 | CANConfigFilter KEYWORD2 18 | ####################################### 19 | # Constants (LITERAL1) 20 | ####################################### 21 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=ESP32CAN 2 | version=0.0.1 3 | author=Michael Wagner 4 | maintainer=https://github.com/miwagner 5 | sentence=ESP32-Arduino-CAN 6 | paragraph=ESP32-Arduino-CAN 7 | category=Device Control 8 | url=https://github.com/miwagner/ESP32-Arduino-CAN 9 | architectures=esp32 10 | -------------------------------------------------------------------------------- /src/CAN.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @section License 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2017, Thomas Barth, barth-dev.de 7 | * 2017, Jaime Breva, jbreva@nayarsystems.com 8 | * 2018, Michael Wagner, mw@iot-make.de 9 | * 10 | * Permission is hereby granted, free of charge, to any person 11 | * obtaining a copy of this software and associated documentation 12 | * files (the "Software"), to deal in the Software without 13 | * restriction, including without limitation the rights to use, copy, 14 | * modify, merge, publish, distribute, sublicense, and/or sell copies 15 | * of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be 19 | * included in all copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 25 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 26 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 27 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | * SOFTWARE. 29 | * 30 | */ 31 | 32 | #include "CAN.h" 33 | 34 | #include "freertos/FreeRTOS.h" 35 | #include "freertos/queue.h" 36 | 37 | #include "esp_intr.h" 38 | #include "soc/dport_reg.h" 39 | #include 40 | 41 | #include "driver/gpio.h" 42 | 43 | #include "can_regdef.h" 44 | #include "CAN_config.h" 45 | 46 | // CAN Filter - no acceptance filter 47 | static CAN_filter_t __filter = { Dual_Mode, 0, 0, 0, 0, 0Xff, 0Xff, 0Xff, 0Xff }; 48 | 49 | static void CAN_read_frame_phy(); 50 | static void CAN_isr(void *arg_p); 51 | static int CAN_write_frame_phy(const CAN_frame_t *p_frame); 52 | static SemaphoreHandle_t sem_tx_complete; 53 | 54 | static void CAN_isr(void *arg_p) { 55 | 56 | // Interrupt flag buffer 57 | __CAN_IRQ_t interrupt; 58 | BaseType_t higherPriorityTaskWoken = pdFALSE; 59 | 60 | // Read interrupt status and clear flags 61 | interrupt = MODULE_CAN->IR.U; 62 | 63 | // Handle RX frame available interrupt 64 | if ((interrupt & __CAN_IRQ_RX) != 0) 65 | CAN_read_frame_phy(&higherPriorityTaskWoken); 66 | 67 | // Handle TX complete interrupt 68 | // Handle error interrupts. 69 | if ((interrupt & (__CAN_IRQ_TX | __CAN_IRQ_ERR //0x4 70 | | __CAN_IRQ_DATA_OVERRUN // 0x8 71 | | __CAN_IRQ_WAKEUP // 0x10 72 | | __CAN_IRQ_ERR_PASSIVE // 0x20 73 | | __CAN_IRQ_ARB_LOST // 0x40 74 | | __CAN_IRQ_BUS_ERR // 0x80 75 | )) != 0) { 76 | xSemaphoreGiveFromISR(sem_tx_complete, &higherPriorityTaskWoken); 77 | } 78 | 79 | // check if any higher priority task has been woken by any handler 80 | if (higherPriorityTaskWoken) 81 | portYIELD_FROM_ISR(); 82 | } 83 | 84 | static void CAN_read_frame_phy(BaseType_t *higherPriorityTaskWoken) { 85 | 86 | // byte iterator 87 | uint8_t __byte_i; 88 | 89 | // frame read buffer 90 | CAN_frame_t __frame; 91 | 92 | // check if we have a queue. If not, operation is aborted. 93 | if (CAN_cfg.rx_queue == NULL) { 94 | // Let the hardware know the frame has been read. 95 | MODULE_CAN->CMR.B.RRB = 1; 96 | return; 97 | } 98 | 99 | // get FIR 100 | __frame.FIR.U = MODULE_CAN->MBX_CTRL.FCTRL.FIR.U; 101 | 102 | // check if this is a standard or extended CAN frame 103 | // standard frame 104 | if (__frame.FIR.B.FF == CAN_frame_std) { 105 | 106 | // Get Message ID 107 | __frame.MsgID = _CAN_GET_STD_ID; 108 | 109 | // deep copy data bytes 110 | for (__byte_i = 0; __byte_i < __frame.FIR.B.DLC; __byte_i++) 111 | __frame.data.u8[__byte_i] = MODULE_CAN->MBX_CTRL.FCTRL.TX_RX.STD.data[__byte_i]; 112 | } 113 | // extended frame 114 | else { 115 | 116 | // Get Message ID 117 | __frame.MsgID = _CAN_GET_EXT_ID; 118 | 119 | // deep copy data bytes 120 | for (__byte_i = 0; __byte_i < __frame.FIR.B.DLC; __byte_i++) 121 | __frame.data.u8[__byte_i] = MODULE_CAN->MBX_CTRL.FCTRL.TX_RX.EXT.data[__byte_i]; 122 | } 123 | 124 | // send frame to input queue 125 | xQueueSendToBackFromISR(CAN_cfg.rx_queue, &__frame, higherPriorityTaskWoken); 126 | 127 | // Let the hardware know the frame has been read. 128 | MODULE_CAN->CMR.B.RRB = 1; 129 | } 130 | 131 | static int CAN_write_frame_phy(const CAN_frame_t *p_frame) { 132 | 133 | // byte iterator 134 | uint8_t __byte_i; 135 | 136 | // copy frame information record 137 | MODULE_CAN->MBX_CTRL.FCTRL.FIR.U = p_frame->FIR.U; 138 | 139 | // standard frame 140 | if (p_frame->FIR.B.FF == CAN_frame_std) { 141 | 142 | // Write message ID 143 | _CAN_SET_STD_ID(p_frame->MsgID); 144 | 145 | // Copy the frame data to the hardware 146 | for (__byte_i = 0; __byte_i < p_frame->FIR.B.DLC; __byte_i++) 147 | MODULE_CAN->MBX_CTRL.FCTRL.TX_RX.STD.data[__byte_i] = p_frame->data.u8[__byte_i]; 148 | 149 | } 150 | // extended frame 151 | else { 152 | 153 | // Write message ID 154 | _CAN_SET_EXT_ID(p_frame->MsgID); 155 | 156 | // Copy the frame data to the hardware 157 | for (__byte_i = 0; __byte_i < p_frame->FIR.B.DLC; __byte_i++) 158 | MODULE_CAN->MBX_CTRL.FCTRL.TX_RX.EXT.data[__byte_i] = p_frame->data.u8[__byte_i]; 159 | } 160 | 161 | // Transmit frame 162 | MODULE_CAN->CMR.B.TR = 1; 163 | 164 | return 0; 165 | } 166 | 167 | int CAN_init() { 168 | 169 | // Time quantum 170 | double __tq; 171 | 172 | // enable module 173 | DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_CAN_CLK_EN); 174 | DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_CAN_RST); 175 | 176 | // configure TX pin 177 | gpio_set_level(CAN_cfg.tx_pin_id, 1); 178 | gpio_set_direction(CAN_cfg.tx_pin_id, GPIO_MODE_OUTPUT); 179 | gpio_matrix_out(CAN_cfg.tx_pin_id, CAN_TX_IDX, 0, 0); 180 | gpio_pad_select_gpio(CAN_cfg.tx_pin_id); 181 | 182 | // configure RX pin 183 | gpio_set_direction(CAN_cfg.rx_pin_id, GPIO_MODE_INPUT); 184 | gpio_matrix_in(CAN_cfg.rx_pin_id, CAN_RX_IDX, 0); 185 | gpio_pad_select_gpio(CAN_cfg.rx_pin_id); 186 | 187 | // set to PELICAN mode 188 | MODULE_CAN->CDR.B.CAN_M = 0x1; 189 | 190 | // synchronization jump width is the same for all baud rates 191 | MODULE_CAN->BTR0.B.SJW = 0x1; 192 | 193 | // TSEG2 is the same for all baud rates 194 | MODULE_CAN->BTR1.B.TSEG2 = 0x1; 195 | 196 | // select time quantum and set TSEG1 197 | switch (CAN_cfg.speed) { 198 | case CAN_SPEED_1000KBPS: 199 | MODULE_CAN->BTR1.B.TSEG1 = 0x4; 200 | __tq = 0.125; 201 | break; 202 | 203 | case CAN_SPEED_800KBPS: 204 | MODULE_CAN->BTR1.B.TSEG1 = 0x6; 205 | __tq = 0.125; 206 | break; 207 | 208 | case CAN_SPEED_200KBPS: 209 | MODULE_CAN->BTR1.B.TSEG1 = 0xc; 210 | MODULE_CAN->BTR1.B.TSEG2 = 0x5; 211 | __tq = 0.25; 212 | break; 213 | 214 | default: 215 | MODULE_CAN->BTR1.B.TSEG1 = 0xc; 216 | __tq = ((float) 1000 / CAN_cfg.speed) / 16; 217 | } 218 | 219 | // set baud rate prescaler 220 | MODULE_CAN->BTR0.B.BRP = (uint8_t) round((((APB_CLK_FREQ * __tq) / 2) - 1) / 1000000) - 1; 221 | 222 | /* Set sampling 223 | * 1 -> triple; the bus is sampled three times; recommended for low/medium speed buses (class A and B) where 224 | * filtering spikes on the bus line is beneficial 0 -> single; the bus is sampled once; recommended for high speed 225 | * buses (SAE class C)*/ 226 | MODULE_CAN->BTR1.B.SAM = 0x1; 227 | 228 | // enable all interrupts 229 | MODULE_CAN->IER.U = 0xff; 230 | 231 | // Set acceptance filter 232 | MODULE_CAN->MOD.B.AFM = __filter.FM; 233 | MODULE_CAN->MBX_CTRL.ACC.CODE[0] = __filter.ACR0; 234 | MODULE_CAN->MBX_CTRL.ACC.CODE[1] = __filter.ACR1; 235 | MODULE_CAN->MBX_CTRL.ACC.CODE[2] = __filter.ACR2; 236 | MODULE_CAN->MBX_CTRL.ACC.CODE[3] = __filter.ACR3; 237 | MODULE_CAN->MBX_CTRL.ACC.MASK[0] = __filter.AMR0; 238 | MODULE_CAN->MBX_CTRL.ACC.MASK[1] = __filter.AMR1; 239 | MODULE_CAN->MBX_CTRL.ACC.MASK[2] = __filter.AMR2; 240 | MODULE_CAN->MBX_CTRL.ACC.MASK[3] = __filter.AMR3; 241 | 242 | // set to normal mode 243 | MODULE_CAN->OCR.B.OCMODE = __CAN_OC_NOM; 244 | 245 | // clear error counters 246 | MODULE_CAN->TXERR.U = 0; 247 | MODULE_CAN->RXERR.U = 0; 248 | (void) MODULE_CAN->ECC; 249 | 250 | // clear interrupt flags 251 | (void) MODULE_CAN->IR.U; 252 | 253 | // install CAN ISR 254 | esp_intr_alloc(ETS_CAN_INTR_SOURCE, 0, CAN_isr, NULL, NULL); 255 | 256 | // allocate the tx complete semaphore 257 | sem_tx_complete = xSemaphoreCreateBinary(); 258 | 259 | // Showtime. Release Reset Mode. 260 | MODULE_CAN->MOD.B.RM = 0; 261 | 262 | return 0; 263 | } 264 | 265 | int CAN_write_frame(const CAN_frame_t *p_frame) { 266 | if (sem_tx_complete == NULL) { 267 | return -1; 268 | } 269 | 270 | // Write the frame to the controller 271 | CAN_write_frame_phy(p_frame); 272 | 273 | // wait for the frame tx to complete 274 | xSemaphoreTake(sem_tx_complete, portMAX_DELAY); 275 | 276 | return 0; 277 | } 278 | 279 | int CAN_stop() { 280 | // enter reset mode 281 | MODULE_CAN->MOD.B.RM = 1; 282 | 283 | return 0; 284 | } 285 | 286 | int CAN_config_filter(const CAN_filter_t* p_filter) { 287 | 288 | __filter.FM = p_filter->FM; 289 | __filter.ACR0 = p_filter->ACR0; 290 | __filter.ACR1 = p_filter->ACR1; 291 | __filter.ACR2 = p_filter->ACR2; 292 | __filter.ACR3 = p_filter->ACR3; 293 | __filter.AMR0 = p_filter->AMR0; 294 | __filter.AMR1 = p_filter->AMR1; 295 | __filter.AMR2 = p_filter->AMR2; 296 | __filter.AMR3 = p_filter->AMR3; 297 | 298 | return 0; 299 | } -------------------------------------------------------------------------------- /src/CAN.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @section License 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2017, Thomas Barth, barth-dev.de 7 | * 2018, Michael Wagner, mw@iot-make.de 8 | * Permission is hereby granted, free of charge, to any person 9 | * obtaining a copy of this software and associated documentation 10 | * files (the "Software"), to deal in the Software without 11 | * restriction, including without limitation the rights to use, copy, 12 | * modify, merge, publish, distribute, sublicense, and/or sell copies 13 | * of the Software, and to permit persons to whom the Software is 14 | * furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | * SOFTWARE. 27 | */ 28 | 29 | #ifndef __DRIVERS_CAN_H__ 30 | #define __DRIVERS_CAN_H__ 31 | 32 | #include 33 | #include "CAN_config.h" 34 | 35 | #ifdef __cplusplus 36 | extern "C" { 37 | #endif 38 | 39 | /** 40 | * \brief CAN frame type (standard/extended) 41 | */ 42 | typedef enum { 43 | CAN_frame_std = 0, /**< Standard frame, using 11 bit identifer. */ 44 | CAN_frame_ext = 1 /**< Extended frame, using 29 bit identifer. */ 45 | } CAN_frame_format_t; 46 | 47 | /** 48 | * \brief CAN RTR 49 | */ 50 | typedef enum { 51 | CAN_no_RTR = 0, /**< No RTR frame. */ 52 | CAN_RTR = 1 /**< RTR frame. */ 53 | } CAN_RTR_t; 54 | 55 | /** \brief Frame information record type */ 56 | typedef union { 57 | uint32_t U; /**< \brief Unsigned access */ 58 | struct { 59 | uint8_t DLC : 4; /**< \brief [3:0] DLC, Data length container */ 60 | unsigned int unknown_2 : 2; /**< \brief \internal unknown */ 61 | CAN_RTR_t RTR : 1; /**< \brief [6:6] RTR, Remote Transmission Request */ 62 | CAN_frame_format_t FF : 1; /**< \brief [7:7] Frame Format, see# CAN_frame_format_t*/ 63 | unsigned int reserved_24 : 24; /**< \brief \internal Reserved */ 64 | } B; 65 | } CAN_FIR_t; 66 | 67 | /** \brief CAN Frame structure */ 68 | typedef struct { 69 | CAN_FIR_t FIR; /**< \brief Frame information record*/ 70 | uint32_t MsgID; /**< \brief Message ID */ 71 | union { 72 | uint8_t u8[8]; /**< \brief Payload byte access*/ 73 | uint32_t u32[2]; /**< \brief Payload u32 access*/ 74 | uint64_t u64; /**< \brief Payload u64 access*/ 75 | } data; 76 | } CAN_frame_t; 77 | 78 | typedef enum { 79 | Dual_Mode=0, /**< \brief The dual acceptance filter option is enabled (two filters, each with the length of 16 bit are active) */ 80 | Single_Mode=1 /**< \brief The single acceptance filter option is enabled (one filter with the length of 32 bit is active) */ 81 | } CAN_filter_mode_t; 82 | 83 | /** \brief CAN Filter structure */ 84 | typedef struct { 85 | CAN_filter_mode_t FM:1; /**< \brief [0:0] Filter Mode */ 86 | uint8_t ACR0; /**< \brief Acceptance Code Register ACR0 */ 87 | uint8_t ACR1; /**< \brief Acceptance Code Register ACR1 */ 88 | uint8_t ACR2; /**< \brief Acceptance Code Register ACR2 */ 89 | uint8_t ACR3; /**< \brief Acceptance Code Register ACR3 */ 90 | uint8_t AMR0; /**< \brief Acceptance Mask Register AMR0 */ 91 | uint8_t AMR1; /**< \brief Acceptance Mask Register AMR1 */ 92 | uint8_t AMR2; /**< \brief Acceptance Mask Register AMR2 */ 93 | uint8_t AMR3; /**< \brief Acceptance Mask Register AMR3 */ 94 | } CAN_filter_t; 95 | 96 | /** 97 | * \brief Initialize the CAN Module 98 | * 99 | * \return 0 CAN Module had been initialized 100 | */ 101 | int CAN_init(void); 102 | 103 | /** 104 | * \brief Send a can frame 105 | * 106 | * \param p_frame Pointer to the frame to be send, see #CAN_frame_t 107 | * \return 0 Frame has been written to the module 108 | */ 109 | int CAN_write_frame(const CAN_frame_t *p_frame); 110 | 111 | /** 112 | * \brief Stops the CAN Module 113 | * 114 | * \return 0 CAN Module was stopped 115 | */ 116 | int CAN_stop(void); 117 | 118 | /** 119 | * \brief Config CAN Filter, must call before CANInit() 120 | * 121 | * \param p_filter Pointer to the filter, see #CAN_filter_t 122 | * \return 0 CAN Filter had been initialized 123 | */ 124 | int CAN_config_filter(const CAN_filter_t* p_filter); 125 | 126 | 127 | #ifdef __cplusplus 128 | } 129 | #endif 130 | 131 | #endif 132 | -------------------------------------------------------------------------------- /src/CAN_config.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @section License 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2017, Thomas Barth, barth-dev.de 7 | * 8 | * Permission is hereby granted, free of charge, to any person 9 | * obtaining a copy of this software and associated documentation 10 | * files (the "Software"), to deal in the Software without 11 | * restriction, including without limitation the rights to use, copy, 12 | * modify, merge, publish, distribute, sublicense, and/or sell copies 13 | * of the Software, and to permit persons to whom the Software is 14 | * furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | * SOFTWARE. 27 | */ 28 | 29 | #ifndef __DRIVERS_CAN_CFG_H__ 30 | #define __DRIVERS_CAN_CFG_H__ 31 | 32 | #include "freertos/FreeRTOS.h" 33 | #include "freertos/queue.h" 34 | #include "freertos/task.h" 35 | #include "driver/gpio.h" 36 | #include "freertos/semphr.h" 37 | 38 | #ifdef __cplusplus 39 | extern "C" { 40 | #endif 41 | 42 | /** \brief CAN Node Bus speed */ 43 | typedef enum { 44 | CAN_SPEED_100KBPS = 100, /**< \brief CAN Node runs at 100kBit/s. */ 45 | CAN_SPEED_125KBPS = 125, /**< \brief CAN Node runs at 125kBit/s. */ 46 | CAN_SPEED_200KBPS = 200, /**< \brief CAN Node runs at 250kBit/s. */ 47 | CAN_SPEED_250KBPS = 250, /**< \brief CAN Node runs at 250kBit/s. */ 48 | CAN_SPEED_500KBPS = 500, /**< \brief CAN Node runs at 500kBit/s. */ 49 | CAN_SPEED_800KBPS = 800, /**< \brief CAN Node runs at 800kBit/s. */ 50 | CAN_SPEED_1000KBPS = 1000 /**< \brief CAN Node runs at 1000kBit/s. */ 51 | } CAN_speed_t; 52 | 53 | /** \brief CAN configuration structure */ 54 | typedef struct { 55 | CAN_speed_t speed; /**< \brief CAN speed. */ 56 | gpio_num_t tx_pin_id; /**< \brief TX pin. */ 57 | gpio_num_t rx_pin_id; /**< \brief RX pin. */ 58 | QueueHandle_t rx_queue; /**< \brief Handler to FreeRTOS RX queue. */ 59 | QueueHandle_t tx_queue; /**< \brief Handler to FreeRTOS TX queue. */ 60 | TaskHandle_t tx_handle; /**< \brief Handler to FreeRTOS TX task. */ 61 | TaskHandle_t rx_handle; /**< \brief Handler to FreeRTOS RX task. */ 62 | } CAN_device_t; 63 | 64 | /** \brief CAN configuration reference */ 65 | extern CAN_device_t CAN_cfg; 66 | 67 | #ifdef __cplusplus 68 | } 69 | #endif 70 | 71 | #endif /* __DRIVERS_CAN_CFG_H__ */ 72 | -------------------------------------------------------------------------------- /src/ESP32CAN.cpp: -------------------------------------------------------------------------------- 1 | #include "ESP32CAN.h" 2 | 3 | int ESP32CAN::CANInit() 4 | { 5 | return CAN_init(); 6 | } 7 | int ESP32CAN::CANWriteFrame(const CAN_frame_t* p_frame) 8 | { 9 | return CAN_write_frame(p_frame); 10 | } 11 | int ESP32CAN::CANStop() 12 | { 13 | return CAN_stop(); 14 | } 15 | int ESP32CAN::CANConfigFilter(const CAN_filter_t* p_filter) 16 | { 17 | return CAN_config_filter(p_filter); 18 | } 19 | 20 | ESP32CAN ESP32Can; 21 | -------------------------------------------------------------------------------- /src/ESP32CAN.h: -------------------------------------------------------------------------------- 1 | #ifndef ESP32CAN_H 2 | #define ESP32CAN_H 3 | 4 | #include "CAN_config.h" 5 | #include "CAN.h" 6 | 7 | class ESP32CAN 8 | { 9 | public: 10 | int CANInit(); 11 | int CANConfigFilter(const CAN_filter_t* p_filter); 12 | int CANWriteFrame(const CAN_frame_t* p_frame); 13 | int CANStop(); 14 | }; 15 | 16 | extern ESP32CAN ESP32Can; 17 | #endif 18 | -------------------------------------------------------------------------------- /src/can_regdef.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @section License 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2017, Thomas Barth, barth-dev.de 7 | * 8 | * Permission is hereby granted, free of charge, to any person 9 | * obtaining a copy of this software and associated documentation 10 | * files (the "Software"), to deal in the Software without 11 | * restriction, including without limitation the rights to use, copy, 12 | * modify, merge, publish, distribute, sublicense, and/or sell copies 13 | * of the Software, and to permit persons to whom the Software is 14 | * furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | * SOFTWARE. 27 | */ 28 | 29 | #ifndef __DRIVERS_CAN_REGDEF_H_ 30 | #define __DRIVERS_CAN_REGDEF_H_ 31 | 32 | #include "CAN.h" //CAN_FIR_t 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | /** \brief Start address of CAN registers */ 39 | #define MODULE_CAN ((volatile CAN_Module_t *) 0x3ff6b000) 40 | 41 | /** \brief Get standard message ID */ 42 | #define _CAN_GET_STD_ID \ 43 | (((uint32_t) MODULE_CAN->MBX_CTRL.FCTRL.TX_RX.STD.ID[0] << 3) | (MODULE_CAN->MBX_CTRL.FCTRL.TX_RX.STD.ID[1] >> 5)) 44 | 45 | /** \brief Get extended message ID */ 46 | #define _CAN_GET_EXT_ID \ 47 | (((uint32_t) MODULE_CAN->MBX_CTRL.FCTRL.TX_RX.EXT.ID[0] << 21) | \ 48 | (MODULE_CAN->MBX_CTRL.FCTRL.TX_RX.EXT.ID[1] << 13) | (MODULE_CAN->MBX_CTRL.FCTRL.TX_RX.EXT.ID[2] << 5) | \ 49 | (MODULE_CAN->MBX_CTRL.FCTRL.TX_RX.EXT.ID[3] >> 3)) 50 | 51 | /** \brief Set standard message ID */ 52 | #define _CAN_SET_STD_ID(x) \ 53 | MODULE_CAN->MBX_CTRL.FCTRL.TX_RX.STD.ID[0] = ((x) >> 3); \ 54 | MODULE_CAN->MBX_CTRL.FCTRL.TX_RX.STD.ID[1] = ((x) << 5); 55 | 56 | /** \brief Set extended message ID */ 57 | #define _CAN_SET_EXT_ID(x) \ 58 | MODULE_CAN->MBX_CTRL.FCTRL.TX_RX.EXT.ID[0] = ((x) >> 21); \ 59 | MODULE_CAN->MBX_CTRL.FCTRL.TX_RX.EXT.ID[1] = ((x) >> 13); \ 60 | MODULE_CAN->MBX_CTRL.FCTRL.TX_RX.EXT.ID[2] = ((x) >> 5); \ 61 | MODULE_CAN->MBX_CTRL.FCTRL.TX_RX.EXT.ID[3] = ((x) << 3); 62 | 63 | /** \brief Interrupt status register */ 64 | typedef enum { 65 | __CAN_IRQ_RX = BIT(0), /**< \brief RX Interrupt */ 66 | __CAN_IRQ_TX = BIT(1), /**< \brief TX Interrupt */ 67 | __CAN_IRQ_ERR = BIT(2), /**< \brief Error Interrupt */ 68 | __CAN_IRQ_DATA_OVERRUN = BIT(3), /**< \brief Data Overrun Interrupt */ 69 | __CAN_IRQ_WAKEUP = BIT(4), /**< \brief Wakeup Interrupt */ 70 | __CAN_IRQ_ERR_PASSIVE = BIT(5), /**< \brief Passive Error Interrupt */ 71 | __CAN_IRQ_ARB_LOST = BIT(6), /**< \brief Arbitration lost interrupt */ 72 | __CAN_IRQ_BUS_ERR = BIT(7), /**< \brief Bus error Interrupt */ 73 | } __CAN_IRQ_t; 74 | 75 | /** \brief OCMODE options. */ 76 | typedef enum { 77 | __CAN_OC_BOM = 0b00, /**< \brief bi-phase output mode */ 78 | __CAN_OC_TOM = 0b01, /**< \brief test output mode */ 79 | __CAN_OC_NOM = 0b10, /**< \brief normal output mode */ 80 | __CAN_OC_COM = 0b11, /**< \brief clock output mode */ 81 | } __CAN_OCMODE_t; 82 | 83 | /** 84 | * CAN controller (SJA1000). 85 | */ 86 | typedef struct { 87 | union { 88 | uint32_t U; /**< \brief Unsigned access */ 89 | struct { 90 | unsigned int RM : 1; /**< \brief MOD.0 Reset Mode */ 91 | unsigned int LOM : 1; /**< \brief MOD.1 Listen Only Mode */ 92 | unsigned int STM : 1; /**< \brief MOD.2 Self Test Mode */ 93 | unsigned int AFM : 1; /**< \brief MOD.3 Acceptance Filter Mode */ 94 | unsigned int SM : 1; /**< \brief MOD.4 Sleep Mode */ 95 | unsigned int reserved_27 : 27; /**< \brief \internal Reserved */ 96 | } B; 97 | } MOD; 98 | union { 99 | uint32_t U; /**< \brief Unsigned access */ 100 | struct { 101 | unsigned int TR : 1; /**< \brief CMR.0 Transmission Request */ 102 | unsigned int AT : 1; /**< \brief CMR.1 Abort Transmission */ 103 | unsigned int RRB : 1; /**< \brief CMR.2 Release Receive Buffer */ 104 | unsigned int CDO : 1; /**< \brief CMR.3 Clear Data Overrun */ 105 | unsigned int GTS : 1; /**< \brief CMR.4 Go To Sleep */ 106 | unsigned int reserved_27 : 27; /**< \brief \internal Reserved */ 107 | } B; 108 | } CMR; 109 | union { 110 | uint32_t U; /**< \brief Unsigned access */ 111 | struct { 112 | unsigned int RBS : 1; /**< \brief SR.0 Receive Buffer Status */ 113 | unsigned int DOS : 1; /**< \brief SR.1 Data Overrun Status */ 114 | unsigned int TBS : 1; /**< \brief SR.2 Transmit Buffer Status */ 115 | unsigned int TCS : 1; /**< \brief SR.3 Transmission Complete Status */ 116 | unsigned int RS : 1; /**< \brief SR.4 Receive Status */ 117 | unsigned int TS : 1; /**< \brief SR.5 Transmit Status */ 118 | unsigned int ES : 1; /**< \brief SR.6 Error Status */ 119 | unsigned int BS : 1; /**< \brief SR.7 Bus Status */ 120 | unsigned int reserved_24 : 24; /**< \brief \internal Reserved */ 121 | } B; 122 | } SR; 123 | union { 124 | uint32_t U; /**< \brief Unsigned access */ 125 | struct { 126 | unsigned int RI : 1; /**< \brief IR.0 Receive Interrupt */ 127 | unsigned int TI : 1; /**< \brief IR.1 Transmit Interrupt */ 128 | unsigned int EI : 1; /**< \brief IR.2 Error Interrupt */ 129 | unsigned int DOI : 1; /**< \brief IR.3 Data Overrun Interrupt */ 130 | unsigned int WUI : 1; /**< \brief IR.4 Wake-Up Interrupt */ 131 | unsigned int EPI : 1; /**< \brief IR.5 Error Passive Interrupt */ 132 | unsigned int ALI : 1; /**< \brief IR.6 Arbitration Lost Interrupt */ 133 | unsigned int BEI : 1; /**< \brief IR.7 Bus Error Interrupt */ 134 | unsigned int reserved_24 : 24; /**< \brief \internal Reserved */ 135 | } B; 136 | } IR; 137 | union { 138 | uint32_t U; /**< \brief Unsigned access */ 139 | struct { 140 | unsigned int RIE : 1; /**< \brief IER.0 Receive Interrupt Enable */ 141 | unsigned int TIE : 1; /**< \brief IER.1 Transmit Interrupt Enable */ 142 | unsigned int EIE : 1; /**< \brief IER.2 Error Interrupt Enable */ 143 | unsigned int DOIE : 1; /**< \brief IER.3 Data Overrun Interrupt Enable */ 144 | unsigned int WUIE : 1; /**< \brief IER.4 Wake-Up Interrupt Enable */ 145 | unsigned int EPIE : 1; /**< \brief IER.5 Error Passive Interrupt Enable */ 146 | unsigned int ALIE : 1; /**< \brief IER.6 Arbitration Lost Interrupt Enable */ 147 | unsigned int BEIE : 1; /**< \brief IER.7 Bus Error Interrupt Enable */ 148 | unsigned int reserved_24 : 24; /**< \brief \internal Reserved */ 149 | } B; 150 | } IER; 151 | uint32_t RESERVED0; 152 | union { 153 | uint32_t U; /**< \brief Unsigned access */ 154 | struct { 155 | unsigned int BRP : 6; /**< \brief BTR0[5:0] Baud Rate Prescaler */ 156 | unsigned int SJW : 2; /**< \brief BTR0[7:6] Synchronization Jump Width*/ 157 | unsigned int reserved_24 : 24; /**< \brief \internal Reserved */ 158 | } B; 159 | } BTR0; 160 | union { 161 | uint32_t U; /**< \brief Unsigned access */ 162 | struct { 163 | unsigned int TSEG1 : 4; /**< \brief BTR1[3:0] Timing Segment 1 */ 164 | unsigned int TSEG2 : 3; /**< \brief BTR1[6:4] Timing Segment 2*/ 165 | unsigned int SAM : 1; /**< \brief BTR1.7 Sampling*/ 166 | unsigned int reserved_24 : 24; /**< \brief \internal Reserved */ 167 | } B; 168 | } BTR1; 169 | union { 170 | uint32_t U; /**< \brief Unsigned access */ 171 | struct { 172 | unsigned int OCMODE : 2; /**< \brief OCR[1:0] Output Control Mode, see # */ 173 | unsigned int OCPOL0 : 1; /**< \brief OCR.2 Output Control Polarity 0 */ 174 | unsigned int OCTN0 : 1; /**< \brief OCR.3 Output Control Transistor N0 */ 175 | unsigned int OCTP0 : 1; /**< \brief OCR.4 Output Control Transistor P0 */ 176 | unsigned int OCPOL1 : 1; /**< \brief OCR.5 Output Control Polarity 1 */ 177 | unsigned int OCTN1 : 1; /**< \brief OCR.6 Output Control Transistor N1 */ 178 | unsigned int OCTP1 : 1; /**< \brief OCR.7 Output Control Transistor P1 */ 179 | unsigned int reserved_24 : 24; /**< \brief \internal Reserved */ 180 | } B; 181 | } OCR; 182 | uint32_t RESERVED1[2]; 183 | union { 184 | uint32_t U; /**< \brief Unsigned access */ 185 | struct { 186 | unsigned int ALC : 8; /**< \brief ALC[7:0] Arbitration Lost Capture */ 187 | unsigned int reserved_24 : 24; /**< \brief \internal Reserved */ 188 | } B; 189 | } ALC; 190 | union { 191 | uint32_t U; /**< \brief Unsigned access */ 192 | struct { 193 | unsigned int ECC : 8; /**< \brief ECC[7:0] Error Code Capture */ 194 | unsigned int reserved_24 : 24; /**< \brief \internal Reserved */ 195 | } B; 196 | } ECC; 197 | union { 198 | uint32_t U; /**< \brief Unsigned access */ 199 | struct { 200 | unsigned int EWLR : 8; /**< \brief EWLR[7:0] Error Warning Limit */ 201 | unsigned int reserved_24 : 24; /**< \brief \internal Reserved */ 202 | } B; 203 | } EWLR; 204 | union { 205 | uint32_t U; /**< \brief Unsigned access */ 206 | struct { 207 | unsigned int RXERR : 8; /**< \brief RXERR[7:0] Receive Error Counter */ 208 | unsigned int reserved_24 : 24; /**< \brief \internal Reserved */ 209 | } B; 210 | } RXERR; 211 | union { 212 | uint32_t U; /**< \brief Unsigned access */ 213 | struct { 214 | unsigned int TXERR : 8; /**< \brief TXERR[7:0] Transmit Error Counter */ 215 | unsigned int reserved_24 : 24; /**< \brief \internal Reserved */ 216 | } B; 217 | } TXERR; 218 | 219 | union { 220 | struct { 221 | uint32_t CODE[4]; /**< \brief Acceptance Message ID */ 222 | uint32_t MASK[4]; /**< \brief Acceptance Mask */ 223 | uint32_t RESERVED2[5]; 224 | } ACC; /**< \brief Acceptance filtering */ 225 | struct { 226 | CAN_FIR_t FIR; /**< \brief Frame information record */ 227 | union { 228 | struct { 229 | uint32_t ID[2]; /**< \brief Standard frame message-ID*/ 230 | uint32_t data[8]; /**< \brief Standard frame payload */ 231 | uint32_t reserved[2]; 232 | } STD; /**< \brief Standard frame format */ 233 | struct { 234 | uint32_t ID[4]; /**< \brief Extended frame message-ID*/ 235 | uint32_t data[8]; /**< \brief Extended frame payload */ 236 | } EXT; /**< \brief Extended frame format */ 237 | } TX_RX; /**< \brief RX/TX interface */ 238 | } FCTRL; /**< \brief Function control regs */ 239 | } MBX_CTRL; /**< \brief Mailbox control */ 240 | union { 241 | uint32_t U; /**< \brief Unsigned access */ 242 | struct { 243 | unsigned int RMC : 8; /**< \brief RMC[7:0] RX Message Counter */ 244 | unsigned int reserved_24 : 24; /**< \brief \internal Reserved Enable */ 245 | } B; 246 | } RMC; 247 | union { 248 | uint32_t U; /**< \brief Unsigned access */ 249 | struct { 250 | unsigned int RBSA : 8; /**< \brief RBSA[7:0] RX Buffer Start Address */ 251 | unsigned int reserved_24 : 24; /**< \brief \internal Reserved Enable */ 252 | } B; 253 | } RBSA; 254 | union { 255 | uint32_t U; /**< \brief Unsigned access */ 256 | struct { 257 | unsigned int COD : 3; /**< \brief CDR[2:0] CLKOUT frequency selector based of fOSC*/ 258 | unsigned int COFF : 1; /**< \brief CDR.3 CLKOUT off*/ 259 | unsigned int reserved_1 : 1; /**< \brief \internal Reserved */ 260 | unsigned int 261 | RXINTEN : 1; /**< \brief CDR.5 This bit allows the TX1 output to be used as a dedicated receive interrupt 262 | output*/ 263 | unsigned int 264 | CBP : 1; /**< \brief CDR.6 allows to bypass the CAN input comparator and is only possible in reset mode.*/ 265 | unsigned int 266 | CAN_M : 1; /**< \brief CDR.7 If CDR.7 is at logic 0 the CAN controller operates in BasicCAN mode. If set to 267 | logic 1 the CAN controller operates in PeliCAN mode. Write access is only possible in reset 268 | mode*/ 269 | unsigned int reserved_24 : 24; /**< \brief \internal Reserved */ 270 | } B; 271 | } CDR; 272 | uint32_t IRAM[2]; 273 | } CAN_Module_t; 274 | 275 | #ifdef __cplusplus 276 | } 277 | #endif 278 | 279 | #endif /* __DRIVERS_CAN_REGDEF_H_ */ 280 | --------------------------------------------------------------------------------