Skip to content

Commit

Permalink
Merge pull request #21184 from maribu/backport/2025.01/cpu/samd5x/can…
Browse files Browse the repository at this point in the history
…-fix-rx

cpu/samd5x/periph_can: fix RX [backport 2025.01]
  • Loading branch information
maribu authored Feb 3, 2025
2 parents d06a7d9 + 97006a8 commit a3627b7
Showing 1 changed file with 30 additions and 1 deletion.
31 changes: 30 additions & 1 deletion cpu/samd5x/periph/can.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@
#include <assert.h>
#include <string.h>

#include "can/device.h"
#include "periph/can.h"
#include "periph/gpio.h"
#include "can/device.h"
#include "pm_layered.h"

#define ENABLE_DEBUG 0
#include "debug.h"
Expand Down Expand Up @@ -107,6 +108,30 @@ static const struct can_bittiming_const bittiming_const = {

static int _power_on(can_t *dev)
{
/* CAN required CLK_CANx_APB and GCLK_CANx to be running and will not
* request any clock by itself. We can ensure both clocks to be running
* by preventing the MCU from entering IDLE state.
*
* The SAMD5x/SAME5x Family Data Sheet says in Section
* "39.6.9 Sleep Mode Operation" says:
*
* > The CAN can be configured to operate in any idle sleep mode. The CAN
* > cannot operate in Standby sleep mode.
* >
* > [...]
* >
* > To leave low power mode, CLK_CANx_APB and GCLK_CANx must be active
* > before writing CCCR.CSR to '0'. The CAN will acknowledge this by
* > resetting CCCR.CSA = 0. Afterwards, the application can restart CAN
* > communication by resetting bit CCCR.INIT.
*
* tl;dr: At most SAM0_PM_IDLE is allowed while not shutting down the CAN
* controller, but even that will pause communication (including RX).
*/
if (IS_USED(MODULE_PM_LAYERED)) {
pm_block(SAM0_PM_IDLE);
}

if (dev->conf->can == CAN0) {
DEBUG_PUTS("CAN0 controller is used");
MCLK->AHBMASK.reg |= MCLK_AHBMASK_CAN0;
Expand All @@ -125,6 +150,10 @@ static int _power_on(can_t *dev)

static int _power_off(can_t *dev)
{
if (IS_USED(MODULE_PM_LAYERED)) {
pm_unblock(SAM0_PM_IDLE);
}

if (dev->conf->can == CAN0) {
DEBUG_PUTS("CAN0 controller is used");
MCLK->AHBMASK.reg &= ~MCLK_AHBMASK_CAN0;
Expand Down

0 comments on commit a3627b7

Please sign in to comment.