# HG changeset patch # User gthomas # Date 1142261162 0 # Node ID afacaa648a92be33f1986c3bc979f951e4843ff8 # Parent 34ebb920ba9b01430ff318ec7b3169f526b034aa Update FlexCAN package - from Uwe Kindler diff --git a/packages/devs/can/m68k/mcf52xx/current/ChangeLog b/packages/devs/can/m68k/mcf52xx/current/ChangeLog --- a/packages/devs/can/m68k/mcf52xx/current/ChangeLog +++ b/packages/devs/can/m68k/mcf52xx/current/ChangeLog @@ -1,3 +1,33 @@ +2006-02-15 Uwe Kindler + + * cdl/can_mcf52xx.cdl Added two interfaces + CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID and + CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_EXT_CAN_ID. + The number of standard and extended message boxes is now + configurable: + CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_STD_MBOXES + CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_EXT_MBOXES + Channged default TX buffer to 15. + + * src/can_mcf52xx.c Added initialisation macro for second + FlexCAN modul. Driver partly rewritten - support of up to + 15 message buffers when reception of all CAN frames is + configured - improves performance when "bursts" of CAN + messages arrive. Changed message buffer configuration - + only the config key CYG_IO_SET_CONFIG_CAN_MSGBUF is + supported now. The exact configuration option is defined + in new data field cyg_can_msgbuf_cfg_id in cyg_can_msgbuf_cfg + structure. + + * tests/flexcan_filter.c + * tests/flexcan_wake.c + * tests/flexcan_remote.c + * tests/flexcan_load.c + Changed message buffer configuration to support of new + config key CYG_IO_SET_CONFIG_CAN_MSGBUF. Removed baudrate + runtime configuration of 250 kBaud - now default + value is used. + 2005-09-20 Uwe Kindler * src/can_mcf52xx.c Only support events of tx message buffers diff --git a/packages/devs/can/m68k/mcf52xx/current/cdl/can_mcf52xx.cdl b/packages/devs/can/m68k/mcf52xx/current/cdl/can_mcf52xx.cdl --- a/packages/devs/can/m68k/mcf52xx/current/cdl/can_mcf52xx.cdl +++ b/packages/devs/can/m68k/mcf52xx/current/cdl/can_mcf52xx.cdl @@ -64,6 +64,22 @@ cdl_package CYGPKG_DEVS_CAN_MCF52xx_FLEX puts $::cdl_system_header "/***** CAN driver proc output end *****/" } + cdl_interface CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID { + display "11 Bit standard ID support" + flavor bool + description " + This interface is implemented if support for CAN + messages with 11 Bit standard CAN ID is required." + } + + cdl_interface CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_EXT_CAN_ID { + display "29 Bit extended ID support" + flavor bool + description " + This interface is implemented if support for CAN + messages with 29 Bit standard CAN ID is required." + } + # Support up to two on-chip FlexCAN modules. The number varies between # processor variants for { set ::flexcan 0 } { $::flexcan < 2 } { incr ::flexcan } { @@ -110,8 +126,8 @@ cdl_package CYGPKG_DEVS_CAN_MCF52xx_FLEX cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_QUEUESIZE_TX { display "Size of TX Queue for the FlexCAN [set ::flexcan] driver" flavor data - default_value 32 - legal_values 16 to 512 + default_value 64 + legal_values 16 to 1024 description " The CAN device driver will run in interrupt mode and will perform buffering of outgoing data. This option controls the number @@ -121,52 +137,14 @@ cdl_package CYGPKG_DEVS_CAN_MCF52xx_FLEX cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_QUEUESIZE_RX { display "Size of RX Queue for the FlexCAN [set ::flexcan] driver" flavor data - default_value 32 - legal_values 16 to 512 + default_value 128 + legal_values 16 to 1024 description " The CAN device driver will run in interrupt mode and will perform buffering of incoming data. This option controls the number of CAN events the RX queue can store." } - cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_RXMASK_GLOBAL { - display "Receive mask for message buffers 0 - 13" - flavor data - default_value 0x1FFFFFFF - description " - The global RX-mask is composed of 4 bytes. The mask bits are - applied to all Rx-Identifiers excluding Rx-buffers 14-15, that - have their specific Rx-mask. (0 corresponding incoming ID bit is - \"don’t care\". 1 corresponding ID bit is checked against the incoming - ID bit, to see if a match exists). By default the message buffers - should only receive messages that exactly match the configured - message buffer CAN identifier - that means alle bits are 1." - } - - cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_RXMASK_14 { - display "Receive mask for message buffer 14" - flavor data - default_value 0x0 - description " - The RX-mask for message buffer 14 is composed of 4 bytes. The mask - bits are applied to message buffer 14. (0 corresponding incoming ID - bit is \"don’t care\". 1 corresponding ID bit is checked against the - incoming ID bit, to see if a match exists). Message buffer 14 is - the receive message buffer and should receive all available CAN - messages - all bits are 0." - } - - cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_RXMASK_15 { - display "Receive mask for message buffer 15" - flavor data - default_value 0x0 - description " - The RX-mask for message buffer 15 is composed of 4 bytes. The mask - bits are applied to message buffer 15. (0 corresponding incoming ID - bit is \"don’t care\". 1 corresponding ID bit is checked against the - incoming ID bit, to see if a match exists)." - } - cdl_option CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN[set ::flexcan]_WAKEINT { display "Wake interrupt priority" flavor data @@ -200,37 +178,53 @@ cdl_package CYGPKG_DEVS_CAN_MCF52xx_FLEX Interrupt priority for bus off interrupt." } - cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_DEFAULT_RX_MBOX_EXT { - display "Default RX buffer for extended frames" + cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_DEFAULT_TX_MBOX { + display "Default TX buffer" flavor data calculated 15 - legal_values 0 to 15 description " - By default one message buffer will be used for reception of - all CAN messages with extended identifier. This option selects one of the - 16 message buffers for reception." + By default one message buffer will be used for message transmission. + This option selects one of the 16 FlexCAN message buffers for + transmission." } - cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_DEFAULT_RX_MBOX_STD { - display "Default RX buffer for standard frames" - flavor data - calculated 14 + cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_STD_MBOXES { + display "11 Bit standard ID msg. buffers" + flavor booldata + implements CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID + default_value 15 legal_values 0 to 15 description " - By default one message buffer will be used for reception of - all CAN messages with standard identifier. This option selects one of - the 16 message buffers for reception." - } - - cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_DEFAULT_TX_MBOX { - display "Default TX buffer" - flavor data - calculated 13 + The FlexCAN module contains 16 message buffers. One message buffer + is reserved for message transmission. The remaining 15 buffers are + available for reception of messages. This configuration option + defines the number of message boxes for reception of CAN messages + with standard identifier. This configuration option does not matter + when you configure message filters at runtime. Only if the FlexCAN + modul is configured to receive all available standard CAN identifiers + (0 - 0x7FF), then this configuration option is important. If you get + RX overrun events, you should raise the number of message boxes or + lower the CAN baud rate." + } + + cdl_option CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_EXT_MBOXES { + display "29 Bit extended ID msg. buffers" + flavor booldata + requires ((CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_STD_MBOXES + CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_EXT_MBOXES) <= 15) + implements CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_EXT_CAN_ID + default_value 0 legal_values 0 to 15 description " - By default one message buffer will be used for message transmission. - This option selects one of the 16 FlexCAN message buffers for - transmission." + The FlexCAN module contain 16 message buffers. One message buffer + is reserved for message transmission. The remaining 15 buffers are + available for reception of messages. This configuration option + defines the number of message boxes for reception of CAN messages + with extended identifier. This configuration option does not matter + when you configure message filters at runtime. Only if the FlexCAN + modul is configured to receive all available standard CAN identifiers + (0 - 0x7FF), then this configuration option is important. If you get + RX overrun events, you should raise the number of message boxes or + lower the CAN baud rate." } cdl_component CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]_MBOXCFG { diff --git a/packages/devs/can/m68k/mcf52xx/current/src/can_mcf52xx.c b/packages/devs/can/m68k/mcf52xx/current/src/can_mcf52xx.c --- a/packages/devs/can/m68k/mcf52xx/current/src/can_mcf52xx.c +++ b/packages/devs/can/m68k/mcf52xx/current/src/can_mcf52xx.c @@ -163,6 +163,12 @@ #define FLEXCAN_BUSOFF_EVENT 17 #define FLEXCAN_WAKE_EVENT 18 +// +// Acceptance mask +// +#define FLEXCAN_ACCEPTANCE_MASK_RX_ALL 0x00 // receive all messages - mbox ID does not matter +#define FLEXCAN_ACCEPTANCE_MASK_RX_ID 0x1FFFFFFF // receive only messages where ID exactly matches mbox ID + //--------------------------------------------------------------------------- // message buffer cfg bits @@ -193,11 +199,18 @@ //--------------------------------------------------------------------------- -// define +// flexcan message buffer configuration // -#define FLEXCAN_MBOX_NO 16 +#define FLEXCAN_MBOX_MIN 0 #define FLEXCAN_MBOX_MAX 15 -#define FLEXCAN_MBOX_LAST_FREE 13 +#define FLEXCAN_MBOX_CNT 16 +#define FLEXCAN_MBOX_TX CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_TX_MBOX +#define FLEXCAN_MBOX_RX_MIN 0 +#define FLEXCAN_MBOX_RX_MAX (FLEXCAN_MBOX_MAX - 1) // one msg box is tx +#define FLEXCAN_MBOX_RX_CNT (FLEXCAN_MBOX_CNT - 1) // one msg box is tx + + +#define FLEXCAN_CTRLSTAT_NOT_READ 0 // indicates that control status register is not read //=========================================================================== @@ -212,7 +225,9 @@ typedef enum MBOX_STATE_DISABLED, // message box unused (free) MBOX_STATE_TX, // TX message box MBOX_STATE_REMOTE_TX, // remote TX msaage box (data will be sent on reception of rtr frame) - MBOX_STATE_RX // RX message box + MBOX_STATE_RX_ALL_STD, // RX message box for standard IDs + MBOX_STATE_RX_ALL_EXT, // RX message box for standard IDs + MBOX_STATE_RX_FILT // RX message box for filter mboxes } flexcan_mbox_state; @@ -226,11 +241,25 @@ typedef struct flexcan_mbox_info_st cyg_interrupt interrupt; // stores interrupt data cyg_handle_t interrupt_handle; // stores interrupt number cyg_uint8 num; // number of message buffer - bool tx_busy; // if true, then transmission is in progress + bool busy; // if true, then transmission or reception is in progress flexcan_mbox_state state; // message box state + cyg_uint8 ctrlstat_shadow; // shadow register of message box ctrlstat register } flexcan_mbox_info; // +// Between ISR and DSR handling there is some kind of circular buffer. +// A DSR is only invoked if no other message box invoked a DSR before +// the DSR will read all available message buffers. This structure +// is for exchange of information between ISR and DSR +// +typedef struct st_rxmbox_circbuf +{ + cyg_uint8 idx_rd; // the message box the DSR will read from + cyg_uint8 idx_wr; // the message box that will receive the next message + cyg_uint8 count; // the number of received message before DSR starts (number of ISR nesting) +} flexcan_rxmbox_circbuf; + +// // flexcan interrupt (busoff, err, wake) data - stores interrupt data for // a non message box interrupt (bus off, err or wake interrupt) // @@ -249,7 +278,7 @@ typedef struct flexcan_int_st isr_vec : (_mbox0_vec) + (_mbox_no), \ isr_priority : (_prio), \ num : (_mbox_no), \ - tx_busy : false \ + busy : false \ } // @@ -268,23 +297,25 @@ typedef struct flexcan_info { cyg_uint8 *base; // base address of flexcan modul cyg_vector_t isr_vec_mbox0; // vector number of ISR vector of first message box - flexcan_mbox_info mboxes[FLEXCAN_MBOX_NO];// message boxes + flexcan_mbox_info mboxes[FLEXCAN_MBOX_CNT];// message boxes cyg_uint32 last_tx_id; // last transmitted message identifier - cyg_uint32 rxgmask; // acceptance filter for message box 0 - 13 - cyg_uint32 rx14mask; // acceptance filter for message box 14 - cyg_uint32 rx15mask; // acceptance filter for message box 15 - flexcan_int boff_int; // bus off interrupt data flexcan_int err_int; // error interrupt data flexcan_int wake_int; // wake interrupt data cyg_uint8 tx_all_mbox; // number of message box for all transmit messages - cyg_uint8 rx_all_mbox_std; // number of message box for reception of all standard CAN messages - cyg_uint8 rx_all_mbox_ext; // number of message box for reception of all extended CAN messages cyg_uint8 free_mboxes; // number of free message boxes for msg filters and rtr buffers cyg_can_state state; // state of CAN controller + flexcan_rxmbox_circbuf rxmbox_std_circbuf; + flexcan_rxmbox_circbuf rxmbox_ext_circbuf; + + cyg_uint8 mboxes_std_cnt; // contains number of standard message boxes available + cyg_uint8 mboxes_ext_cnt; // number of message boxes with ext id + cyg_uint8 mboxes_rx_all_cnt;// number of all available mboxes + + bool rx_all; // true if reception of call can messages is active cyg_uint16 imask_shadow; // interrupt mask shadow register #ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT cyg_can_message last_tx_msg; // stores last transmitted message for TX events @@ -322,13 +353,11 @@ typedef struct flexcan_info _mbox13_isr_prio, \ _mbox14_isr_prio, \ _mbox15_isr_prio, \ - _rxgmask, \ - _rx14mask, \ - _rx15mask, \ _boff_isr_vec, _boff_isr_prio, \ _err_isr_vec, _err_isr_prio, \ _wake_isr_vec, _wake_isr_prio, \ - _tx_all_mbox, _rx_all_mbox_std, _rx_all_mbox_ext) \ + _tx_all_mbox, \ + _std_mboxes, _ext_mboxes) \ flexcan_info _l = { \ (void *)( _baseaddr), \ (_isr_vec_mbox0), \ @@ -351,17 +380,16 @@ flexcan_info _l = { FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox15_isr_prio),15), \ }, \ last_tx_id : 0xFFFFFFFF, \ - rxgmask : _rxgmask, \ - rx14mask : _rx14mask, \ - rx15mask : _rx15mask, \ boff_int : FLEXCAN_INT_INIT(_boff_isr_vec, _boff_isr_prio), \ err_int : FLEXCAN_INT_INIT(_err_isr_vec, _err_isr_prio), \ wake_int : FLEXCAN_INT_INIT(_wake_isr_vec, _wake_isr_prio), \ tx_all_mbox : _tx_all_mbox, \ - rx_all_mbox_std : _rx_all_mbox_std, \ - rx_all_mbox_ext : _rx_all_mbox_ext, \ - free_mboxes : FLEXCAN_MBOX_LAST_FREE, \ - state : CYGNUM_CAN_STATE_ACTIVE \ + free_mboxes : ((_std_mboxes) + (_ext_mboxes)), \ + state : CYGNUM_CAN_STATE_ACTIVE, \ + rx_all : true, \ + mboxes_std_cnt : _std_mboxes, \ + mboxes_ext_cnt : _ext_mboxes, \ + mboxes_rx_all_cnt : ((_std_mboxes) + (_ext_mboxes)) \ }; @@ -374,9 +402,26 @@ flexcan_info _l = { #define _FLEXCAN_MBOX_INTPRIO(n) CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX##n #define FLEXCAN_MBOX_INTPRIO(n) _FLEXCAN_MBOX_INTPRIO(n) +// +// Define number of message boxes if they are not defined yet +// +#ifndef CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_STD_MBOXES +#define CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_STD_MBOXES 0 +#endif +#ifndef CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_EXT_MBOXES +#define CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_EXT_MBOXES 0 +#endif +#ifndef CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_STD_MBOXES +#define CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_STD_MBOXES 0 +#endif +#ifndef CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_EXT_MBOXES +#define CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_EXT_MBOXES 0 +#endif + +#ifdef CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN0 // -// FlexCAN channel initialisation +// FlexCAN channel initialisation for FlexCAN channel 0 // FLEXCAN_INFO(flexcan_can0_info, HAL_MCF52xx_MBAR + HAL_MCF52xx_FLEXCAN0_BASE, @@ -397,9 +442,6 @@ FLEXCAN_INFO(flexcan_can0_info, CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX13, CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX14, CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX15, - CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_RXMASK_GLOBAL, - CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_RXMASK_14, - CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_RXMASK_15, HAL_MCF52xx_FLEXCAN0_BOFF_ISRVEC, CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_BOFFINT, HAL_MCF52xx_FLEXCAN0_ERR_ISRVEC, @@ -407,8 +449,43 @@ FLEXCAN_INFO(flexcan_can0_info, HAL_MCF52xx_FLEXCAN0_WAKE_ISRVEC, CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_WAKEINT, CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_TX_MBOX, - CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_RX_MBOX_STD, - CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_RX_MBOX_EXT); + CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_STD_MBOXES, + CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_EXT_MBOXES); +#endif // CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan] + +#ifdef CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN1 +// +// FlexCAN channel initialisation for FlexCAN channel 1 +// +FLEXCAN_INFO(flexcan_can0_info, + HAL_MCF52xx_MBAR + HAL_MCF52xx_FLEXCAN0_BASE, + HAL_MCF52xx_FLEXCAN1_MBOX0_ISRVEC, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX0, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX1, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX2, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX3, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX4, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX5, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX6, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX7, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX8, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX9, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX10, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX11, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX12, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX13, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX14, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX15, + HAL_MCF52xx_FLEXCAN1_BOFF_ISRVEC, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_BOFFINT, + HAL_MCF52xx_FLEXCAN1_ERR_ISRVEC, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_ERRINT, + HAL_MCF52xx_FLEXCAN1_WAKE_ISRVEC, + CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_WAKEINT, + CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_DEFAULT_TX_MBOX, + CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_STD_MBOXES, + CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_EXT_MBOXES); +#endif // CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN1 // // message box structure for hardware access of message box @@ -485,10 +562,18 @@ static void flexcan_stop_xmit(can // // TX and RX ISRs and DSRs // -static cyg_uint32 flexcan_mbox_rx_isr(cyg_vector_t, cyg_addrword_t); -static void flexcan_mbox_rx_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t); +#ifdef CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID +static cyg_uint32 flexcan_mbox_rx_std_isr(cyg_vector_t, cyg_addrword_t); +static void flexcan_mbox_rx_std_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t); +#endif // #ifdef CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID +#ifdef CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_EXT_CAN_ID +static cyg_uint32 flexcan_mbox_rx_ext_isr(cyg_vector_t, cyg_addrword_t); +static void flexcan_mbox_rx_ext_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t); +#endif // CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_EXT_ID +static cyg_uint32 flexcan_mbox_rx_filt_isr(cyg_vector_t, cyg_addrword_t); static cyg_uint32 flexcan_mbox_tx_isr(cyg_vector_t, cyg_addrword_t); static void flexcan_mbox_tx_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t); +static void flexcan_mbox_rx_filt_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t ); // // All other flexcan interrupt handlers @@ -500,9 +585,11 @@ static void flexcan_busoff_dsr(cy static cyg_uint32 flexcan_wake_isr(cyg_vector_t, cyg_addrword_t); static void flexcan_wake_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t); - +// +// Flexcan utility functions +// static bool flexcan_cfg_mbox_tx(flexcan_mbox *pmbox, cyg_can_message *pmsg, bool rtr); -static void flexcan_cfg_mbox_rx(flexcan_mbox *pmbox, cyg_can_message *pmsg); +static void flexcan_cfg_mbox_rx(flexcan_mbox *pmbox, cyg_can_message *pmsg, bool enable); static void flexcan_read_from_mbox(can_channel *chan, cyg_uint8 mbox, cyg_can_event *pevent, cyg_uint8 *ctrlstat); static void flexcan_set_acceptance_mask(cyg_uint16 *rxmask_reg, cyg_uint32 mask, cyg_can_id_type ext); static void flexcan_start_chip(can_channel *chan); @@ -513,11 +600,13 @@ static bool flexcan_set_baud(can_channel static bool flexcan_config(can_channel* chan, cyg_can_info_t* config, cyg_bool init); static cyg_int8 flexcan_alloc_mbox(flexcan_info *info); static void flexcan_disable_mbox(can_channel *chan, cyg_uint32 mbox_id); -static void flexcan_setup_rxmbox(can_channel *chan, cyg_uint32 mbox_id, cyg_can_message *pmsg); +static void flexcan_setup_rxmbox(can_channel *chan, cyg_uint32 mbox_id, cyg_ISR_t *isr, cyg_can_message *pmsg, bool enable, bool int_enable); static void flexcan_setup_txmbox(can_channel *chan, cyg_uint32 mbox_id, cyg_can_message *pmsg); static void flexcan_setup_rtrmbox(can_channel *chan, cyg_uint32 mbox_id, cyg_can_message *pmsg); static void flexcan_mboxint_enable(flexcan_info *info, cyg_uint32 mbox_id); static void flexcan_mboxint_disable(flexcan_info *info, cyg_uint32 mbox_id); +static void flexcan_config_rx_all(can_channel *chan); +static void flexcan_enable_rxmbox(can_channel *chan, cyg_uint32 mbox_id); CAN_LOWLEVEL_FUNS(flexcan_lowlevel_funs, @@ -567,6 +656,33 @@ flexcan_lookup(struct cyg_devtab_entry** //=========================================================================== +// Enable hardware message box for reception +//=========================================================================== +static __inline__ void flexcan_hwmbox_enable_rx(flexcan_regs *flexcan, cyg_uint32 mbox_id) +{ + HAL_WRITE_UINT8(&(flexcan->mbox[mbox_id].ctrlstat), MBOX_RXCODE_EMPTY); +} + + +//=========================================================================== +// Disable hardware message box +//=========================================================================== +static __inline__ void flexcan_hwmbox_disable(flexcan_regs *flexcan, cyg_uint32 mbox_id) +{ + HAL_WRITE_UINT8(&(flexcan->mbox[mbox_id].ctrlstat), MBOX_RXCODE_NOT_ACTIVE); +} + + +//=========================================================================== +// lock mbox by reading control status register +//=========================================================================== +static __inline__ void flexcan_hwmbox_lock(flexcan_regs *flexcan, cyg_uint32 mbox_id, cyg_uint8 *pctrlstat) +{ + HAL_READ_UINT8(&(flexcan->mbox[mbox_id].ctrlstat), *pctrlstat); // this read will lock the mbox +} + + +//=========================================================================== // Enable message box interrupt for one message box //=========================================================================== static void flexcan_mboxint_enable(flexcan_info *info, cyg_uint32 mbox_id) @@ -589,6 +705,7 @@ static void flexcan_mboxint_disable(flex HAL_WRITE_UINT16(&flexcan->IMASK, info->imask_shadow); } + //=========================================================================== // Allocate message box // Try to find a free message box and return its ID @@ -596,11 +713,11 @@ static void flexcan_mboxint_disable(flex static cyg_int8 flexcan_alloc_mbox(flexcan_info *info) { cyg_uint8 i; - cyg_int8 res = -1; + cyg_int8 res = CYGNUM_CAN_MSGBUF_NA; if (info->free_mboxes) { - for (i = 0; i < FLEXCAN_MBOX_LAST_FREE; ++i) + for (i = (FLEXCAN_MBOX_RX_CNT - info->free_mboxes); i <= FLEXCAN_MBOX_RX_MAX; ++i) { if (MBOX_STATE_DISABLED == info->mboxes[i].state) { @@ -608,7 +725,7 @@ static cyg_int8 flexcan_alloc_mbox(flexc res = i; break; } - } // for (i = 0; i < FLEXCAN_MBOX_LAST_FREE; ++i) + } } // if (info->free_mboxes) return res; @@ -616,38 +733,111 @@ static cyg_int8 flexcan_alloc_mbox(flexc //=========================================================================== +// Enable a previously configured rx mbox - a mbox ready to recive +//=========================================================================== +static void flexcan_enable_rxmbox(can_channel *chan, + cyg_uint32 mbox_id) +{ + flexcan_info *info = (flexcan_info *)chan->dev_priv; + flexcan_regs *flexcan = (flexcan_regs *)info->base; + + flexcan_hwmbox_enable_rx(flexcan, mbox_id); + flexcan_mboxint_enable(info, mbox_id); +} + +//=========================================================================== // Prepare message buffer filter -// Setup a RX message box for reception of a certain CAN identifier +// Setup a RX message box for reception of a certain CAN identifier but do +// not enable it //=========================================================================== static void flexcan_setup_rxmbox(can_channel *chan, cyg_uint32 mbox_id, - cyg_can_message *pmsg) + cyg_ISR_t *isr, + cyg_can_message *pmsg, + bool enable, + bool int_enable) { flexcan_info *info = (flexcan_info *)chan->dev_priv; flexcan_regs *flexcan = (flexcan_regs *)info->base; flexcan_mbox_info *pmbox; - - info->mboxes[mbox_id].state = MBOX_STATE_RX; - pmbox = &info->mboxes[mbox_id]; - flexcan_cfg_mbox_rx(&flexcan->mbox[mbox_id], pmsg); + cyg_DSR_t *dsr_func = &flexcan_mbox_rx_filt_dsr; // - // prepare message box interrupt for message box + // Set state of message buffer accoring to ISR function that + // will be registered + // +#ifdef CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID + if (*isr == flexcan_mbox_rx_std_isr) + { + // + // If we have only one single RX all message box then we use + // the filter ISR instead of RX all standard ISR because it + // is better suited for a single RX mbox // + if (info->mboxes_std_cnt > 1) + { + info->mboxes[mbox_id].state = MBOX_STATE_RX_ALL_STD; + dsr_func = &flexcan_mbox_rx_std_dsr; + } + else + { + info->mboxes[mbox_id].state = MBOX_STATE_RX_FILT; + isr = flexcan_mbox_rx_filt_isr; + } + } + else +#endif // CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID +#ifdef CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_EXT_CAN_ID + if (*isr == flexcan_mbox_rx_ext_isr) + { + // + // If we have only one single RX all message box then we use + // the filter ISR instead of RX all standard ISR because it + // is better suited for a single RX mbox + // + if (info->mboxes_ext_cnt > 1) + { + info->mboxes[mbox_id].state = MBOX_STATE_RX_ALL_EXT; + dsr_func = &flexcan_mbox_rx_ext_dsr; + } + else + { + info->mboxes[mbox_id].state = MBOX_STATE_RX_FILT; + isr = flexcan_mbox_rx_filt_isr; + } + } + else +#endif // CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_EXT_CAN_ID + if (*isr == flexcan_mbox_rx_filt_isr) + { + info->mboxes[mbox_id].state = MBOX_STATE_RX_FILT; + } + else + { + CYG_ASSERT(0, "Invalid ISR function pointer"); + } + + pmbox = &info->mboxes[mbox_id]; + flexcan_cfg_mbox_rx(&flexcan->mbox[mbox_id], pmsg, enable); + cyg_drv_interrupt_create(pmbox->isr_vec, pmbox->isr_priority, (cyg_addrword_t) chan, - &flexcan_mbox_rx_isr, - &flexcan_mbox_rx_dsr, + isr, + dsr_func, &(pmbox->interrupt_handle), &(pmbox->interrupt)); cyg_drv_interrupt_attach(pmbox->interrupt_handle); cyg_drv_interrupt_unmask(pmbox->isr_vec); // - // now enable interrupt for this message box + // now enable interrupt for this message box - but only if we + // really should do it // + if (int_enable) + { flexcan_mboxint_enable(info, mbox_id); + } } @@ -721,6 +911,7 @@ static void flexcan_setup_txmbox(can_cha flexcan_mboxint_enable(info, mbox_id); } + //=========================================================================== // Setup a RTR response message box //=========================================================================== @@ -730,195 +921,274 @@ static void flexcan_setup_rtrmbox(can_ch { flexcan_info *info = (flexcan_info *)chan->dev_priv; flexcan_regs *flexcan = (flexcan_regs *)info->base; - flexcan_mbox_info *pmbox; info->mboxes[mbox_id].state = MBOX_STATE_REMOTE_TX; - pmbox = &info->mboxes[mbox_id]; flexcan_cfg_mbox_tx(&flexcan->mbox[mbox_id], pmsg, true); +} - // - // prepare message box interrupt for message box - // - cyg_drv_interrupt_create(pmbox->isr_vec, - pmbox->isr_priority, - (cyg_addrword_t) chan, - &flexcan_mbox_rx_isr, - &flexcan_mbox_rx_dsr, - &(pmbox->interrupt_handle), - &(pmbox->interrupt)); - cyg_drv_interrupt_attach(pmbox->interrupt_handle); - cyg_drv_interrupt_unmask(pmbox->isr_vec); + +//=========================================================================== +// Setup the list of message boxes ready to receive a message +//=========================================================================== +static void flexcan_setup_rxmbox_circbuf(flexcan_rxmbox_circbuf *pbuf) +{ + pbuf->count = 0; + pbuf->idx_rd = 0; + pbuf->idx_wr = 0; } //=========================================================================== -// Set device configuration +// Setup flexCAN modul for reception of any kind of message //=========================================================================== -static Cyg_ErrNo -flexcan_set_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len) +static void flexcan_config_rx_all(can_channel *chan) { - Cyg_ErrNo res = ENOERR; flexcan_info *info = (flexcan_info *)chan->dev_priv; + flexcan_regs *flexcan = (flexcan_regs *)info->base; + cyg_int8 i; - switch(key) - { // - //Setup a new CAN configuration. This will i.e. setup a new baud rate + // setup all available message boxes for reception of of messages + // All standard and extended message buffers will be configured // - case CYG_IO_SET_CONFIG_CAN_INFO: + for (i = 0; i < info->mboxes_rx_all_cnt; ++i) { - cyg_can_info_t* config = (cyg_can_info_t*) buf; - if (*len < sizeof(cyg_can_info_t)) + cyg_can_message filter_param; + filter_param.id = 0; + + // + // configure message buffers for standard frames + // +#ifdef CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID + if (i < info->mboxes_std_cnt) { - return -EINVAL; + filter_param.ext = CYGNUM_CAN_ID_STD; + flexcan_setup_rxmbox(chan, i, &flexcan_mbox_rx_std_isr, &filter_param, false, true); } - *len = sizeof(cyg_can_info_t); - if (!flexcan_config(chan, config, false)) +#endif // CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID + + // + // configure message buffers for extended frames + // +#ifdef CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_EXT_CAN_ID + else { - return -EINVAL; + filter_param.ext = CYGNUM_CAN_ID_EXT; + flexcan_setup_rxmbox(chan, i, &flexcan_mbox_rx_ext_isr, &filter_param, false, true); } +#endif // CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID } - break; // - // Try to add a new RTR response message buffer for automatic transmisson - // of data frame on reception of a remote frame + // We need to receive all available CAN messages so we have to set the acceptance filter + // properly + // + flexcan_set_acceptance_mask(&flexcan->RXGMASK_HI, FLEXCAN_ACCEPTANCE_MASK_RX_ALL, CYGNUM_CAN_ID_EXT); + flexcan_set_acceptance_mask(&flexcan->RX14MASK_HI, FLEXCAN_ACCEPTANCE_MASK_RX_ALL, CYGNUM_CAN_ID_EXT); + info->free_mboxes = FLEXCAN_MBOX_RX_CNT - info->mboxes_rx_all_cnt; + info->rx_all = true; + + // + // now finally setup the first active message boxes and enable ist // - case CYG_IO_SET_CONFIG_CAN_REMOTE_BUF: +#ifdef CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID + if (info->mboxes_std_cnt) { - cyg_can_remote_buf *rtr_buf = (cyg_can_remote_buf*) buf; + flexcan_setup_rxmbox_circbuf(&info->rxmbox_std_circbuf); + flexcan_enable_rxmbox(chan, 0); + } +#endif // CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID - if (*len != sizeof(cyg_can_remote_buf)) +#ifdef CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_EXT_CAN_ID + if (info->mboxes_ext_cnt) { - return -EINVAL; + flexcan_setup_rxmbox_circbuf(&info->rxmbox_ext_circbuf); + flexcan_enable_rxmbox(chan, info->mboxes_std_cnt); } - *len = sizeof(cyg_can_remote_buf); +#endif // CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID + +} + +//=========================================================================== +// Setup Flex CAN moduls in a state where all message boxes are disabled +// After this call single message filters and buffers can be added +//=========================================================================== +static void flexcan_config_rx_none(can_channel *chan) +{ + flexcan_info *info = (flexcan_info *)chan->dev_priv; + flexcan_regs *flexcan = (flexcan_regs *)info->base; + cyg_int8 i; // - // If we need to create a new remote buffer then we check if there - // is one message box free and then setup this box for remote frame - // reception + // setup all RX messages moxes into a disabled state // - if (CYGNUM_CAN_MSGBUF_INIT == rtr_buf->handle) + for (i = 0; i < FLEXCAN_MBOX_RX_CNT; ++i) { - cyg_int8 mbox_index = flexcan_alloc_mbox(info); + flexcan_disable_mbox(chan, i); + } - if (mbox_index > -1) + // + // If we want to receive only certain CAN identiffiers then the ID does matter and + // we have to setup the acceptance mask properly + // + flexcan_set_acceptance_mask(&flexcan->RXGMASK_HI, FLEXCAN_ACCEPTANCE_MASK_RX_ID, CYGNUM_CAN_ID_EXT); + flexcan_set_acceptance_mask(&flexcan->RX14MASK_HI, FLEXCAN_ACCEPTANCE_MASK_RX_ID, CYGNUM_CAN_ID_EXT); + info->free_mboxes = FLEXCAN_MBOX_RX_CNT; + info->rx_all = false; +} + + +//=========================================================================== +// Configure message buffers +//=========================================================================== +static Cyg_ErrNo flexcan_set_config_msgbuf(can_channel *chan, cyg_can_msgbuf_cfg *buf) +{ + Cyg_ErrNo res = ENOERR; + flexcan_info *info = (flexcan_info *)chan->dev_priv; + + switch (buf->cfg_id) { // - // if we have a free message buffer then we setup this buffer - // for remote frame reception + // clear all message filters and remote buffers - prepare for message buffer + // configuration // - rtr_buf->handle = mbox_index; - flexcan_setup_rtrmbox(chan, rtr_buf->handle, &rtr_buf->msg); + case CYGNUM_CAN_MSGBUF_RESET_ALL : + { + flexcan_config_rx_none(chan); } - else - { - rtr_buf->handle = CYGNUM_CAN_MSGBUF_NA; - } - } // if (CYGNUM_CAN_RTR_BUF_INIT == rtr_buf->handle) - else // if (!(CYGNUM_CAN_MBUF_INIT == rtr_buf->handle)) - { + break; + // - // If we have a valid rtr buf handle then we can store data into - // rtr message box + // setup FlexCAN modul for reception of all standard and extended messages // - if ((rtr_buf->handle >= 0) && (rtr_buf->handle < FLEXCAN_MBOX_LAST_FREE)) + case CYGNUM_CAN_MSGBUF_RX_FILTER_ALL : { - flexcan_regs *flexcan = (flexcan_regs *)info->base; - flexcan_cfg_mbox_tx(&flexcan->mbox[rtr_buf->handle], &rtr_buf->msg, true); + if (!info->rx_all) // if rx_all is enabled we do not need to do anything + { + flexcan_config_rx_none(chan); // set into default state + flexcan_config_rx_all(chan); // setup RX all state } - else - { - return -EINVAL; - } - } // if (!(CYGNUM_CAN_MBUF_INIT == rtr_buf->handle)) } break; // - // Add a new message filter for reception of a certain CAN id. A call - // to this function will disable the RX all message boxes + // add single message filter, message with filter ID will be received // - case CYG_IO_SET_CONFIG_CAN_FILTER_MSG : + case CYGNUM_CAN_MSGBUF_RX_FILTER_ADD : { - cyg_int8 mbox_index; cyg_can_filter *filter = (cyg_can_filter*) buf; - if (*len != sizeof(cyg_can_filter)) + // + // if FlexCAN is configured to receive all messages then it is not + // allowed to add single message filters because then more than + // one message buffer would receive the same CAN id + // + if (info->rx_all) { - return -EINVAL; + return -EPERM; } - *len = sizeof(cyg_can_filter); // // try to allocate a free message box - if we have a free one // then we can prepare the message box for reception of the // desired message id // - mbox_index = flexcan_alloc_mbox(info); - if (mbox_index > -1) + filter->handle = flexcan_alloc_mbox(info); + if (filter->handle > CYGNUM_CAN_MSGBUF_NA) { + flexcan_setup_rxmbox(chan, filter->handle, &flexcan_mbox_rx_filt_isr, &filter->msg, true, true); + } + } + break; //CYGNUM_CAN_MSGBUF_RX_FILTER_ADD + // - // if message filtering is used the generic RX mbox should - // be disabled + // Try to add a new RTR response message buffer for automatic transmisson + // of data frame on reception of a remote frame // - if (MBOX_STATE_DISABLED != info->mboxes[info->rx_all_mbox_std].state) + case CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD : { - flexcan_disable_mbox(chan, info->rx_all_mbox_std); - } + cyg_can_remote_buf *rtr_buf = (cyg_can_remote_buf*) buf; + rtr_buf->handle = flexcan_alloc_mbox(info); - if (MBOX_STATE_DISABLED != info->mboxes[info->rx_all_mbox_ext].state) + if (rtr_buf->handle > CYGNUM_CAN_MSGBUF_NA) { - flexcan_disable_mbox(chan, info->rx_all_mbox_ext); + // + // if we have a free message buffer then we setup this buffer + // for remote frame reception + // + flexcan_setup_rtrmbox(chan, rtr_buf->handle, &rtr_buf->msg); + } } + break; // - // generic RX mbox is disabled and now we can setup message filter + // write data into remote response buffer + // + case CYGNUM_CAN_MSGBUF_REMOTE_BUF_WRITE : + { + cyg_can_remote_buf *rtr_buf = (cyg_can_remote_buf*) buf; + + // + // If we have a valid rtr buf handle then we can store data into + // rtr message box // - filter->handle = mbox_index; - flexcan_setup_rxmbox(chan, mbox_index, &filter->msg); + if ((rtr_buf->handle >= 0) && (rtr_buf->handle <= FLEXCAN_MBOX_RX_MAX)) + { + flexcan_regs *flexcan = (flexcan_regs *)info->base; + flexcan_cfg_mbox_tx(&flexcan->mbox[rtr_buf->handle], &rtr_buf->msg, true); } else { - filter->handle = CYGNUM_CAN_MSGBUF_NA; + return -EINVAL; } } - break; // CYG_IO_SET_CONFIG_CAN_FILTER_MSG + break; + } // switch (buf->cfg_id) - // - // Setup the FlexCAN modul for reception of any kind of CAN messages - // This call will setup 2 message boxes, one for all standad frames and one - // for all extended frames. This function will diable all other message - // filters - // - case CYG_IO_SET_CONFIG_CAN_FILTER_ALL: + return res; +} + +//=========================================================================== +// Set device configuration +//=========================================================================== +static Cyg_ErrNo +flexcan_set_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len) +{ + Cyg_ErrNo res = ENOERR; + + switch(key) { - cyg_uint8 i; - flexcan_mbox_info *pmbox; - cyg_can_message filter_param; // - // before we can enable the generic receive message box - // we have to disable all other RX message boxes + //Setup a new CAN configuration. This will i.e. setup a new baud rate // - for (i = 0; i < FLEXCAN_MBOX_LAST_FREE; ++i) + case CYG_IO_SET_CONFIG_CAN_INFO: { - pmbox = &info->mboxes[i]; - if (MBOX_STATE_RX == pmbox->state) + cyg_can_info_t* config = (cyg_can_info_t*) buf; + if (*len < sizeof(cyg_can_info_t)) { - flexcan_disable_mbox(chan, i); + return -EINVAL; + } + *len = sizeof(cyg_can_info_t); + if (!flexcan_config(chan, config, false)) + { + return -EINVAL; } } + break; // - // id does not matter here because the message buffers 14 and 15 - // have their own acceptance mask + // configure message buffers // - filter_param.id = 0; - filter_param.ext = CYGNUM_CAN_ID_STD; - flexcan_setup_rxmbox(chan, info->rx_all_mbox_std, &filter_param); - filter_param.ext = CYGNUM_CAN_ID_EXT; - flexcan_setup_rxmbox(chan, info->rx_all_mbox_ext, &filter_param); + case CYG_IO_SET_CONFIG_CAN_MSGBUF : + { + cyg_can_msgbuf_cfg *msg_buf = (cyg_can_msgbuf_cfg *) buf; + + if (*len != sizeof(cyg_can_msgbuf_cfg)) + { + return -EINVAL; + } + + flexcan_set_config_msgbuf(chan, msg_buf); } break; @@ -1002,7 +1272,7 @@ flexcan_get_config(can_channel *chan, cy } *len = sizeof(cyg_can_msgbuf_info); - mbox_info->count = FLEXCAN_MBOX_LAST_FREE; + mbox_info->count = FLEXCAN_MBOX_RX_CNT; mbox_info->free = info->free_mboxes; } break; @@ -1034,16 +1304,47 @@ flexcan_get_config(can_channel *chan, cy //=========================================================================== +// Check if we received self transmitted frame +//=========================================================================== +static bool flexcan_is_no_self_tx(cyg_can_event *pevent, flexcan_info *info, flexcan_mbox_info *pmbox) +{ + // + // If we received a self transmitted frame + // then this is not really an rx event and we return false. We rely on the + // fact here that two devices in network do not send the same identifier + // + if (pevent->msg.id == info->last_tx_id) + { + info->last_tx_id = 0xFFFFFFFF; // set last received ID to an invalid value + return false; + } + else + { + pevent->flags |= CYGNUM_CAN_EVENT_RX; + + // + // check if an overun occured in this message box + // + if ((pmbox->ctrlstat_shadow & MBOX_RXCODE_OVERRUN) == MBOX_RXCODE_OVERRUN) + { + pevent->flags |= CYGNUM_CAN_EVENT_OVERRUN_RX; + } + + return true; + } +} + + +//=========================================================================== // Read one event from can hardware - called from high level I/O CAN driver //=========================================================================== static bool flexcan_getevent(can_channel *chan, cyg_can_event *pevent, void *pdata) { flexcan_info *info = (flexcan_info *)chan->dev_priv; flexcan_regs *flexcan = (flexcan_regs *)info->base; - cyg_uint8 mbox_ctrlstat; bool res = true; - cyg_uint8 event_id = *((cyg_uint8 *)pdata); cyg_uint16 estat; + cyg_uint8 event_id = *((cyg_uint8 *)pdata); // // if event_id is 0 - 15 the we have a message box event @@ -1051,7 +1352,6 @@ static bool flexcan_getevent(can_channel if (event_id < FLEXCAN_ERR_EVENT) { flexcan_mbox_info *pmbox_info; - pmbox_info = &info->mboxes[event_id]; // @@ -1062,41 +1362,25 @@ static bool flexcan_getevent(can_channel // // If we have an RX event then we need to read the received data from // message box that caused this event and fill it into message queue of - // high level I/O CAN driver - // - case MBOX_STATE_RX: + // high level I/O CAN driver. We could handle this stuff in a function + // because it is the same like MBOX_STATE_RX_ALL_EXT but speed is more + // important here than codesize + // + case MBOX_STATE_RX_ALL_STD: + case MBOX_STATE_RX_ALL_EXT: + case MBOX_STATE_RX_FILT: + { // // read data from message box - during processing of this function // the message box is locked and cannot receive further messages // - flexcan_read_from_mbox(chan, event_id, pevent, &mbox_ctrlstat); - - // - // If we received a self transmitted frame - // then this is not really an rx event and we return false. We rely on the - // fact here that two devices in network do not send the same identifier - // - if (pevent->msg.id == info->last_tx_id) - { - info->last_tx_id = 0xFFFFFFFF; // set last received ID to an invalid value - res = false; - } - else - { - pevent->flags = CYGNUM_CAN_EVENT_RX; - - // - // check if an overun occured in this message box - // - if ((mbox_ctrlstat & MBOX_RXCODE_OVERRUN) == MBOX_RXCODE_OVERRUN) - { - pevent->flags |= CYGNUM_CAN_EVENT_OVERRUN_RX; - } + flexcan_read_from_mbox(chan, event_id, pevent, &(pmbox_info->ctrlstat_shadow)); + res = flexcan_is_no_self_tx(pevent, info, pmbox_info); } break; #ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT -// + // // If a TX message box cause the event then we store the last transmitted // message into the receive message queue // @@ -1189,7 +1473,7 @@ static bool flexcan_putmsg(can_channel * // // check if device is busy sending a message // - if (pmbox->tx_busy) + if (pmbox->busy) { // // if device is busy and the interrupt flag is set, then we know @@ -1205,7 +1489,7 @@ static bool flexcan_putmsg(can_channel * } } - pmbox->tx_busy = true; // mark transmitter as busy + pmbox->busy = true; // mark transmitter as busy info->last_tx_id = pmsg->id; // store message in order to identify self recieved frames #ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT @@ -1283,10 +1567,6 @@ static bool flexcan_config(can_channel* cyg_uint16 tmp16; cyg_uint8 tmp8; cyg_uint8 i; - cyg_can_message rx_all_filter = - { - id : 0, // CAN identifier - }; // // the first thing we need to do is to stop the chip @@ -1334,17 +1614,10 @@ static bool flexcan_config(can_channel* & ~FLEXCAN_CTRL0_ERRMASK); // - // setup message box acceptance filter - // - flexcan_set_acceptance_mask(&flexcan->RXGMASK_HI, info->rxgmask, CYGNUM_CAN_ID_EXT); - flexcan_set_acceptance_mask(&flexcan->RX14MASK_HI, info->rx14mask, CYGNUM_CAN_ID_EXT); - flexcan_set_acceptance_mask(&flexcan->RX15MASK_HI, info->rx15mask, CYGNUM_CAN_ID_EXT); - - // // deactivate all message buffers - this is mandatory for configuration // of message buffers // - for (i = 0; i < 16; ++i) + for (i = FLEXCAN_MBOX_MIN; i <= FLEXCAN_MBOX_MAX; ++i) { HAL_WRITE_UINT16(&flexcan->mbox[i], MBOX_RXCODE_NOT_ACTIVE); } @@ -1366,13 +1639,9 @@ static bool flexcan_config(can_channel* HAL_WRITE_UINT8(&flexcan->CANCTRL1, (tmp8 & ~FLEXCAN_CTRL1_LBUF)); // - // Message box 14 is our receiv message box. We configure it for - // reception of any message + // setup all rx message buffers // - rx_all_filter.ext = CYGNUM_CAN_ID_STD; - flexcan_setup_rxmbox(chan, info->rx_all_mbox_std, &rx_all_filter); - rx_all_filter.ext = CYGNUM_CAN_ID_EXT; - flexcan_setup_rxmbox(chan, info->rx_all_mbox_ext, &rx_all_filter); + flexcan_config_rx_all(chan); // // bus off interrupt and error interrupt @@ -1650,9 +1919,10 @@ static void flexcan_wake_dsr(cyg_vector_ //=========================================================================== -// Flexcan message box isr +// Flexcan message box isr for rx messages if message filtering is +// enabled //=========================================================================== -static cyg_uint32 flexcan_mbox_rx_isr(cyg_vector_t vec, cyg_addrword_t data) +static cyg_uint32 flexcan_mbox_rx_filt_isr(cyg_vector_t vec, cyg_addrword_t data) { can_channel *chan = (can_channel *)data; flexcan_info *info = (flexcan_info *)chan->dev_priv; @@ -1671,6 +1941,7 @@ static cyg_uint32 flexcan_mbox_rx_isr(cy // reenable it later // flexcan_mboxint_disable(info, mbox); + info->mboxes[mbox].ctrlstat_shadow = FLEXCAN_CTRLSTAT_NOT_READ; // // for clearing the interrupt we first read the flag register as 1 @@ -1690,10 +1961,243 @@ static cyg_uint32 flexcan_mbox_rx_isr(cy } +#ifdef CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_EXT_CAN_ID //=========================================================================== -// Flexcan message box dsr +// Flexcan message box isr for extended identifiers if reception of all +// available messages is enabled +//=========================================================================== +static cyg_uint32 flexcan_mbox_rx_ext_isr(cyg_vector_t vec, cyg_addrword_t data) +{ + can_channel *chan = (can_channel *)data; + flexcan_info *info = (flexcan_info *)chan->dev_priv; + flexcan_regs *flexcan = (flexcan_regs *)info->base; + cyg_uint16 iflag; + flexcan_rxmbox_circbuf *prx_mbox_list = &(info->rxmbox_ext_circbuf); + + // + // number of message box can be calculated from vector that caused + // interrupt - we pass this message box number as additional data to the + // callback because it is required in the receive event function later + // + cyg_uint8 mbox = vec - info->isr_vec_mbox0; + if (++prx_mbox_list->count < info->mboxes_ext_cnt) + { + prx_mbox_list->idx_wr = (prx_mbox_list->idx_wr + 1) % info->mboxes_ext_cnt; + flexcan_hwmbox_enable_rx(flexcan, prx_mbox_list->idx_wr + info->mboxes_std_cnt); + flexcan_hwmbox_lock(flexcan, mbox, &(info->mboxes[mbox].ctrlstat_shadow)); + flexcan_hwmbox_disable(flexcan, mbox); // now disable this message box - it is already locked + // + // first we disable interrupts of this message box - the DSR will + // reenable it later + // + flexcan_mboxint_disable(info, mbox); + } + else + { + prx_mbox_list->count = info->mboxes_ext_cnt; + info->mboxes[mbox].ctrlstat_shadow = FLEXCAN_CTRLSTAT_NOT_READ; + } + + // + // for clearing the interrupt we first read the flag register as 1 + // and then write it as 1 (and not as zero like the manual stated) + // we clear only the flag of this interrupt and leave all other + // message box interrupts untouched + // + HAL_READ_UINT16(&flexcan->IFLAG, iflag); + HAL_WRITE_UINT16(&flexcan->IFLAG, (0x0001 << mbox)); + + // + // On the mcf5272 there is no need to acknowledge internal + // interrupts, only external ones. + // cyg_drv_interrupt_acknowledge(vec); If counter of mbox list is > 1 + // then we know that there is already a DSR running and we do not + // need to invoke one + // + if (prx_mbox_list->count > 1) + { + return CYG_ISR_HANDLED; + } + else + { + return CYG_ISR_CALL_DSR; + } +} + + +//=========================================================================== +// FlexCAN message box DSR for extended CAN frames +//=========================================================================== +static void flexcan_mbox_rx_ext_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data) +{ + can_channel * chan = (can_channel *)data; + flexcan_info *info = (flexcan_info *)chan->dev_priv; + flexcan_rxmbox_circbuf *prx_mbox_list = &(info->rxmbox_ext_circbuf); + cyg_uint8 mbox; + cyg_uint8 mbox_cnt; + + // + // we do not process the message box we received as event_id + // we take the message boxes from the ring buffer + // + do + { + cyg_drv_isr_lock(); + mbox_cnt = --prx_mbox_list->count; + cyg_drv_isr_unlock(); + + mbox = prx_mbox_list->idx_rd + info->mboxes_std_cnt; + prx_mbox_list->idx_rd = (prx_mbox_list->idx_rd + 1) % info->mboxes_ext_cnt; + chan->callbacks->rcv_event(chan, &mbox); + flexcan_mboxint_enable(info, mbox); + + // + // if the last message box is enabled, then we have to enable + // another one now because the last message box is filled already + // + if (mbox_cnt == (info->mboxes_ext_cnt - 1)) + { + cyg_uint8 active_mbox; + cyg_uint8 next_mbox; + flexcan_regs *flexcan = (flexcan_regs *)info->base; + + cyg_drv_isr_lock(); + active_mbox = prx_mbox_list->idx_wr; + next_mbox = prx_mbox_list->idx_wr = (prx_mbox_list->idx_wr + 1) % info->mboxes_ext_cnt; + cyg_drv_isr_unlock(); + + active_mbox += info->mboxes_std_cnt; + next_mbox += info->mboxes_std_cnt; + flexcan_hwmbox_lock(flexcan, active_mbox, &(info->mboxes[active_mbox].ctrlstat_shadow)); + flexcan_hwmbox_disable(flexcan, active_mbox); // now disable this message box - it is already locked + flexcan_hwmbox_enable_rx(flexcan, next_mbox); + } + } + while (mbox_cnt); +} + +#endif // #ifdef CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_EXT_CAN_ID + + +#ifdef CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID +//=========================================================================== +// Flexcan message box isr for standard identifiers if reception of all +// available messages is enabled +//=========================================================================== +static cyg_uint32 flexcan_mbox_rx_std_isr(cyg_vector_t vec, cyg_addrword_t data) +{ + can_channel *chan = (can_channel *)data; + flexcan_info *info = (flexcan_info *)chan->dev_priv; + flexcan_regs *flexcan = (flexcan_regs *)info->base; + cyg_uint16 iflag; + flexcan_rxmbox_circbuf *prx_mbox_list = &(info->rxmbox_std_circbuf); + + // + // number of message box can be calculated from vector that caused + // interrupt - we pass this message box number as additional data to the + // callback because it is required in the receive event function later + // + cyg_uint8 mbox = vec - info->isr_vec_mbox0; + if (++prx_mbox_list->count < info->mboxes_std_cnt) + { + prx_mbox_list->idx_wr = (prx_mbox_list->idx_wr + 1) % info->mboxes_std_cnt; + flexcan_hwmbox_enable_rx(flexcan, prx_mbox_list->idx_wr); + flexcan_hwmbox_lock(flexcan, mbox, &(info->mboxes[mbox].ctrlstat_shadow)); + flexcan_hwmbox_disable(flexcan, mbox); // now disable this message box - it is already locked + // + // first we disable interrupts of this message box - the DSR will + // reenable it later + // + flexcan_mboxint_disable(info, mbox); + } + else + { + prx_mbox_list->count = info->mboxes_std_cnt; + info->mboxes[mbox].ctrlstat_shadow = FLEXCAN_CTRLSTAT_NOT_READ; + } + + // + // for clearing the interrupt we first read the flag register as 1 + // and then write it as 1 (and not as zero like the manual stated) + // we clear only the flag of this interrupt and leave all other + // message box interrupts untouched + // + HAL_READ_UINT16(&flexcan->IFLAG, iflag); + HAL_WRITE_UINT16(&flexcan->IFLAG, (0x0001 << mbox)); + + // + // On the mcf5272 there is no need to acknowledge internal + // interrupts, only external ones. + // cyg_drv_interrupt_acknowledge(vec); If counter of mbox list is > 1 + // then we know that there is already a DSR running and we do not + // need to invoke one + // + if (prx_mbox_list->count > 1) + { + return CYG_ISR_HANDLED; + } + else + { + return CYG_ISR_CALL_DSR; + } +} + + +//=========================================================================== +// Flexcan message box dsr for standard CAN frames +//=========================================================================== +static void flexcan_mbox_rx_std_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data) +{ + can_channel * chan = (can_channel *)data; + flexcan_info *info = (flexcan_info *)chan->dev_priv; + flexcan_rxmbox_circbuf *prx_mbox_list = &(info->rxmbox_std_circbuf); + cyg_uint8 mbox; + cyg_uint8 mbox_cnt; + + // + // we do not process the message box we received as event_id + // we take the message boxes from the ring buffer + // + do + { + cyg_drv_isr_lock(); + mbox_cnt = --prx_mbox_list->count; + cyg_drv_isr_unlock(); + + mbox = prx_mbox_list->idx_rd; + prx_mbox_list->idx_rd = (prx_mbox_list->idx_rd + 1) % info->mboxes_std_cnt; + chan->callbacks->rcv_event(chan, &mbox); + flexcan_mboxint_enable(info, mbox); + + // + // if the last message box is enabled, then we have to enable + // another one now because the last message box is filled already + // + if (mbox_cnt == (info->mboxes_std_cnt - 1)) + { + cyg_uint8 active_mbox; + cyg_uint8 next_mbox; + flexcan_regs *flexcan = (flexcan_regs *)info->base; + + cyg_drv_isr_lock(); + active_mbox = prx_mbox_list->idx_wr; + next_mbox = prx_mbox_list->idx_wr = (prx_mbox_list->idx_wr + 1) % info->mboxes_ext_cnt; + cyg_drv_isr_unlock(); + + flexcan_hwmbox_lock(flexcan, active_mbox, &(info->mboxes[active_mbox].ctrlstat_shadow)); + flexcan_hwmbox_disable(flexcan, active_mbox); // now disable this message box - it is already locked + flexcan_hwmbox_enable_rx(flexcan, next_mbox); + } + } + while (mbox_cnt); +} +#endif // CYGINT_DEVS_CAN_MCF52xx_FLEXCAN_SUPP_STD_CAN_ID + + //=========================================================================== -static void flexcan_mbox_rx_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data) +// FlexCAN DSR for message filters +//=========================================================================== +static void flexcan_mbox_rx_filt_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data) { can_channel *chan = (can_channel *)data; flexcan_info *info = (flexcan_info *)chan->dev_priv; @@ -1791,7 +2295,7 @@ static void flexcan_mbox_tx_dsr(cyg_vect chan->callbacks->rcv_event(chan, &mbox); #endif - pmbox->tx_busy = false; + pmbox->busy = false; // // send next message @@ -2049,7 +2553,8 @@ static bool flexcan_cfg_mbox_tx(flexcan_ // Configure message box for reception of a certain CAN identifier //=========================================================================== static void flexcan_cfg_mbox_rx(flexcan_mbox *pmbox, - cyg_can_message *pmsg) + cyg_can_message *pmsg, + bool enable) { cyg_uint16 id; @@ -2074,7 +2579,10 @@ static void flexcan_cfg_mbox_rx(flexcan_ HAL_WRITE_UINT16(&pmbox->id_lo, 0); } + if (enable) + { HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_RXCODE_EMPTY); + } } @@ -2091,9 +2599,16 @@ static void flexcan_read_from_mbox(can_c flexcan_mbox *pmbox = &flexcan->mbox[mbox]; cyg_can_message *pmsg = &pevent->msg; cyg_uint16 id; - cyg_uint8 i; + bool enable_mbox = false; + // + // If controlstat was not read, then read it now + // + if (FLEXCAN_CTRLSTAT_NOT_READ == *ctrlstat) + { HAL_READ_UINT8(&pmbox->ctrlstat, *ctrlstat); // this read will lock the mbox + enable_mbox = true; + } // // If message buffer is busy then it is now beeing filled with a new message @@ -2148,20 +2663,14 @@ static void flexcan_read_from_mbox(can_c HAL_READ_UINT8_VECTOR(&pmbox->data, pmsg->data, pmsg->dlc, 1); // - // now zero out the remaining bytes in can message in order - // to deliver a defined state - // - for (i = pmsg->dlc; i < 8; ++i) - { - pmsg->data[i] = 0; - } - - // // now mark this mbox as empty and read the free running timer // to unlock this mbox // + if (enable_mbox) + { HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_RXCODE_EMPTY); HAL_READ_UINT16(&flexcan->TIMER, id); + } #ifdef CYGOPT_IO_CAN_SUPPORT_TIMESTAMP pevent->timestamp = id; #endif diff --git a/packages/devs/can/m68k/mcf52xx/current/tests/flexcan_filter.c b/packages/devs/can/m68k/mcf52xx/current/tests/flexcan_filter.c --- a/packages/devs/can/m68k/mcf52xx/current/tests/flexcan_filter.c +++ b/packages/devs/can/m68k/mcf52xx/current/tests/flexcan_filter.c @@ -108,6 +108,7 @@ void can0_thread(cyg_addrword_t data) cyg_uint8 i; cyg_can_hdi hdi; cyg_can_msgbuf_info msgbox_info; + cyg_can_msgbuf_cfg msgbox_cfg; len = sizeof(hdi); @@ -126,6 +127,28 @@ void can0_thread(cyg_addrword_t data) } // + // We have free message boxes available and now we can setup the message + // filters, during this configuration process we set the FlexCAN modul into + // stopped state + // + mode = CYGNUM_CAN_MODE_STOP; + len = sizeof(mode); + if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MODE ,&mode, &len)) + { + CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); + } + + // + // Now reset message buffer configuration - this is mandatory bevore adding + // + msgbox_cfg.cfg_id = CYGNUM_CAN_MSGBUF_RESET_ALL; + len = sizeof(msgbox_cfg); + if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MSGBUF ,&msgbox_cfg, &len)) + { + CYG_TEST_FAIL_FINISH("Error restting message buffer configuration of /dev/can0"); + } + + // // Now query number of available and free message boxes // len = sizeof(msgbox_info); @@ -143,18 +166,6 @@ void can0_thread(cyg_addrword_t data) } // - // We have free message boxes available and now we can setup the message - // filters, during this configuration process we set the FlexCAN modul into - // stopped state - // - mode = CYGNUM_CAN_MODE_STOP; - len = sizeof(mode); - if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MODE ,&mode, &len)) - { - CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); - } - - // // Now device is stopped an we can setup all free message buffers // we setup as many standard CAN message filters as there are free // message buffers available. @@ -163,6 +174,7 @@ void can0_thread(cyg_addrword_t data) { cyg_can_filter rx_filter; + rx_filter.cfg_id = CYGNUM_CAN_MSGBUF_RX_FILTER_ADD; rx_filter.msg.id = i; if (i % 2) @@ -175,7 +187,7 @@ void can0_thread(cyg_addrword_t data) } len = sizeof(rx_filter); - if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_FILTER_MSG ,&rx_filter, &len)) + if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MSGBUF ,&rx_filter, &len)) { CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); } @@ -234,7 +246,10 @@ void can0_thread(cyg_addrword_t data) // // Now enable reception of all available CAN messages // - if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_FILTER_ALL , 0, 0)) + cyg_can_filter rx_filter; + rx_filter.cfg_id = CYGNUM_CAN_MSGBUF_RX_FILTER_ALL; + len = sizeof(rx_filter); + if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MSGBUF , &rx_filter, &len)) { CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); } @@ -279,9 +294,6 @@ void can0_thread(cyg_addrword_t data) void cyg_start(void) { - cyg_uint32 len; - cyg_can_info_t can_cfg; - CYG_TEST_INIT(); // @@ -292,15 +304,19 @@ cyg_start(void) CYG_TEST_FAIL_FINISH("Error opening /dev/can0"); } + // We do not setup baudrate and take dafauklt baudrate from config tool instead + /* // // setup CAN baudrate 250 KBaud // + cyg_uint32 len; + cyg_can_info_t can_cfg; can_cfg.baud = CYGNUM_CAN_KBAUD_250; len = sizeof(can_cfg); if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_INFO ,&can_cfg, &len)) { CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); - } + }*/ // // create the two threads which access the CAN device driver diff --git a/packages/devs/can/m68k/mcf52xx/current/tests/flexcan_load.c b/packages/devs/can/m68k/mcf52xx/current/tests/flexcan_load.c --- a/packages/devs/can/m68k/mcf52xx/current/tests/flexcan_load.c +++ b/packages/devs/can/m68k/mcf52xx/current/tests/flexcan_load.c @@ -245,9 +245,6 @@ void can1_thread(cyg_addrword_t data) void cyg_start(void) { - cyg_uint32 len; - cyg_can_info_t can_cfg; - CYG_TEST_INIT(); // @@ -258,15 +255,20 @@ cyg_start(void) CYG_TEST_FAIL_FINISH("Error opening /dev/can0"); } + // We do not setup baudrate and take dafauklt baudrate from config tool instead + /* // // setup CAN baudrate 250 KBaud // + cyg_uint32 len; + cyg_can_info_t can_cfg; can_cfg.baud = CYGNUM_CAN_KBAUD_250; len = sizeof(can_cfg); if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_INFO ,&can_cfg, &len)) { CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); } + */ // // create the two threads which access the CAN device driver diff --git a/packages/devs/can/m68k/mcf52xx/current/tests/flexcan_remote.c b/packages/devs/can/m68k/mcf52xx/current/tests/flexcan_remote.c --- a/packages/devs/can/m68k/mcf52xx/current/tests/flexcan_remote.c +++ b/packages/devs/can/m68k/mcf52xx/current/tests/flexcan_remote.c @@ -134,12 +134,32 @@ void can0_thread(cyg_addrword_t data) CYG_TEST_FAIL_FINISH("Error stopping FlexCAN /dev/can0"); } + // + // We would like to setup 2 remote buffers - check if we have enough + // free message buffers + // + len = sizeof(msgbox_info); + if (ENOERR != cyg_io_get_config(hDrvFlexCAN, CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO ,&msgbox_info, &len)) + { + CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0"); + } + else + { + diag_printf("Message boxes available: %d free: %d\n", + msgbox_info.count, msgbox_info.free); + } + + if (msgbox_info.free < 2) + { + CYG_TEST_FAIL_FINISH("Not enough free message buffers/dev/can0"); + } + // // Setup the first remote response buffer for resception of standard // remote frames // - rtr_buf.handle = CYGNUM_CAN_MSGBUF_INIT; + rtr_buf.cfg_id = CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD; rtr_buf.msg.id = 0x7FF; rtr_buf.msg.ext = CYGNUM_CAN_ID_STD; rtr_buf.msg.rtr = CYGNUM_CAN_FRAME_DATA; @@ -147,7 +167,7 @@ void can0_thread(cyg_addrword_t data) rtr_buf.msg.data[0] = 0xAB; len = sizeof(rtr_buf); - if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_REMOTE_BUF ,&rtr_buf, &len)) + if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MSGBUF ,&rtr_buf, &len)) { CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); } @@ -156,7 +176,7 @@ void can0_thread(cyg_addrword_t data) // setup the second remote response buffer for reception of extended // remote frames // - rtr_buf2.handle = CYGNUM_CAN_MSGBUF_INIT; + rtr_buf2.cfg_id = CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD; rtr_buf2.msg.id = 0x800; rtr_buf2.msg.ext = CYGNUM_CAN_ID_EXT; rtr_buf2.msg.rtr = CYGNUM_CAN_FRAME_DATA; @@ -164,7 +184,7 @@ void can0_thread(cyg_addrword_t data) rtr_buf2.msg.data[0] = 0xAB; len = sizeof(rtr_buf2); - if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_REMOTE_BUF ,&rtr_buf2, &len)) + if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MSGBUF ,&rtr_buf2, &len)) { CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); } @@ -228,9 +248,6 @@ void can0_thread(cyg_addrword_t data) void cyg_start(void) { - cyg_uint32 len; - cyg_can_info_t can_cfg; - CYG_TEST_INIT(); // @@ -243,13 +260,16 @@ cyg_start(void) // // setup CAN baudrate 250 KBaud - // + // We do not setup baud rate and use the default baud rate instead + /* + cyg_uint32 len; + cyg_can_info_t can_cfg; can_cfg.baud = CYGNUM_CAN_KBAUD_250; len = sizeof(can_cfg); if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_INFO ,&can_cfg, &len)) { CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); - } + }*/ // // create the two threads which access the CAN device driver diff --git a/packages/devs/can/m68k/mcf52xx/current/tests/flexcan_wake.c b/packages/devs/can/m68k/mcf52xx/current/tests/flexcan_wake.c --- a/packages/devs/can/m68k/mcf52xx/current/tests/flexcan_wake.c +++ b/packages/devs/can/m68k/mcf52xx/current/tests/flexcan_wake.c @@ -139,7 +139,7 @@ void can0_thread(cyg_addrword_t data) // Setup the first remote response buffer for resception of standard // remote frames // - rtr_buf.handle = CYGNUM_CAN_MSGBUF_INIT; + rtr_buf.cfg_id = CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD; rtr_buf.msg.id = 0x7FF; rtr_buf.msg.ext = CYGNUM_CAN_ID_STD; rtr_buf.msg.rtr = CYGNUM_CAN_FRAME_DATA; @@ -147,7 +147,7 @@ void can0_thread(cyg_addrword_t data) rtr_buf.msg.data[0] = 0xAB; len = sizeof(rtr_buf); - if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_REMOTE_BUF ,&rtr_buf, &len)) + if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MSGBUF ,&rtr_buf, &len)) { CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); } @@ -251,9 +251,6 @@ void can0_thread(cyg_addrword_t data) void cyg_start(void) { - cyg_uint32 len; - cyg_can_info_t can_cfg; - CYG_TEST_INIT(); // @@ -264,15 +261,19 @@ cyg_start(void) CYG_TEST_FAIL_FINISH("Error opening /dev/can0"); } + // We do not setup baudrate and take dafauklt baudrate from config tool instead + /* // // setup CAN baudrate 250 KBaud // + cyg_uint32 len; + cyg_can_info_t can_cfg; can_cfg.baud = CYGNUM_CAN_KBAUD_250; len = sizeof(can_cfg); if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_INFO ,&can_cfg, &len)) { CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); - } + }*/ // // create the two threads which access the CAN device driver diff --git a/packages/io/can/current/ChangeLog b/packages/io/can/current/ChangeLog --- a/packages/io/can/current/ChangeLog +++ b/packages/io/can/current/ChangeLog @@ -1,3 +1,9 @@ +2006-02-15 Uwe Kindler + + * include/can_io.h Added message buffer configuration identifier: + CYGNUM_CAN_MSGBUF_RESET_ALL, CYGNUM_CAN_MSGBUF_RX_FILTER_ALL ... + Added cfg_id field to cyg_can_msgbuf_cfg data structure. + 2005-09-11 Uwe Kindler * include/can_io.h Added support for get_config to CAN_LOWLEVEL_FUNS diff --git a/packages/io/can/current/doc/can_driver_doc.html b/packages/io/can/current/doc/can_driver_doc.html --- a/packages/io/can/current/doc/can_driver_doc.html +++ b/packages/io/can/current/doc/can_driver_doc.html @@ -204,11 +204,8 @@ CYG_IO_SET_CONFIG_CAN_INPUT_FLUSH
- CYG_IO_SET_CONFIG_CAN_TIMEOUT
- CYG_IO_SET_CONFIG_CAN_REMOTE_BUF
+ CYG_IO_SET_CONFIG_CAN_TIMEOUT
CYG_IO_SET_CONFIG_CAN_MSGBUF
CYG_IO_SET_CONFIG_CAN_MODE
- CYG_IO_SET_CONFIG_CAN_FILTER_ALL
- CYG_IO_SET_CONFIG_CAN_FILTER_MSG

Runtime Configuration

@@ -284,21 +281,21 @@

FullCAN:
If the Bit 2 is set to one, the CAN controller supports more than one message buffer.

-

CYGNUM_CAN_HDI_FULLCAN    // supports more than one message buffer
+

CYGNUM_CAN_HDI_FULLCAN                // supports more than one message buffer

SW-Filter:
If Bit3 is set to one then the CAN driver supports some kind of software message filtering.

-

CYGNUM_CAN_HDI_FILT_SW    // software message filtering supported
+

CYGNUM_CAN_HDI_FILT_SW                // software message filtering supported

Timestamp:
If Bit 4 is set to one then the CAN hardware supports timestamps for CAN messages

-

CYGNUM_CAN_HDI_TIMESTAMP    // CAN hardware supports timestamps
+

CYGNUM_CAN_HDI_TIMESTAMP              // CAN hardware supports timestamps

Reading message buffer configuration

typedef struct cyg_can_msgbox_info_st
{
    c
yg_uint8 count; // number of message buffers available for this device
-     
cyg_uint8 free; // number of free message buffers
+     
cyg_uint8 free;  // number of free message buffers
} cyg_can_msgbuf_info;

CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO - If the CAN hardware supports more than one message buffer for reception of CAN message (flag CYGNUM_CAN_HDI_FULLCAN is set after reading hardware description interface with CYG_IO_GET_CONFIG_CAN_HDI) then this function reads the number of message buffers the CAN hardware supports and the number of free message buffers. The field count contains the number of message buffers supported by device and the field free contains the number of free message buffers. The free message buffers are available for setting up remote buffers (CYG_IO_SET_CONFIG_CAN_REMOTE_BUF) and message filters (CYG_IO_SET_CONFIG_CAN_FILTER_MSG).

Reading state of CAN hardware

@@ -337,21 +334,46 @@
enable switching between blocking and nonblocking calls separatly for read and write calls. If blocking calls are configured then the read/write functions return only if a message was stored into TX buffer or a event was received from RX buffer. If nonblocking calls are enabled and there is no space in TX buffer or RX buffer is empty then the function returns immediatelly with -EAGAIN. If nonblocking calls are enabled and additionally timeouts are supported by driver, then the read/write functions wait until timeout value is expired and then return witn -EINTR. If the read/write operation succeeds during the timed wait then the functions return succesfully with ENOERR. +

Message buffer configuration

+

typedef struct cyg_can_msgbox_cfg_st
+
{
+     
cyg_can_msgbuf_cfg_id cfg_id; // configuration id - cfg. what to do with message buffer
+     
cyg_can_msgbuf_handle handle; // handle to message buffer
+     
cyg_can_message msg;          // CAN message - for configuration of buffer
+
} cyg_can_msgbuf_cfg;

+

Full CAN controllers often support more the one message buffer. These message buffers are often configurable for transmission or reception of certain CAN messages or as a remote buffer. If a CAN hardware supports more than one message buffer then it is possible to configure the CAN hardware to receive only CAN messages with certain identifiers or to configure hardware support for remote buffers. If message filtering is done by hardware, the number of received CAN messages decreases and so also the time for processing received CAN messages and the memory required for buffering received messages decreases. This saves valuable memory and processing time. The eCos CAN driver supports a generic way of adding message filters or remote buffers. By default the CAN driver is configured for reception of any kind of CAN standard and extended frames. Configuration of message buffers is done by calling cyg_io_set_config() with the config key:

+

CYG_IO_SET_CONFIG_CAN_MSGBUF
+

+

and exchanging cyg_can_msgbuf_cfg data structures. The cfg_id field contains the configuration ID that tells the driver what to do with a message buffer, the handle field contains a reference to a certain message buffer and the msg field is necessary for configuration of message buffer parameters. The following configuration identifiers are supported:

+

CYGNUM_CAN_MSGBUF_RESET_ALL        // clears alle message buffers, no message will be received, all remote buffers deleted
+
CYGNUM_CAN_MSGBUF_RX_FILTER_ALL    // cfg driver for reception of all can messges
+
CYGNUM_CAN_MSGBUF_RX_FILTER_ADD    // add single message filter
+
CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD   // add new remote response buffer
+
CYGNUM_CAN_MSGBUF_REMOTE_BUF_WRITE // stores data into existing remote buffer (remote buf handle required)

+

Example code for resetting all message buffers:

+

cyg_can_msgbuf_cfg msgbox_cfg;

+

msgbox_cfg.cfg_id = CYGNUM_CAN_MSGBUF_RESET_ALL;
+
len = sizeof(msgbox_cfg);
+
if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MSGBUF ,&msgbox_cfg, &len))
+
{
+     
// handle configuration error
+
}

Remote frame response buffer configuration

The remote frame is a message frame which is transmitted to request a data frame. Some CAN hardware generates receive interrupts when a remote transmission request arrives. Other CAN hardware, i.e. the FlexCAN module, does not generate any receive interrupt. These CAN hardware chips, i.e. the FlexCAN module, can be configured to transmit a data frame automatically in response to a remote frame. In oder to support any kind of CAN hardware the eCos CAN driver provides a generic handling of remote transmission requests.

-

The transmission of the data frame in response to a remote frame is completely handled by the CAN driver. If the hardware driver, like the driver for the FlexCAN modul, supports harware message buffers, then the response frame is automatically transmitted if a remote transmission request with a matching ID arrives. If a CAN hardware does provide hardware support for sending the data frames in response to a remote frame, then this need to be implemented in software by the hardware device driver.

-

In order to respond to a remote frame, a remote frame reponse buffer need to be initialized before a data frame CAN be sent in response to a remote frame. This is achieved by by exchanging cyg_can_remote_buf data structures with the driver via the cyg_io_set_config() function using the config key CYG_IO_SET_CONFIG_CAN_REMOTE_BUF. Once the buffer is initialized, the CAN data can be changed at any time by the application.

+

The transmission of the data frame in response to a remote frame is completely handled by the CAN driver. If the hardware driver, like the driver for the FlexCAN modul, supports harware message buffers, then the response frame is automatically transmitted if a remote transmission request with a matching ID arrives. If a CAN hardware does not provide hardware support for sending data frames in response to a remote frame, then this need to be implemented in software by the hardware device driver.

+

It is always possible to add remote response buffers. It does not matter if the driver is configured for reception of all CAN messages or if message filtering is used. As long as there are free message buffers available, it is possible to add remote response buffers.

+

In order to respond to a remote frame, a remote frame reponse buffer need to be initialized before a data frame can be sent in response to a remote frame. This is achieved by by exchanging cyg_can_remote_buf data structures with the driver via the cyg_io_set_config() function using the config key CYG_IO_SET_CONFIG_CAN_MSGBUF. Once the buffer is initialized, the CAN data can be changed at any time by the application.

typedef struct cyg_can_msgbuf_cfg_st
-
{
-     cyg_int8 handle;
-     cyg_can_message msg;
-
} cyg_can_remote_buf;
+
{
    cyg_can_msgbuf_cfg_id cfg_id; // configuration id - cfg. what to do with message buffer
+     
cyg_can_msgbuf_handle handle; // handle to message buffer
+     
cyg_can_message msg;          // CAN message - for configuration of buffer
+ } cyg_can_remote_buf;

The CAN frame that should be transmitted in response to a remote frame is stored in the msg field of the cyg_can_remote_buf data structure. If there is no buffer initialized for this data, the value of the handle field need to be set to CYGNUM_CAN_MSGBUF_INIT. After the call to cyg_io_set_config() the handle field contains a valid value ( >= 0) or the value CYGNUM_CAN_MSGBUF_NA ( < 0) if no free buffer is available. With the valid handle value the CAN data can be changed later by calling cyg_io_set_config(). Before adding remote buffers the device should be stopped and after configuration it should be set into operational mode again

Example code for setting up a remote response buffer:

cyg_can_remote_buf rtr_buf;

- // prepare the remote response buffer
+ // prepare the remote response buffer
rtr_buf.cfg_id  = CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD;
rtr_buf.handle  = CYGNUM_CAN_MSGBUF_INIT;
rtr_buf.msg.id  = 0x7FF;
rtr_buf.msg.ext = CYGNUM_CAN_ID_STD;
@@ -359,32 +381,103 @@
rtr_buf.msg.dlc = 1;
rtr_buf.msg.data[0] = 0xAB;

+ len = sizeof(rtr_buf);
-
if (ENOERR != cyg_io_set_config(hDrvFlexCAN,
                                CYG_IO_SET_CONFIG_CAN_REMOTE_BUF ,
+
if (ENOERR != cyg_io_set_config(hDrvFlexCAN,
+                                 CYG_IO_SET_CONFIG_CAN_MSGBUF,
+                                 &rtr_buf, &len))
{
+     // handle configuration error
}

if (rtr_buf.handle == CYGNUM_CAN_MSGBUF_NA)
{
+     // no free message buffer available - handle this problem here
}
-
// change CAN data for a buffer that is already initialized
+
+
+ + // change CAN data for a buffer that is already initialized
+
rtr_buf.cfg_id = CYGNUM_CAN_MSGBUF_REMOTE_BUF_WRITE;
+ + rtr_buf.msg.data[0] = 0x11;

+ + len = sizeof(rtr_buf);
-
if (ENOERR != cyg_io_set_config(hDrvFlexCAN,
                                CYG_IO_SET_CONFIG_CAN_REMOTE_BUF ,
+
if (ENOERR != cyg_io_set_config(hDrvFlexCAN,
+ +                                 CYG_IO_SET_CONFIG_CAN_MSGBUF,
+ +                                 &rtr_buf, &len))
{
+ +     // handle configuration error
}

+

Message filter configuration

+

If message filtering is done by hardware the number of received CAN messages decreases and so also the time for processing received CAN messages and the memory required for buffering received messages decreases. This saves valuable memory and processing time. The eCos CAN driver supports a generic way of adding message filters. By default the CAN driver is configured for reception of any kind of CAN standard and extended frames. As soon as a message filter is added, the CAN driver will only receive the CAN frames with the identifier of the CAN filter. By adding a number of message filters it is possible for the CAN hardware to receive an number of different CAN messages.

+

Adding message filters is only possible if driver is not configured for reception of all available CAN messages. If driver is configured for recption of all CAN messages then message buffers neet to be reset before adding single message filters.

+

In order to add a message filter, a message buffer need to be initialized. This is achieved by by exchanging cyg_can_filter data structures with the driver via the cyg_io_set_config() function using the config key CYG_IO_SET_CONFIG_CAN_MSGBUF. Once the buffer is initialized, the CAN hardware can recive messages with the identifier of the filter.

+

typedef struct cyg_can_msgbox_cfg_st
+
{
+     cyg_can_msgbuf_cfg_id cfg_id;
+     
cyg_can_msgbuf_handle handle;
+ +     
cyg_can_message       msg;
+
} cyg_can_filter;

+

After the call to cyg_io_set_config() the handle field contains a valid value ( >= 0) or the value CYGNUM_CAN_MSGBUF_NA ( < 0) if no free buffer is available. Before adding message filters the device should be stopped and after configuration it should be set into operational mode again

+

Example code for setting up a message filter:

+

cyg_can_msgbuf_cfg msgbox_cfg;
+ cyg_can_filter rx_filter;
+
+ // reset all message buffers

+ msgbox_cfg.cfg_id = CYGNUM_CAN_MSGBUF_RESET_ALL;
+
len = sizeof(msgbox_cfg);
+
if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MSGBUF ,&msgbox_cfg, &len))
+
{
+     
// handle configuration error
+
}
+
+
// prepare the message filter
+ rx_filter.cfg_id = CYGNUM_CAN_MSGBUF_RX_FILTER_ADD
+
rx_filter.msg.id  = 0x800;
+ rx_filter.msg.ext = CYGNUM_CAN_ID_EXT;
+
+ len = sizeof(rx_filter);
+ if (ENOERR != cyg_io_set_config(hDrvFlexCAN,
+                                 CYG_IO_SET_CONFIG_CAN_MSGBUF,
+                                 &rx_filter, &len))
+
{
+     
// handle configuration error;
+
}
+
else if (CYGNUM_CAN_MSGBUF_NA == rx_filter.handle)
+
{
+     // no free message buffer available - handle this problem here
+ }

+

Receive all CAN messages

After startup of your device the CAN driver is configured for reception of all available CAN messages. If you change this configuration by adding single message filters then you can reset this default state with the configuration ID:

CYGNUM_CAN_MSGBUF_RX_FILTER_ALL

+

A call to this function will clear all message filters and remote buffers and prepares the CAN hardware for recption of any kind of CAN standard and extended frames. It is not neccesary to reset the message buffer configuration before this configuration is setup because this should be done by device driver.

+

Example code for setup of a receive all CAN frames configuration:

+

cyg_can_filter rx_filter;
+
+ // now setup a RX all configuration
+
rx_filter.cfg_id = CYGNUM_CAN_MSGBUF_RX_FILTER_ALL;
+
len = sizeof(rx_filter);
+
if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MSGBUF , &rx_filter, &len))
+
{
+     
CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0");
+
}

Set mode of CAN hardware

typedef enum
{
@@ -393,39 +486,10 @@   
CYGNUM_CAN_MODE_STANDBY // set controller into standby / sleep mode
} cyg_can_mode;

CYG_IO_SET_CONFIG_CAN_MODE - This function changes the operating mode of the CAN controller. Possible values for mode are defined in the cyg_can_mode enumeration. Befor the hardware configuration of the device is changed, that means if baudrate is changed or the message buffer and filter configuration is changed, the CAN hardware should be set into stop mode and if configuration is finished, then device should be set back into operational mode. Before the device is set into standby mode, the output buffers should be flushed or drained because transmission of a CAN message may wake up the CAN hardware. If a received message wakes up the CAN hardware from standby mode then a CYGNUM_CAN_EVENT_LEAVING_STANDBY event will be inserted into receive message buffer or the CYGNUM_CAN_EVENT_LEAVING_STANDBY flag will be set for the message that caused wake up of CAN hardware.

-

Message filter configuration

-

CYG_IO_SET_CONFIG_CAN_FILTER_MSG - Full CAN controlles often support more the one message buffer for reception of CAN messages. If a CAN hardware supports more then one message buffer it is possible to configure the CAN hardware to receive only CAN messages with certain identifiers. If message filtering is done by hardware the number of received CAN messages decreases and so also the time for processing received CAN messages and the memory required for buffering received messagews decreases. This saves valuable memory and processing time. The eCos CAN driver supports a generic way of adding message filters. By default the CAN driver is configured for reception of any kind of CAN standard and extended frames. As soon as a message filter is added, the CAN driver will only receive the CAN frames with the identifier of the CAN filter. By adding a number of message filters it is possible for the CAN hardware to receive an number of different CAN messages.

-

In order to add a message filter, a message buffer need to be initialized. This is achieved by by exchanging cyg_can_filter data structures with the driver via the cyg_io_set_config() function using the config key CYG_IO_SET_CONFIG_CAN_FILTER_MSG. Once the buffer is initialized, the CAN hardware can recive messages with the identifier of the filter.

-

typedef struct cyg_can_msgbox_cfg_st
-
{
-     
cyg_can_msgbuf_handle handle;
-     
cyg_can_message       msg;
-
} cyg_can_filter;

-

After the call to cyg_io_set_config() the handle field contains a valid value ( >= 0) or the value CYGNUM_CAN_MSGBUF_NA ( < 0) if no free buffer is available. Before adding message filters the device should be stopped and after configuration it should be set into operational mode again

-

Example code for setting up a message filter:

-

cyg_can_filter rx_filter;
-
- // prepare the message filter
- rx_filter.msg.id  = 0x800;
- rx_filter.msg.ext = CYGNUM_CAN_ID_EXT;
-
- len = sizeof(rx_filter);
- if (ENOERR != cyg_io_set_config(hDrvFlexCAN,
-                                 CYG_IO_SET_CONFIG_CAN_FILTER_MSG,
-                                 &rx_filter, &len))
-
{
-     
// handle configuration error;
-
}
-
else if (CYGNUM_CAN_MSGBUF_NA == rx_filter.handle)
-
{
-     // no free message buffer available - handle this problem here
- }

-

Message filter reset

-

CYG_IO_SET_CONFIG_CAN_FILTER_ALL - A call to this function will clear all message filters (the remote buffers are not affected by this call) and prepares the CAN hardware for recption of any kind of CAN standard and extended frames.

FlexCAN device driver

The FlexCAN module is a communication controller implementing the controller area network (CAN) protocol, an asynchronous communications protocol used in automotive and industrial control systems. It is a high speed (1 Mbit/sec), short distance, priority based protocol which can communicate using a variety of mediums (for example, fiber optic cable or an unshielded twisted pair of wires). The FlexCAN supports both the standard and extended identifier (ID) message formats specified in the CAN protocol specification, revision 2.0, part B.

It supports up to 16 flexible flexible message buffers of 0-8 bytes data length, each configurable as Rx or Tx, all supporting standard and extended messages.

-

The message buffer 13 of the FlexCAN modul is reserved for transmission of CAN messages. Message buffer 14 is reserved for reception of any kind of standard frames and message buffer 15 is reserved for reception of any kind of extended frames. Message buffers 0 - 12 are available for configuration of remote buffers and message filters.

+

The message buffer 16 of the FlexCAN modul is reserved for transmission of CAN messages. Message buffers 1 - 15 are available for configuration of remote buffers and message filters. If the FlexCAN modul is configured for reception of all CAN frames, then the user can select the number of buffers used for reception of CAN frames. The interrupt priority of each message box is configurable.

\ No newline at end of file diff --git a/packages/io/can/current/include/canio.h b/packages/io/can/current/include/canio.h --- a/packages/io/can/current/include/canio.h +++ b/packages/io/can/current/include/canio.h @@ -122,7 +122,7 @@ typedef enum // // State of CAN controller // -typedef enum +typedef enum e_cyg_can_state { CYGNUM_CAN_STATE_ACTIVE, // CAN controller is active, no errors CYGNUM_CAN_STATE_STOPPED, // CAN controller is in stopped mode @@ -138,7 +138,7 @@ typedef enum // // Identifiers for operating mode of the CAN controller. // -typedef enum +typedef enum e_cyg_can_mode { CYGNUM_CAN_MODE_STOP, // set controller into stop mode CYGNUM_CAN_MODE_START, // set controller into operational mode @@ -148,7 +148,7 @@ typedef enum // // Type of CAN identifier. // -typedef enum +typedef enum e_cyg_can_id_type { CYGNUM_CAN_ID_STD = 0x00, // standard ID 11 Bit CYGNUM_CAN_ID_EXT = 0x01 // extended ID 29 Bit @@ -157,17 +157,27 @@ typedef enum // // Type of CAN frame // -typedef enum +typedef enum e_cyg_can_frame_type { CYGNUM_CAN_FRAME_DATA = 0x00, // CAN data frame CYGNUM_CAN_FRAME_RTR = 0x01 // CAN remote transmission request } cyg_can_frame_type; +// +// Message buffer configuration identifier - we do not use an enum here so that +// a specific device driver can add its own configuration identifier +// +typedef cyg_uint8 cyg_can_msgbuf_cfg_id; +#define CYGNUM_CAN_MSGBUF_RESET_ALL 0 // no message will be received, all remote buffers deleted +#define CYGNUM_CAN_MSGBUF_RX_FILTER_ALL 1 // cfg driver for reception of all can messges +#define CYGNUM_CAN_MSGBUF_RX_FILTER_ADD 2 // add single message filter +#define CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD 3 // add new remote response buffer +#define CYGNUM_CAN_MSGBUF_REMOTE_BUF_WRITE 4 // store data into existing remote buffer (remote buf handle required) // // CAN message type for transport or transmit of CAN messages // -typedef struct can_message +typedef struct st_cyg_can_message { cyg_uint32 id; // 11 Bit or 29 Bit CAN identifier - cyg_can_id_type cyg_uint8 data[8];// 8 data bytes @@ -236,7 +246,7 @@ typedef struct cyg_can_timeout_info_st // this data type defines a handle to a message buffer or message box // of the CAN hardware device // -typedef cyg_int8 cyg_can_msgbuf_handle; +typedef cyg_int32 cyg_can_msgbuf_handle; // @@ -244,8 +254,9 @@ typedef cyg_int8 cyg_can_msgbuf_handle; // typedef struct cyg_can_msgbox_cfg_st { - cyg_can_msgbuf_handle handle; - cyg_can_message msg; + cyg_can_msgbuf_cfg_id cfg_id; // configuration id - cfg. what to do with message buffer + cyg_can_msgbuf_handle handle; // handle to message buffer + cyg_can_message msg; // CAN message - for configuration of buffer } cyg_can_msgbuf_cfg; // @@ -264,10 +275,10 @@ typedef cyg_can_msgbuf_cfg cyg_can_filte typedef cyg_can_msgbuf_cfg cyg_can_remote_buf; // -// Values for the handle field of the cyg_can_rtr_buf_t data structure +// Values for the handle field of the cyg_can_rtr_buf, cyg_can_filter and +// cyg_can_msgbuf_cfg data structure // #define CYGNUM_CAN_MSGBUF_NA -0x01 // no free message buffer available -#define CYGNUM_CAN_MSGBUF_INIT -0x02 // initialize the remote message buffer // diff --git a/packages/io/common/current/ChangeLog b/packages/io/common/current/ChangeLog --- a/packages/io/common/current/ChangeLog +++ b/packages/io/common/current/ChangeLog @@ -1,3 +1,11 @@ +2006-02-15 Uwe Kindler + + * include/config_keys.h Replaced CAN configuration keys + CYG_IO_SET_CONFIG_CAN_REMOTE_BUF, + CYG_IO_SET_CONFIG_CAN_FILTER_ALL and + CYG_IO_SET_CONFIG_CAN_FILTER_MSG with new single config key + CYG_IO_SET_CONFIG_CAN_MSGBUF + 2005-12-02 Andrew Lunn * src/iosys.c: diff --git a/packages/io/common/current/include/config_keys.h b/packages/io/common/current/include/config_keys.h --- a/packages/io/common/current/include/config_keys.h +++ b/packages/io/common/current/include/config_keys.h @@ -143,10 +143,9 @@ #define CYG_IO_SET_CONFIG_CAN_OUTPUT_FLUSH 0x0883 #define CYG_IO_SET_CONFIG_CAN_INPUT_FLUSH 0x0884 #define CYG_IO_SET_CONFIG_CAN_TIMEOUT 0x0885 -#define CYG_IO_SET_CONFIG_CAN_REMOTE_BUF 0x0886 +#define CYG_IO_SET_CONFIG_CAN_MSGBUF 0x0886 #define CYG_IO_SET_CONFIG_CAN_MODE 0x0887 -#define CYG_IO_SET_CONFIG_CAN_FILTER_ALL 0x0888 -#define CYG_IO_SET_CONFIG_CAN_FILTER_MSG 0x0889 +#define CYG_IO_SET_CONFIG_CAN_ABORT 0x0888