/ src / ESP32SJA1000.cpp
ESP32SJA1000.cpp
  1  // Copyright (c) Sandeep Mistry. All rights reserved.
  2  // Licensed under the MIT license. See LICENSE file in the project root for full license information.
  3  
  4  #ifdef ARDUINO_ARCH_ESP32
  5  
  6  #include "esp_intr.h"
  7  #include "soc/dport_reg.h"
  8  #include "driver/gpio.h"
  9  
 10  #include "ESP32SJA1000.h"
 11  
 12  #define REG_BASE                   0x3ff6b000
 13  
 14  #define REG_MOD                    0x00
 15  #define REG_CMR                    0x01
 16  #define REG_SR                     0x02
 17  #define REG_IR                     0x03
 18  #define REG_IER                    0x04
 19  
 20  #define REG_BTR0                   0x06
 21  #define REG_BTR1                   0x07
 22  #define REG_OCR                    0x08
 23  
 24  #define REG_ALC                    0x0b
 25  #define REG_ECC                    0x0c
 26  #define REG_EWLR                   0x0d
 27  #define REG_RXERR                  0x0e
 28  #define REG_TXERR                  0x0f
 29  #define REG_SFF                    0x10
 30  #define REG_EFF                    0x10
 31  #define REG_ACRn(n)                (0x10 + n)
 32  #define REG_AMRn(n)                (0x14 + n)
 33  
 34  #define REG_CDR                    0x1F
 35  
 36  
 37  ESP32SJA1000Class::ESP32SJA1000Class() :
 38    CANControllerClass(),
 39    _rxPin(DEFAULT_CAN_RX_PIN),
 40    _txPin(DEFAULT_CAN_TX_PIN),
 41    _loopback(false),
 42    _intrHandle(NULL)
 43  {
 44  }
 45  
 46  ESP32SJA1000Class::~ESP32SJA1000Class()
 47  {
 48  }
 49  
 50  int ESP32SJA1000Class::begin(long baudRate)
 51  {
 52    CANControllerClass::begin(baudRate);
 53  
 54    _loopback = false;
 55  
 56    DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_CAN_RST);
 57    DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_CAN_CLK_EN);
 58  
 59    // RX pin
 60    gpio_set_direction(_rxPin, GPIO_MODE_INPUT);
 61    gpio_matrix_in(_rxPin, CAN_RX_IDX, 0);
 62    gpio_pad_select_gpio(_rxPin);
 63  
 64    // TX pin
 65    gpio_set_direction(_txPin, GPIO_MODE_OUTPUT);
 66    gpio_matrix_out(_txPin, CAN_TX_IDX, 0, 0);
 67    gpio_pad_select_gpio(_txPin);
 68  
 69    modifyRegister(REG_CDR, 0x80, 0x80); // pelican mode
 70    modifyRegister(REG_BTR0, 0xc0, 0x40); // SJW = 1
 71    modifyRegister(REG_BTR1, 0x70, 0x10); // TSEG2 = 1
 72  
 73    switch (baudRate) {
 74      case (long)1000E3:
 75        modifyRegister(REG_BTR1, 0x0f, 0x04);
 76        modifyRegister(REG_BTR0, 0x3f, 4);
 77        break;
 78  
 79      case (long)500E3:
 80        modifyRegister(REG_BTR1, 0x0f, 0x0c);
 81        modifyRegister(REG_BTR0, 0x3f, 4);
 82        break;
 83  
 84      case (long)250E3:
 85        modifyRegister(REG_BTR1, 0x0f, 0x0c);
 86        modifyRegister(REG_BTR0, 0x3f, 9);
 87        break;
 88  
 89      case (long)200E3:
 90        modifyRegister(REG_BTR1, 0x0f, 0x0c);
 91        modifyRegister(REG_BTR0, 0x3f, 12);
 92        break;
 93  
 94      case (long)125E3:
 95        modifyRegister(REG_BTR1, 0x0f, 0x0c);
 96        modifyRegister(REG_BTR0, 0x3f, 19);
 97        break;
 98  
 99      case (long)100E3:
100        modifyRegister(REG_BTR1, 0x0f, 0x0c);
101        modifyRegister(REG_BTR0, 0x3f, 24);
102        break;
103  
104      case (long)80E3:
105        modifyRegister(REG_BTR1, 0x0f, 0x0c);
106        modifyRegister(REG_BTR0, 0x3f, 30);
107        break;
108  
109      case (long)50E3:
110        modifyRegister(REG_BTR1, 0x0f, 0x0c);
111        modifyRegister(REG_BTR0, 0x3f, 49);
112        break;
113  
114  /*
115     Due to limitations in ESP32 hardware and/or RTOS software, baudrate can't be lower than 50kbps.
116     See https://esp32.com/viewtopic.php?t=2142
117  */
118      default:
119        return 0;
120        break;
121    }
122  
123    modifyRegister(REG_BTR1, 0x80, 0x80); // SAM = 1
124    writeRegister(REG_IER, 0xff); // enable all interrupts
125  
126    // set filter to allow anything
127    writeRegister(REG_ACRn(0), 0x00);
128    writeRegister(REG_ACRn(1), 0x00);
129    writeRegister(REG_ACRn(2), 0x00);
130    writeRegister(REG_ACRn(3), 0x00);
131    writeRegister(REG_AMRn(0), 0xff);
132    writeRegister(REG_AMRn(1), 0xff);
133    writeRegister(REG_AMRn(2), 0xff);
134    writeRegister(REG_AMRn(3), 0xff);
135  
136    modifyRegister(REG_OCR, 0x03, 0x02); // normal output mode
137    // reset error counters
138    writeRegister(REG_TXERR, 0x00);
139    writeRegister(REG_RXERR, 0x00);
140  
141    // clear errors and interrupts
142    readRegister(REG_ECC);
143    readRegister(REG_IR);
144  
145    // normal mode
146    modifyRegister(REG_MOD, 0x08, 0x08);
147    modifyRegister(REG_MOD, 0x17, 0x00);
148  
149    return 1;
150  }
151  
152  void ESP32SJA1000Class::end()
153  {
154    if (_intrHandle) {
155      esp_intr_free(_intrHandle);
156      _intrHandle = NULL;
157    }
158  
159    DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_CAN_RST);
160    DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_CAN_CLK_EN);
161  
162    CANControllerClass::end();
163  }
164  
165  int ESP32SJA1000Class::endPacket()
166  {
167    if (!CANControllerClass::endPacket()) {
168      return 0;
169    }
170  
171    // wait for TX buffer to free
172    while ((readRegister(REG_SR) & 0x04) != 0x04) {
173      yield();
174    }
175  
176    int dataReg;
177  
178    if (_txExtended) {
179      writeRegister(REG_EFF, 0x80 | (_txRtr ? 0x40 : 0x00) | (0x0f & _txLength));
180      writeRegister(REG_EFF + 1, _txId >> 21);
181      writeRegister(REG_EFF + 2, _txId >> 13);
182      writeRegister(REG_EFF + 3, _txId >> 5);
183      writeRegister(REG_EFF + 4, _txId << 3);
184  
185      dataReg = REG_EFF + 5;
186    } else {
187      writeRegister(REG_SFF, (_txRtr ? 0x40 : 0x00) | (0x0f & _txLength));
188      writeRegister(REG_SFF + 1, _txId >> 3);
189      writeRegister(REG_SFF + 2, _txId << 5);
190  
191      dataReg = REG_SFF + 3;
192    }
193  
194    for (int i = 0; i < _txLength; i++) {
195      writeRegister(dataReg + i, _txData[i]);
196    }
197  
198    if ( _loopback) {
199      // self reception request
200      modifyRegister(REG_CMR, 0x1f, 0x10);
201    } else {
202      // transmit request
203      modifyRegister(REG_CMR, 0x1f, 0x01);
204    }
205  
206    // wait for TX complete
207    while ((readRegister(REG_SR) & 0x08) != 0x08) {
208      if (readRegister(REG_ECC) == 0xd9) {
209        modifyRegister(REG_CMR, 0x1f, 0x02); // error, abort
210        return 0;
211      }
212      yield();
213    }
214  
215    return 1;
216  }
217  
218  int ESP32SJA1000Class::parsePacket()
219  {
220    if ((readRegister(REG_SR) & 0x01) != 0x01) {
221      // no packet
222      return 0;
223    }
224  
225    _rxExtended = (readRegister(REG_SFF) & 0x80) ? true : false;
226    _rxRtr = (readRegister(REG_SFF) & 0x40) ? true : false;
227    _rxDlc = (readRegister(REG_SFF) & 0x0f);
228    _rxIndex = 0;
229  
230    int dataReg;
231  
232    if (_rxExtended) {
233      _rxId = (readRegister(REG_EFF + 1) << 21) |
234              (readRegister(REG_EFF + 2) << 13) |
235              (readRegister(REG_EFF + 3) << 5) |
236              (readRegister(REG_EFF + 4) >> 3);
237  
238      dataReg = REG_EFF + 5;
239    } else {
240      _rxId = (readRegister(REG_SFF + 1) << 3) | ((readRegister(REG_SFF + 2) >> 5) & 0x07);
241  
242      dataReg = REG_SFF + 3;
243    }
244  
245    if (_rxRtr) {
246      _rxLength = 0;
247    } else {
248      _rxLength = _rxDlc;
249  
250      for (int i = 0; i < _rxLength; i++) {
251        _rxData[i] = readRegister(dataReg + i);
252      }
253    }
254  
255    // release RX buffer
256    modifyRegister(REG_CMR, 0x04, 0x04);
257  
258    return _rxDlc;
259  }
260  
261  void ESP32SJA1000Class::onReceive(void(*callback)(int))
262  {
263    CANControllerClass::onReceive(callback);
264  
265    if (_intrHandle) {
266      esp_intr_free(_intrHandle);
267      _intrHandle = NULL;
268    }
269  
270    if (callback) {
271      esp_intr_alloc(ETS_CAN_INTR_SOURCE, 0, ESP32SJA1000Class::onInterrupt, this, &_intrHandle);
272    }
273  }
274  
275  int ESP32SJA1000Class::filter(int id, int mask)
276  {
277    id &= 0x7ff;
278    mask = ~(mask & 0x7ff);
279  
280    modifyRegister(REG_MOD, 0x17, 0x01); // reset
281  
282    writeRegister(REG_ACRn(0), id >> 3);
283    writeRegister(REG_ACRn(1), id << 5);
284    writeRegister(REG_ACRn(2), 0x00);
285    writeRegister(REG_ACRn(3), 0x00);
286  
287    writeRegister(REG_AMRn(0), mask >> 3);
288    writeRegister(REG_AMRn(1), (mask << 5) | 0x1f);
289    writeRegister(REG_AMRn(2), 0xff);
290    writeRegister(REG_AMRn(3), 0xff);
291  
292    modifyRegister(REG_MOD, 0x17, 0x00); // normal
293  
294    return 1;
295  }
296  
297  int ESP32SJA1000Class::filterExtended(long id, long mask)
298  {
299    id &= 0x1FFFFFFF;
300    mask &= ~(mask & 0x1FFFFFFF);
301  
302    modifyRegister(REG_MOD, 0x17, 0x01); // reset
303  
304    writeRegister(REG_ACRn(0), id >> 21);
305    writeRegister(REG_ACRn(1), id >> 13);
306    writeRegister(REG_ACRn(2), id >> 5);
307    writeRegister(REG_ACRn(3), id << 5);
308  
309    writeRegister(REG_AMRn(0), mask >> 21);
310    writeRegister(REG_AMRn(1), mask >> 13);
311    writeRegister(REG_AMRn(2), mask >> 5);
312    writeRegister(REG_AMRn(3), (mask << 5) | 0x1f);
313  
314    modifyRegister(REG_MOD, 0x17, 0x00); // normal
315  
316    return 1;
317  }
318  
319  int ESP32SJA1000Class::observe()
320  {
321    modifyRegister(REG_MOD, 0x17, 0x01); // reset
322    modifyRegister(REG_MOD, 0x17, 0x02); // observe
323  
324    return 1;
325  }
326  
327  int ESP32SJA1000Class::loopback()
328  {
329    _loopback = true;
330  
331    modifyRegister(REG_MOD, 0x17, 0x01); // reset
332    modifyRegister(REG_MOD, 0x17, 0x04); // self test mode
333  
334    return 1;
335  }
336  
337  int ESP32SJA1000Class::sleep()
338  {
339    modifyRegister(REG_MOD, 0x1f, 0x10);
340  
341    return 1;
342  }
343  
344  int ESP32SJA1000Class::wakeup()
345  {
346    modifyRegister(REG_MOD, 0x1f, 0x00);
347  
348    return 1;
349  }
350  
351  void ESP32SJA1000Class::setPins(int rx, int tx)
352  {
353    _rxPin = (gpio_num_t)rx;
354    _txPin = (gpio_num_t)tx;
355  }
356  
357  void ESP32SJA1000Class::dumpRegisters(Stream& out)
358  {
359    for (int i = 0; i < 32; i++) {
360      byte b = readRegister(i);
361  
362      out.print("0x");
363      if (i < 16) {
364        out.print('0');
365      }
366      out.print(i, HEX);
367      out.print(": 0x");
368      if (b < 16) {
369        out.print('0');
370      }
371      out.println(b, HEX);
372    }
373  }
374  
375  void ESP32SJA1000Class::handleInterrupt()
376  {
377    uint8_t ir = readRegister(REG_IR);
378  
379    if (ir & 0x01) {
380      // received packet, parse and call callback
381      parsePacket();
382  
383      _onReceive(available());
384    }
385  }
386  
387  uint8_t ESP32SJA1000Class::readRegister(uint8_t address)
388  {
389    volatile uint32_t* reg = (volatile uint32_t*)(REG_BASE + address * 4);
390  
391    return *reg;
392  }
393  
394  void ESP32SJA1000Class::modifyRegister(uint8_t address, uint8_t mask, uint8_t value)
395  {
396    volatile uint32_t* reg = (volatile uint32_t*)(REG_BASE + address * 4);
397  
398    *reg = (*reg & ~mask) | value;
399  }
400  
401  void ESP32SJA1000Class::writeRegister(uint8_t address, uint8_t value)
402  {
403    volatile uint32_t* reg = (volatile uint32_t*)(REG_BASE + address * 4);
404  
405    *reg = value;
406  }
407  
408  void ESP32SJA1000Class::onInterrupt(void* arg)
409  {
410    ((ESP32SJA1000Class*)arg)->handleInterrupt();
411  }
412  
413  ESP32SJA1000Class CAN;
414  
415  #endif