Skip to content
Merged
Show file tree
Hide file tree
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
77 changes: 44 additions & 33 deletions drivers/can/can_mcan.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,34 @@ LOG_MODULE_DECLARE(can_driver, CONFIG_CAN_LOG_LEVEL);
#define MCAN_MAX_DLC CAN_MAX_DLC
#endif

static void memcpy32_volatile(volatile void *dst_, const volatile void *src_,
size_t len)
{
volatile uint32_t *dst = dst_;
const volatile uint32_t *src = src_;

__ASSERT(len % 4 == 0, "len must be a multiple of 4!");
len /= sizeof(uint32_t);

while (len--) {
*dst = *src;
++dst;
++src;
}
}

static void memset32_volatile(volatile void *dst_, uint32_t val, size_t len)
{
volatile uint32_t *dst = dst_;

__ASSERT(len % 4 == 0, "len must be a multiple of 4!");
len /= sizeof(uint32_t);

while (len--) {
*dst++ = val;
}
}

static int can_exit_sleep_mode(struct can_mcan_reg *can)
{
uint32_t start_time;
Expand Down Expand Up @@ -389,12 +417,7 @@ int can_mcan_init(const struct device *dev, const struct can_mcan_config *cfg,
}

/* No memset because only aligned ptr are allowed */
for (uint32_t *ptr = (uint32_t *)msg_ram;
ptr < (uint32_t *)msg_ram +
sizeof(struct can_mcan_msg_sram) / sizeof(uint32_t);
ptr++) {
*ptr = 0;
}
memset32_volatile(msg_ram, 0, sizeof(struct can_mcan_msg_sram));

return 0;
}
Expand Down Expand Up @@ -486,15 +509,15 @@ static void can_mcan_get_message(struct can_mcan_data *data,
uint32_t get_idx, filt_idx;
struct zcan_frame frame;
can_rx_callback_t cb;
volatile uint32_t *src, *dst, *end;
int data_length;
void *cb_arg;
struct can_mcan_rx_fifo_hdr hdr;

while ((*fifo_status_reg & CAN_MCAN_RXF0S_F0FL)) {
get_idx = (*fifo_status_reg & CAN_MCAN_RXF0S_F0GI) >>
CAN_MCAN_RXF0S_F0GI_POS;
hdr = fifo[get_idx].hdr;
memcpy32_volatile(&hdr, &fifo[get_idx].hdr,
sizeof(struct can_mcan_rx_fifo_hdr));

if (hdr.xtd) {
frame.id = hdr.ext_id;
Expand Down Expand Up @@ -525,13 +548,8 @@ static void can_mcan_get_message(struct can_mcan_data *data,
data_length = can_dlc_to_bytes(frame.dlc);
if (data_length <= sizeof(frame.data)) {
/* data needs to be written in 32 bit blocks!*/
for (src = fifo[get_idx].data_32,
dst = frame.data_32,
end = dst + CAN_DIV_CEIL(data_length, sizeof(uint32_t));
dst < end;
src++, dst++) {
*dst = *src;
}
memcpy32_volatile(frame.data_32, fifo[get_idx].data_32,
ROUND_UP(data_length, sizeof(uint32_t)));

if (frame.id_type == CAN_STANDARD_IDENTIFIER) {
LOG_DBG("Frame on filter %d, ID: 0x%x",
Expand Down Expand Up @@ -647,8 +665,6 @@ int can_mcan_send(const struct can_mcan_config *cfg,
uint32_t put_idx;
int ret;
struct can_mcan_mm mm;
volatile uint32_t *dst, *end;
const uint32_t *src;

LOG_DBG("Sending %d bytes. Id: 0x%x, ID type: %s %s %s %s",
data_length, frame->id,
Expand Down Expand Up @@ -696,15 +712,9 @@ int can_mcan_send(const struct can_mcan_config *cfg,
tx_hdr.ext_id = frame->id;
}

msg_ram->tx_buffer[put_idx].hdr = tx_hdr;

for (src = frame->data_32,
dst = msg_ram->tx_buffer[put_idx].data_32,
end = dst + CAN_DIV_CEIL(data_length, sizeof(uint32_t));
dst < end;
src++, dst++) {
*dst = *src;
}
memcpy32_volatile(&msg_ram->tx_buffer[put_idx].hdr, &tx_hdr, sizeof(tx_hdr));
memcpy32_volatile(msg_ram->tx_buffer[put_idx].data_32, frame->data_32,
ROUND_UP(data_length, 4));

data->tx_fin_cb[put_idx] = callback;
data->tx_fin_cb_arg[put_idx] = callback_arg;
Expand Down Expand Up @@ -761,7 +771,8 @@ int can_mcan_attach_std(struct can_mcan_data *data,
filter_element.sfce = filter_nr & 0x01 ? CAN_MCAN_FCE_FIFO1 :
CAN_MCAN_FCE_FIFO0;

msg_ram->std_filt[filter_nr] = filter_element;
memcpy32_volatile(&msg_ram->std_filt[filter_nr], &filter_element,
sizeof(struct can_mcan_std_filter));

k_mutex_unlock(&data->inst_mutex);

Expand Down Expand Up @@ -820,7 +831,8 @@ static int can_mcan_attach_ext(struct can_mcan_data *data,
filter_element.efce = filter_nr & 0x01 ? CAN_MCAN_FCE_FIFO1 :
CAN_MCAN_FCE_FIFO0;

msg_ram->ext_filt[filter_nr] = filter_element;
memcpy32_volatile(&msg_ram->ext_filt[filter_nr], &filter_element,
sizeof(struct can_mcan_ext_filter));

k_mutex_unlock(&data->inst_mutex);

Expand Down Expand Up @@ -874,9 +886,6 @@ int can_mcan_attach_isr(struct can_mcan_data *data,
void can_mcan_detach(struct can_mcan_data *data,
struct can_mcan_msg_sram *msg_ram, int filter_nr)
{
const struct can_mcan_ext_filter ext_filter = {0};
const struct can_mcan_std_filter std_filter = {0};

k_mutex_lock(&data->inst_mutex, K_FOREVER);
if (filter_nr >= NUM_STD_FILTER_DATA) {
filter_nr -= NUM_STD_FILTER_DATA;
Expand All @@ -885,10 +894,12 @@ void can_mcan_detach(struct can_mcan_data *data,
return;
}

msg_ram->ext_filt[filter_nr] = ext_filter;
memset32_volatile(&msg_ram->ext_filt[filter_nr], 0,
sizeof(struct can_mcan_ext_filter));
data->rx_cb_ext[filter_nr] = NULL;
} else {
msg_ram->std_filt[filter_nr] = std_filter;
memset32_volatile(&msg_ram->std_filt[filter_nr], 0,
sizeof(struct can_mcan_std_filter));
data->rx_cb_std[filter_nr] = NULL;
}

Expand Down
16 changes: 8 additions & 8 deletions drivers/can/can_mcan.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@ struct can_mcan_rx_fifo_hdr {
volatile uint32_t res : 2; /* Reserved */
volatile uint32_t fidx : 7; /* Filter Index */
volatile uint32_t anmf : 1; /* Accepted non-matching frame */
} __packed;
} __packed __aligned(4);

struct can_mcan_rx_fifo {
struct can_mcan_rx_fifo_hdr hdr;
union {
volatile uint8_t data[64];
volatile uint32_t data_32[16];
};
} __packed;
} __packed __aligned(4);

struct can_mcan_mm {
volatile uint8_t idx : 5;
Expand Down Expand Up @@ -84,15 +84,15 @@ struct can_mcan_tx_buffer_hdr {
volatile uint8_t res2 : 1; /* Reserved */
volatile uint8_t efc : 1; /* Event FIFO control (Store Tx events) */
struct can_mcan_mm mm; /* Message marker */
} __packed;
} __packed __aligned(4);

struct can_mcan_tx_buffer {
struct can_mcan_tx_buffer_hdr hdr;
union {
volatile uint8_t data[64];
volatile uint32_t data_32[16];
};
} __packed;
} __packed __aligned(4);

#define CAN_MCAN_TE_TX 0x1 /* TX event */
#define CAN_MCAN_TE_TXC 0x2 /* TX event in spite of cancellation */
Expand All @@ -109,7 +109,7 @@ struct can_mcan_tx_event_fifo {
volatile uint8_t fdf : 1; /* FD Format */
volatile uint8_t et : 2; /* Event type */
struct can_mcan_mm mm; /* Message marker */
} __packed;
} __packed __aligned(4);

#define CAN_MCAN_FCE_DISABLE 0x0
#define CAN_MCAN_FCE_FIFO0 0x1
Expand All @@ -130,7 +130,7 @@ struct can_mcan_std_filter {
volatile uint32_t id1 : 11;
volatile uint32_t sfce : 3; /* Filter config */
volatile uint32_t sft : 2; /* Filter type */
} __packed;
} __packed __aligned(4);

#define CAN_MCAN_EFT_RANGE_XIDAM 0x0
#define CAN_MCAN_EFT_DUAL 0x1
Expand All @@ -143,7 +143,7 @@ struct can_mcan_ext_filter {
volatile uint32_t id2 : 29; /* ID2 for dual or range, mask otherwise */
volatile uint32_t res : 1;
volatile uint32_t eft : 2; /* Filter type */
} __packed;
} __packed __aligned(4);

struct can_mcan_msg_sram {
volatile struct can_mcan_std_filter std_filt[NUM_STD_FILTER_ELEMENTS];
Expand All @@ -153,7 +153,7 @@ struct can_mcan_msg_sram {
volatile struct can_mcan_rx_fifo rx_buffer[NUM_RX_BUF_ELEMENTS];
volatile struct can_mcan_tx_event_fifo tx_event_fifo[NUM_TX_BUF_ELEMENTS];
volatile struct can_mcan_tx_buffer tx_buffer[NUM_TX_BUF_ELEMENTS];
} __packed;
} __packed __aligned(4);

struct can_mcan_data {
struct k_mutex inst_mutex;
Expand Down