Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cpu/samd5x/periph_can: fix RX [backport 2025.01] #21184

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 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_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 Expand Up @@ -214,7 +243,7 @@

/* Set bit timing */
dev->conf->can->NBTP.reg = (uint32_t)((CAN_NBTP_NTSEG2(dev->candev.bittiming.phase_seg2 - 1))
| (CAN_NBTP_NTSEG1(dev->candev.bittiming.phase_seg1 + dev->candev.bittiming.prop_seg - 1))

Check warning on line 246 in cpu/samd5x/periph/can.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
| (CAN_NBTP_NBRP(dev->candev.bittiming.brp - 1))
| (CAN_NBTP_NSJW(dev->candev.bittiming.sjw - 1)));
}
Expand Down Expand Up @@ -355,9 +384,9 @@
| CAN_RXF1C_F1S((uint32_t)(ARRAY_SIZE(dev->msg_ram_conf.rx_fifo_1)));
dev->conf->can->RXBC.reg = CAN_RXBC_RBSA((uint32_t)(dev->msg_ram_conf.rx_buffer));
dev->conf->can->TXEFC.reg = CAN_TXEFC_EFSA((uint32_t)(dev->msg_ram_conf.tx_event_fifo))
| CAN_TXEFC_EFS((uint32_t)(ARRAY_SIZE(dev->msg_ram_conf.tx_event_fifo)));

Check warning on line 387 in cpu/samd5x/periph/can.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
dev->conf->can->TXBC.reg = CAN_TXBC_TBSA((uint32_t)(dev->msg_ram_conf.tx_fifo_queue))
| CAN_TXBC_TFQS((uint32_t)(ARRAY_SIZE(dev->msg_ram_conf.tx_fifo_queue)));

Check warning on line 389 in cpu/samd5x/periph/can.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters

/* In the vendor file, the data field size in CanMramTxbe is set to 64 bytes
although it can be configurable. That's why 64 bytes is used here by default */
Expand Down Expand Up @@ -458,7 +487,7 @@
/* Write the second word */
dev->msg_ram_conf.tx_fifo_queue[can_mm.put].TXBE_1.reg = txbe1;

memcpy((void *)dev->msg_ram_conf.tx_fifo_queue[can_mm.put].TXBE_DATA, frame->data, frame->can_dlc);

Check warning on line 490 in cpu/samd5x/periph/can.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters

/* Request transmission */
dev->conf->can->TXBAR.reg |= (1 << can_mm.put);
Expand Down Expand Up @@ -544,9 +573,9 @@
DEBUG("Extended Filter to add at idx = %d\n", idx);
dev->msg_ram_conf.ext_filter[idx].XIDFE_0.reg |= CAN_XIDFE_0_EFEC(filter_conf);
/* For now, only CLASSIC filters are supported */
dev->msg_ram_conf.ext_filter[idx].XIDFE_1.reg |= CAN_XIDFE_1_EFT(CANDEV_SAMD5X_CLASSIC_FILTER);

Check warning on line 576 in cpu/samd5x/periph/can.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
dev->msg_ram_conf.ext_filter[idx].XIDFE_0.reg |= CAN_XIDFE_0_EFID1(filter->can_id);
dev->msg_ram_conf.ext_filter[idx].XIDFE_1.reg |= CAN_XIDFE_1_EFID2(filter->can_mask & CAN_EFF_MASK);

Check warning on line 578 in cpu/samd5x/periph/can.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
DEBUG("Extended filter element N°%d: F0 = 0x%08lx, F1 = 0x%08lx\n", idx,
(uint32_t)(dev->msg_ram_conf.ext_filter[idx].XIDFE_0.reg),
(uint32_t)(dev->msg_ram_conf.ext_filter[idx].XIDFE_1.reg));
Expand Down Expand Up @@ -583,9 +612,9 @@
DEBUG("Standard Filter to add at idx = %d\n", idx);
/* For now, only CLASSIC filters are supported */
dev->msg_ram_conf.std_filter[idx].SIDFE_0.reg = CAN_SIDFE_0_SFEC(filter_conf)
| CAN_SIDFE_0_SFT(CANDEV_SAMD5X_CLASSIC_FILTER)

Check warning on line 615 in cpu/samd5x/periph/can.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
| CAN_SIDFE_0_SFID1(filter->can_id & CAN_SFF_MASK)

Check warning on line 616 in cpu/samd5x/periph/can.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
| CAN_SIDFE_0_SFID2(filter->can_mask & CAN_SFF_MASK);

Check warning on line 617 in cpu/samd5x/periph/can.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters

DEBUG("Standard filter element N°%d: S0 = 0x%08lx\n", idx,
(uint32_t)(dev->msg_ram_conf.std_filter[idx].SIDFE_0.reg));
Expand Down Expand Up @@ -749,7 +778,7 @@
frame_received.can_dlc =
(dev->msg_ram_conf.rx_fifo_0[rx_get_idx].RXF0E_1.reg & CAN_RXF0E_1_DLC_Msk) >>
CAN_RXF0E_1_DLC_Pos;
memcpy(frame_received.data, (uint32_t *)dev->msg_ram_conf.rx_fifo_0[rx_get_idx].RXF0E_DATA, frame_received.can_dlc);

Check warning on line 781 in cpu/samd5x/periph/can.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters

dev->conf->can->RXF0A.reg = CAN_RXF0A_F0AI(rx_get_idx);
if (dev->candev.event_callback) {
Expand Down