So, just a solution for future ppl who are using CAN for ATSAMC21J, below are sections of the code that im using for CAN tx and rx with the help of Atmel Start
void CAN_tx(uint32_t tx_address, uint8_t tx_message[8]) {
struct can_message msg;
struct can_filter filter;
//insert code to copy received message into tx_message_2
if (rtr == 1)
{
/*Send extended message with ID: rtr_id and 8 byte data 0 to 7*/
msg.id = rtr_id;
msg.type = CAN_TYPE_DATA;
//msg.data = rx_data;
msg.data = tx_message;
msg.len = 8;
msg.fmt = CAN_FMT_EXTID;
can_async_register_callback(&CAN_0, CAN_ASYNC_TX_CB, (FUNC_PTR)CAN_0_tx_callback);
can_async_enable(&CAN_0);
can_async_write(&CAN_0, &msg);
button_pressed = 0;
rtr = 0;
}
else
{
/*Send extended message with ID: 0x155555A5 and 8 byte data rx_data*/
msg.id = tx_address;
msg.type = CAN_TYPE_DATA;
msg.data = rx_data;
//msg.data = tx_message_2;
msg.len = 8;
msg.fmt = CAN_FMT_EXTID;
can_async_register_callback(&CAN_0, CAN_ASYNC_TX_CB, (FUNC_PTR)CAN_0_tx_callback);
can_async_enable(&CAN_0);
can_async_write(&CAN_0, &msg);
button_pressed = 0;
}
}
void CAN0_Handler(void)
{
volatile uint32_t status, interrupt;
status = CAN0->IR.reg;
interrupt = CAN0->IR.reg;
if (interrupt & CAN_IR_RF0N) { // Rx New Message
received_msg = 1;
PORT->Group[0].OUTTGL.reg |= PORT_PA15; // Toggle LED
CAN0->IR.bit.RF0N = 1; // Reset Interrupt
}
}
main
while (1)
{
if (received_msg == 1)
{
int buffer_index = CAN0->RXF0S.bit.F0GI;
CAN_0_rx_callback(&CAN_0); // save data into rx_data
CAN0->RXF0A.bit.F0AI = buffer_index;
received_msg = 0;
button_pressed = 1;
//PORT->Group[0].OUTTGL.reg |= PORT_PA15; // Toggle LED
}
if (button_pressed == 1) // or when message received
{
CAN_tx(0x155555A5, tx_message_2);
button_pressed = 0;
}
}