This is far from trivial to do for this part, took me quite a while and then I'm something of a veteran when it comes to writing CAN drivers. Turns out that you have to be in order to use CAN on SAM C21, because the documentation for this CAN controller is by far the worst I've ever seen.
(On the positive side, the controller hardware itself is very good & modern, with both mailbox features and built-in DMA-like features that map incoming data straight to RAM etc.)
First of all, it should be noted that the app notes and code examples provided by Atmel/Microchip are poor and contain errors. You can trust the vague MCU manual (which doesn't contain examples...), but you cannot trust the app notes nor the ASF source documentation. The very part of the app note you quote is blatantly incorrect and written by some rookie who doesn't know CAN controllers (and didn't RTFM).
I had to grind facts against Microchip's support wall for quite a while before they finally gave in and admitted that the ASF driver and app notes were incorrectly documented. Seems they haven't updated them though... I discovered these problems and reported them to Microchip almost one year ago.
The documentation incorrectly claims that you calculate baudrate by adding the tq of SJW, SEG1 and SEG2 - those who know CAN controllers know that this is nonsense - SJW has nothing to do with bit length - and the app note does not correspond with the MCU manual either (which doesn't give you the formula at all). By luck they came up with the sum of 16 in their examples, by failing to take the +1 needed by the register for each segment, and so they worked by luck, for one specific clock & baudrate.
The correct formula, which you cannot find explicitly anywhere in documentation, is this:
total_tq = sync_seg_tq + (phase_seg1_tq+1) + (phase_seg2_tq+1)
Where "sync_seg" is the initial segment of fixed 1 tq length, which is NOT the same thing as SJW (synchronization jump width). The +1 parts are hinted at by the MCU manual.
Now what does this tq gibberish mean? In CAN bus timing, each bit is synchronized and divided in a number of units known as time quanta (tq). When configuring the baudrate, one should strive to get the sample point as close to 87.5% of the bit length as possible (industry de facto and CANopen standard). We do this by configuring the length of the various tq segments. Ideally one strives to have 14 tq before the sample point and 2tq after it, for a total of 16 tq (14/16 = 87.5%).
If this is possible or not for a given baudrate depends on the CAN controller's peripheral clock. On SAMC21, you have to first setup the system clock, then have one of the "GCLK" drive the CAN peripheral. If you run at 8MHz and want 125kbps, then one possible configuration is 8MHz divided by 4 for a CAN controller clock of 2MHz. That is, each tq is clocked at 2MHz, and 2MHz/16 = 125kHz.
- The desired clock divisor is 4.
- The desired amount of tq before sample point is 14: 1 tq sync seg + 13 tq phase seg1.
- The desired amount of tq after sample point is 2: 2 tq phase seg2.
- Recommended SJW is 1 or 2 for 125kbps, this is the error tolerance you allow - should be set higher for higher baudrates. Lets go with 2, though 1 will work too.
Assuming you use the ASF register map, you should then have this setup:
can_port->NBTP.reg = CAN_NBTP_NBRP(4-1) |
can_port->DBTP.reg = CAN_DBTP_DBRP(4-1) |