Mercurial > ecos
changeset 2420:113240d85246
* doc/can.sgml: Callback on event documentation.
* src/can.c: Change one wakeup to callback in a comment.
* include/canio.h: changed cyg_addrword_t to CYG_ADDRWORD so
can will compile without the kernel.
| author | asl |
|---|---|
| date | Fri, 24 Aug 2007 13:41:25 +0000 |
| parents | 2e7c1dfc434c |
| children | 51899a482fdd |
| files | packages/io/can/current/ChangeLog packages/io/can/current/doc/can.sgml packages/io/can/current/include/canio.h packages/io/can/current/src/can.c |
| diffstat | 4 files changed, 2153 insertions(+), 2068 deletions(-) [+] |
line wrap: on
line diff
--- a/packages/io/can/current/ChangeLog +++ b/packages/io/can/current/ChangeLog @@ -1,162 +1,169 @@ -2007-08-06 Alexey Shusharin <mrfinch@mail.ru> - Andrew Lunn <andrew.lunn@ascom.ch> - - * cdl/io_can.cdl: Added option CYGOPT_IO_CAN_SUPPORT_CALLBACK - - * include/canio.h: Added struct cyg_can_callback_cfg for setting - callback configurations. - - * include/can.h: Added declaration and initialization of callback - configuration in struct can_channel. - - * src/can.c: Added callback configuration changing and - application function call. - -2007-07-02 Uwe Kindler <uwe_kindler@web.de> - - * cdl/io_can.cdl: Added interface CYGINT_IO_CAN_CHANNELS for - counting available CAN channels - - * include/canio.h: Changed type cyg_can_msgbuf_info. The two - fields are 16 bit now because device drivers may support more - than 256 message buffers (i.e. the LPC2xxx CAN driver) - -2007-06-20 Uwe Kindler <uwe_kindler@web.de> - - * test/can_filter: Changed filter loop counter from cyg_uint8 to - cyg_uint16 because LPC2xxx CAN driver supports more than 256 - message buffers. - -2007-03-23 Uwe Kindler <uwe_kindler@web.de> - - * cdl/io_can.cdl: Added several interfaces for implementation by - device drivers. - Moved several configuration options from device drivers to the - generic CAN driver. With this design a device driver does not - need to provide all configuration options in its CDL file - it - simply needs to implement the provided interfaces. The drawback - of this decicsion is, that it is not possible to control these - options independently for several CAN devices. (But most platforms - will have only 1 channel) - Added configuration option CYGBLD_IO_CAN_EXTRA_TESTS. This option - enables the build of the interactive CAN tests. - - * test/can_filter: Added interactive message filtering test - - * test/can_hdi: Added interactive hardware description interface - test - - * test/can_load: Added interactive message handling (reception, - transmission) test. - - * test/can_remote: Added interactive remote response buffer test - - * test/can_tx: Added interactive basic TX test. All tests are not - part of the eCos test framework because they are interactive. That - means, they require interaction with another user controlled - CAN node. - - * include/can.h: Added identifier masks for standard and extended - identifiers. - Added the line #include CYGDAT_IO_CAN_DEVICE_INL. This enables a - device driver to provide an own device inline file. In this inline - file the driver may define own data types for CAN messages (for - internal storage of CAN messages (see AT91SAM7 CAN driver)) - - * include/canio.h: Added baudrate CYGNUM_CAN_KBAUD_AUTO - support of - automatic baudrate detection if a driver supports such a feature. - Added state CYGNUM_CAN_STATE_CONFIG and mode CYGNUM_CAN_MODE_CONFIG. - The application may use these identifiers to set the CAN device into - a state where it is safe to add/remove/configure message buffers. - Added union data type cyg_can_msg_data. With this data type a 4 byte - alignment of message data is guaranteed, an byte, word and dword - access to the data is possible and an assignment of two CAN datas are - possible now. - cyg_can_message now uses cyg_can_msg_data union for CAN data. - Replaced SW-Filt flag by autobaud flag in HDI. - Added CAN message access macros for read/write acces of CAN message - structures. These macros hide implementation of CAN message from - application. - - * src/can.c: Added support for device driver defined CAN message - data types - -2006-12-19 Sergei Gavrikov <sg@sgs.gomel.by> - - * doc/can.sgml: Correctly close para tag. - -2006-12-13 Uwe Kindler <uwe_kindler@web.de> - - * doc/can.sgml: CAN driver SGML documentation added. - -2006-08-25 Gary Thomas <gary@mlbassoc.com> - - * cdl/io_can.cdl: Set parent for more intuitive ConfigTool layout. - -2006-03-27 Uwe Kindler <uwe_kindler@web.de> - - * src/can.c can_rcv_event() Clear the flag field in new event before - calling into low level hardware driver. - -2006-02-15 Uwe Kindler <uwe_kindler@web.de> - - * 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 <uwe_kindler@web.de> - - * include/can_io.h Added support for get_config to CAN_LOWLEVEL_FUNS - structure. - Added additional CAN events. - Added support for can state (cyg_can_state) and CAN mode (cyg_can_mode). - Changed data type of cyg_can_buf_info_t data structure from cyg_int32 - to cyg_uint32. - Added support for message box configuration (cyg_can_msgbuf_info). - Added support for message filtering (cyg_cn_filter). - Renamed cyg_can_rtr_buf to cyg_can_remote_buf. - Renamed CYGNUM_CAN_RTR_BUF_NA and CYGNUM_CAN_RTR_BUF_INIT to - CYGNUM_CAN_MSGBUF_NA and CYGNUM_CAN_MSGBUF_INIT because they are - also used for message filtering. - Added support for hardware description interface. - Added support for CYG_IO_SET_CONFIG_CAN_INPUT_FLUSH, - CYG_IO_SET_CONFIG_CAN_OUTPUT_FLUSH and CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN. - - * doc/can_driver_doc.html Additional configuration options - documented. - -2005-05-24 Uwe Kindler <uwe_kindler@web.de> - - * Generic CAN driver package created - -//=========================================================================== -//####ECOSGPLCOPYRIGHTBEGIN#### -// ------------------------------------------- -// This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 2003, 2004 eCosCentric Limited -// -// eCos 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 2 or (at your option) any later version. -// -// eCos 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 eCos; if not, write to the Free Software Foundation, Inc., -// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -// -// As a special exception, if other files instantiate templates or use macros -// or inline functions from this file, or you compile this file and link it -// with other works to produce a work based on this file, this file does not -// by itself cause the resulting work to be covered by the GNU General Public -// License. However the source code for this file must still be made available -// in accordance with section (3) of the GNU General Public License. -// -// This exception does not invalidate any other reasons why a work based on -// this file might be covered by the GNU General Public License. -// ------------------------------------------- -//####ECOSGPLCOPYRIGHTEND#### -//=========================================================================== +2007-08-23 Alexey Shusharin <mrfinch@mail.ru> + + * doc/can.sgml: Callback on event documentation. + * src/can.c: Change one wakeup to callback in a comment. + * include/canio.h: changed cyg_addrword_t to CYG_ADDRWORD so + can will compile without the kernel. + +2007-08-06 Alexey Shusharin <mrfinch@mail.ru> + Andrew Lunn <andrew.lunn@ascom.ch> + + * cdl/io_can.cdl: Added option CYGOPT_IO_CAN_SUPPORT_CALLBACK + + * include/canio.h: Added struct cyg_can_callback_cfg for setting + callback configurations. + + * include/can.h: Added declaration and initialization of callback + configuration in struct can_channel. + + * src/can.c: Added callback configuration changing and + application function call. + +2007-07-02 Uwe Kindler <uwe_kindler@web.de> + + * cdl/io_can.cdl: Added interface CYGINT_IO_CAN_CHANNELS for + counting available CAN channels + + * include/canio.h: Changed type cyg_can_msgbuf_info. The two + fields are 16 bit now because device drivers may support more + than 256 message buffers (i.e. the LPC2xxx CAN driver) + +2007-06-20 Uwe Kindler <uwe_kindler@web.de> + + * test/can_filter: Changed filter loop counter from cyg_uint8 to + cyg_uint16 because LPC2xxx CAN driver supports more than 256 + message buffers. + +2007-03-23 Uwe Kindler <uwe_kindler@web.de> + + * cdl/io_can.cdl: Added several interfaces for implementation by + device drivers. + Moved several configuration options from device drivers to the + generic CAN driver. With this design a device driver does not + need to provide all configuration options in its CDL file - it + simply needs to implement the provided interfaces. The drawback + of this decicsion is, that it is not possible to control these + options independently for several CAN devices. (But most platforms + will have only 1 channel) + Added configuration option CYGBLD_IO_CAN_EXTRA_TESTS. This option + enables the build of the interactive CAN tests. + + * test/can_filter: Added interactive message filtering test + + * test/can_hdi: Added interactive hardware description interface + test + + * test/can_load: Added interactive message handling (reception, + transmission) test. + + * test/can_remote: Added interactive remote response buffer test + + * test/can_tx: Added interactive basic TX test. All tests are not + part of the eCos test framework because they are interactive. That + means, they require interaction with another user controlled + CAN node. + + * include/can.h: Added identifier masks for standard and extended + identifiers. + Added the line #include CYGDAT_IO_CAN_DEVICE_INL. This enables a + device driver to provide an own device inline file. In this inline + file the driver may define own data types for CAN messages (for + internal storage of CAN messages (see AT91SAM7 CAN driver)) + + * include/canio.h: Added baudrate CYGNUM_CAN_KBAUD_AUTO - support of + automatic baudrate detection if a driver supports such a feature. + Added state CYGNUM_CAN_STATE_CONFIG and mode CYGNUM_CAN_MODE_CONFIG. + The application may use these identifiers to set the CAN device into + a state where it is safe to add/remove/configure message buffers. + Added union data type cyg_can_msg_data. With this data type a 4 byte + alignment of message data is guaranteed, an byte, word and dword + access to the data is possible and an assignment of two CAN datas are + possible now. + cyg_can_message now uses cyg_can_msg_data union for CAN data. + Replaced SW-Filt flag by autobaud flag in HDI. + Added CAN message access macros for read/write acces of CAN message + structures. These macros hide implementation of CAN message from + application. + + * src/can.c: Added support for device driver defined CAN message + data types + +2006-12-19 Sergei Gavrikov <sg@sgs.gomel.by> + + * doc/can.sgml: Correctly close para tag. + +2006-12-13 Uwe Kindler <uwe_kindler@web.de> + + * doc/can.sgml: CAN driver SGML documentation added. + +2006-08-25 Gary Thomas <gary@mlbassoc.com> + + * cdl/io_can.cdl: Set parent for more intuitive ConfigTool layout. + +2006-03-27 Uwe Kindler <uwe_kindler@web.de> + + * src/can.c can_rcv_event() Clear the flag field in new event before + calling into low level hardware driver. + +2006-02-15 Uwe Kindler <uwe_kindler@web.de> + + * 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 <uwe_kindler@web.de> + + * include/can_io.h Added support for get_config to CAN_LOWLEVEL_FUNS + structure. + Added additional CAN events. + Added support for can state (cyg_can_state) and CAN mode (cyg_can_mode). + Changed data type of cyg_can_buf_info_t data structure from cyg_int32 + to cyg_uint32. + Added support for message box configuration (cyg_can_msgbuf_info). + Added support for message filtering (cyg_cn_filter). + Renamed cyg_can_rtr_buf to cyg_can_remote_buf. + Renamed CYGNUM_CAN_RTR_BUF_NA and CYGNUM_CAN_RTR_BUF_INIT to + CYGNUM_CAN_MSGBUF_NA and CYGNUM_CAN_MSGBUF_INIT because they are + also used for message filtering. + Added support for hardware description interface. + Added support for CYG_IO_SET_CONFIG_CAN_INPUT_FLUSH, + CYG_IO_SET_CONFIG_CAN_OUTPUT_FLUSH and CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN. + + * doc/can_driver_doc.html Additional configuration options + documented. + +2005-05-24 Uwe Kindler <uwe_kindler@web.de> + + * Generic CAN driver package created + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2003, 2004 eCosCentric Limited +// +// eCos 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 2 or (at your option) any later version. +// +// eCos 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 eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//===========================================================================
--- a/packages/io/can/current/doc/can.sgml +++ b/packages/io/can/current/doc/can.sgml @@ -1,1902 +1,1980 @@ -<!-- {{{ Banner --> - -<!-- =============================================================== --> -<!-- --> -<!-- can.sgml --> -<!-- --> -<!-- Generic CAN documentation. --> -<!-- --> -<!-- =============================================================== --> -<!-- ####COPYRIGHTBEGIN#### --> -<!-- --> -<!-- =============================================================== --> -<!-- Copyright (C) 2004 eCosCentric Limited --> -<!-- This material may be distributed only subject to the terms --> -<!-- and conditions set forth in the Open Publication License, v1.0 --> -<!-- or later (the latest version is presently available at --> -<!-- http://www.opencontent.org/openpub/) --> -<!-- Distribution of the work or derivative of the work in any --> -<!-- standard (paper) book form is prohibited unless prior --> -<!-- permission obtained from the copyright holder --> -<!-- =============================================================== --> -<!-- --> -<!-- ####COPYRIGHTEND#### --> -<!-- =============================================================== --> -<!-- #####DESCRIPTIONBEGIN#### --> -<!-- --> -<!-- Author(s): Uwe Kindler --> -<!-- Date: 2006/12/04 --> -<!-- --> -<!-- ####DESCRIPTIONEND#### --> -<!-- =============================================================== --> - -<!-- }}} --> - -<PART id="io-can"><title>CAN Support</title> - -<CHAPTER id="io-can-overview"> -<TITLE>Overview</TITLE> - -<SECTION id="io-can-overview-descr"> -<TITLE>Description</TITLE> - -<PARA> -The Controller Area Network, CAN, is a multicast shared, differential -serial bus standard especially suited for networking "intelligent" -devices as well as sensors and actuators within a system or sub-system. -The protocol was originally developed in the 1980s by Robert Bosch GmbH -aiming at automotive applications. Nowadays CAN has gained widespread use -and is used in industrial automation as well as in automotive, mobile -machines and in many embedded control applications. -</PARA> - -<PARA> -The CAN protocol is defined by the ISO 11898-1 standard. The physical layer -uses differential transmission on a twisted pair wire. CAN uses a -non-destructive bit-wise arbitration to control access to the bus. -</PARA> - -<PARA> -There is no explicit address in the messages because in CAN networks there -is no addressing of subscribers or stations, but instead, each message carries -a prioritized identifier. A transmitter sends a message to all CAN nodes -(broadcasting). The identifier may serve as an identification of the contents -of the message and also determines the priority that the message enjoys in -competition for bus access. A node decides on the basis of this identifier -received whether it should process the message or not. -</PARA> - -<PARA> -The CAN messages are small (at most eight data bytes) and are protected -by a checksum. Each CAN message consists of an 11 bit message ID, up to 8 -bytes of data and, a CRC checksum and a number of control bits. These -short messages ensure a robust transfer of data in electromagnetically -noisy environments. An extended version of the CAN frame supports 29 bit -message identifiers. -</PARA> - -<PARA> -Basically there are two different operational modes for CAN receivers - -FullCAN and BasicCAN. The difference between these two modes is the -Object Storage function. The BasicCAN architecture is quite similar to a -simple UART. A BasicCAN device has typically one transmit buffer and two -receive buffers. The CAN chip handles only the transmitting and receiving -of the data (and the error handling) and so most of the manipulation of the -data has to be done by the CPU. The CPU has to request the transmitting or -acknowledge the receiving of the data through the interrupt flags. This will -burden the CPU and take up much of the CPU time. -</PARA> - -<PARA> -The FullCAN architecture is more suitable for high-speed performance. It -has its own storage area on chip and works with a number of message buffers -or message boxes. The CAN controller has its own Acceptance Filtering Mask -on chip. It can thus determine which frames are to be received by examining -the identifiers. The CPU in this case will only receive the valid (wanted) -frames and hence improve the performance of the CPU. -</PARA> - -<PARA> -You can find more information at the -<ulink url="http://www.can-cia.org/">CAN in Automation</ulink> website. -</PARA> - -</SECTION> <!-- "io-can-description" --> - -<SECTION id="io-can-ecos-support"> -<TITLE>eCos Support for CAN</TITLE> - -<PARA> -The eCos CAN subsystem supports the BasicCAN and FullCAN mode. The architecture -and the interface of the eCos CAN driver is quite similar to the eCos serial -driver and supports the same interface. -</PARA> - -<PARA> -The eCos CAN support for any given platform is spread over a number of different -packages: -</PARA> - -<itemizedlist> - <listitem> - <para> - -This package, <varname>CYGPKG_IO_CAN</varname>, exports a generic -device independent CAN I/O API for accessing devices attached to a CAN -network. This API handles issues such as locking between threads. The -package does not contain any hardware-specific code. Instead it will -call into a CAN device driver to handle the hardware device -access. This package also defines the inderface that such hardware -drivers should provide. - </para> - </listitem> - <listitem> - <para> -Each CAN device will have its own device driver, which is implemented -as a separate package, for example -<varname>CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN</varname>. For devices that may -be attached to a variety of different boards the device driver will be -generic and a second platform specific package will be used to customize -it to each platform. For devices that are associated with a specific -chipset, only a single package may be present. - </para> - </listitem> -</itemizedlist> - -<PARA> -Typically all appropriate packages will be loaded automatically when -you configure eCos for a given platform. If the application does not use -any of the CAN I/O facilities, directly or indirectly, then linker garbage -collection should eliminate all unnecessary code and data. All necessary -initialization should happen automatically. However the exact details may -depend on the platform, so the platform HAL documentation should be -checked for further details. -</PARA> - -<PARA> -There is an important exception to this: if the CAN devices are attached -to an expansion connector, such as PCI, then the platform HAL will not -know about these devices. Instead the necessary packages will need to be -added explicitly during configuration. -</PARA> -</SECTION> -</CHAPTER> - -<CHAPTER id="io-can-api"> -<TITLE>User API</TITLE> - -<PARA> -The CAN driver uses the standard eCos I/O API functions. All functions -except <function>cyg_io_lookup()</function> require an I/O "handle". -</PARA> - -<PARA> -All functions return a value of the type <type>Cyg_ErrNo</type>. -If an error condition is detected, this value will be negative and the -absolute value indicates the actual error, as specified in -<filename>cyg/error/codes.h</filename>. The only other legal return values -will be <varname>ENOERR</varname>, <varname>-EINTR</varname> and -<varname>-EAGAIN</varname>. All other function arguments are pointers -(references). This allows the drivers to pass information efficiently, -both into and out of the driver. The most striking example of this is the -<parameter>len</parameter> value passed to the read and write functions. -This parameter contains the desired length of data on input to the -function and the actual transferred length on return. -</PARA> - -<PROGRAMLISTING> -// Lookup a CAN device and return its handle -Cyg_ErrNo <FUNCTION><!-- <index></index> -->cyg_io_lookup</function>( - const char <parameter>*name</parameter>, - cyg_io_handle_t <parameter>*handle</parameter> ) -</PROGRAMLISTING> - -<PARA> -This function maps a CAN device name onto an appropriate handle. If the -named device is not in the system, then the error -<varname>-ENOENT</varname> is returned. If the device is found, then -the handle for the device is returned by way of the handle pointer -<parameter>*handle</parameter>. -</PARA> - -<PROGRAMLISTING> -// Send a CAN message -Cyg_ErrNo <FUNCTION><!-- <index></index> -->cyg_io_write</function>( - cyg_io_handle_t <parameter>handle</parameter>, - const void <parameter>*buf</parameter>, - cyg_uint32 <parameter>*len</parameter> ) -</PROGRAMLISTING> - -<PARA> -This function sends one single CAN message (not a buffer of CAN messages) -to a device. The size of data to send is contained in -<parameter>*len</parameter> and the actual size sent will be returned in -the same place. -</PARA> - -<PROGRAMLISTING> -// Read one CAN event from device -Cyg_ErrNo <!-- <index></index> --><function>cyg_io_read</function>( - cyg_io_handle_t <parameter>handle</parameter>, - void <parameter>*buf</parameter>, - cyg_uint32 <parameter>*len</parameter> ) -</PROGRAMLISTING> - -<PARA> -This function receives one single CAN event from a device. The desired size -of data to receive is contained in <parameter>*len</parameter> and the -actual size obtained will be returned in the same place. -</PARA> - -<PROGRAMLISTING> -// Read configuration of a CAN device -Cyg_ErrNo <FUNCTION><!-- <index></index> -->cyg_io_get_config</FUNCTION>( - cyg_io_handle_t <parameter>handle</parameter>, - cyg_uint32 <parameter>key</parameter>, - void *<parameter>buf</parameter>, - cyg_uint32 *<parameter>len</parameter> ) -</PROGRAMLISTING> - -<PARA> -This function is used to obtain run-time configuration about a -device. The type of information retrieved is specified by the -<parameter>key</parameter>. The data will be returned in the given -buffer. The value of <parameter>*len</parameter> should contain the -amount of data requested, which must be at least as large as the size -appropriate to the selected key. The actual size of data retrieved is -placed in <parameter>*len</parameter>. The appropriate key values -are all listed in the file <filename><cyg/io/config_keys.h></filename>. -</PARA> - -<PROGRAMLISTING> -// Change configuration of a CAN device -Cyg_ErrNo <!-- <index></index> --><function>cyg_io_set_config</function>( - cyg_io_handle_t <parameter>handle</parameter>, - cyg_uint32 <parameter>key</parameter>, - const void <parameter>*buf</parameter>, - cyg_uint32 <parameter>*len</parameter> ) -</PROGRAMLISTING> - -<PARA> -This function is used to manipulate or change the run-time -configuration of a device. The type of information is specified by the -<parameter>key</parameter>. The data will be obtained from the given -buffer. The value of <parameter>*len</parameter> should contain the -amount of data provided, which must match the size appropriate to the -selected key. The appropriate key values are all listed in the file -<filename><cyg/io/config_keys.h></filename>. -</PARA> -</CHAPTER> - -<CHAPTER id="io-can-driver-details"> -<TITLE>CAN driver details</TITLE> - -<PARA> -Allow applications and other packages to access CAN devices. -</PARA> - -<SECTION id="io-can-driver-description"> -<TITLE>Description</TITLE> - -<PARA> -A raw CAN driver is is provided as a standard part of the eCos system. -</PARA> - -<PARA> -Use the include file <filename><cyg/io/canio.h></filename> for this driver. -</PARA> - -<PARA> -The CAN driver is capable of sending single CAN messages to a device and -receiving single CAN events from a CAN device. Controls are provided to -configure the actual hardware, but there is no manipulation of the data by -this driver. -</PARA> - -<PARA> -There may be many instances of this driver in a given system, one for each -CAN channel. Each channel corresponds to a physical device and there will -typically be a device module created for this purpose. The device modules -themselves are configurable, allowing specification of the actual hardware -details. -</PARA> -</SECTION> - -<SECTION id="io-can-api-details"> -<TITLE>API Details</TITLE> - -<SECTION> -<TITLE>cyg_io_write</TITLE> - -<PROGRAMLISTING> -cyg_io_write(handle, buf, len) -</PROGRAMLISTING> - -<PARA> -To transmit a message an application must fill a <type>cyg_can_message</type> -buffer and call <function>cyg_io_write()</function>. -This function sends one single CAN message (not a buffer of CAN messages) -to a device. The size of data to send is contained in <parameter>*len</parameter> -and the actual size sent will be returned in the same place. A pointer to a -<type>cyg_can_message</type> is contained in <parameter>*buf</parameter>. -The driver maintains a buffer to hold the data. The size of the intermediate -buffer is configurable within the interface module. The data is not modified -at all while it is being buffered. On return, <parameter>*len</parameter> -contains the amount of characters actually consumed - that means -<parameter>*len</parameter> always contains -<function>sizeof(cyg_can_message)</function>. -</PARA> - -<PARA> -It is possible to configure the write call to be blocking (default) or -non-blocking. Non-blocking mode requires both the configuration option -<varname>CYGOPT_IO_CAN_SUPPORT_NONBLOCKING</varname> to be enabled, and -the specific device to be set to non-blocking mode for writes -(see <function>cyg_io_set_config()</function>). In blocking mode, the -call will not return until there is space in the buffer and the content -of the CAN message has been consumed. In non-blocking mode, if there is -no space in buffer for the CAN message, <varname>-EAGAIN</varname> is -returned and the caller must try again. -</PARA> - -<PARA> -It is possible to configure the write call to be non-blocking with timeout. -None-blocking mode with timeout requires the configuration option -<varname>CYGOPT_IO_CAN_SUPPORT_NONBLOCKING</varname> and -<varname>CYGOPT_IO_CAN_SUPPORT_TIMEOUTS</varname> to be enabled, requires -the eCos kernel package to be included and the specific device to be set -to non-blocking mode for writes (see <function>cyg_io_set_config() -</function>). -In non-blocking mode with timeouts, if there is no space in buffer for the -CAN message, the driver waits a certain amount of time (the timeout time) -for space in the buffer. If there is still no space in buffer after -expiration of the timeout time, <varname>-EINTR</varname> is returned and -the caller must try again. -</PARA> - -<PARA> -If a message was sucessfully sent, the function returns <varname>ENOERR</varname>. -</PARA> -</SECTION> - -<SECTION> -<TITLE>CAN Messages</TITLE> - -<PARA> -The CAN driver uses <structname>cyg_can_message</structname> structures to -pass messages between the application and the CAN driver. The type -cyg_can_message provides a device independent type of CAN message. -Before calling the write function this message should be setup properly. -</PARA> - -<PROGRAMLISTING> -typedef struct can_message -{ - cyg_uint32 id; - cyg_uint8 data[8]; - cyg_can_id_type ext; - cyg_can_frame_type rtr; - cyg_uint8 dlc; -} cyg_can_message; -</PROGRAMLISTING> - -<PARA> -The structure contains the following fields: -</PARA> - -<variablelist> - <varlistentry> - <term><type>cyg_uint32</type> <varname>id</varname></term> - <listitem><para> -Message ID. This is the ID to be transmitted with the message, or the -ID received. If the <structfield>ext</structfield> field is set, then -this will contain a 29 bit ID, otherwise it will contain an 11 bit ID. - </para></listitem> - </varlistentry> - <varlistentry> - <term><type>cyg_uint32</type> <varname>data</varname></term> - <listitem><para> -Message data. Only the first <structfield>dlc</structfield> bytes of -data are valid. If the <structfield>rtr</structfield> field is set, -then the contents of this field are ignored. - </para></listitem> - </varlistentry> - <varlistentry> - <term><type>cyg_can_id_type</type> <varname>ext</varname></term> - <listitem><para> -Extended ID. If this field is <varname>CYGNUM_CAN_ID_EXT</varname> then the -<structname>id</structname> field contains a 29 bit extended ID. If it -contains <varname>CYGNUM_CAN_ID_STD</varname> then the ID is 11 bits. - </para></listitem> - </varlistentry> - <varlistentry> - <term><type>cyg_can_frame_type</type> <varname>rtr</varname></term> - <listitem><para> -Remote Transmission Request. If this field contains -<varname>CYGNUM_CAN_FRAME_RTR</varname> then the RTR bit on the message -will be set and the <structfield>data</structfield> field will be ignored. -If the field contains <varname>CYGNUM_CAN_FRAME_DATA</varname> then a -normal data frame will be send. - </para></listitem> - </varlistentry> - <varlistentry> - <term><type>cyg_uint8</type> <varname>dlc</varname></term> - <listitem><para> -The length of the data carried in the message. This can range from -zero to 8. In a message with the <structfield>rtr</structfield> field set, -this indicates the size of data being requested. - </para></listitem> - </varlistentry> -</variablelist> - -<PARA> -Example code for sending one single CAN message: -</PARA> - -<PROGRAMLISTING> -cyg_can_message tx_msg; -cyg_uint32 len; -Cyg_ErrNo ret; - -tx_msg.id = 0x100; -tx_msg.ext = CYGNUM_CAN_ID_EXT; -tx_msg.rtr = CYGNUM_CAN_FRAME_DATA; -tx_msg.dlc = 1; -tx_msg.data[0] = 0xF1; - -len = sizeof(tx_msg); -ret = cyg_io_write(hDrvCAN, &tx_msg, &len); -</PROGRAMLISTING> -</SECTION><!-- can-cyg_can_message --> - -<SECTION> -<TITLE>cyg_io_read</TITLE> - -<PROGRAMLISTING> -cyg_io_read(handle, buf, len) -</PROGRAMLISTING> - -<PARA> -To receive a message the application calls <function>cyg_can_recv()</function>. -This function receives one single event from a device. The desired size -of data to receive is contained in <parameter>*len</parameter> and the -actual size obtained will be returned in the same place. A pointer to -a <type>cyg_can_event</type> is contained in <parameter>*buf</parameter>. -No manipulation of the data is performed before being transferred. -Again, this buffering is completely configurable. On return, -<parameter>*len</parameter> contains <function>sizeof(cyg_can_event)</function>. -</PARA> - -<PARA> -It is possible to configure the read call to be blocking (default) or -non-blocking. Non-blocking mode requires both the configuration option -<varname>CYGOPT_IO_CAN_SUPPORT_NONBLOCKING</varname> to be enabled, -and the specific device to be set to non-blocking mode for reads -(see <function>cyg_io_set_config()</function>). In blocking mode, -the call will not return until one single CAN event has been read. -In non-blocking mode, if there is no CAN event in buffer, the call -returns immediately with <varname>-EAGAIN</varname> and the caller must -try again. -</PARA> - -<PARA> -It is possible to configure the write call to be non-blocking with timeout. -None-blocking mode with timeout requires the configuration option -<varname>CYGOPT_IO_CAN_SUPPORT_NONBLOCKING</varname> and -<varname>CYGOPT_IO_CAN_SUPPORT_TIMEOUTS</varname> to be enabled, -requires the eCos kernel package to be included and the specific device -to be set to non-blocking mode for reads (see -<function>cyg_io_set_config()</function>). In non-blocking mode with timeouts, -if there is no CAN event in receive buffer, the driver waits a certain amount -of time (the timeout time) for a CAN event to arrive. If there is still no -CAN event in buffer after expiration of the timeout time, <varname>-EINTR</varname> -is returned and the caller must try again. -</PARA> - -<PARA> -If a event was sucessfully received, the function returns <varname>ENOERR</varname>. -</PARA> -</SECTION><!-- cyg_io_read --> - - -<SECTION> -<TITLE>CAN Events</TITLE> - -<PARA> -The CAN driver uses <structname>cyg_can_event</structname> structures to -pass events from hardware device driver to the generic CAN driver. -A <structname>cyg_can_event</structname> provides a generic device -independent type for handling CAN events that may occur. -</PARA> - -<PROGRAMLISTING> -typedef struct cyg_can_event_st -{ - cyg_uint32 timestamp; - cyg_can_message msg; - cyg_uint16 flags; -} cyg_can_event; -</PROGRAMLISTING> - -<PARA> -The structure contains the following fields: -</PARA> - -<variablelist> - <varlistentry> - <term><type>cyg_uint32</type> <varname>timestamp</varname></term> - <listitem><para> -If the hardware CAN device driver supports timestamps then this field may -contain a timestamp value for an event that occured. - </para></listitem> - </varlistentry> - <varlistentry> - <term><type>cyg_can_message</type> <varname>msg</varname></term> - <listitem><para> -CAN message. The msg field contains a CAN message if an RX or TX event -occured. If another type of event occured, -the <structfield>data</structfield> field of -the <structfield>msg</structfield> may contain additional event -specific data. - </para></listitem> - </varlistentry> - <varlistentry> - <term><type>cyg_uint16</type> <varname>flags</varname></term> - <listitem><para> -Event flags. The <varname>flags</varname> field contains 16 bits that -indicate which kind of events occured. - </para></listitem> - </varlistentry> -</variablelist> - -<PARA> -The following events are supported and after receiving an event the -application should check the flag field against these values: -</PARA> - -<PROGRAMLISTING> -typedef enum -{ - CYGNUM_CAN_EVENT_RX = 0x0001, // message received - CYGNUM_CAN_EVENT_TX = 0x0002, // message transmitted - CYGNUM_CAN_EVENT_WARNING_RX = 0x0004, // (TEC) reached warning level (>96) - CYGNUM_CAN_EVENT_WARNING_TX = 0x0008, // (REC) reached warning level (>96) - CYGNUM_CAN_EVENT_ERR_PASSIVE = 0x0010, // CAN "error passive" occured - CYGNUM_CAN_EVENT_BUS_OFF = 0x0020, // CAN "bus off" error occured - CYGNUM_CAN_EVENT_OVERRUN_RX = 0x0040, // overrun in RX queue or hardware - CYGNUM_CAN_EVENT_OVERRUN_TX = 0x0080, // overrun in TX queue occured - CYGNUM_CAN_EVENT_CAN_ERR = 0x0100, // a CAN bit or frame error occured - CYGNUM_CAN_EVENT_LEAVING_STANDBY = 0x0200, // CAN hardware leaves standby - CYGNUM_CAN_EVENT_ENTERING_STANDBY = 0x0400, // CAN hardware enters standby - CYGNUM_CAN_EVENT_ARBITRATION_LOST = 0x0800, // arbitration lost - CYGNUM_CAN_EVENT_DEVICE_CHANGED = 0x1000, // device changed event - CYGNUM_CAN_EVENT_PHY_FAULT = 0x2000, // General failure of physical layer - CYGNUM_CAN_EVENT_PHY_H = 0x4000, // Fault on CAN-H (Low Speed CAN) - CYGNUM_CAN_EVENT_PHY_L = 0x8000, // Fault on CAN-L (Low Speed CAN) -} cyg_can_event_flags; -</PROGRAMLISTING> - -<PARA> -Often the flags field will contain only one single set flag. But it is -possible that a number of flags is set and so the flag field should always -be checked by a receiver. I.e. if the <varname>CYGNUM_CAN_EVENT_RX</varname> -is set then also the <varname>CYGNUM_CAN_EVENT_OVERRUN_RX</varname> -may be set if the received message caused an RX overrun. -</PARA> - -<PARA> -The internal receive buffers of the CAN device driver are circular buffers. -That means that even if the buffers are completely filled new messages -will be received. In this case the newest message will always overwrite -the oldest message in receive buffer. If this happens the -<varname>CYGNUM_CAN_EVENT_OVERRUN_RX</varname> flag will be set for this -new message that caused overwriting of the old one. The -<varname>CYGNUM_CAN_EVENT_OVERRUN_RX</varname> flag will be set also if -a overrun occures in hardware message buffers of the CAN device. -</PARA> - -<PARA> -Example code for receiving one single CAN event: -</PARA> - -<PROGRAMLISTING> -cyg_can_event rx_event; -cyg_uint32 len; -Cyg_ErrNo ret; - -len = sizeof(rx_event); -ret = cyg_io_read(hDrvCAN, &rx_event, &len); - -if (ENOERR == ret) -{ - if (rx_event.flags & CYGNUM_CAN_EVENT_RX) - { - // handle RX event - } - - if (rx_event.flags & ~CYGNUM_CAN_EVENT_RX) - { - // handle other events - } -} -else if (-EINTR == ret) -{ - // handle timeout -} -</PROGRAMLISTING> -</SECTION><!-- can-cyg_can_event --> - - -<SECTION> -<TITLE>cyg_io_get_config</TITLE> - -<PROGRAMLISTING> -cyg_io_get_config(handle, key, buf, len) -</PROGRAMLISTING> - -<PARA> -This function is used to obtain run-time configuration about a device. -The type of information retrieved is specified by the <parameter>key</parameter>. -The data will be returned in the given buffer. The value of -<parameter>*len</parameter> should contain the amount of data requested, -which must be at least as large as the size appropriate to the selected -<parameter>key</parameter>. The actual size of data retrieved is placed -in <parameter>*len</parameter>. The appropriate key values are all listed -in the file <filename><cyg/io/config_keys.h></filename>. -</PARA> - -<PARA> -The following config keys are currently supported: -</PARA> - -<PROGRAMLISTING> -CYG_IO_GET_CONFIG_READ_BLOCKING -CYG_IO_GET_CONFIG_WRITE_BLOCKING -CYG_IO_GET_CONFIG_CAN_INFO -CYG_IO_GET_CONFIG_CAN_BUFFER_INFO -CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO -CYG_IO_GET_CONFIG_CAN_TIMEOUT -CYG_IO_GET_CONFIG_CAN_HDI -CYG_IO_GET_CONFIG_CAN_STATE -</PROGRAMLISTING> -</SECTION><!-- can-cyg-io-get-config --> - -<SECTION> -<TITLE>cyg_io_set_config</TITLE> - -<PROGRAMLISTING> -cyg_io_set_config(handle, key, buf, len) -</PROGRAMLISTING> - -<PARA> -This function is used to manipulate or change the run-time configuration -of a device. The type of information is specified by the <parameter>key</parameter>. -The data will be obtained from the given buffer. The value of -<parameter>*len</parameter> should contain the amount of data provided, -which must match the size appropriate to the selected <parameter>key</parameter>. -The appropriate key values are all listed in the file -<filename><cyg/io/config_keys.h></filename>. -</PARA> - -<PARA> -The following config keys are currently supported: -</PARA> - -<PROGRAMLISTING> -CYG_IO_SET_CONFIG_READ_BLOCKING -CYG_IO_SET_CONFIG_WRITE_BLOCKING -CYG_IO_SET_CONFIG_CAN_INFO -CYG_IO_SET_CONFIG_CAN_OUTPUT_DRAIN -CYG_IO_SET_CONFIG_CAN_OUTPUT_FLUSH -CYG_IO_SET_CONFIG_CAN_INPUT_FLUSH -CYG_IO_SET_CONFIG_CAN_TIMEOUT -CYG_IO_SET_CONFIG_CAN_MSGBUF -CYG_IO_SET_CONFIG_CAN_MODE -</PROGRAMLISTING> -</SECTION><!-- can-cyg-io-set-config --> -</SECTION><!-- io-can-api-details --> - -<SECTION id="io-can-runtime-cfg"> -<TITLE>Runtime Configuration</TITLE> - -<PARA> -Runtime configuration is achieved by exchanging data structures with the -driver via the <function>cyg_io_set_config()</function> and -<function>cyg_io_get_config()</function> functions. -</PARA> - -<SECTION> -<TITLE>Device configuration</TITLE> - -<PROGRAMLISTING> -typedef struct cyg_can_info_st { - cyg_can_baud_rate_t baud; -} cyg_can_info_t; -</PROGRAMLISTING> - -<PARA> -Device configuration is achieved by by exchanging -<structname>cyg_can_info_t</structname> data structures with the driver -via the <function>cyg_io_set_config()</function> and -<function>cyg_io_get_config()</function> functions using the config keys -<varname>CYG_IO_GET_CONFIG_CAN_INFO</varname> and -<varname>CYG_IO_SET_CONFIG_CAN_INFO</varname>. -The field <structfield>baud</structfield> contains a baud rate selection. -This must be one of the following values: -</PARA> - -<PROGRAMLISTING> -CYGNUM_CAN_KBAUD_10 -CYGNUM_CAN_KBAUD_20 -CYGNUM_CAN_KBAUD_50 -CYGNUM_CAN_KBAUD_100 -CYGNUM_CAN_KBAUD_125 -CYGNUM_CAN_KBAUD_250 -CYGNUM_CAN_KBAUD_500 -CYGNUM_CAN_KBAUD_800 -CYGNUM_CAN_KBAUD_1000 -</PROGRAMLISTING> -</SECTION><!-- can-cyg-io-set-config --> - -<SECTION> -<TITLE>Timeout configuration</TITLE> - -<PROGRAMLISTING> -typedef struct cyg_can_timeout_info_st -{ - cyg_uint32 rx_timeout; - cyg_uint32 tx_timeout; -} cyg_can_timeout_info_t; -</PROGRAMLISTING> - -<PARA> -Timeout configuration is achieved by by exchanging -<structname>cyg_can_timeout_info_t</structname> data structures with the -driver via the <function>cyg_io_set_config()</function> and -<function>cyg_io_get_config()</function> functions using the config keys -<varname>CYG_IO_SET_CONFIG_CAN_TIMEOUT</varname> and -<varname>CYG_IO_SET_CONFIG_CAN_TIMEOUT</varname>. -</PARA> - -<variablelist> - <varlistentry> - <term><type>cyg_uint32</type> <varname>rx_timeout</varname></term> - <listitem><para> -Timeout for <function>cyg_io_read</function> calls. - </para></listitem> - </varlistentry> - <varlistentry> - <term><type>cyg_uint32</type> <varname>tx_timeout</varname></term> - <listitem><para> -Timeout for <function>cyg_io_write</function> calls. - </para></listitem> - </varlistentry> -</variablelist> - -<PARA> -Timeout runtime configuration is supported if the configuration options -<varname>CYGOPT_IO_CAN_SUPPORT_NONBLOCKING</varname> -and <varname>CYGOPT_IO_CAN_SUPPORT_TIMEOUTS</varname> are enabled. -</PARA> -</SECTION><!-- can-timeout-config --> - -<SECTION> -<TITLE>Reading buffer configuration</TITLE> - -<PROGRAMLISTING> -typedef struct cyg_can_buf_info_st -{ - cyg_int32 rx_bufsize; - cyg_int32 rx_count; - cyg_int32 tx_bufsize; - cyg_int32 tx_count; -} cyg_can_buf_info_t; -</PROGRAMLISTING> - -<PARA> -<varname>CYG_IO_GET_CONFIG_CAN_BUFFER_INFO</varname> - This function -retrieves the current state of the software buffers in the CAN drivers. -For the transmit buffer it returns the the total number of -<type>cyg_can_message</type> objects in buffer and the current number of -<type>cyg_can_message</type> objects occupied in the buffer. -For the receive buffer it returns the total number of -<type>cyg_can_event</type> objects in receive buffer and the current -number of <type>cyg_can_event</type> objects occupied in the buffer. -It does not take into account any buffering such as FIFOs or holding -registers that the CAN hardware device itself may have. -</PARA> - -<variablelist> - <varlistentry> - <term><type>cyg_uint32</type> <varname>rx_bufsize</varname></term> - <listitem><para> -Total number of <type>cyg_can_event</type> buffers in receive queue. - </para></listitem> - </varlistentry> - <varlistentry> - <term><type>cyg_uint32</type> <varname>rx_count</varname></term> - <listitem><para> -Current number of <type>cyg_can_event</type> buffers occupied in receive queue. - </para></listitem> - </varlistentry> - <varlistentry> - <term><type>cyg_uint32</type> <varname>tx_bufsize</varname></term> - <listitem><para> -Total number of <type>cyg_can_message</type> buffers in transmit queue. - </para></listitem> - </varlistentry> - <varlistentry> - <term><type>cyg_uint32</type> <varname>rtx_count</varname></term> - <listitem><para> -Current number of <type>cyg_can_message</type> buffers occupied in transmit queue. - </para></listitem> - </varlistentry> -</variablelist> -</SECTION> <!-- can-read-buffer-config --> - - -<SECTION> -<TITLE>Reading hardware description information</TITLE> - -<PROGRAMLISTING> -typedef struct cyg_can_hdi_st -{ - cyg_uint8 support_flags; - cyg_uint8 controller_type; -} cyg_can_hdi; -</PROGRAMLISTING> - -<PARA> -<varname>CYG_IO_GET_CONFIG_CAN_HDI</varname> - This function retrieves -information about the used hardware. The Hardware Description Interface -provides a method to gather information about the CAN hardware and the -functionality of the driver. For this purpose the structure -<structname>cyg_can_hdi</structname> is defined. -</PARA> - -<variablelist> - <varlistentry> - <term><type>cyg_uint8</type> <varname>support_flags</varname></term> - <listitem><para> -Contains information about the capabilities of the used CAN hardware. - </para></listitem> - </varlistentry> - <varlistentry> - <term><type>cyg_uint8</type> <varname>controller_type</varname></term> - <listitem><para> -A number that identifies the CAN controller type. - </para></listitem> - </varlistentry> -</variablelist> - -<PARA> -The following flags are available in the field <structfield>support_flags</structfield>: -</PARA> - -<PROGRAMLISTING> -| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | -+-------+-------+-------+-------+-------+-------+-------+-------+ -| res | res | res |timest.|SW-Filt|FullCAN| Frametype | -</PROGRAMLISTING> - -<variablelist> - <varlistentry> - <term><parameter>Frametype</parameter></term> - <listitem><para> -Bit 0 and Bit 1 of the structure describe the possibilities of the CAN -controller. The following values are defined: - <PROGRAMLISTING> -CYGNUM_CAN_HDI_FRAMETYPE_STD // receives only standard frame -CYGNUM_CAN_HDI_FRAMETYPE_EXT_PASSIVE // can receive but not send extended frames -CYGNUM_CAN_HDI_FRAMETYPE_EXT_ACTIVE // can send and receive extended frames - </PROGRAMLISTING> - </para></listitem> - </varlistentry> - <varlistentry> - <term><parameter>FullCAN</parameter></term> - <listitem><para> -If the Bit 2 - <varname>CYGNUM_CAN_HDI_FULLCAN </varname> - is set to one, -the CAN controller supports more than one message buffer. - </para></listitem> - </varlistentry> - <varlistentry> - <term><parameter>SW-Filter</parameter></term> - <listitem><para> -If Bit 3 - <varname>CYGNUM_CAN_HDI_FILT_SW</varname> - is set to one then -the CAN driver supports some kind of software message filtering. - </para></listitem> - </varlistentry> - <varlistentry> - <term><parameter>Timestamp</parameter></term> - <listitem><para> -If Bit 4 - <varname>CYGNUM_CAN_HDI_TIMESTAMP</varname> - is set to one then -the CAN hardware supports timestamps for CAN messages - </para></listitem> - </varlistentry> -</variablelist> -</SECTION> <!-- can-read-buffer-config --> - -<SECTION> -<TITLE>Reading hardware message buffer configuration</TITLE> -<PROGRAMLISTING> -typedef struct cyg_can_msgbox_info_st -{ - cyg_uint8 count; // number of message buffers available for this device - cyg_uint8 free; // number of free message buffers -} cyg_can_msgbuf_info; -</PROGRAMLISTING> - -<PARA> -<varname>CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO</varname> - If the CAN hardware supports -more than one message buffer for reception of CAN messages (flag -<varname>CYGNUM_CAN_HDI_FULLCAN</varname> is set while reading hardware description -interface with <varname>CYG_IO_GET_CONFIG_CAN_HDI</varname>) then this function -reads the number of message buffers the CAN hardware supports and the number of -free message buffers. -</PARA> - -<variablelist> - <varlistentry> - <term><type>cyg_uint8</type> <varname>count</varname></term> - <listitem><para> -Counts the number of message buffers supported by the device. - </para></listitem> - </varlistentry> - <varlistentry> - <term><type>cyg_uint8</type> <varname>free</varname></term> - <listitem><para> -Contains the number of free message buffers. The free message buffers are -available for setting up remote buffers (<varname>CYG_IO_SET_CONFIG_CAN_REMOTE_BUF</varname>) -and message filters (<varname>CYG_IO_SET_CONFIG_CAN_FILTER_MSG</varname>). - </para></listitem> - </varlistentry> -</variablelist> -</SECTION> <!-- can-read-buffer-config --> - -<SECTION> -<TITLE>Reading state of CAN hardware</TITLE> - -<PROGRAMLISTING> -typedef enum -{ - CYGNUM_CAN_STATE_ACTIVE, // CAN controller active, no errors - CYGNUM_CAN_STATE_STOPPED, // CAN controller in stopped mode - CYGNUM_CAN_STATE_STANDBY, // CAN controller in Sleep mode - CYGNUM_CAN_STATE_BUS_WARN, // CAN controller active, warning level is reached - CYGNUM_CAN_STATE_ERR_PASSIVE, // CAN controller went into error passive mode - CYGNUM_CAN_STATE_BUS_OFF, // CAN controller went into bus off mode - CYGNUM_CAN_STATE_PHY_FAULT, // General failure of physical layer - CYGNUM_CAN_STATE_PHY_H, // Fault on CAN-H detected (Low Speed CAN) - CYGNUM_CAN_STATE_PHY_L, // Fault on CAN-L detected (Low Speed CAN) -} cyg_can_state; -</PROGRAMLISTING> - -<PARA> -<varname>CYG_IO_GET_CONFIG_CAN_STATE</varname> - This function retrieves the -present state of the CAN controller. Possible values are defined in the -<type>cyg_can_state</type> enumeration. -</PARA> -</SECTION> <!-- can-read-hw-state --> - - -<SECTION> -<TITLE>Changing mode of CAN hardware</TITLE> - -<PARA> -<varname>CYG_IO_SET_CONFIG_CAN_MODE</varname> - This function changes -the operating mode of the CAN controller. The identifiers for the different -operating modes are defined in the <type>cyg_can_mode</type> enumeration. -</PARA> - -<PROGRAMLISTING> -typedef enum -{ - CYGNUM_CAN_MODE_STOP, // set controller into stop mode - CYGNUM_CAN_MODE_START, // set controller into operational mode - CYGNUM_CAN_MODE_STANDBY // set controller into standby / sleep mode -} cyg_can_mode; -</PROGRAMLISTING> - -<variablelist> - <varlistentry> - <term><type>CYGNUM_CAN_MODE_STOP</type></term> - <listitem><para> -Set controller into stop mode - </para></listitem> - </varlistentry> - <varlistentry> - <term><type>CYGNUM_CAN_MODE_START</type></term> - <listitem><para> -Set controller into operational mode - </para></listitem> - </varlistentry> - <varlistentry> - <term><type>CYGNUM_CAN_MODE_STANDBY</type></term> - <listitem><para> -Set controller into standby / sleep mode. - </para></listitem> - </varlistentry> -</variablelist> - -<PARA> -Before the hardware configuration of the device is changed, that means -if baud rate 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 <varname>CYGNUM_CAN_EVENT_LEAVING_STANDBY</varname> event will be -inserted into receive message buffer or -the <varname>CYGNUM_CAN_EVENT_LEAVING_STANDBY</varname> flag will be -set for the message that caused wake up of CAN hardware. -</PARA> -</SECTION> <!-- can-mode-cfg --> - -<SECTION> -<TITLE>Flush or drain buffers</TITLE> - -<PARA> -<varname>CYG_IO_SET_CONFIG_CAN_OUTPUT_DRAIN</varname> - This function -waits for any buffered output to complete. This function only -completes when there is no more data remaining to be sent to the -device. -</PARA> - -<PARA> -<varname>CYG_IO_SET_CONFIG_CAN_OUTPUT_FLUSH</varname> - This function -discards any buffered output for the device. -</PARA> - -<PARA> -<varname>CYG_IO_SET_CONFIG_CAN_INPUT_FLUSH</varname> - This function -discards any buffered input for the device. -</PARA> -</SECTION> - -<SECTION> -<TITLE>Configuring blocking/non-blocking calls</TITLE> -<PARA> -By default all calls to <function>cyg_io_read()</function> -and <function>cyg_io_write()</function> are blocking calls. The config -keys -</PARA> - -<PROGRAMLISTING> -CYG_IO_SET_CONFIG_READ_BLOCKING -CYG_IO_SET_CONFIG_WRITE_BLOCKING -</PROGRAMLISTING> - -<PARA> -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 non-blocking calls -are enabled and there is no space in TX buffer or RX buffer is empty -then the function returns immediately -with <varname>-EAGAIN</varname>. -</PARA> - -<PARA> -If non-blocking calls are enabled and additionally timeouts are -supported by driver, then the read/write functions wait until timeout -value is expired and then return with <varname>-EINTR</varname>. If -the read/write operation succeeds during the timed wait then the -functions return succesfully with -<varname>ENOERR</varname>. -</PARA> - -<PARA> -To query if <function>cyg_io_read()</function> -and <function>cyg_io_write()</function> are blocking or non-blocking -you can use the config keys -</PARA> - -<PROGRAMLISTING> -CYG_IO_GET_CONFIG_READ_BLOCKING -CYG_IO_GET_CONFIG_WRITE_BLOCKING -</PROGRAMLISTING> -</SECTION> <!-- can-cfg-unblock --> - -<SECTION> -<TITLE>Message buffer management</TITLE> - -<PARA> -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 buffers. 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. -</PARA> - -<PARA> -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 <function>cyg_io_set_config()</function> with the config key -</PARA> - -<PROGRAMLISTING> -CYG_IO_SET_CONFIG_CAN_MSGBUF -</PROGRAMLISTING> - -<PARA> -and by exchanging <type>cyg_can_msgbuf_cfg</type> data structures. -</PARA> - -<PROGRAMLISTING> -typedef struct cyg_can_msgbox_cfg_st -{ - cyg_can_msgbuf_cfg_id cfg_id; // configuration id - cyg_can_msgbuf_handle handle; // handle to message buffer - cyg_can_message msg; // CAN message - for configuration of buffer -} cyg_can_msgbuf_cfg; -</PROGRAMLISTING> -<variablelist> - <varlistentry> - <term><type>cyg_can_msgbuf_cfg_id</type> <varname>cfg_id</varname></term> - <listitem><para> The <varname>cfg_id</varname> field -contains the configuration ID that tells the driver what to do with a -message buffer. - </para></listitem> - </varlistentry> - <varlistentry> - <term><type>cyg_can_msgbuf_handle</type> <varname>handle</varname></term> - <listitem><para> -Contains a reference to a certain message buffer. - </para></listitem> - </varlistentry> - <varlistentry> - <term><type>cyg_can_message</type> <varname>msg</varname></term> - <listitem><para> -Required for configuration of message buffer parameters. - </para></listitem> - </varlistentry> -</variablelist> - -<PARA> -The following configuration identifiers are supported: -</PARA> - -<PROGRAMLISTING> -CYGNUM_CAN_MSGBUF_RESET_ALL // clears alle message buffers -CYGNUM_CAN_MSGBUF_RX_FILTER_ALL // cfg driver for reception of all can messages -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 -</PROGRAMLISTING> - -<variablelist> - <varlistentry> - <term><type>CYGNUM_CAN_MSGBUF_RESET_ALL</type></term> - <listitem><para> -Clears alle message buffers - no message will be received and all remote buffers are deleted. - </para></listitem> - </varlistentry> - <varlistentry> - <term><type>CYGNUM_CAN_MSGBUF_RX_FILTER_ALL</type></term> - <listitem><para> -Configure driver for reception of all can messages - </para></listitem> - </varlistentry> - <varlistentry> - <term><type>CYGNUM_CAN_MSGBUF_RX_FILTER_ADD</type></term> - <listitem><para> -Add single message filter. - </para></listitem> - </varlistentry> - <varlistentry> - <term><type>CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD</type></term> - <listitem><para> -Add new remote response buffer. - </para></listitem> - </varlistentry> - <varlistentry> - <term><type>CYGNUM_CAN_MSGBUF_REMOTE_BUF_WRITE</type></term> - <listitem><para> -Stores data into existing remote buffer (remote buffer handle required). - </para></listitem> - </varlistentry> -</variablelist> - -<PARA> -Example code for resetting all message buffers: -</PARA> - -<PROGRAMLISTING> -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 -} -</PROGRAMLISTING> -</SECTION> <!-- can-msgbuf-cfg --> - - -<SECTION> -<TITLE>Remote frame response buffer configuration</TITLE> - -<PARA> -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 -Motorola FlexCAN module, does not generate any receive -interrupt. These CAN hardware chips like the FlexCAN module can be -configured to transmit a data frame automatically in response to a -remote frame. In order to support any kind of CAN hardware the eCos CAN -driver provides a generic handling of remote transmission requests. -</PARA> - -<PARA> -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 module, supports hardware 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. -</PARA> - -<PARA> -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. -</PARA> - -<PARA> -In order to respond to a remote frame, a remote frame response buffer -need to be initialized before a data frame can be sent in response to -a remote frame. This is achieved by by -exchanging <type>cyg_can_remote_buf</type> data structures with the -driver via the <function>cyg_io_set_config()</function> function using -the config key <varname>CYG_IO_SET_CONFIG_CAN_MSGBUF</varname>. Once -the buffer is initialized, the CAN data can be changed at any time by -the application. -</PARA> - -<PROGRAMLISTING> -typedef struct cyg_can_msgbuf_cfg_st -{ - cyg_can_msgbuf_cfg_id cfg_id; // configuration id - cyg_can_msgbuf_handle handle; // handle to message buffer - cyg_can_message msg; // CAN message - for configuration of buffer -} cyg_can_remote_buf; -</PROGRAMLISTING> -<variablelist> - <varlistentry> - <term><type>cyg_can_msgbuf_cfg_id</type> <varname>cfg_id</varname></term> - <listitem><para> -The <varname>cfg_id</varname> field contains the configuration ID that tells the driver what to do with -a message buffer (<varname>CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD</varname> or -<varname>CYGNUM_CAN_MSGBUF_REMOTE_BUF_WRITE</varname>). - </para></listitem> - </varlistentry> - <varlistentry> - <term><type>cyg_can_msgbuf_handle</type> <varname>handle</varname></term> - <listitem><para> -If there is no buffer initialized for this data, the value of the handle field need to be set to -<varname>CYGNUM_CAN_MSGBUF_INIT</varname>. After the call to <function>cyg_io_set_config()</function> -the handle field contains a valid remote buffer handle ( >= 0) or the value -<varname>CYGNUM_CAN_MSGBUF_NA</varname> ( < 0) if no free buffer is available. - </para></listitem> - </varlistentry> - <varlistentry> - <term><type>cyg_can_message</type> <varname>msg</varname></term> - <listitem><para> -The CAN frame that should be transmitted in response to a remote frame. - </para></listitem> - </varlistentry> -</variablelist> - -<PARA> -Example code for setting up a remote response buffer: -</PARA> - -<PROGRAMLISTING> -cyg_can_remote_buf rtr_buf; - -// 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; -rtr_buf.msg.rtr = CYGNUM_CAN_FRAME_DATA; -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_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 -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_MSGBUF, - &rtr_buf, &len)) -{ - // handle configuration error -} -</PROGRAMLISTING> -</SECTION> <!-- can-rtrbuf-cfg --> - - -<SECTION> -<TITLE>Message filter configuration</TITLE> - -<PARA> -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. -</PARA> - -<PARA> -Adding message filters is only possible if driver is not configured -for reception of all available CAN messages. If the driver is -configured for reception of all CAN messages then message buffers need -to be reset before adding single message filters. -</PARA> - -<PARA> -In order to add a message filter, a message buffer need to be -initialized. This is achieved by -exchanging <type>cyg_can_filter</type> data structures with the driver -via the <function>cyg_io_set_config()</function> function using the -config key <varname>CYG_IO_SET_CONFIG_CAN_MSGBUF</varname>. Once the -buffer is initialized, the CAN hardware can receive messages with the -identifier of the filter. -</PARA> - -<PROGRAMLISTING> -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; -</PROGRAMLISTING> - -<variablelist> - <varlistentry> - <term><type>cyg_can_msgbuf_cfg_id</type> <varname>cfg_id</varname></term> - <listitem><para> -The <varname>cfg_id</varname> field contains the configuration ID that tells the driver what to do with -a message buffer. - </para></listitem> - </varlistentry> - <varlistentry> - <term><type>cyg_can_msgbuf_handle</type> <varname>handle</varname></term> - <listitem><para> -After the call to <function>cyg_io_set_config()</function> the handle field contains a valid value -( >= 0) or the value <varname>CYGNUM_CAN_MSGBUF_NA</varname> ( < 0) if no free buffer is available. - </para></listitem> - </varlistentry> - <varlistentry> - <term><type>cyg_can_message</type> <varname>msg</varname></term> - <listitem><para> -The fields <structfield>id</structfield> and <structfield>ext</structfield> of the <structfield>msg</structfield> -configure the type of message to receive by a certain message filter. - </para></listitem> - </varlistentry> -</variablelist> - -<PARA> -Before adding message filters the device should be stopped and after -configuration it should be set into operational mode again. -</PARA> - -<PARA> -Example code for setting up a message filter: -</PARA> - -<PROGRAMLISTING> -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 -} -</PROGRAMLISTING> -</SECTION> <!-- can-msgfilt-cfg --> - - -<SECTION id="can-msgfilt-deact"> -<TITLE>Message filter deactivation</TITLE> - -<PARA> -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: -</PARA> - -<PROGRAMLISTING> -CYGNUM_CAN_MSGBUF_RX_FILTER_ALL -</PROGRAMLISTING> - -<PARA> -This message buffer configuration id will clear all message filters -and remote buffers and prepares the CAN hardware for reception of any -kind of CAN standard and extended frames. It is not necessary to reset -the message buffer configuration before this configuration step is -executed because this should be done by device driver. -</PARA> - -<PARA> -Example code for deactivation of message filtering: -</PARA> - -<PROGRAMLISTING> -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"); -} -</PROGRAMLISTING> -</SECTION> <!-- can-msgfilt-cfg --> -</SECTION> -</CHAPTER> - -<CHAPTER id="io-can-configuration"> -<TITLE>Configuration</TITLE> - -<PARA> -The CAN subsystem has a number of configuration options. -</PARA> - -<variablelist> - <varlistentry> - <term><type>cdl_interface CYGINT_IO_CAN_TIMESTAMP</type></term> - <listitem><para> -A hardware device driver that supports timestamps should implement this interface. - </para></listitem> - </varlistentry> - <varlistentry> - <term><type>cdl_option CYGOPT_IO_CAN_SUPPORT_TIMESTAMP</type></term> - <listitem><para> -If the CAN hardware driver supports some kind of timestamps then this option enables -propagation of timestamps to higher layers. This may add some extra code to hardware -drivers. - </para></listitem> - </varlistentry> - <varlistentry> - <term><type>cdl_option CYGOPT_IO_CAN_TX_EVENT_SUPPORT</type></term> - <listitem> -<para> This option enables support for TX -events. If a CAN message is transmitted successfully a TX event will -be inserted into the receive event queue and propagated to higher -layers. If this option is enabled the RX event queue will be filled -faster. -</para></listitem> - </varlistentry> - <varlistentry> - <term><type>cdl_option CYGOPT_IO_CAN_SUPPORT_NONBLOCKING</type></term> - <listitem> -<para> -This option enables extra code in the generic CAN driver which allows -clients to switch read() and write() call semantics from blocking to -non-blocking. -</para></listitem> - </varlistentry> - <varlistentry> - <term><type>cdl_option CYGNUM_IO_CAN_DEFAULT_TIMEOUT_READ</type></term> - <listitem><para> -The initial timeout value in clock ticks for <FUNCTION>cyg_io_read()</FUNCTION> calls. - </para></listitem> - </varlistentry> - <varlistentry> - <term><type>cdl_option CYGNUM_IO_CAN_DEFAULT_TIMEOUT_WRITE</type></term> - <listitem><para> The initial timeout value in clock ticks -for <FUNCTION>cyg_io_write()</FUNCTION> calls. - </para></listitem> - </varlistentry> -</variablelist> -</CHAPTER> - - -<CHAPTER id="io-can-device-drivers"> -<TITLE>Writing a CAN hardware device driver</TITLE> - -<PARA> -A CAN driver is nothing more than a named entity that supports the -basic I/O functions - read, write, get config, and set config. The -device driver uses and manages interrupts from the device. While the -interface is generic and device driver independent, the actual driver -implementation is completely up to the device driver designer. -</PARA> - -<PARA> -That said, the reason for using a device driver is to provide access -to a CAN device from application code in as general purpose a fashion -as reasonable. Most driver writers are also concerned with making this -access as simple as possible while being as efficient as possible. -</PARA> - -<PARA> -Like other device drivers the CAN device driver is concerned with the -movement of information - the CAN messages. In order to make the most -efficient use of system resources, interrupts are used. This will -allow other application processing to take place while the data -transfers are under way, with interrupts used to indicate when various -events have occurred. For example, a CAN device typically generates an -interrupt after a CAN message has been sent or a CAN message has been -received by a CAN hardware message buffer. It makes sense to allow -further application processing while the data is being sent since this -can take quite a long time. The interrupt can be used to allow the -driver to send a CAN message as soon as the current one is complete, -without any active participation by the application code. -</PARA> - -<PARA> -The main building blocks for CAN device drivers are found in the -include files -<filename><cyg/io/devtab.h></filename> and <filename><cyg/io/can.h></filename> -</PARA> - -<PARA> -Like many other device drivers in eCos, CAN device drivers are described by a device -table entry, using the <type>cyg_devtab_entry_t</type> type. The entry should be created using -the <varname>DEVTAB_ENTRY()</varname> macro. -</PARA> - - -<SECTION id="io-can-how-to-write-interface-driver"> -<TITLE>How to Write a CAN Hardware Interface Driver</TITLE> - -<PARA> -The standard CAN driver supplied with eCos is structured as a hardware -independent portion and a hardware dependent interface module. To add -support for a new CAN device, the user should be able to use the -existing hardware independent portion and just add their own interface -driver which handles the details of the actual device. The user should -have no need to change the hardware independent portion. -</PARA> - -<PARA> -The interfaces used by the CAN driver and CAN implementation modules -are contained in the file <filename><cyg/io/can.h></filename>. -</PARA> - -<SECTION> -<title>DevTab Entry</TITLE> - -<PARA> -The interface module contains the devtab entry (or entries if a single -module supports more than one interface). This entry should have the -form: -</PARA> - -<PROGRAMLISTING> -DEVTAB_ENTRY(<<module_name>>, - <<device_name>>, - 0, - &can_devio, - <<module_init>>, - <<module_lookup>>, - &<<can_channel>> - ); -</PROGRAMLISTING> - -<variablelist> -<title>Arguments</title> - <varlistentry> - <term><parameter>module_name</parameter></term> - <listitem><para>The "C" label for this devtab entry</para></listitem> - </varlistentry> - <varlistentry> - <term><parameter>device_name</parameter></term> - <listitem><para>The "C" string for the - device. E.g. <filename>/dev/can0</filename>.</para></listitem> - </varlistentry> - <varlistentry> - <term><parameter>can_devio</parameter></term> - <listitem><para>The table of I/O functions. This set is defined in - the hardware independent CAN driver and should be used.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><parameter>module_init</parameter></term> - <listitem><para>The hardware module initialization function.</para></listitem> - </varlistentry> - <varlistentry> - <term><parameter>module_lookup</parameter></term> - <listitem><para>The device lookup function. This function - typically sets up the CAN device for actual use, turning on - interrupts, configuring the message buffers, etc.</para></listitem> - </varlistentry> - <varlistentry> - <term><parameter>can_channel</parameter></term> - <listitem><para>This table (defined below) contains the interface - between the interface module and the CAN driver proper.</para></listitem> - </varlistentry> -</variablelist> - -<PARA> -Example devtab entry for Motorola FlexCAN device driver: -</PARA> - -<PROGRAMLISTING> -DEVTAB_ENTRY(flexcan_devtab, - CYGDAT_DEVS_CAN_MCF52xx_FLEXCAN0_NAME, - 0, // Does not depend on a lower level interface - &cyg_io_can_devio, - flexcan_init, - flexcan_lookup, // CAN driver may need initializing - &flexcan_can0_chan - ); -</PROGRAMLISTING> -</SECTION> - - -<SECTION> -<title>CAN Channel Structure</TITLE> - -<PARA> -Each CAN device must have a “CAN channel”. -This is a set of data which describes all operations on the device. -It also contains buffers, etc. The CAN channel is created by the macro: -</PARA> - -<PROGRAMLISTING> -CAN_CHANNEL_USING_INTERRUPTS(l, funs, dev_priv, baud, - out_buf, out_buflen, - in_buf, in_buflen) -</PROGRAMLISTING> - -<variablelist> - <title>Arguments</title> - <varlistentry> - <term><parameter>l</parameter></term> - <listitem><para>The "C" label for this structure.</para></listitem> - </varlistentry> - <varlistentry> - <term><parameter>funs</parameter></term> - <listitem><para>The set of interface functions (see below).</para></listitem> - </varlistentry> - <varlistentry> - <term><structfield>dev_priv</structfield></term> - <listitem><para>A placeholder for any device specific data for - this channel.</para></listitem> - </varlistentry> - <varlistentry> - <term><structfield>baud</structfield></term> - <listitem><para>The initial baud rate value - (<type>cyg_can_baud_rate_t</type>).</para></listitem> - </varlistentry> - <varlistentry> - <term><structfield>out_buf</structfield></term> - <listitem><para>Pointer to the output buffer</para></listitem> - </varlistentry> - <varlistentry> - <term><structfield>out_buflen</structfield></term> - <listitem><para>The length of the output buffer.</para></listitem> - </varlistentry> - <varlistentry> - <term><structfield>in_buf</structfield></term> - <listitem><para>pointer to the input buffer.</para></listitem> - </varlistentry> - <varlistentry> - <term><structfield>in_buflen</structfield></term> - <listitem><para>The length of the input buffer.</PARA></listitem> - </varlistentry> -</variablelist> - -<PARA> -Example CAN channel implementation for Motorola FlexCAN device driver: -</PARA> - -<PROGRAMLISTING> -CAN_CHANNEL_USING_INTERRUPTS( - flexcan_can0_chan, - flexcan_lowlevel_funs, - flexcan_can0_info, - CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_KBAUD), - flexcan_can0_txbuf, CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_TX, - flexcan_can0_rxbuf, CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_RX -); -</PROGRAMLISTING> - -<PARA> -The interface from the hardware independent driver into the hardware -interface module is contained in the <structfield>funs</structfield> -table. This is defined by the macro: -</PARA> -</SECTION> - -<SECTION> -<TITLE>CAN Lowlevel Functions Structure</TITLE> - -<PROGRAMLISTING> -CAN_LOWLEVEL_FUNS(l, putmsg, getevent, get_config, set_config, start_xmit, stop_xmit) -</PROGRAMLISTING> - -<variablelist> - <title>Arguments</title> - <varlistentry> - <term><structfield>l</structfield></term> - <listitem><para>The "C" label for this structure.</para></listitem> - </varlistentry> - <varlistentry> - <term><structfield>putmsg</structfield></term> - <listitem> - <para><literal> - bool (*putmsg)(can_channel *priv, cyg_can_message *pmsg, void *pdata) - </literal></para> - <para> - This function sends one CAN message to the interface. It should - return <literal>true</literal> if the message is actually - consumed. It should return <literal>false</literal> if there is - no space in the interface - </para> - </listitem> - </varlistentry> - <varlistentry> - <term><structfield>getevent</structfield></term> - <listitem> - <para><literal> - bool (*getevent)(can_channel *priv, cyg_can_event *pevent, void *pdata) - </literal></para> - <para> - This function fetches one event from the interface. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term><structfield>get_config</structfield></term> - <listitem> - <para><literal> - Cyg_ErrNo (*get_config)(can_channel *priv, cyg_uint32 key, const void *xbuf, cyg_uint32 *len) - </literal></para> - <para> - This function is used to query the configuration of a CAN channel. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term><structfield>set_config</structfield></term> - <listitem> - <para><literal> - Cyg_ErrNo (*set_config)(can_channel *priv, cyg_uint32 key, const void *xbuf, cyg_uint32 *len) - </literal></para> - <para> - This function is used to change configuration of a CAN channel. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term><parameter>start_xmit</parameter></term> - <listitem><para><literal>void (*start_xmit)(can_channel *priv)</literal></para> - <para> - Enable the transmit channel and turn on transmit interrupts. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term><parameter>stop_xmit</parameter></term> - <listitem> - <para><literal>void (*stop_xmit)(can_channel *priv)</literal></para> - <para>Disable the transmit channel and turn transmit interrupts off.</PARA> - </listitem> - </varlistentry> -</variablelist> - -<PARA> -Example implementation of low level function structure for Motorola FlexCAN -device driver: -</PARA> - -<PROGRAMLISTING> -CAN_LOWLEVEL_FUNS(flexcan_lowlevel_funs, - flexcan_putmsg, - flexcan_getevent, - flexcan_get_config, - flexcan_set_config, - flexcan_start_xmit, - flexcan_stop_xmit - ); -</PROGRAMLISTING> -</SECTION> - -<SECTION> -<TITLE>Callbacks</TITLE> - -<PARA> -The device interface module can execute functions in the -hardware independent driver via <literal>chan->callbacks</literal>. -These functions are available: -</PARA> - -<PROGRAMLISTING> -void (*can_init)(can_channel *chan) -</PROGRAMLISTING> - -<PARA>This function is used to initialize the CAN channel.</PARA> - -<PROGRAMLISTING> -void (*xmt_msg)(can_channel *chan, void *pdata) -</PROGRAMLISTING> - -<PARA> -This function would be called from an interrupt handler after a -transmit interrupt indicating that additional messages may be -sent. The upper driver will call the <function>putmsg</function> -function as appropriate to send more data to the device. -</PARA> - -<PROGRAMLISTING> -void (*rcv_event)(can_channel *chan, void *pdata) -</PROGRAMLISTING> - -<PARA> -This function is used to tell the driver that a message has arrived -at the interface or that an event has occurred. This function is typically -called from the interrupt handler. -</PARA> -</SECTION><!-- Callbacks --> - -</SECTION><!-- id="io-can-how-to-write-interface-driver" --> -</CHAPTER> - -</PART> +<!-- {{{ Banner --> + +<!-- =============================================================== --> +<!-- --> +<!-- can.sgml --> +<!-- --> +<!-- Generic CAN documentation. --> +<!-- --> +<!-- =============================================================== --> +<!-- ####COPYRIGHTBEGIN#### --> +<!-- --> +<!-- =============================================================== --> +<!-- Copyright (C) 2004 eCosCentric Limited --> +<!-- This material may be distributed only subject to the terms --> +<!-- and conditions set forth in the Open Publication License, v1.0 --> +<!-- or later (the latest version is presently available at --> +<!-- http://www.opencontent.org/openpub/) --> +<!-- Distribution of the work or derivative of the work in any --> +<!-- standard (paper) book form is prohibited unless prior --> +<!-- permission obtained from the copyright holder --> +<!-- =============================================================== --> +<!-- --> +<!-- ####COPYRIGHTEND#### --> +<!-- =============================================================== --> +<!-- #####DESCRIPTIONBEGIN#### --> +<!-- --> +<!-- Author(s): Uwe Kindler --> +<!-- Date: 2006/12/04 --> +<!-- --> +<!-- ####DESCRIPTIONEND#### --> +<!-- =============================================================== --> + +<!-- }}} --> + +<PART id="io-can"><title>CAN Support</title> + +<CHAPTER id="io-can-overview"> +<TITLE>Overview</TITLE> + +<SECTION id="io-can-overview-descr"> +<TITLE>Description</TITLE> + +<PARA> +The Controller Area Network, CAN, is a multicast shared, differential +serial bus standard especially suited for networking "intelligent" +devices as well as sensors and actuators within a system or sub-system. +The protocol was originally developed in the 1980s by Robert Bosch GmbH +aiming at automotive applications. Nowadays CAN has gained widespread use +and is used in industrial automation as well as in automotive, mobile +machines and in many embedded control applications. +</PARA> + +<PARA> +The CAN protocol is defined by the ISO 11898-1 standard. The physical layer +uses differential transmission on a twisted pair wire. CAN uses a +non-destructive bit-wise arbitration to control access to the bus. +</PARA> + +<PARA> +There is no explicit address in the messages because in CAN networks there +is no addressing of subscribers or stations, but instead, each message carries +a prioritized identifier. A transmitter sends a message to all CAN nodes +(broadcasting). The identifier may serve as an identification of the contents +of the message and also determines the priority that the message enjoys in +competition for bus access. A node decides on the basis of this identifier +received whether it should process the message or not. +</PARA> + +<PARA> +The CAN messages are small (at most eight data bytes) and are protected +by a checksum. Each CAN message consists of an 11 bit message ID, up to 8 +bytes of data and, a CRC checksum and a number of control bits. These +short messages ensure a robust transfer of data in electromagnetically +noisy environments. An extended version of the CAN frame supports 29 bit +message identifiers. +</PARA> + +<PARA> +Basically there are two different operational modes for CAN receivers - +FullCAN and BasicCAN. The difference between these two modes is the +Object Storage function. The BasicCAN architecture is quite similar to a +simple UART. A BasicCAN device has typically one transmit buffer and two +receive buffers. The CAN chip handles only the transmitting and receiving +of the data (and the error handling) and so most of the manipulation of the +data has to be done by the CPU. The CPU has to request the transmitting or +acknowledge the receiving of the data through the interrupt flags. This will +burden the CPU and take up much of the CPU time. +</PARA> + +<PARA> +The FullCAN architecture is more suitable for high-speed performance. It +has its own storage area on chip and works with a number of message buffers +or message boxes. The CAN controller has its own Acceptance Filtering Mask +on chip. It can thus determine which frames are to be received by examining +the identifiers. The CPU in this case will only receive the valid (wanted) +frames and hence improve the performance of the CPU. +</PARA> + +<PARA> +You can find more information at the +<ulink url="http://www.can-cia.org/">CAN in Automation</ulink> website. +</PARA> + +</SECTION> <!-- "io-can-description" --> + +<SECTION id="io-can-ecos-support"> +<TITLE>eCos Support for CAN</TITLE> + +<PARA> +The eCos CAN subsystem supports the BasicCAN and FullCAN mode. The architecture +and the interface of the eCos CAN driver is quite similar to the eCos serial +driver and supports the same interface. +</PARA> + +<PARA> +The eCos CAN support for any given platform is spread over a number of different +packages: +</PARA> + +<itemizedlist> + <listitem> + <para> + +This package, <varname>CYGPKG_IO_CAN</varname>, exports a generic +device independent CAN I/O API for accessing devices attached to a CAN +network. This API handles issues such as locking between threads. The +package does not contain any hardware-specific code. Instead it will +call into a CAN device driver to handle the hardware device +access. This package also defines the inderface that such hardware +drivers should provide. + </para> + </listitem> + <listitem> + <para> +Each CAN device will have its own device driver, which is implemented +as a separate package, for example +<varname>CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN</varname>. For devices that may +be attached to a variety of different boards the device driver will be +generic and a second platform specific package will be used to customize +it to each platform. For devices that are associated with a specific +chipset, only a single package may be present. + </para> + </listitem> +</itemizedlist> + +<PARA> +Typically all appropriate packages will be loaded automatically when +you configure eCos for a given platform. If the application does not use +any of the CAN I/O facilities, directly or indirectly, then linker garbage +collection should eliminate all unnecessary code and data. All necessary +initialization should happen automatically. However the exact details may +depend on the platform, so the platform HAL documentation should be +checked for further details. +</PARA> + +<PARA> +There is an important exception to this: if the CAN devices are attached +to an expansion connector, such as PCI, then the platform HAL will not +know about these devices. Instead the necessary packages will need to be +added explicitly during configuration. +</PARA> +</SECTION> +</CHAPTER> + +<CHAPTER id="io-can-api"> +<TITLE>User API</TITLE> + +<PARA> +The CAN driver uses the standard eCos I/O API functions. All functions +except <function>cyg_io_lookup()</function> require an I/O "handle". +</PARA> + +<PARA> +All functions return a value of the type <type>Cyg_ErrNo</type>. +If an error condition is detected, this value will be negative and the +absolute value indicates the actual error, as specified in +<filename>cyg/error/codes.h</filename>. The only other legal return values +will be <varname>ENOERR</varname>, <varname>-EINTR</varname> and +<varname>-EAGAIN</varname>. All other function arguments are pointers +(references). This allows the drivers to pass information efficiently, +both into and out of the driver. The most striking example of this is the +<parameter>len</parameter> value passed to the read and write functions. +This parameter contains the desired length of data on input to the +function and the actual transferred length on return. +</PARA> + +<PROGRAMLISTING> +// Lookup a CAN device and return its handle +Cyg_ErrNo <FUNCTION><!-- <index></index> -->cyg_io_lookup</function>( + const char <parameter>*name</parameter>, + cyg_io_handle_t <parameter>*handle</parameter> ) +</PROGRAMLISTING> + +<PARA> +This function maps a CAN device name onto an appropriate handle. If the +named device is not in the system, then the error +<varname>-ENOENT</varname> is returned. If the device is found, then +the handle for the device is returned by way of the handle pointer +<parameter>*handle</parameter>. +</PARA> + +<PROGRAMLISTING> +// Send a CAN message +Cyg_ErrNo <FUNCTION><!-- <index></index> -->cyg_io_write</function>( + cyg_io_handle_t <parameter>handle</parameter>, + const void <parameter>*buf</parameter>, + cyg_uint32 <parameter>*len</parameter> ) +</PROGRAMLISTING> + +<PARA> +This function sends one single CAN message (not a buffer of CAN messages) +to a device. The size of data to send is contained in +<parameter>*len</parameter> and the actual size sent will be returned in +the same place. +</PARA> + +<PROGRAMLISTING> +// Read one CAN event from device +Cyg_ErrNo <!-- <index></index> --><function>cyg_io_read</function>( + cyg_io_handle_t <parameter>handle</parameter>, + void <parameter>*buf</parameter>, + cyg_uint32 <parameter>*len</parameter> ) +</PROGRAMLISTING> + +<PARA> +This function receives one single CAN event from a device. The desired size +of data to receive is contained in <parameter>*len</parameter> and the +actual size obtained will be returned in the same place. +</PARA> + +<PROGRAMLISTING> +// Read configuration of a CAN device +Cyg_ErrNo <FUNCTION><!-- <index></index> -->cyg_io_get_config</FUNCTION>( + cyg_io_handle_t <parameter>handle</parameter>, + cyg_uint32 <parameter>key</parameter>, + void *<parameter>buf</parameter>, + cyg_uint32 *<parameter>len</parameter> ) +</PROGRAMLISTING> + +<PARA> +This function is used to obtain run-time configuration about a +device. The type of information retrieved is specified by the +<parameter>key</parameter>. The data will be returned in the given +buffer. The value of <parameter>*len</parameter> should contain the +amount of data requested, which must be at least as large as the size +appropriate to the selected key. The actual size of data retrieved is +placed in <parameter>*len</parameter>. The appropriate key values +are all listed in the file <filename><cyg/io/config_keys.h></filename>. +</PARA> + +<PROGRAMLISTING> +// Change configuration of a CAN device +Cyg_ErrNo <!-- <index></index> --><function>cyg_io_set_config</function>( + cyg_io_handle_t <parameter>handle</parameter>, + cyg_uint32 <parameter>key</parameter>, + const void <parameter>*buf</parameter>, + cyg_uint32 <parameter>*len</parameter> ) +</PROGRAMLISTING> + +<PARA> +This function is used to manipulate or change the run-time +configuration of a device. The type of information is specified by the +<parameter>key</parameter>. The data will be obtained from the given +buffer. The value of <parameter>*len</parameter> should contain the +amount of data provided, which must match the size appropriate to the +selected key. The appropriate key values are all listed in the file +<filename><cyg/io/config_keys.h></filename>. +</PARA> +</CHAPTER> + +<CHAPTER id="io-can-driver-details"> +<TITLE>CAN driver details</TITLE> + +<PARA> +Allow applications and other packages to access CAN devices. +</PARA> + +<SECTION id="io-can-driver-description"> +<TITLE>Description</TITLE> + +<PARA> +A raw CAN driver is is provided as a standard part of the eCos system. +</PARA> + +<PARA> +Use the include file <filename><cyg/io/canio.h></filename> for this driver. +</PARA> + +<PARA> +The CAN driver is capable of sending single CAN messages to a device and +receiving single CAN events from a CAN device. Controls are provided to +configure the actual hardware, but there is no manipulation of the data by +this driver. +</PARA> + +<PARA> +There may be many instances of this driver in a given system, one for each +CAN channel. Each channel corresponds to a physical device and there will +typically be a device module created for this purpose. The device modules +themselves are configurable, allowing specification of the actual hardware +details. +</PARA> +</SECTION> + +<SECTION id="io-can-api-details"> +<TITLE>API Details</TITLE> + +<SECTION> +<TITLE>cyg_io_write</TITLE> + +<PROGRAMLISTING> +cyg_io_write(handle, buf, len) +</PROGRAMLISTING> + +<PARA> +To transmit a message an application must fill a <type>cyg_can_message</type> +buffer and call <function>cyg_io_write()</function>. +This function sends one single CAN message (not a buffer of CAN messages) +to a device. The size of data to send is contained in <parameter>*len</parameter> +and the actual size sent will be returned in the same place. A pointer to a +<type>cyg_can_message</type> is contained in <parameter>*buf</parameter>. +The driver maintains a buffer to hold the data. The size of the intermediate +buffer is configurable within the interface module. The data is not modified +at all while it is being buffered. On return, <parameter>*len</parameter> +contains the amount of characters actually consumed - that means +<parameter>*len</parameter> always contains +<function>sizeof(cyg_can_message)</function>. +</PARA> + +<PARA> +It is possible to configure the write call to be blocking (default) or +non-blocking. Non-blocking mode requires both the configuration option +<varname>CYGOPT_IO_CAN_SUPPORT_NONBLOCKING</varname> to be enabled, and +the specific device to be set to non-blocking mode for writes +(see <function>cyg_io_set_config()</function>). In blocking mode, the +call will not return until there is space in the buffer and the content +of the CAN message has been consumed. In non-blocking mode, if there is +no space in buffer for the CAN message, <varname>-EAGAIN</varname> is +returned and the caller must try again. +</PARA> + +<PARA> +It is possible to configure the write call to be non-blocking with timeout. +None-blocking mode with timeout requires the configuration option +<varname>CYGOPT_IO_CAN_SUPPORT_NONBLOCKING</varname> and +<varname>CYGOPT_IO_CAN_SUPPORT_TIMEOUTS</varname> to be enabled, requires +the eCos kernel package to be included and the specific device to be set +to non-blocking mode for writes (see <function>cyg_io_set_config() +</function>). +In non-blocking mode with timeouts, if there is no space in buffer for the +CAN message, the driver waits a certain amount of time (the timeout time) +for space in the buffer. If there is still no space in buffer after +expiration of the timeout time, <varname>-EINTR</varname> is returned and +the caller must try again. +</PARA> + +<PARA> +If a message was sucessfully sent, the function returns <varname>ENOERR</varname>. +</PARA> +</SECTION> + +<SECTION> +<TITLE>CAN Messages</TITLE> + +<PARA> +The CAN driver uses <structname>cyg_can_message</structname> structures to +pass messages between the application and the CAN driver. The type +cyg_can_message provides a device independent type of CAN message. +Before calling the write function this message should be setup properly. +</PARA> + +<PROGRAMLISTING> +typedef struct can_message +{ + cyg_uint32 id; + cyg_uint8 data[8]; + cyg_can_id_type ext; + cyg_can_frame_type rtr; + cyg_uint8 dlc; +} cyg_can_message; +</PROGRAMLISTING> + +<PARA> +The structure contains the following fields: +</PARA> + +<variablelist> + <varlistentry> + <term><type>cyg_uint32</type> <varname>id</varname></term> + <listitem><para> +Message ID. This is the ID to be transmitted with the message, or the +ID received. If the <structfield>ext</structfield> field is set, then +this will contain a 29 bit ID, otherwise it will contain an 11 bit ID. + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>cyg_uint32</type> <varname>data</varname></term> + <listitem><para> +Message data. Only the first <structfield>dlc</structfield> bytes of +data are valid. If the <structfield>rtr</structfield> field is set, +then the contents of this field are ignored. + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>cyg_can_id_type</type> <varname>ext</varname></term> + <listitem><para> +Extended ID. If this field is <varname>CYGNUM_CAN_ID_EXT</varname> then the +<structname>id</structname> field contains a 29 bit extended ID. If it +contains <varname>CYGNUM_CAN_ID_STD</varname> then the ID is 11 bits. + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>cyg_can_frame_type</type> <varname>rtr</varname></term> + <listitem><para> +Remote Transmission Request. If this field contains +<varname>CYGNUM_CAN_FRAME_RTR</varname> then the RTR bit on the message +will be set and the <structfield>data</structfield> field will be ignored. +If the field contains <varname>CYGNUM_CAN_FRAME_DATA</varname> then a +normal data frame will be send. + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>cyg_uint8</type> <varname>dlc</varname></term> + <listitem><para> +The length of the data carried in the message. This can range from +zero to 8. In a message with the <structfield>rtr</structfield> field set, +this indicates the size of data being requested. + </para></listitem> + </varlistentry> +</variablelist> + +<PARA> +Example code for sending one single CAN message: +</PARA> + +<PROGRAMLISTING> +cyg_can_message tx_msg; +cyg_uint32 len; +Cyg_ErrNo ret; + +tx_msg.id = 0x100; +tx_msg.ext = CYGNUM_CAN_ID_EXT; +tx_msg.rtr = CYGNUM_CAN_FRAME_DATA; +tx_msg.dlc = 1; +tx_msg.data[0] = 0xF1; + +len = sizeof(tx_msg); +ret = cyg_io_write(hDrvCAN, &tx_msg, &len); +</PROGRAMLISTING> +</SECTION><!-- can-cyg_can_message --> + +<SECTION> +<TITLE>cyg_io_read</TITLE> + +<PROGRAMLISTING> +cyg_io_read(handle, buf, len) +</PROGRAMLISTING> + +<PARA> +To receive a message the application calls <function>cyg_can_recv()</function>. +This function receives one single event from a device. The desired size +of data to receive is contained in <parameter>*len</parameter> and the +actual size obtained will be returned in the same place. A pointer to +a <type>cyg_can_event</type> is contained in <parameter>*buf</parameter>. +No manipulation of the data is performed before being transferred. +Again, this buffering is completely configurable. On return, +<parameter>*len</parameter> contains <function>sizeof(cyg_can_event)</function>. +</PARA> + +<PARA> +It is possible to configure the read call to be blocking (default) or +non-blocking. Non-blocking mode requires both the configuration option +<varname>CYGOPT_IO_CAN_SUPPORT_NONBLOCKING</varname> to be enabled, +and the specific device to be set to non-blocking mode for reads +(see <function>cyg_io_set_config()</function>). In blocking mode, +the call will not return until one single CAN event has been read. +In non-blocking mode, if there is no CAN event in buffer, the call +returns immediately with <varname>-EAGAIN</varname> and the caller must +try again. +</PARA> + +<PARA> +It is possible to configure the write call to be non-blocking with timeout. +None-blocking mode with timeout requires the configuration option +<varname>CYGOPT_IO_CAN_SUPPORT_NONBLOCKING</varname> and +<varname>CYGOPT_IO_CAN_SUPPORT_TIMEOUTS</varname> to be enabled, +requires the eCos kernel package to be included and the specific device +to be set to non-blocking mode for reads (see +<function>cyg_io_set_config()</function>). In non-blocking mode with timeouts, +if there is no CAN event in receive buffer, the driver waits a certain amount +of time (the timeout time) for a CAN event to arrive. If there is still no +CAN event in buffer after expiration of the timeout time, <varname>-EINTR</varname> +is returned and the caller must try again. +</PARA> + +<PARA> +If a event was sucessfully received, the function returns <varname>ENOERR</varname>. +</PARA> +</SECTION><!-- cyg_io_read --> + + +<SECTION> +<TITLE>CAN Events</TITLE> + +<PARA> +The CAN driver uses <structname>cyg_can_event</structname> structures to +pass events from hardware device driver to the generic CAN driver. +A <structname>cyg_can_event</structname> provides a generic device +independent type for handling CAN events that may occur. +</PARA> + +<PROGRAMLISTING> +typedef struct cyg_can_event_st +{ + cyg_uint32 timestamp; + cyg_can_message msg; + cyg_uint16 flags; +} cyg_can_event; +</PROGRAMLISTING> + +<PARA> +The structure contains the following fields: +</PARA> + +<variablelist> + <varlistentry> + <term><type>cyg_uint32</type> <varname>timestamp</varname></term> + <listitem><para> +If the hardware CAN device driver supports timestamps then this field may +contain a timestamp value for an event that occured. + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>cyg_can_message</type> <varname>msg</varname></term> + <listitem><para> +CAN message. The msg field contains a CAN message if an RX or TX event +occured. If another type of event occured, +the <structfield>data</structfield> field of +the <structfield>msg</structfield> may contain additional event +specific data. + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>cyg_uint16</type> <varname>flags</varname></term> + <listitem><para> +Event flags. The <varname>flags</varname> field contains 16 bits that +indicate which kind of events occured. + </para></listitem> + </varlistentry> +</variablelist> + +<PARA> +The following events are supported and after receiving an event the +application should check the flag field against these values: +</PARA> + +<PROGRAMLISTING> +typedef enum +{ + CYGNUM_CAN_EVENT_RX = 0x0001, // message received + CYGNUM_CAN_EVENT_TX = 0x0002, // message transmitted + CYGNUM_CAN_EVENT_WARNING_RX = 0x0004, // (TEC) reached warning level (>96) + CYGNUM_CAN_EVENT_WARNING_TX = 0x0008, // (REC) reached warning level (>96) + CYGNUM_CAN_EVENT_ERR_PASSIVE = 0x0010, // CAN "error passive" occured + CYGNUM_CAN_EVENT_BUS_OFF = 0x0020, // CAN "bus off" error occured + CYGNUM_CAN_EVENT_OVERRUN_RX = 0x0040, // overrun in RX queue or hardware + CYGNUM_CAN_EVENT_OVERRUN_TX = 0x0080, // overrun in TX queue occured + CYGNUM_CAN_EVENT_CAN_ERR = 0x0100, // a CAN bit or frame error occured + CYGNUM_CAN_EVENT_LEAVING_STANDBY = 0x0200, // CAN hardware leaves standby + CYGNUM_CAN_EVENT_ENTERING_STANDBY = 0x0400, // CAN hardware enters standby + CYGNUM_CAN_EVENT_ARBITRATION_LOST = 0x0800, // arbitration lost + CYGNUM_CAN_EVENT_FILTER_ERR = 0x1000, // CAN message filter / acceptance filter error + CYGNUM_CAN_EVENT_PHY_FAULT = 0x2000, // General failure of physical layer + CYGNUM_CAN_EVENT_PHY_H = 0x4000, // Fault on CAN-H (Low Speed CAN) + CYGNUM_CAN_EVENT_PHY_L = 0x8000, // Fault on CAN-L (Low Speed CAN) +} cyg_can_event_flags; +</PROGRAMLISTING> + +<PARA> +Often the flags field will contain only one single set flag. But it is +possible that a number of flags is set and so the flag field should always +be checked by a receiver. I.e. if the <varname>CYGNUM_CAN_EVENT_RX</varname> +is set then also the <varname>CYGNUM_CAN_EVENT_OVERRUN_RX</varname> +may be set if the received message caused an RX overrun. +</PARA> + +<PARA> +The internal receive buffers of the CAN device driver are circular buffers. +That means that even if the buffers are completely filled new messages +will be received. In this case the newest message will always overwrite +the oldest message in receive buffer. If this happens the +<varname>CYGNUM_CAN_EVENT_OVERRUN_RX</varname> flag will be set for this +new message that caused overwriting of the old one. The +<varname>CYGNUM_CAN_EVENT_OVERRUN_RX</varname> flag will be set also if +a overrun occures in hardware message buffers of the CAN device. +</PARA> + +<PARA> +Example code for receiving one single CAN event: +</PARA> + +<PROGRAMLISTING> +cyg_can_event rx_event; +cyg_uint32 len; +Cyg_ErrNo ret; + +len = sizeof(rx_event); +ret = cyg_io_read(hDrvCAN, &rx_event, &len); + +if (ENOERR == ret) +{ + if (rx_event.flags & CYGNUM_CAN_EVENT_RX) + { + // handle RX event + } + + if (rx_event.flags & ~CYGNUM_CAN_EVENT_RX) + { + // handle other events + } +} +else if (-EINTR == ret) +{ + // handle timeout +} +</PROGRAMLISTING> +</SECTION><!-- can-cyg_can_event --> + + +<SECTION> +<TITLE>cyg_io_get_config</TITLE> + +<PROGRAMLISTING> +cyg_io_get_config(handle, key, buf, len) +</PROGRAMLISTING> + +<PARA> +This function is used to obtain run-time configuration about a device. +The type of information retrieved is specified by the <parameter>key</parameter>. +The data will be returned in the given buffer. The value of +<parameter>*len</parameter> should contain the amount of data requested, +which must be at least as large as the size appropriate to the selected +<parameter>key</parameter>. The actual size of data retrieved is placed +in <parameter>*len</parameter>. The appropriate key values are all listed +in the file <filename><cyg/io/config_keys.h></filename>. +</PARA> + +<PARA> +The following config keys are currently supported: +</PARA> + +<PROGRAMLISTING> +CYG_IO_GET_CONFIG_READ_BLOCKING +CYG_IO_GET_CONFIG_WRITE_BLOCKING +CYG_IO_GET_CONFIG_CAN_INFO +CYG_IO_GET_CONFIG_CAN_BUFFER_INFO +CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO +CYG_IO_GET_CONFIG_CAN_TIMEOUT +CYG_IO_GET_CONFIG_CAN_HDI +CYG_IO_GET_CONFIG_CAN_STATE +</PROGRAMLISTING> +</SECTION><!-- can-cyg-io-get-config --> + +<SECTION> +<TITLE>cyg_io_set_config</TITLE> + +<PROGRAMLISTING> +cyg_io_set_config(handle, key, buf, len) +</PROGRAMLISTING> + +<PARA> +This function is used to manipulate or change the run-time configuration +of a device. The type of information is specified by the <parameter>key</parameter>. +The data will be obtained from the given buffer. The value of +<parameter>*len</parameter> should contain the amount of data provided, +which must match the size appropriate to the selected <parameter>key</parameter>. +The appropriate key values are all listed in the file +<filename><cyg/io/config_keys.h></filename>. +</PARA> + +<PARA> +The following config keys are currently supported: +</PARA> + +<PROGRAMLISTING> +CYG_IO_SET_CONFIG_READ_BLOCKING +CYG_IO_SET_CONFIG_WRITE_BLOCKING +CYG_IO_SET_CONFIG_CAN_INFO +CYG_IO_SET_CONFIG_CAN_OUTPUT_DRAIN +CYG_IO_SET_CONFIG_CAN_OUTPUT_FLUSH +CYG_IO_SET_CONFIG_CAN_INPUT_FLUSH +CYG_IO_SET_CONFIG_CAN_TIMEOUT +CYG_IO_SET_CONFIG_CAN_MSGBUF +CYG_IO_SET_CONFIG_CAN_MODE +CYG_IO_SET_CONFIG_CAN_ABORT +CYG_IO_SET_CONFIG_CAN_CALLBACK +</PROGRAMLISTING> +</SECTION><!-- can-cyg-io-set-config --> +</SECTION><!-- io-can-api-details --> + +<SECTION id="io-can-runtime-cfg"> +<TITLE>Runtime Configuration</TITLE> + +<PARA> +Runtime configuration is achieved by exchanging data structures with the +driver via the <function>cyg_io_set_config()</function> and +<function>cyg_io_get_config()</function> functions. +</PARA> + +<SECTION> +<TITLE>Device configuration</TITLE> + +<PROGRAMLISTING> +typedef struct cyg_can_info_st { + cyg_can_baud_rate_t baud; +} cyg_can_info_t; +</PROGRAMLISTING> + +<PARA> +Device configuration is achieved by by exchanging +<structname>cyg_can_info_t</structname> data structures with the driver +via the <function>cyg_io_set_config()</function> and +<function>cyg_io_get_config()</function> functions using the config keys +<varname>CYG_IO_GET_CONFIG_CAN_INFO</varname> and +<varname>CYG_IO_SET_CONFIG_CAN_INFO</varname>. +The field <structfield>baud</structfield> contains a baud rate selection. +This must be one of the following values: +</PARA> + +<PROGRAMLISTING> +CYGNUM_CAN_KBAUD_10 +CYGNUM_CAN_KBAUD_20 +CYGNUM_CAN_KBAUD_50 +CYGNUM_CAN_KBAUD_100 +CYGNUM_CAN_KBAUD_125 +CYGNUM_CAN_KBAUD_250 +CYGNUM_CAN_KBAUD_500 +CYGNUM_CAN_KBAUD_800 +CYGNUM_CAN_KBAUD_1000 +</PROGRAMLISTING> +</SECTION><!-- can-cyg-io-set-config --> + +<SECTION> +<TITLE>Timeout configuration</TITLE> + +<PROGRAMLISTING> +typedef struct cyg_can_timeout_info_st +{ + cyg_uint32 rx_timeout; + cyg_uint32 tx_timeout; +} cyg_can_timeout_info_t; +</PROGRAMLISTING> + +<PARA> +Timeout configuration is achieved by by exchanging +<structname>cyg_can_timeout_info_t</structname> data structures with the +driver via the <function>cyg_io_set_config()</function> and +<function>cyg_io_get_config()</function> functions using the config keys +<varname>CYG_IO_SET_CONFIG_CAN_TIMEOUT</varname> and +<varname>CYG_IO_SET_CONFIG_CAN_TIMEOUT</varname>. +</PARA> + +<variablelist> + <varlistentry> + <term><type>cyg_uint32</type> <varname>rx_timeout</varname></term> + <listitem><para> +Timeout for <function>cyg_io_read</function> calls. + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>cyg_uint32</type> <varname>tx_timeout</varname></term> + <listitem><para> +Timeout for <function>cyg_io_write</function> calls. + </para></listitem> + </varlistentry> +</variablelist> + +<PARA> +Timeout runtime configuration is supported if the configuration options +<varname>CYGOPT_IO_CAN_SUPPORT_NONBLOCKING</varname> +and <varname>CYGOPT_IO_CAN_SUPPORT_TIMEOUTS</varname> are enabled. +</PARA> +</SECTION><!-- can-timeout-config --> + +<SECTION> +<TITLE>Reading buffer configuration</TITLE> + +<PROGRAMLISTING> +typedef struct cyg_can_buf_info_st +{ + cyg_int32 rx_bufsize; + cyg_int32 rx_count; + cyg_int32 tx_bufsize; + cyg_int32 tx_count; +} cyg_can_buf_info_t; +</PROGRAMLISTING> + +<PARA> +<varname>CYG_IO_GET_CONFIG_CAN_BUFFER_INFO</varname> - This function +retrieves the current state of the software buffers in the CAN drivers. +For the transmit buffer it returns the the total number of +<type>cyg_can_message</type> objects in buffer and the current number of +<type>cyg_can_message</type> objects occupied in the buffer. +For the receive buffer it returns the total number of +<type>cyg_can_event</type> objects in receive buffer and the current +number of <type>cyg_can_event</type> objects occupied in the buffer. +It does not take into account any buffering such as FIFOs or holding +registers that the CAN hardware device itself may have. +</PARA> + +<variablelist> + <varlistentry> + <term><type>cyg_uint32</type> <varname>rx_bufsize</varname></term> + <listitem><para> +Total number of <type>cyg_can_event</type> buffers in receive queue. + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>cyg_uint32</type> <varname>rx_count</varname></term> + <listitem><para> +Current number of <type>cyg_can_event</type> buffers occupied in receive queue. + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>cyg_uint32</type> <varname>tx_bufsize</varname></term> + <listitem><para> +Total number of <type>cyg_can_message</type> buffers in transmit queue. + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>cyg_uint32</type> <varname>rtx_count</varname></term> + <listitem><para> +Current number of <type>cyg_can_message</type> buffers occupied in transmit queue. + </para></listitem> + </varlistentry> +</variablelist> +</SECTION> <!-- can-read-buffer-config --> + + +<SECTION> +<TITLE>Reading hardware description information</TITLE> + +<PROGRAMLISTING> +typedef struct cyg_can_hdi_st +{ + cyg_uint8 support_flags; + cyg_uint8 controller_type; +} cyg_can_hdi; +</PROGRAMLISTING> + +<PARA> +<varname>CYG_IO_GET_CONFIG_CAN_HDI</varname> - This function retrieves +information about the used hardware. The Hardware Description Interface +provides a method to gather information about the CAN hardware and the +functionality of the driver. For this purpose the structure +<structname>cyg_can_hdi</structname> is defined. +</PARA> + +<variablelist> + <varlistentry> + <term><type>cyg_uint8</type> <varname>support_flags</varname></term> + <listitem><para> +Contains information about the capabilities of the used CAN hardware. + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>cyg_uint8</type> <varname>controller_type</varname></term> + <listitem><para> +A number that identifies the CAN controller type. + </para></listitem> + </varlistentry> +</variablelist> + +<PARA> +The following flags are available in the field <structfield>support_flags</structfield>: +</PARA> + +<PROGRAMLISTING> +| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ++-------+-------+-------+-------+-------+-------+-------+-------+ +| res | res | res |timest.|SW-Filt|FullCAN| Frametype | +</PROGRAMLISTING> + +<variablelist> + <varlistentry> + <term><parameter>Frametype</parameter></term> + <listitem><para> +Bit 0 and Bit 1 of the structure describe the possibilities of the CAN +controller. The following values are defined: + <PROGRAMLISTING> +CYGNUM_CAN_HDI_FRAMETYPE_STD // receives only standard frame +CYGNUM_CAN_HDI_FRAMETYPE_EXT_PASSIVE // can receive but not send extended frames +CYGNUM_CAN_HDI_FRAMETYPE_EXT_ACTIVE // can send and receive extended frames + </PROGRAMLISTING> + </para></listitem> + </varlistentry> + <varlistentry> + <term><parameter>FullCAN</parameter></term> + <listitem><para> +If the Bit 2 - <varname>CYGNUM_CAN_HDI_FULLCAN </varname> - is set to one, +the CAN controller supports more than one message buffer. + </para></listitem> + </varlistentry> + <varlistentry> + <term><parameter>SW-Filter</parameter></term> + <listitem><para> +If Bit 3 - <varname>CYGNUM_CAN_HDI_FILT_SW</varname> - is set to one then +the CAN driver supports some kind of software message filtering. + </para></listitem> + </varlistentry> + <varlistentry> + <term><parameter>Timestamp</parameter></term> + <listitem><para> +If Bit 4 - <varname>CYGNUM_CAN_HDI_TIMESTAMP</varname> - is set to one then +the CAN hardware supports timestamps for CAN messages + </para></listitem> + </varlistentry> +</variablelist> +</SECTION> <!-- can-read-buffer-config --> + +<SECTION> +<TITLE>Reading hardware message buffer configuration</TITLE> +<PROGRAMLISTING> +typedef struct cyg_can_msgbox_info_st +{ + cyg_uint8 count; // number of message buffers available for this device + cyg_uint8 free; // number of free message buffers +} cyg_can_msgbuf_info; +</PROGRAMLISTING> + +<PARA> +<varname>CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO</varname> - If the CAN hardware supports +more than one message buffer for reception of CAN messages (flag +<varname>CYGNUM_CAN_HDI_FULLCAN</varname> is set while reading hardware description +interface with <varname>CYG_IO_GET_CONFIG_CAN_HDI</varname>) then this function +reads the number of message buffers the CAN hardware supports and the number of +free message buffers. +</PARA> + +<variablelist> + <varlistentry> + <term><type>cyg_uint8</type> <varname>count</varname></term> + <listitem><para> +Counts the number of message buffers supported by the device. + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>cyg_uint8</type> <varname>free</varname></term> + <listitem><para> +Contains the number of free message buffers. The free message buffers are +available for setting up remote buffers (<varname>CYG_IO_SET_CONFIG_CAN_REMOTE_BUF</varname>) +and message filters (<varname>CYG_IO_SET_CONFIG_CAN_FILTER_MSG</varname>). + </para></listitem> + </varlistentry> +</variablelist> +</SECTION> <!-- can-read-buffer-config --> + +<SECTION> +<TITLE>Reading state of CAN hardware</TITLE> + +<PROGRAMLISTING> +typedef enum +{ + CYGNUM_CAN_STATE_ACTIVE, // CAN controller active, no errors + CYGNUM_CAN_STATE_STOPPED, // CAN controller in stopped mode + CYGNUM_CAN_STATE_STANDBY, // CAN controller in Sleep mode + CYGNUM_CAN_STATE_BUS_WARN, // CAN controller active, warning level is reached + CYGNUM_CAN_STATE_ERR_PASSIVE, // CAN controller went into error passive mode + CYGNUM_CAN_STATE_BUS_OFF, // CAN controller went into bus off mode + CYGNUM_CAN_STATE_PHY_FAULT, // General failure of physical layer + CYGNUM_CAN_STATE_PHY_H, // Fault on CAN-H detected (Low Speed CAN) + CYGNUM_CAN_STATE_PHY_L, // Fault on CAN-L detected (Low Speed CAN) +} cyg_can_state; +</PROGRAMLISTING> + +<PARA> +<varname>CYG_IO_GET_CONFIG_CAN_STATE</varname> - This function retrieves the +present state of the CAN controller. Possible values are defined in the +<type>cyg_can_state</type> enumeration. +</PARA> +</SECTION> <!-- can-read-hw-state --> + + +<SECTION> +<TITLE>Changing mode of CAN hardware</TITLE> + +<PARA> +<varname>CYG_IO_SET_CONFIG_CAN_MODE</varname> - This function changes +the operating mode of the CAN controller. The identifiers for the different +operating modes are defined in the <type>cyg_can_mode</type> enumeration. +</PARA> + +<PROGRAMLISTING> +typedef enum +{ + CYGNUM_CAN_MODE_STOP, // set controller into stop mode + CYGNUM_CAN_MODE_START, // set controller into operational mode + CYGNUM_CAN_MODE_STANDBY // set controller into standby / sleep mode +} cyg_can_mode; +</PROGRAMLISTING> + +<variablelist> + <varlistentry> + <term><type>CYGNUM_CAN_MODE_STOP</type></term> + <listitem><para> +Set controller into stop mode + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>CYGNUM_CAN_MODE_START</type></term> + <listitem><para> +Set controller into operational mode + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>CYGNUM_CAN_MODE_STANDBY</type></term> + <listitem><para> +Set controller into standby / sleep mode. + </para></listitem> + </varlistentry> +</variablelist> + +<PARA> +Before the hardware configuration of the device is changed, that means +if baud rate 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 <varname>CYGNUM_CAN_EVENT_LEAVING_STANDBY</varname> event will be +inserted into receive message buffer or +the <varname>CYGNUM_CAN_EVENT_LEAVING_STANDBY</varname> flag will be +set for the message that caused wake up of CAN hardware. +</PARA> +</SECTION> <!-- can-mode-cfg --> + +<SECTION> +<TITLE>Flush or drain buffers</TITLE> + +<PARA> +<varname>CYG_IO_SET_CONFIG_CAN_OUTPUT_DRAIN</varname> - This function +waits for any buffered output to complete. This function only +completes when there is no more data remaining to be sent to the +device. +</PARA> + +<PARA> +<varname>CYG_IO_SET_CONFIG_CAN_OUTPUT_FLUSH</varname> - This function +discards any buffered output for the device. +</PARA> + +<PARA> +<varname>CYG_IO_SET_CONFIG_CAN_INPUT_FLUSH</varname> - This function +discards any buffered input for the device. +</PARA> +</SECTION> + +<SECTION> +<TITLE>Configuring blocking/non-blocking calls</TITLE> +<PARA> +By default all calls to <function>cyg_io_read()</function> +and <function>cyg_io_write()</function> are blocking calls. The config +keys +</PARA> + +<PROGRAMLISTING> +CYG_IO_SET_CONFIG_READ_BLOCKING +CYG_IO_SET_CONFIG_WRITE_BLOCKING +</PROGRAMLISTING> + +<PARA> +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 non-blocking calls +are enabled and there is no space in TX buffer or RX buffer is empty +then the function returns immediately +with <varname>-EAGAIN</varname>. +</PARA> + +<PARA> +If non-blocking calls are enabled and additionally timeouts are +supported by driver, then the read/write functions wait until timeout +value is expired and then return with <varname>-EINTR</varname>. If +the read/write operation succeeds during the timed wait then the +functions return succesfully with +<varname>ENOERR</varname>. +</PARA> + +<PARA> +To query if <function>cyg_io_read()</function> +and <function>cyg_io_write()</function> are blocking or non-blocking +you can use the config keys +</PARA> + +<PROGRAMLISTING> +CYG_IO_GET_CONFIG_READ_BLOCKING +CYG_IO_GET_CONFIG_WRITE_BLOCKING +</PROGRAMLISTING> +</SECTION> <!-- can-cfg-unblock --> + +<SECTION> +<TITLE>Message buffer management</TITLE> + +<PARA> +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 buffers. 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. +</PARA> + +<PARA> +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 <function>cyg_io_set_config()</function> with the config key +</PARA> + +<PROGRAMLISTING> +CYG_IO_SET_CONFIG_CAN_MSGBUF +</PROGRAMLISTING> + +<PARA> +and by exchanging <type>cyg_can_msgbuf_cfg</type> data structures. +</PARA> + +<PROGRAMLISTING> +typedef struct cyg_can_msgbox_cfg_st +{ + cyg_can_msgbuf_cfg_id cfg_id; // configuration id + cyg_can_msgbuf_handle handle; // handle to message buffer + cyg_can_message msg; // CAN message - for configuration of buffer +} cyg_can_msgbuf_cfg; +</PROGRAMLISTING> +<variablelist> + <varlistentry> + <term><type>cyg_can_msgbuf_cfg_id</type> <varname>cfg_id</varname></term> + <listitem><para> The <varname>cfg_id</varname> field +contains the configuration ID that tells the driver what to do with a +message buffer. + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>cyg_can_msgbuf_handle</type> <varname>handle</varname></term> + <listitem><para> +Contains a reference to a certain message buffer. + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>cyg_can_message</type> <varname>msg</varname></term> + <listitem><para> +Required for configuration of message buffer parameters. + </para></listitem> + </varlistentry> +</variablelist> + +<PARA> +The following configuration identifiers are supported: +</PARA> + +<PROGRAMLISTING> +CYGNUM_CAN_MSGBUF_RESET_ALL // clears alle message buffers +CYGNUM_CAN_MSGBUF_RX_FILTER_ALL // cfg driver for reception of all can messages +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 +</PROGRAMLISTING> + +<variablelist> + <varlistentry> + <term><type>CYGNUM_CAN_MSGBUF_RESET_ALL</type></term> + <listitem><para> +Clears alle message buffers - no message will be received and all remote buffers are deleted. + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>CYGNUM_CAN_MSGBUF_RX_FILTER_ALL</type></term> + <listitem><para> +Configure driver for reception of all can messages + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>CYGNUM_CAN_MSGBUF_RX_FILTER_ADD</type></term> + <listitem><para> +Add single message filter. + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD</type></term> + <listitem><para> +Add new remote response buffer. + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>CYGNUM_CAN_MSGBUF_REMOTE_BUF_WRITE</type></term> + <listitem><para> +Stores data into existing remote buffer (remote buffer handle required). + </para></listitem> + </varlistentry> +</variablelist> + +<PARA> +Example code for resetting all message buffers: +</PARA> + +<PROGRAMLISTING> +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 +} +</PROGRAMLISTING> +</SECTION> <!-- can-msgbuf-cfg --> + + +<SECTION> +<TITLE>Remote frame response buffer configuration</TITLE> + +<PARA> +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 +Motorola FlexCAN module, does not generate any receive +interrupt. These CAN hardware chips like the FlexCAN module can be +configured to transmit a data frame automatically in response to a +remote frame. In order to support any kind of CAN hardware the eCos CAN +driver provides a generic handling of remote transmission requests. +</PARA> + +<PARA> +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 module, supports hardware 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. +</PARA> + +<PARA> +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. +</PARA> + +<PARA> +In order to respond to a remote frame, a remote frame response buffer +need to be initialized before a data frame can be sent in response to +a remote frame. This is achieved by by +exchanging <type>cyg_can_remote_buf</type> data structures with the +driver via the <function>cyg_io_set_config()</function> function using +the config key <varname>CYG_IO_SET_CONFIG_CAN_MSGBUF</varname>. Once +the buffer is initialized, the CAN data can be changed at any time by +the application. +</PARA> + +<PROGRAMLISTING> +typedef struct cyg_can_msgbuf_cfg_st +{ + cyg_can_msgbuf_cfg_id cfg_id; // configuration id + cyg_can_msgbuf_handle handle; // handle to message buffer + cyg_can_message msg; // CAN message - for configuration of buffer +} cyg_can_remote_buf; +</PROGRAMLISTING> +<variablelist> + <varlistentry> + <term><type>cyg_can_msgbuf_cfg_id</type> <varname>cfg_id</varname></term> + <listitem><para> +The <varname>cfg_id</varname> field contains the configuration ID that tells the driver what to do with +a message buffer (<varname>CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD</varname> or +<varname>CYGNUM_CAN_MSGBUF_REMOTE_BUF_WRITE</varname>). + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>cyg_can_msgbuf_handle</type> <varname>handle</varname></term> + <listitem><para> +If there is no buffer initialized for this data, the value of the handle field need to be set to +<varname>CYGNUM_CAN_MSGBUF_INIT</varname>. After the call to <function>cyg_io_set_config()</function> +the handle field contains a valid remote buffer handle ( >= 0) or the value +<varname>CYGNUM_CAN_MSGBUF_NA</varname> ( < 0) if no free buffer is available. + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>cyg_can_message</type> <varname>msg</varname></term> + <listitem><para> +The CAN frame that should be transmitted in response to a remote frame. + </para></listitem> + </varlistentry> +</variablelist> + +<PARA> +Example code for setting up a remote response buffer: +</PARA> + +<PROGRAMLISTING> +cyg_can_remote_buf rtr_buf; + +// 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; +rtr_buf.msg.rtr = CYGNUM_CAN_FRAME_DATA; +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_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 +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_MSGBUF, + &rtr_buf, &len)) +{ + // handle configuration error +} +</PROGRAMLISTING> +</SECTION> <!-- can-rtrbuf-cfg --> + + +<SECTION> +<TITLE>Message filter configuration</TITLE> + +<PARA> +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. +</PARA> + +<PARA> +Adding message filters is only possible if driver is not configured +for reception of all available CAN messages. If the driver is +configured for reception of all CAN messages then message buffers need +to be reset before adding single message filters. +</PARA> + +<PARA> +In order to add a message filter, a message buffer need to be +initialized. This is achieved by +exchanging <type>cyg_can_filter</type> data structures with the driver +via the <function>cyg_io_set_config()</function> function using the +config key <varname>CYG_IO_SET_CONFIG_CAN_MSGBUF</varname>. Once the +buffer is initialized, the CAN hardware can receive messages with the +identifier of the filter. +</PARA> + +<PROGRAMLISTING> +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; +</PROGRAMLISTING> + +<variablelist> + <varlistentry> + <term><type>cyg_can_msgbuf_cfg_id</type> <varname>cfg_id</varname></term> + <listitem><para> +The <varname>cfg_id</varname> field contains the configuration ID that tells the driver what to do with +a message buffer. + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>cyg_can_msgbuf_handle</type> <varname>handle</varname></term> + <listitem><para> +After the call to <function>cyg_io_set_config()</function> the handle field contains a valid value +( >= 0) or the value <varname>CYGNUM_CAN_MSGBUF_NA</varname> ( < 0) if no free buffer is available. + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>cyg_can_message</type> <varname>msg</varname></term> + <listitem><para> +The fields <structfield>id</structfield> and <structfield>ext</structfield> of the <structfield>msg</structfield> +configure the type of message to receive by a certain message filter. + </para></listitem> + </varlistentry> +</variablelist> + +<PARA> +Before adding message filters the device should be stopped and after +configuration it should be set into operational mode again. +</PARA> + +<PARA> +Example code for setting up a message filter: +</PARA> + +<PROGRAMLISTING> +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 +} +</PROGRAMLISTING> +</SECTION> <!-- can-msgfilt-cfg --> + + +<SECTION id="can-msgfilt-deact"> +<TITLE>Message filter deactivation</TITLE> + +<PARA> +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: +</PARA> + +<PROGRAMLISTING> +CYGNUM_CAN_MSGBUF_RX_FILTER_ALL +</PROGRAMLISTING> + +<PARA> +This message buffer configuration id will clear all message filters +and remote buffers and prepares the CAN hardware for reception of any +kind of CAN standard and extended frames. It is not necessary to reset +the message buffer configuration before this configuration step is +executed because this should be done by device driver. +</PARA> + +<PARA> +Example code for deactivation of message filtering: +</PARA> + +<PROGRAMLISTING> +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"); +} +</PROGRAMLISTING> +</SECTION> <!-- can-msgfilt-deact --> + +<SECTION id="can-event-callback"> +<TITLE>Configuring a callback on events</TITLE> + +<PARA> +By default application cannot get information about an event arriving +in the RX buffer until it calls +the <function>cyg_io_read()</function>. Usually this leads applications +to use accessory threads to wait for new CAN events. +</PARA> + +<PARA> +The CDL option <varname>CYGOPT_IO_CAN_SUPPORT_CALLBACK</varname> +allows application to use a callback on event arrival. It is +configured by passing a <structname>cyg_can_callback_cfg</structname> +data structure to the driver via +the <function>cyg_io_set_config()</function> function using the config +key +<varname>CYG_IO_SET_CONFIG_CAN_CALLBACK</varname>. +</PARA> + +<PROGRAMLISTING> +CYG_IO_SET_CONFIG_CAN_CALLBACK +</PROGRAMLISTING> + +<PROGRAMLISTING> +typedef void (*cyg_can_event_cb_t)(cyg_uint16, CYG_ADDRWORD); + +typedef struct cyg_can_callback_cfg_st +{ + cyg_can_event_cb_t callback_func; // callback function + cyg_uint16 flag_mask; // flags mask + CYG_ADDRWORD data; // data passed to callback +} cyg_can_callback_cfg; +</PROGRAMLISTING> + +<variablelist> + <varlistentry> + <term><type>cyg_can_event_cb_t</type> <varname>callback_func</varname></term> + <listitem><para> +Pointer to the callback function. The function will be called from DSR context so +you should be careful to only call API functions that are safe in DSR +context. The First parameter is a combination of event flags for events that have +occurred. Second parameter is a user defined data pointer or value. + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>CYG_ADDRWORD</type> <varname>data</varname></term> + <listitem><para> +Additional user data that will be passed to callback function as a second parameter. + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>cyg_uint16</type> <varname>flag_mask</varname></term> + <listitem><para> +Should be set with a combination +of <varname>CYGNUM_CAN_EVENT_*</varname> flags. If one of these +events happens, the callback function will be called, with the +actually event flags passed as a parameter. To disable the callback +function from being called set <varname>flag_mask</varname> to 0. + </para></listitem> + </varlistentry> +</variablelist> + +</SECTION> <!-- can-event-callback --> + +</SECTION> +</CHAPTER> + +<CHAPTER id="io-can-configuration"> +<TITLE>Configuration</TITLE> + +<PARA> +The CAN subsystem has a number of configuration options. +</PARA> + +<variablelist> + <varlistentry> + <term><type>cdl_interface CYGINT_IO_CAN_TIMESTAMP</type></term> + <listitem><para> +A hardware device driver that supports timestamps should implement this interface. + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>cdl_option CYGOPT_IO_CAN_SUPPORT_TIMESTAMP</type></term> + <listitem><para> +If the CAN hardware driver supports some kind of timestamps then this option enables +propagation of timestamps to higher layers. This may add some extra code to hardware +drivers. + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>cdl_option CYGOPT_IO_CAN_TX_EVENT_SUPPORT</type></term> + <listitem> +<para> This option enables support for TX +events. If a CAN message is transmitted successfully a TX event will +be inserted into the receive event queue and propagated to higher +layers. If this option is enabled the RX event queue will be filled +faster. +</para></listitem> + </varlistentry> + <varlistentry> + <term><type>cdl_option CYGOPT_IO_CAN_SUPPORT_NONBLOCKING</type></term> + <listitem> +<para> +This option enables extra code in the generic CAN driver which allows +clients to switch read() and write() call semantics from blocking to +non-blocking. +</para></listitem> + </varlistentry> + <varlistentry> + <term><type>cdl_option CYGOPT_IO_CAN_SUPPORT_CALLBACK</type></term> + <listitem> +<para> +This option enables extra code in the generic CAN driver which allows +an application to register a callback for events. The callback function +is called from DSR context so you should be careful to only call API +functions that are safe in DSR context. +</para></listitem> + </varlistentry> + <varlistentry> + <term><type>cdl_option CYGNUM_IO_CAN_DEFAULT_TIMEOUT_READ</type></term> + <listitem><para> +The initial timeout value in clock ticks for <FUNCTION>cyg_io_read()</FUNCTION> calls. + </para></listitem> + </varlistentry> + <varlistentry> + <term><type>cdl_option CYGNUM_IO_CAN_DEFAULT_TIMEOUT_WRITE</type></term> + <listitem><para> The initial timeout value in clock ticks +for <FUNCTION>cyg_io_write()</FUNCTION> calls. + </para></listitem> + </varlistentry> +</variablelist> +</CHAPTER> + + +<CHAPTER id="io-can-device-drivers"> +<TITLE>Writing a CAN hardware device driver</TITLE> + +<PARA> +A CAN driver is nothing more than a named entity that supports the +basic I/O functions - read, write, get config, and set config. The +device driver uses and manages interrupts from the device. While the +interface is generic and device driver independent, the actual driver +implementation is completely up to the device driver designer. +</PARA> + +<PARA> +That said, the reason for using a device driver is to provide access +to a CAN device from application code in as general purpose a fashion +as reasonable. Most driver writers are also concerned with making this +access as simple as possible while being as efficient as possible. +</PARA> + +<PARA> +Like other device drivers the CAN device driver is concerned with the +movement of information - the CAN messages. In order to make the most +efficient use of system resources, interrupts are used. This will +allow other application processing to take place while the data +transfers are under way, with interrupts used to indicate when various +events have occurred. For example, a CAN device typically generates an +interrupt after a CAN message has been sent or a CAN message has been +received by a CAN hardware message buffer. It makes sense to allow +further application processing while the data is being sent since this +can take quite a long time. The interrupt can be used to allow the +driver to send a CAN message as soon as the current one is complete, +without any active participation by the application code. +</PARA> + +<PARA> +The main building blocks for CAN device drivers are found in the +include files +<filename><cyg/io/devtab.h></filename> and <filename><cyg/io/can.h></filename> +</PARA> + +<PARA> +Like many other device drivers in eCos, CAN device drivers are described by a device +table entry, using the <type>cyg_devtab_entry_t</type> type. The entry should be created using +the <varname>DEVTAB_ENTRY()</varname> macro. +</PARA> + + +<SECTION id="io-can-how-to-write-interface-driver"> +<TITLE>How to Write a CAN Hardware Interface Driver</TITLE> + +<PARA> +The standard CAN driver supplied with eCos is structured as a hardware +independent portion and a hardware dependent interface module. To add +support for a new CAN device, the user should be able to use the +existing hardware independent portion and just add their own interface +driver which handles the details of the actual device. The user should +have no need to change the hardware independent portion. +</PARA> + +<PARA> +The interfaces used by the CAN driver and CAN implementation modules +are contained in the file <filename><cyg/io/can.h></filename>. +</PARA> + +<SECTION> +<title>DevTab Entry</TITLE> + +<PARA> +The interface module contains the devtab entry (or entries if a single +module supports more than one interface). This entry should have the +form: +</PARA> + +<PROGRAMLISTING> +DEVTAB_ENTRY(<<module_name>>, + <<device_name>>, + 0, + &can_devio, + <<module_init>>, + <<module_lookup>>, + &<<can_channel>> + ); +</PROGRAMLISTING> + +<variablelist> +<title>Arguments</title> + <varlistentry> + <term><parameter>module_name</parameter></term> + <listitem><para>The "C" label for this devtab entry</para></listitem> + </varlistentry> + <varlistentry> + <term><parameter>device_name</parameter></term> + <listitem><para>The "C" string for the + device. E.g. <filename>/dev/can0</filename>.</para></listitem> + </varlistentry> + <varlistentry> + <term><parameter>can_devio</parameter></term> + <listitem><para>The table of I/O functions. This set is defined in + the hardware independent CAN driver and should be used.</para> + </listitem> + </varlistentry> + <varlistentry> + <term><parameter>module_init</parameter></term> + <listitem><para>The hardware module initialization function.</para></listitem> + </varlistentry> + <varlistentry> + <term><parameter>module_lookup</parameter></term> + <listitem><para>The device lookup function. This function + typically sets up the CAN device for actual use, turning on + interrupts, configuring the message buffers, etc.</para></listitem> + </varlistentry> + <varlistentry> + <term><parameter>can_channel</parameter></term> + <listitem><para>This table (defined below) contains the interface + between the interface module and the CAN driver proper.</para></listitem> + </varlistentry> +</variablelist> + +<PARA> +Example devtab entry for Motorola FlexCAN device driver: +</PARA> + +<PROGRAMLISTING> +DEVTAB_ENTRY(flexcan_devtab, + CYGDAT_DEVS_CAN_MCF52xx_FLEXCAN0_NAME, + 0, // Does not depend on a lower level interface + &cyg_io_can_devio, + flexcan_init, + flexcan_lookup, // CAN driver may need initializing + &flexcan_can0_chan + ); +</PROGRAMLISTING> +</SECTION> + + +<SECTION> +<title>CAN Channel Structure</TITLE> + +<PARA> +Each CAN device must have a “CAN channel”. +This is a set of data which describes all operations on the device. +It also contains buffers, etc. The CAN channel is created by the macro: +</PARA> + +<PROGRAMLISTING> +CAN_CHANNEL_USING_INTERRUPTS(l, funs, dev_priv, baud, + out_buf, out_buflen, + in_buf, in_buflen) +</PROGRAMLISTING> + +<variablelist> + <title>Arguments</title> + <varlistentry> + <term><parameter>l</parameter></term> + <listitem><para>The "C" label for this structure.</para></listitem> + </varlistentry> + <varlistentry> + <term><parameter>funs</parameter></term> + <listitem><para>The set of interface functions (see below).</para></listitem> + </varlistentry> + <varlistentry> + <term><structfield>dev_priv</structfield></term> + <listitem><para>A placeholder for any device specific data for + this channel.</para></listitem> + </varlistentry> + <varlistentry> + <term><structfield>baud</structfield></term> + <listitem><para>The initial baud rate value + (<type>cyg_can_baud_rate_t</type>).</para></listitem> + </varlistentry> + <varlistentry> + <term><structfield>out_buf</structfield></term> + <listitem><para>Pointer to the output buffer</para></listitem> + </varlistentry> + <varlistentry> + <term><structfield>out_buflen</structfield></term> + <listitem><para>The length of the output buffer.</para></listitem> + </varlistentry> + <varlistentry> + <term><structfield>in_buf</structfield></term> + <listitem><para>pointer to the input buffer.</para></listitem> + </varlistentry> + <varlistentry> + <term><structfield>in_buflen</structfield></term> + <listitem><para>The length of the input buffer.</PARA></listitem> + </varlistentry> +</variablelist> + +<PARA> +Example CAN channel implementation for Motorola FlexCAN device driver: +</PARA> + +<PROGRAMLISTING> +CAN_CHANNEL_USING_INTERRUPTS( + flexcan_can0_chan, + flexcan_lowlevel_funs, + flexcan_can0_info, + CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_KBAUD), + flexcan_can0_txbuf, CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_TX, + flexcan_can0_rxbuf, CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_RX +); +</PROGRAMLISTING> + +<PARA> +The interface from the hardware independent driver into the hardware +interface module is contained in the <structfield>funs</structfield> +table. This is defined by the macro: +</PARA> +</SECTION> + +<SECTION> +<TITLE>CAN Lowlevel Functions Structure</TITLE> + +<PROGRAMLISTING> +CAN_LOWLEVEL_FUNS(l, putmsg, getevent, get_config, set_config, start_xmit, stop_xmit) +</PROGRAMLISTING> + +<variablelist> + <title>Arguments</title> + <varlistentry> + <term><structfield>l</structfield></term> + <listitem><para>The "C" label for this structure.</para></listitem> + </varlistentry> + <varlistentry> + <term><structfield>putmsg</structfield></term> + <listitem> + <para><literal> + bool (*putmsg)(can_channel *priv, cyg_can_message *pmsg, void *pdata) + </literal></para> + <para> + This function sends one CAN message to the interface. It should + return <literal>true</literal> if the message is actually + consumed. It should return <literal>false</literal> if there is + no space in the interface + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><structfield>getevent</structfield></term> + <listitem> + <para><literal> + bool (*getevent)(can_channel *priv, cyg_can_event *pevent, void *pdata) + </literal></para> + <para> + This function fetches one event from the interface. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><structfield>get_config</structfield></term> + <listitem> + <para><literal> + Cyg_ErrNo (*get_config)(can_channel *priv, cyg_uint32 key, const void *xbuf, cyg_uint32 *len) + </literal></para> + <para> + This function is used to query the configuration of a CAN channel. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><structfield>set_config</structfield></term> + <listitem> + <para><literal> + Cyg_ErrNo (*set_config)(can_channel *priv, cyg_uint32 key, const void *xbuf, cyg_uint32 *len) + </literal></para> + <para> + This function is used to change configuration of a CAN channel. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><parameter>start_xmit</parameter></term> + <listitem><para><literal>void (*start_xmit)(can_channel *priv)</literal></para> + <para> + Enable the transmit channel and turn on transmit interrupts. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><parameter>stop_xmit</parameter></term> + <listitem> + <para><literal>void (*stop_xmit)(can_channel *priv)</literal></para> + <para>Disable the transmit channel and turn transmit interrupts off.</PARA> + </listitem> + </varlistentry> +</variablelist> + +<PARA> +Example implementation of low level function structure for Motorola FlexCAN +device driver: +</PARA> + +<PROGRAMLISTING> +CAN_LOWLEVEL_FUNS(flexcan_lowlevel_funs, + flexcan_putmsg, + flexcan_getevent, + flexcan_get_config, + flexcan_set_config, + flexcan_start_xmit, + flexcan_stop_xmit + ); +</PROGRAMLISTING> +</SECTION> + +<SECTION> +<TITLE>Callbacks</TITLE> + +<PARA> +The device interface module can execute functions in the +hardware independent driver via <literal>chan->callbacks</literal>. +These functions are available: +</PARA> + +<PROGRAMLISTING> +void (*can_init)(can_channel *chan) +</PROGRAMLISTING> + +<PARA>This function is used to initialize the CAN channel.</PARA> + +<PROGRAMLISTING> +void (*xmt_msg)(can_channel *chan, void *pdata) +</PROGRAMLISTING> + +<PARA> +This function would be called from an interrupt handler after a +transmit interrupt indicating that additional messages may be +sent. The upper driver will call the <function>putmsg</function> +function as appropriate to send more data to the device. +</PARA> + +<PROGRAMLISTING> +void (*rcv_event)(can_channel *chan, void *pdata) +</PROGRAMLISTING> + +<PARA> +This function is used to tell the driver that a message has arrived +at the interface or that an event has occurred. This function is typically +called from the interrupt handler. +</PARA> +</SECTION><!-- Callbacks --> + +</SECTION><!-- id="io-can-how-to-write-interface-driver" --> +</CHAPTER> + +</PART>
--- a/packages/io/can/current/include/canio.h +++ b/packages/io/can/current/include/canio.h @@ -331,7 +331,7 @@ typedef struct cyg_can_hdi_st // Callback configuration structure. // -typedef void (*cyg_can_event_cb_t)(cyg_uint16, cyg_addrword_t); +typedef void (*cyg_can_event_cb_t)(cyg_uint16, CYG_ADDRWORD); // // flag_mask should be set with a combination of CYGNUM_CAN_EVENT_* flags. // If one of these events happens, the callback function will be called, @@ -341,7 +341,7 @@ typedef struct cyg_can_callback_cfg_st { cyg_can_event_cb_t callback_func; // callback function cyg_uint16 flag_mask; // flags mask - cyg_addrword_t data; // data passed to callback + CYG_ADDRWORD data; // data passed to callback } cyg_can_callback_cfg;
--- a/packages/io/can/current/src/can.c +++ b/packages/io/can/current/src/can.c @@ -668,8 +668,8 @@ static Cyg_ErrNo can_set_config(cyg_io_h #ifdef CYGOPT_IO_CAN_SUPPORT_CALLBACK // - // Set waking calls configuration - // To disable waking calls set waking_mask = 0 + // Set callback configuration + // To disable callback set flag_mask = 0 // case CYG_IO_SET_CONFIG_CAN_CALLBACK: {
