aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/obldc/can/can.c203
-rw-r--r--include/libopenstm32/can.h45
-rw-r--r--include/libopenstm32/common.h1
-rw-r--r--lib/Makefile2
-rw-r--r--lib/can.c352
5 files changed, 473 insertions, 130 deletions
diff --git a/examples/obldc/can/can.c b/examples/obldc/can/can.c
index d81eeb9..bc5f23f 100644
--- a/examples/obldc/can/can.c
+++ b/examples/obldc/can/can.c
@@ -88,8 +88,6 @@ void systick_setup()
void can_setup()
{
- u32 wait_ack = 0x00000000;
- u32 can_msr_inak_timeout = 0x000FFFFF;
/* Enable peripheral clocks */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_AFIOEN);
@@ -109,156 +107,111 @@ void can_setup()
nvic_enable_irq(NVIC_USB_LP_CAN_RX0_IRQ);
nvic_set_priority(NVIC_USB_LP_CAN_RX0_IRQ, 1);
- /* --- reset CAN periphery ------------------------------------------ */
-
- rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_CANRST);
- rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_CANRST);
-
- /* --- CAN cell init ------------------------------------------------ */
-
- /* Exit from sleep mode */
- CAN_MCR(CAN1) &= ~CAN_MCR_SLEEP;
-
- /* Request initialization "enter" */
- CAN_MCR(CAN1) |= CAN_MCR_INRQ;
-
- /* Wait for acknowledge */
- while ((wait_ack != can_msr_inak_timeout) &&
- ((CAN_MSR(CAN1) & CAN_MSR_INAK) != CAN_MSR_INAK)) {
- wait_ack++;
- }
-
- /* Check the acknowledge */
- if ((CAN_MSR(CAN1) & CAN_MSR_INAK) != CAN_MSR_INAK) {
- /* we should set some flag here or so because we failed */
- gpio_clear(GPIOB, GPIO1);
- } else {
-
- /* set the automatic bus-off management */
- CAN_MCR(CAN1) &= ~CAN_MCR_TTCM;
- CAN_MCR(CAN1) |= CAN_MCR_ABOM;
- CAN_MCR(CAN1) &= ~CAN_MCR_AWUM;
- CAN_MCR(CAN1) &= ~CAN_MCR_NART;
- CAN_MCR(CAN1) &= ~CAN_MCR_TXFP;
-
- /* Set bit timings */
- CAN_BTR(CAN1) = 0x00000000 |
- CAN_BTR_SJW_1TQ |
- CAN_BTR_TS2_4TQ |
- CAN_BTR_TS1_3TQ |
- (u32)(CAN_BTR_BRP_MASK & (12 - 1));
-
- /* Request initialization "leave" */
- CAN_MCR(CAN1) &= ~CAN_MCR_INRQ;
-
- /* Wait for acknowledge */
- wait_ack = 0x00000000;
- while ((wait_ack != can_msr_inak_timeout) &&
- ((CAN_MSR(CAN1) & CAN_MSR_INAK) == CAN_MSR_INAK)) {
- wait_ack++;
- }
-
- if ((CAN_MSR(CAN1) & CAN_MSR_INAK) == CAN_MSR_INAK) {
- /* set some flag here because we failed */
- gpio_clear(GPIOB, GPIO1);
- } else {
- /* set some flag here because we succeeded */
- gpio_set(GPIOB, GPIO1);
+ /* reset CAN */
+ can_reset(CAN1);
+
+ /* CAN cell init */
+ if (can_init(CAN1,
+ false, /* TTCM: Time triggered comm mode? */
+ true, /* ABOM: Automatic bus-off management? */
+ false, /* AWUM: Automatic wakeup mode? */
+ false, /* NART: No automatic retransmission? */
+ false, /* RFLM: Receive FIFO locked mode? */
+ false, /* TXFP: Transmit FIFO priority? */
+ CAN_BTR_SJW_1TQ,
+ CAN_BTR_TS1_3TQ,
+ CAN_BTR_TS2_4TQ,
+ 12)) { /* BRP+1: Baud rate prescaler */
+
+ gpio_set(GPIOA, GPIO6); /* LED0 off */
+ gpio_set(GPIOA, GPIO7); /* LED1 off */
+ gpio_set(GPIOB, GPIO0); /* LED2 off */
+ gpio_clear(GPIOB, GPIO1); /* LED3 on */
+
+ /* die because we failed to initialize */
+ while(1){
+ __asm("nop");
}
}
/* --- CAN filter 0 init -------------------------------------------- */
- u32 filter_select_bit = 0x00000001;
-
- /* Request initialization "enter" */
- CAN_FMR(CAN1) |= CAN_FMR_FINIT;
-
- /* Deactivate the filter */
- CAN_FA1R(CAN1) &= ~filter_select_bit;
-
- /* Set 32-bit scale for the filter */
- CAN_FS1R(CAN1) |= filter_select_bit;
-
- /* Set the filter id to 0 */
- CAN_FiR1(CAN1, 0) = 0x00000000;
-
- /* Set the filter id mask to 0 */
- CAN_FiR2(CAN1, 0) = 0x00000000;
-
- /* Set filter mode to Id/Mask mode */
- CAN_FM1R(CAN1) &= ~filter_select_bit;
-
- /* Select FIFO0 as filter assignement */
- CAN_FFA1R(CAN1) &= ~filter_select_bit;
-
- /* Reactivate the filter */
- CAN_FA1R(CAN1) |= filter_select_bit;
-
- /* Request initialization "leave" */
- CAN_FMR(CAN1) &= ~CAN_FMR_FINIT;
+ can_filter_id_mask_32bit_init(CAN1,
+ 0, /* Filter id */
+ 0, /* CAN id */
+ 0, /* CAN id mask */
+ 0, /* FIFO assignement (in this case FIFO0) */
+ true); /* Enable the filter */
/* --- Enable CAN rx interrupt -------------------------------------- */
- CAN_IER(CAN1) |= CAN_IER_FMPIE0;
-}
-
-void can_transmit(u32 id, u8 length, u8 data)
-{
- u32 mailbox = 0;
-
- if ((CAN_TSR(CAN1) & CAN_TSR_TME0) == CAN_TSR_TME0) {
- mailbox = CAN_MBOX0;
- gpio_set(GPIOB, GPIO0);
- } else if ((CAN_TSR(CAN1) & CAN_TSR_TME1) == CAN_TSR_TME1) {
- mailbox = CAN_MBOX1;
- gpio_set(GPIOB, GPIO0);
- } else if ((CAN_TSR(CAN1) & CAN_TSR_TME2) == CAN_TSR_TME2) {
- mailbox = CAN_MBOX2;
- gpio_set(GPIOB, GPIO0);
- } else {
- mailbox = 0; /* no mailbox */
- gpio_clear(GPIOB, GPIO0);
- }
-
- if ( mailbox != 0 ) { /* check if we have an empty mailbox */
- /* Set the ID */
- CAN_TIxR(CAN1, mailbox) |= id << CAN_TIxR_STID_SHIFT;
-
- /* Set the DLC */
- CAN_TDTxR(CAN1, mailbox) &= 0xFFFFFFFF0;
- CAN_TDTxR(CAN1, mailbox) |= length & CAN_TDTxR_DLC_MASK;
-
- /* Set the data */
- CAN_TDLxR(CAN1, mailbox) = data;
- CAN_TDHxR(CAN1, mailbox) = 0x00000000;
-
- /* Request transmission */
- CAN_TIxR(CAN1, mailbox) |= CAN_TIxR_TXRQ;
- }
+ can_enable_irq(CAN1, CAN_IER_FMPIE0);
}
void sys_tick_handler()
{
static int temp32 = 0;
+ static u8 data[8] = {0,1,2,0,0,0,0,0};
temp32++;
/* we call this handler every 1ms so 1000ms = 1s on/off */
if (temp32 == 1000) {
- gpio_toggle(GPIOA, GPIO6); /* LED2 on/off */
temp32 = 0;
/* --- Transmit CAN frame ----------------------------------- */
- can_transmit(0, 0, 10);
+ data[0]++;
+ if(can_transmit(CAN1,
+ 0, /* (EX/ST)ID: CAN id */
+ false, /* IDE: CAN id extended? */
+ false, /* RTR: Request Transmit? */
+ 8, /* DLC: Data Length */
+ data) == -1) {
+ gpio_set(GPIOA, GPIO6); /* LED0 off */
+ gpio_set(GPIOA, GPIO7); /* LED1 off */
+ gpio_clear(GPIOB, GPIO0); /* LED2 on */
+ gpio_set(GPIOB, GPIO1); /* LED3 off */
+ }
}
}
void usb_lp_can_rx0_isr(void)
{
- gpio_toggle(GPIOA, GPIO7);
- CAN_RF0R(CAN1) |= CAN_RF0R_RFOM0;
+ u32 id;
+ bool ext;
+ bool rtr;
+ u32 fmi;
+ u8 length;
+ u8 data[8];
+
+ can_receive(CAN1, 0, false, &id, &ext, &rtr, &fmi, &length, data);
+
+ if (data[0] & 1) {
+ gpio_clear(GPIOA, GPIO6);
+ } else {
+ gpio_set(GPIOA, GPIO6);
+ }
+
+ if (data[0] & 2) {
+ gpio_clear(GPIOA, GPIO7);
+ } else {
+ gpio_set(GPIOA, GPIO7);
+ }
+
+ if (data[0] & 4) {
+ gpio_clear(GPIOB, GPIO0);
+ } else {
+ gpio_set(GPIOB, GPIO0);
+ }
+
+ if (data[0] & 8) {
+ gpio_clear(GPIOB, GPIO1);
+ } else {
+ gpio_set(GPIOB, GPIO1);
+ }
+
+ can_fifo_release(CAN1, 0);
}
int main(void)
diff --git a/include/libopenstm32/can.h b/include/libopenstm32/can.h
index dfa4f5c..43de374 100644
--- a/include/libopenstm32/can.h
+++ b/include/libopenstm32/can.h
@@ -528,10 +528,9 @@
#define CAN_RDTxR_TIME_MASK (0xFFFF << 15)
#define CAN_RDTxR_TIME_SHIFT 15
-/* 15:6 Reserved, forced by hardware to 0 */
-
-/* TGT: Transmit global time */
-#define CAN_RDTxR_TGT (1 << 5)
+/* FMI[7:0]: Filter match index */
+#define CAN_RDTxR_FMI_MASK (0xFF << 8)
+#define CAN_RDTxR_FMI_SHIFT 8
/* 7:4 Reserved, forced by hardware to 0 */
@@ -607,4 +606,42 @@
/* FB[31:0]: Filter bits */
+/* --- CAN functions -------------------------------------------------------- */
+
+void can_reset(u32 canport);
+int can_init(u32 canport,
+ bool ttcm, bool abom, bool awum, bool nart, bool rflm, bool txfp,
+ u32 sjw, u32 ts1, u32 ts2, u32 brp);
+
+void can_filter_init(u32 canport, u32 nr, bool scale_32bit, bool id_list_mode,
+ u32 fr1, u32 fr2,
+ u32 fifo, bool enable);
+
+void can_filter_id_mask_16bit_init(u32 canport, u32 nr,
+ u16 id1, u16 mask1,
+ u16 id2, u16 mask2,
+ u32 fifo, bool enable);
+void can_filter_id_mask_32bit_init(u32 canport, u32 nr,
+ u32 id, u32 mask,
+ u32 fifo, bool enable);
+void can_filter_id_list_16bit_init(u32 canport, u32 nr,
+ u16 id1, u16 id2,
+ u16 id3, u16 id4,
+ u32 fifo, bool enable);
+void can_filter_id_list_32bit_init(u32 canport, u32 nr,
+ u32 id1, u32 id2,
+ u32 fifo, bool enable);
+
+void can_enable_irq(u32 canport, u32 irq);
+void can_disable_irq(u32 canport, u32 irq);
+
+int can_transmit(u32 canport, u32 id,
+ bool ext, bool rtr,
+ u8 length, u8 *data);
+void can_receive(u32 canport, u8 fifo, bool release,
+ u32 *id, bool *ext, bool *rtr, u32 *fmi,
+ u8 *length, u8 *data);
+
+void can_fifo_release(u32 canport, u8 fifo);
+
#endif /* LIBOPENSTM32_CAN_H */
diff --git a/include/libopenstm32/common.h b/include/libopenstm32/common.h
index fc06dd9..81b2f52 100644
--- a/include/libopenstm32/common.h
+++ b/include/libopenstm32/common.h
@@ -21,6 +21,7 @@
#define LIBOPENSTM32_COMMON_H
#include <stdint.h>
+#include <stdbool.h>
/* Type definitions for shorter and nicer code */
typedef int8_t s8;
diff --git a/lib/Makefile b/lib/Makefile
index 2e57624..5f61993 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -29,7 +29,7 @@ CFLAGS = -Os -g -Wall -Wextra -I../include -fno-common \
ARFLAGS = rcs
OBJS = vector.o rcc.o gpio.o usart.o adc.o spi.o flash.o nvic.o \
rtc.o i2c.o dma.o systick.o exti.o scb.o ethernet.o \
- usb_f103.o usb.o usb_control.o usb_standard.o
+ usb_f103.o usb.o usb_control.o usb_standard.o can.o
VPATH += usb
diff --git a/lib/can.c b/lib/can.c
new file mode 100644
index 0000000..eb7ac58
--- /dev/null
+++ b/lib/can.c
@@ -0,0 +1,352 @@
+/*
+ * This file is part of the libopenstm32 project.
+ *
+ * Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopenstm32/can.h>
+
+#include <libopenstm32/rcc.h>
+
+void can_reset(u32 canport)
+{
+ if(canport == CAN1){
+ rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_CAN1RST);
+ rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_CAN1RST);
+ }else{
+ rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1RSTR_CAN2RST);
+ rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1RSTR_CAN2RST);
+ }
+}
+
+int can_init(u32 canport,
+ bool ttcm, bool abom, bool awum, bool nart, bool rflm, bool txfp,
+ u32 sjw, u32 ts1, u32 ts2, u32 brp)
+{
+ u32 wait_ack = 0x00000000;
+ u32 can_msr_inak_timeout = 0x0000FFFF;
+ int ret = 0;
+
+ /* Exit from sleep mode */
+ CAN_MCR(canport) &= ~CAN_MCR_SLEEP;
+
+ /* Request initialization "enter" */
+ CAN_MCR(canport) |= CAN_MCR_INRQ;
+
+ /* Wait for acknowledge */
+ while ((wait_ack != can_msr_inak_timeout) &&
+ ((CAN_MSR(canport) & CAN_MSR_INAK) != CAN_MSR_INAK)) {
+ wait_ack++;
+ }
+
+ /* Check the acknowledge */
+ if ((CAN_MSR(canport) & CAN_MSR_INAK) != CAN_MSR_INAK) {
+ ret = 1;
+ } else {
+
+ /* set the automatic bus-off management */
+ if (ttcm) {
+ CAN_MCR(canport) |= CAN_MCR_TTCM;
+ } else {
+ CAN_MCR(canport) &= ~CAN_MCR_TTCM;
+ }
+
+ if (abom) {
+ CAN_MCR(canport) |= CAN_MCR_ABOM;
+ } else {
+ CAN_MCR(canport) &= ~CAN_MCR_ABOM;
+ }
+
+
+ if (awum) {
+ CAN_MCR(canport) |= CAN_MCR_AWUM;
+ } else {
+ CAN_MCR(canport) &= ~CAN_MCR_AWUM;
+ }
+
+ if (nart) {
+ CAN_MCR(canport) |= CAN_MCR_NART;
+ } else {
+ CAN_MCR(canport) &= ~CAN_MCR_NART;
+ }
+
+
+ if (rflm) {
+ CAN_MCR(canport) |= CAN_MCR_RFLM;
+ } else {
+ CAN_MCR(canport) &= ~CAN_MCR_RFLM;
+ }
+
+ if (txfp) {
+ CAN_MCR(canport) |= CAN_MCR_TXFP;
+ } else {
+ CAN_MCR(canport) &= ~CAN_MCR_TXFP;
+ }
+
+ /* Set bit timings */
+ CAN_BTR(canport) = sjw |
+ ts2 |
+ ts1 |
+ (u32)(CAN_BTR_BRP_MASK & (brp - 1));
+
+ /* Request initialization "leave" */
+ CAN_MCR(canport) &= ~CAN_MCR_INRQ;
+
+ /* Wait for acknowledge */
+ wait_ack = 0x00000000;
+ while ((wait_ack != can_msr_inak_timeout) &&
+ ((CAN_MSR(canport) & CAN_MSR_INAK) == CAN_MSR_INAK)) {
+ wait_ack++;
+ }
+
+ if ((CAN_MSR(canport) & CAN_MSR_INAK) == CAN_MSR_INAK) {
+ ret = 1;
+ }
+ }
+
+
+ return ret;
+}
+
+void can_filter_init(u32 canport, u32 nr, bool scale_32bit, bool id_list_mode,
+ u32 fr1, u32 fr2,
+ u32 fifo, bool enable)
+{
+ u32 filter_select_bit = 0x00000001 << nr;
+
+ /* Request initialization "enter" */
+ CAN_FMR(canport) |= CAN_FMR_FINIT;
+
+ /* Deactivate the filter */
+ CAN_FA1R(canport) &= ~filter_select_bit;
+
+ if (scale_32bit) {
+ /* Set 32-bit scale for the filter */
+ CAN_FS1R(canport) |= filter_select_bit;
+ } else {
+ /* Set 16-bit scale for the filter */
+ CAN_FS1R(canport) &= ~filter_select_bit;
+ }
+
+ if (id_list_mode) {
+ /* Set filter mode to id list mode */
+ CAN_FM1R(canport) |= filter_select_bit;
+ } else {
+ /* Set filter mode to id/mask mode */
+ CAN_FM1R(canport) &= ~filter_select_bit;
+ }
+
+ /* Set the first filter register */
+ CAN_FiR1(canport, nr) = fr1;
+
+ /* Set the second filter register */
+ CAN_FiR2(canport, nr) = fr2;
+
+ if (fifo) {
+ /* Select FIFO1 as filter assignement */
+ CAN_FFA1R(canport) |= filter_select_bit;
+ } else {
+ /* Select FIFO0 as filter assignement */
+ CAN_FFA1R(canport) &= ~filter_select_bit;
+ }
+
+ if (enable) {
+ /* Activate the filter */
+ CAN_FA1R(canport) |= filter_select_bit;
+ }
+
+ /* Request initialization "leave" */
+ CAN_FMR(canport) &= ~CAN_FMR_FINIT;
+
+}
+
+void can_filter_id_mask_16bit_init(u32 canport, u32 nr,
+ u16 id1, u16 mask1,
+ u16 id2, u16 mask2,
+ u32 fifo, bool enable)
+{
+ can_filter_init(canport, nr, false, false,
+ ((u32)id1 << 16) | (u32)mask1,
+ ((u32)id2 << 16) | (u32)mask2,
+ fifo, enable);
+}
+
+
+void can_filter_id_mask_32bit_init(u32 canport, u32 nr,
+ u32 id, u32 mask,
+ u32 fifo, bool enable)
+{
+ can_filter_init(canport, nr, true, false,
+ id, mask,
+ fifo, enable);
+}
+
+void can_filter_id_list_16bit_init(u32 canport, u32 nr,
+ u16 id1, u16 id2,
+ u16 id3, u16 id4,
+ u32 fifo, bool enable)
+{
+ can_filter_init(canport, nr, false, true,
+ ((u32)id1 << 16) | (u32)id2,
+ ((u32)id3 << 16) | (u32)id4,
+ fifo, enable);
+}
+
+void can_filter_id_list_32bit_init(u32 canport, u32 nr,
+ u32 id1, u32 id2,
+ u32 fifo, bool enable)
+{
+ can_filter_init(canport, nr, true, true,
+ id1, id2,
+ fifo, enable);
+}
+
+void can_enable_irq(u32 canport, u32 irq)
+{
+
+ CAN_IER(canport) |= irq;
+}
+
+void can_disable_irq(u32 canport, u32 irq)
+{
+
+ CAN_IER(canport) &= ~irq;
+}
+
+int can_transmit(u32 canport, u32 id, bool ext, bool rtr, u8 length, u8 *data)
+{
+ int ret = 0;
+ u32 mailbox = 0;
+ int i;
+
+ if ((CAN_TSR(canport) & CAN_TSR_TME0) == CAN_TSR_TME0) {
+ ret = 0;
+ mailbox = CAN_MBOX0;
+ } else if ((CAN_TSR(canport) & CAN_TSR_TME1) == CAN_TSR_TME1) {
+ ret = 1;
+ mailbox = CAN_MBOX1;
+ } else if ((CAN_TSR(canport) & CAN_TSR_TME2) == CAN_TSR_TME2) {
+ ret = 2;
+ mailbox = CAN_MBOX2;
+ } else {
+ ret = -1;
+ }
+
+ if (ret != -1) { /* check if we have an empty mailbox */
+ if (ext) {
+ /* Set extended id */
+ CAN_TIxR(canport, mailbox) |= id << CAN_TIxR_EXID_SHIFT;
+ /* Set extended id indicator bit */
+ CAN_TIxR(canport, mailbox) |= CAN_TIxR_IDE;
+ } else {
+ /* Set standard id */
+ CAN_TIxR(canport, mailbox) |= id << CAN_TIxR_STID_SHIFT;
+ /* Unset extended id indicator bit */
+ CAN_TIxR(canport, mailbox) &= ~CAN_TIxR_IDE;
+ }
+
+ if (rtr) {
+ /* Set remote transmission request bit */
+ CAN_TIxR(canport, mailbox) |= CAN_TIxR_RTR;
+ } else {
+ /* Unset remote transmission request bit */
+ CAN_TIxR(canport, mailbox) &= ~CAN_TIxR_RTR;
+ }
+
+ /* Set the DLC */
+ CAN_TDTxR(canport, mailbox) &= 0xFFFFFFFF0;
+ CAN_TDTxR(canport, mailbox) |= length & CAN_TDTxR_DLC_MASK;
+
+ /* Set the data */
+ CAN_TDLxR(canport, mailbox) = 0;
+ CAN_TDHxR(canport, mailbox) = 0;
+ for (i = 0; (i < 4) && (i < length); i++) {
+ CAN_TDLxR(canport, mailbox) |= (u32)data[i] << (8 * i);
+ }
+ for (i = 4; (i < 8) && (i < length); i++) {
+ CAN_TDHxR(canport, mailbox) |= (u32)data[i] << (8 * (i-4));
+ }
+
+ /* Request transmission */
+ CAN_TIxR(canport, mailbox) |= CAN_TIxR_TXRQ;
+ }
+
+ return ret;
+}
+
+void can_fifo_release(u32 canport, u8 fifo)
+{
+ if (fifo == 0) {
+ CAN_RF0R(canport) |= CAN_RF1R_RFOM1;
+ } else {
+ CAN_RF1R(canport) |= CAN_RF1R_RFOM1;
+ }
+}
+
+void can_receive(u32 canport, u8 fifo, bool release,
+ u32 *id, bool *ext, bool *rtr, u32 *fmi,
+ u8 *length, u8 *data)
+{
+ u32 fifo_id = 0;
+ int i;
+
+ if (fifo == 0) {
+ fifo_id = CAN_FIFO0;
+ } else {
+ fifo_id = CAN_FIFO1;
+ }
+
+ /* get type of CAN id and CAN id */
+ if (CAN_RIxR(canport, fifo_id) & CAN_RIxR_IDE) {
+ *ext = true;
+ /* Get extended CAN id */
+ *id = ((CAN_RIxR(canport, fifo_id) & CAN_RIxR_EXID_MASK) >
+ CAN_RIxR_EXID_SHIFT);
+ } else {
+ *ext = false;
+ /* Get standard CAN id */
+ *id = ((CAN_RIxR(canport, fifo_id) & CAN_RIxR_STID_MASK) >
+ CAN_RIxR_STID_SHIFT);
+ }
+
+ /* get request transmit flag */
+ if (CAN_RIxR(canport, fifo_id) & CAN_RIxR_RTR) {
+ *rtr = true;
+ } else {
+ *rtr = false;
+ }
+
+ /* get filter match id */
+ *fmi = ((CAN_RDTxR(canport, fifo_id) & CAN_RDTxR_FMI_MASK) >
+ CAN_RDTxR_FMI_SHIFT);
+
+ /* get data length */
+ *length = CAN_RDTxR(canport, fifo_id) & CAN_RDTxR_DLC_MASK;
+
+ /* get data */
+ for (i=0; (i < 4) && (i < *length); i++) {
+ data[i] = (CAN_RDLxR(canport, fifo_id) >> (8 * i)) & 0xFF;
+ }
+
+ for (i=4; (i < 8) && (i < *length); i++) {
+ data[i] = (CAN_RDHxR(canport, fifo_id) >> (8 * (i - 4))) & 0xFF;
+ }
+
+ /* release the fifo */
+ if (release) {
+ can_fifo_release(CAN1, 0);
+ }
+}