test

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     _irq() {
00035     can_init(rxPin, txPin, abom);
00036     can_irq_init((uint32_t)this, (&CAN::_irq_handler ));
00037 }
00038 
00039 /**
00040  * @brief
00041  * @note
00042  * @param
00043  * @retval
00044  */
00045 CAN::~CAN (void) {
00046     can_irq_free();
00047     can_free();
00048 }
00049 
00050 /**
00051  * @brief
00052  * @note
00053  * @param
00054  * @retval
00055  */
00056 int CAN::frequency(int f) {
00057     return can_frequency(f);
00058 }
00059 
00060 /**
00061  * @brief
00062  * @note
00063  * @param
00064  * @retval
00065  */
00066 int CAN::write(CANMessage msg) {
00067     return can_write(msg, 0);
00068 }
00069 
00070 /**
00071  * @brief
00072  * @note
00073  * @param
00074  * @retval
00075  */
00076 int CAN::read(CANMessage& msg, int handle) {
00077     return can_read(&msg, handle);
00078 }
00079 
00080 /**
00081  * @brief
00082  * @note
00083  * @param
00084  * @retval
00085  */
00086 void CAN::reset(void) {
00087     can_reset();
00088 }
00089 
00090 /**
00091  * @brief
00092  * @note
00093  * @param
00094  * @retval
00095  */
00096 unsigned char CAN::rderror(void) {
00097     return can_rderror();
00098 }
00099 
00100 /**
00101  * @brief
00102  * @note
00103  * @param
00104  * @retval
00105  */
00106 unsigned char CAN::tderror(void) {
00107     return can_tderror();
00108 }
00109 
00110 /**
00111  * @brief
00112  * @note
00113  * @param
00114  * @retval
00115  */
00116 void CAN::monitor(bool silent) {
00117     can_monitor((silent) ? 1 : 0);
00118 }
00119 
00120 /**
00121  * @brief
00122  * @note
00123  * @param
00124  * @retval
00125  */
00126 int CAN::mode(Mode mode) {
00127     return can_mode((CanMode) mode);
00128 }
00129 
00130 /**
00131  * @brief   Sets up a CAN filter
00132  * @note    At the present, CANnucleo supports only mask mode and 32-bit filter scale.
00133  *          Identifier list mode filtering and 16-bit filter scale are not supported.
00134  *          There are 14 filters available (0 - 13) for the application to set up.
00135  *          Each filter is a 32-bit filter defined by a filter ID and a filter mask.
00136  *          If no filter is set up then no CAN message is accepted (received)!
00137  *          That's why filter #0 is set up in the constructor to receive all CAN messages by default.
00138  *          On reception of a message it is compared with filter #0. If there is a match, the message is stored.
00139  *          If there is no match, the incoming identifier is then compared with the next filter.
00140  *          If the received identifier does not match any of the identifiers configured in the filters,
00141  *          the message is discarded by hardware without disturbing the software.
00142  *
00143  * @param   id: 'Filter ID' defines the bit values to be compared with the corresponding received bits
00144  *
00145  * Mapping of 32-bits (4-bytes) : | STID[10:3] | STID[2:0] EXID[17:13] | EXID[12:5] |  EXID[4:0] IDE RTR 0 |
00146  *
00147  * STID - Stardard Identifier bits
00148  * EXID - Extended Identifier bits
00149  * [x:y]- bit range
00150  * IDE  - Identifier Extension bit (0 -> Standard Identifier, 1 -> Extended Identifier)
00151  * RTR  - Remote Transmission Request bit (0 -> Remote Transmission Request, 1 -> Standard message)
00152  *
00153  * @param   mask: 'Filter mask' defines which bits of the 'Filter ID' are compared with the received bits
00154  *                and which bits are disregarded.
00155 
00156  * Mapping of 32-bits (4-bytes) : | STID[10:3] | STID[2:0] EXID[17:13] | EXID[12:5] |  EXID[4:0] IDE RTR 0 |
00157  *
00158  * STID - Stardard Identifier bits
00159  * EXID - Extended Identifier bits
00160  * [x:y]- bit range
00161  * IDE  - Identifier Extension bit
00162  * RTR  - Remote Transmission Request bit
00163  *
00164  * 1 -> bit is considered
00165  * 0 -> bit is disregarded
00166  *
00167  * ----------------------------------------
00168  * Example of filter set up and filtering:
00169  * ----------------------------------------
00170 *
00171  * Let's assume we would like to receive only messages 
00172  * with standard identifier STID = 0x0207  (STID[15:0] = 00000010 00000111)
00173  *
00174  * We map the STID to filter ID by shifting the bits appropriately:
00175  * Filter id = STID << (16 + (15 - 10)) = STID << 21 = 01000000 11100000 00000000 00000000 = 0x40E00000
00176  *
00177  * To compare only the bits representing STID we set the filter mask adequately:
00178  * Filter mask = 11111111 11100000 00000000 00000100 = 0xFFE00004
00179  *               |||||||| |||                    |
00180  *               -------- ---                    |
00181  *                   |     |                     |
00182  *            STID[10:3]  STID[2:0]             IDE   
00183  *
00184  * Recall that filter #0 has been set up in the constructor to receive all CAN messages by default.
00185  * So we have to reconfigure it. If we were set up filter #1 here then filter #0 would receive all the messages
00186  * and no message would reach filter #1!
00187  *
00188  * To reconfigure (set up) filter #0 we call:
00189  *     can.filter(0x0207 << 21, 0xFFE00004, CANAny, 0);
00190  *
00191  *             Only these bits of 'Filter id' (set to 1 here in 'Filter mask') are compared with the corresponding
00192  *             bits of received message (the others are disregarded)
00193  *                                |
00194  *                 ---------------------------------
00195  *                 |||||||| |||                    |
00196  *   Filter mask = 11111111 11100000 00000000 00000100 (= 0xFFE00004)
00197  *   Filter id   = 01000000 11100000 00000000 00000000 (= 0x40E00000)
00198  *                 |||||||| |||                    |
00199  *                 ---------------------------------
00200  *                                |
00201  *            To receive the message the values of these bits must match.
00202  *            Otherwise the message is passed to the next filter or
00203  *            discarded if this was the last active filter.
00204  *                                |
00205  *                 ---------------------------------
00206  *                 |||||||| |||                    |
00207  *   Received id = 01000000 11100000 00000000 00000010 (= 0x40E00002)
00208  *                             ||||| |||||||| ||||| ||
00209  *                             -----------------------
00210  *                                         |
00211  *                          These bits (set to 0 in 'Filter mask') are disregarded (masked).
00212  *                          They can have arbitrary values.
00213  *
00214  * NOTE: For the meaning of individual bits see the mapping of 32-bits explained above.
00215  *
00216  * @param   format: This parameter must be CANAny
00217  * @param   handle: Selects the filter. This parameter must be a number between 0 and 13.
00218  * @retval  0 - successful
00219  *          1 - error
00220  *          2 - busy
00221  *          3 - time out  
00222  */
00223 int CAN::filter(unsigned int id, unsigned int mask, CANFormat format /* = CANAny */, int handle /* = 0 */) {
00224     return can_filter(id, mask, format, handle);
00225 }
00226 
00227 /**
00228  * @brief   Attaches handler funcion to CAN1 RX0 Interrupt
00229  * @note    Only CAN1 RX0 Interrupt supported
00230  * @param   fptr: pointer to a void (*)(void) function
00231  * @param   type: not used (only CAN1 RX0 Interrupt supported) 
00232  * @retval
00233  */
00234 void CAN::attach(void (*fptr) (void), IrqType type) {
00235     HAL_NVIC_DisableIRQ(CAN_IRQ);
00236     if(fptr)
00237         _irq[(CanIrqType)type].attach(fptr);
00238     HAL_NVIC_EnableIRQ(CAN_IRQ);
00239 }
00240 
00241 /**
00242  * @brief
00243  * @note
00244  * @param
00245  * @retval
00246  */
00247 void CAN::_irq_handler (uint32_t id, CanIrqType type) {
00248     CAN*    handler = (CAN*)id;
00249     handler->_irq[type].call();
00250 }
00251 
00252 }   // namespace mbed
00253 
00254 
00255 
00256 
00257 
00258 
00259 
00260