Working fork to test F0 application

Dependents:   ppCANOpen_Example

Fork of CANnucleo by Zoltan Hudak

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers CAN.cpp Source File

CAN.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2006-2013 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  *
00016  * Modified by Zoltan Hudak    <hudakz@inbox.com>
00017  *
00018  */
00019 #include "CAN.h"
00020 #include "cmsis.h"
00021 
00022 namespace   mbed
00023 {
00024     
00025 /**
00026  * @brief   Constructor
00027  * @note    Constructs an instance of CAN class
00028  * @param   rxPin: CAN Rx pin name
00029  * @param   txPin: CAN Tx pin name
00030  * @param   abom:  Automatic recovery from bus-off state (defaults to enabled)
00031  * @retval
00032  */
00033 CAN::CAN(PinName rxPin, PinName txPin, FunctionalState abom /* = ENABLE */) :
00034     _can(),
00035     _irq() {
00036     can_init(&_can, rxPin, txPin, abom);
00037     can_irq_init(&_can, (&CAN::_irq_handler ), (uint32_t)this);
00038 }
00039 
00040 /**
00041  * @brief
00042  * @note
00043  * @param
00044  * @retval
00045  */
00046 CAN::~CAN (void) {
00047     can_irq_free(&_can);
00048     can_free(&_can);
00049 }
00050 
00051 /**
00052  * @brief
00053  * @note
00054  * @param
00055  * @retval
00056  */
00057 int CAN::frequency(int f) {
00058     return can_frequency(&_can, f);
00059 }
00060 
00061 /**
00062  * @brief
00063  * @note
00064  * @param
00065  * @retval
00066  */
00067 int CAN::write(CANMessage msg) {
00068     return can_write(&_can, msg, 0);
00069 }
00070 
00071 /**
00072  * @brief
00073  * @note
00074  * @param
00075  * @retval
00076  */
00077 int CAN::read(CANMessage& msg, int handle) {
00078     return can_read(&_can, &msg, handle);
00079 }
00080 
00081 /**
00082  * @brief
00083  * @note
00084  * @param
00085  * @retval
00086  */
00087 void CAN::reset(void) {
00088     can_reset(&_can);
00089 }
00090 
00091 /**
00092  * @brief
00093  * @note
00094  * @param
00095  * @retval
00096  */
00097 unsigned char CAN::rderror(void) {
00098     return can_rderror(&_can);
00099 }
00100 
00101 /**
00102  * @brief
00103  * @note
00104  * @param
00105  * @retval
00106  */
00107 unsigned char CAN::tderror(void) {
00108     return can_tderror(&_can);
00109 }
00110 
00111 /**
00112  * @brief
00113  * @note
00114  * @param
00115  * @retval
00116  */
00117 void CAN::monitor(bool silent) {
00118     can_monitor(&_can, (silent) ? 1 : 0);
00119 }
00120 
00121 /**
00122  * @brief
00123  * @note
00124  * @param
00125  * @retval
00126  */
00127 int CAN::mode(Mode mode) {
00128     return can_mode(&_can, (CanMode) mode);
00129 }
00130 
00131 /**
00132  * @brief   Sets up a CAN filter
00133  * @note    At the present, CANnucleo supports only mask mode and 32-bit filter scale.
00134  *          Identifier list mode filtering and 16-bit filter scale are not supported.
00135  *          There are 14 filters available (0 - 13) for the application to set up.
00136  *          Each filter is a 32-bit filter defined by a filter ID and a filter mask.
00137  *          If no filter is set up then no CAN message is accepted (received)!
00138  *          That's why filter #0 is set up in the constructor to receive all CAN messages by default.
00139  *          On reception of a message it is compared with filter #0. If there is a match, the message is stored.
00140  *          If there is no match, the incoming identifier is then compared with the next filter.
00141  *          If the received identifier does not match any of the identifiers configured in the filters,
00142  *          the message is discarded by hardware without disturbing the software.
00143  *
00144  * @param   id: 'Filter ID' defines the bit values to be compared with the corresponding received bits
00145  *
00146  * Mapping of 32-bits (4-bytes) : | STID[10:3] | STID[2:0] EXID[17:13] | EXID[12:5] |  EXID[4:0] IDE RTR 0 |
00147  *
00148  * STID - Stardard Identifier bits
00149  * EXID - Extended Identifier bits
00150  * [x:y]- bit range
00151  * IDE  - Identifier Extension bit (0 -> Standard Identifier, 1 -> Extended Identifier)
00152  * RTR  - Remote Transmission Request bit (0 -> Remote Transmission Request, 1 -> Standard message)
00153  *
00154  * @param   mask: 'Filter mask' defines which bits of the 'Filter ID' are compared with the received bits
00155  *                and which bits are disregarded.
00156 
00157  * Mapping of 32-bits (4-bytes) : | STID[10:3] | STID[2:0] EXID[17:13] | EXID[12:5] |  EXID[4:0] IDE RTR 0 |
00158  *
00159  * STID - Stardard Identifier bits
00160  * EXID - Extended Identifier bits
00161  * [x:y]- bit range
00162  * IDE  - Identifier Extension bit
00163  * RTR  - Remote Transmission Request bit
00164  *
00165  * 1 -> bit is considered
00166  * 0 -> bit is disregarded
00167  *
00168  * ----------------------------------------
00169  * Example of filter set up and filtering:
00170  * ----------------------------------------
00171 *
00172  * Let's assume we would like to receive only messages 
00173  * with standard identifier STID = 0x0207  (STID[15:0] = 00000010 00000111)
00174  *
00175  * We map the STID to filter ID by shifting the bits appropriately:
00176  * Filter id = STID << (16 + (15 - 10)) = STID << 21 = 01000000 11100000 00000000 00000000 = 0x40E00000
00177  *
00178  * To compare only the bits representing STID we set the filter mask adequately:
00179  * Filter mask = 11111111 11100000 00000000 00000100 = 0xFFE00004
00180  *               |||||||| |||                    |
00181  *               -------- ---                    |
00182  *                   |     |                     |
00183  *            STID[10:3]  STID[2:0]             IDE   
00184  *
00185  * Keep in mind that filter #0 was already set up in the constructor to receive all CAN messages by default.
00186  * So we have to reconfigure it. If we were set up filter #1 here then filter #0 would receive all the messages
00187  * and no message would reach filter #1!
00188  *
00189  * To set up filter #0 we call:
00190  *     can.filter(0x0207 << 21, 0xFFE00004, CANAny, 0);
00191  *
00192  *             Only these bits (set to 1) of filter id are compared with the corresponding
00193  *             bits of received message (the others are disregarded)
00194  *                                |
00195  *                 ---------------------------------
00196  *                 |||||||| |||                    |
00197  *   Filter mask = 11111111 11100000 00000000 00000100 (= 0xFFE00004)
00198  *   Filter id   = 01000000 11100000 00000000 00000000 (= 0x40E00000)
00199  *                 |||||||| |||                    |
00200  *                 ---------------------------------
00201  *                                |
00202  *            To receive the message the values of these bits must match.
00203  *            Otherwise the message is passed to the next filter or
00204  *            discarded if this was the last active filter.
00205  *                                |
00206  *                 ---------------------------------
00207  *                 |||||||| |||                    |
00208  *   Received id = 01000000 11100000 00000000 00000010 (= 0x40E00002)
00209  *                             ||||| |||||||| ||||| ||
00210  *                             -----------------------
00211  *                                         |
00212  *                          These bits (set to 0 in filter mask) are disregarded (masked).
00213  *                          They can have arbitrary values.
00214  *
00215  * NOTE: For the meaning of individual bits see the mapping of 32-bits explained above.
00216  *
00217  * @param   format: This parameter must be CANAny
00218  * @param   handle: Selects the filter. This parameter must be a number between 0 and 13.
00219  * @param   retval: 0 - successful
00220  *                  1 - error
00221  *                  2 - busy
00222  *                  3 - time out  
00223  */
00224 int CAN::filter(unsigned int id, unsigned int mask, CANFormat format /* = CANAny */, int handle /* = 0 */) {
00225     return can_filter(&_can, id, mask, format, handle);
00226 }
00227 
00228 /**
00229  * @brief   Attaches handler funcion to CAN1 RX0 Interrupt
00230  * @note    Only CAN1 RX0 Interrupt supported
00231  * @param   fptr: pointer to a void (*)(void) function
00232  * @param   type: not used (only CAN1 RX0 Interrupt supported) 
00233  * @retval
00234  */
00235 void CAN::attach(void (*fptr) (void), IrqType type) {
00236     HAL_NVIC_DisableIRQ(CAN_IRQ);
00237     if(fptr) {
00238         can_irq_set(fptr);
00239     }
00240     can_irq_init(&_can, &CAN::_irq_handler , (uint32_t) this);
00241     HAL_NVIC_EnableIRQ(CAN_IRQ);
00242 }
00243 
00244 /**
00245  * @brief
00246  * @note
00247  * @param
00248  * @retval
00249  */
00250 void CAN::_irq_handler (uint32_t id, CanIrqType type) {
00251     CAN*    handler = (CAN*)id;
00252     handler->_irq[type].call();
00253 }
00254 
00255 }   // namespace mbed
00256 
00257 
00258 
00259 
00260 
00261