pub

Fork of CANnucleo by Zoltan Hudak

Committer:
hudakz
Date:
Tue Aug 16 21:09:11 2016 +0000
Revision:
25:353237492903
Parent:
24:c5d348e65e24
Child:
28:eed6929956ea
Updated.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hudakz 0:e29bc8e0dddd 1 /* mbed Microcontroller Library
hudakz 0:e29bc8e0dddd 2 * Copyright (c) 2006-2013 ARM Limited
hudakz 0:e29bc8e0dddd 3 *
hudakz 0:e29bc8e0dddd 4 * Licensed under the Apache License, Version 2.0 (the "License");
hudakz 0:e29bc8e0dddd 5 * you may not use this file except in compliance with the License.
hudakz 0:e29bc8e0dddd 6 * You may obtain a copy of the License at
hudakz 0:e29bc8e0dddd 7 *
hudakz 0:e29bc8e0dddd 8 * http://www.apache.org/licenses/LICENSE-2.0
hudakz 0:e29bc8e0dddd 9 *
hudakz 0:e29bc8e0dddd 10 * Unless required by applicable law or agreed to in writing, software
hudakz 0:e29bc8e0dddd 11 * distributed under the License is distributed on an "AS IS" BASIS,
hudakz 0:e29bc8e0dddd 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
hudakz 0:e29bc8e0dddd 13 * See the License for the specific language governing permissions and
hudakz 0:e29bc8e0dddd 14 * limitations under the License.
hudakz 0:e29bc8e0dddd 15 *
hudakz 0:e29bc8e0dddd 16 * Modified by Zoltan Hudak <hudakz@inbox.com>
hudakz 0:e29bc8e0dddd 17 *
hudakz 0:e29bc8e0dddd 18 */
hudakz 24:c5d348e65e24 19 #ifndef CANNUCLEO_H
hudakz 24:c5d348e65e24 20 #define CANNUCLEO_H
hudakz 0:e29bc8e0dddd 21
hudakz 0:e29bc8e0dddd 22 #include "platform.h"
hudakz 24:c5d348e65e24 23 #include "cannucleo_api.h"
hudakz 0:e29bc8e0dddd 24 #include "can_helper.h"
hudakz 25:353237492903 25 #include "Callback.h"
hudakz 25:353237492903 26 #include "PlatformMutex.h"
hudakz 24:c5d348e65e24 27 #undef DEVICE_CAN
hudakz 24:c5d348e65e24 28
hudakz 23:ea766d08c9db 29 namespace CANnucleo
hudakz 0:e29bc8e0dddd 30 {
hudakz 0:e29bc8e0dddd 31
hudakz 0:e29bc8e0dddd 32 /** CANMessage class
hudakz 0:e29bc8e0dddd 33 */
hudakz 0:e29bc8e0dddd 34 class CANMessage : public CAN_Message
hudakz 0:e29bc8e0dddd 35 {
hudakz 0:e29bc8e0dddd 36
hudakz 0:e29bc8e0dddd 37 public:
hudakz 0:e29bc8e0dddd 38 /** Creates empty CAN message.
hudakz 0:e29bc8e0dddd 39 */
hudakz 0:e29bc8e0dddd 40 CANMessage() : CAN_Message() {
hudakz 0:e29bc8e0dddd 41 len = 8;
hudakz 0:e29bc8e0dddd 42 type = CANData;
hudakz 0:e29bc8e0dddd 43 format = CANStandard;
hudakz 0:e29bc8e0dddd 44 id = 0;
hudakz 0:e29bc8e0dddd 45 memset(data, 0, 8);
hudakz 0:e29bc8e0dddd 46 }
hudakz 0:e29bc8e0dddd 47
hudakz 0:e29bc8e0dddd 48 /** Creates CAN message with specific content.
hudakz 0:e29bc8e0dddd 49 */
hudakz 0:e29bc8e0dddd 50 CANMessage(int _id, const char *_data, char _len = 8, CANType _type = CANData, CANFormat _format = CANStandard) {
hudakz 0:e29bc8e0dddd 51 len = _len & 0xF;
hudakz 0:e29bc8e0dddd 52 type = _type;
hudakz 0:e29bc8e0dddd 53 format = _format;
hudakz 0:e29bc8e0dddd 54 id = _id;
hudakz 0:e29bc8e0dddd 55 memcpy(data, _data, _len);
hudakz 0:e29bc8e0dddd 56 }
hudakz 0:e29bc8e0dddd 57
hudakz 0:e29bc8e0dddd 58 /** Creates CAN remote message.
hudakz 0:e29bc8e0dddd 59 */
hudakz 0:e29bc8e0dddd 60 CANMessage(int _id, CANFormat _format = CANStandard) {
hudakz 0:e29bc8e0dddd 61 len = 0;
hudakz 0:e29bc8e0dddd 62 type = CANRemote;
hudakz 0:e29bc8e0dddd 63 format = _format;
hudakz 0:e29bc8e0dddd 64 id = _id;
hudakz 0:e29bc8e0dddd 65 memset(data, 0, 8);
hudakz 0:e29bc8e0dddd 66 }
hudakz 0:e29bc8e0dddd 67
hudakz 0:e29bc8e0dddd 68 /*********************************************************************/
hudakz 0:e29bc8e0dddd 69 /*********************************************************************/
hudakz 0:e29bc8e0dddd 70 /*********************************************************************/
hudakz 4:38403b42718b 71 /** Copy constructor.
hudakz 4:38403b42718b 72 */
hudakz 4:38403b42718b 73 CANMessage(const CANMessage& canMessage) {
hudakz 4:38403b42718b 74 len = canMessage.len;
hudakz 4:38403b42718b 75 type = canMessage.type;
hudakz 4:38403b42718b 76 format = canMessage.format;
hudakz 4:38403b42718b 77 id = canMessage.id;
hudakz 4:38403b42718b 78 memcpy(data, canMessage.data, canMessage.len);
hudakz 4:38403b42718b 79 }
hudakz 4:38403b42718b 80
hudakz 0:e29bc8e0dddd 81 /** Clears CAN message content
hudakz 0:e29bc8e0dddd 82 */
hudakz 0:e29bc8e0dddd 83 void clear(void) {
hudakz 0:e29bc8e0dddd 84 len = 0;
hudakz 0:e29bc8e0dddd 85 type = CANData;
hudakz 0:e29bc8e0dddd 86 format = CANStandard;
hudakz 0:e29bc8e0dddd 87 id = 0;
hudakz 0:e29bc8e0dddd 88 memset(data, 0, 8);
hudakz 0:e29bc8e0dddd 89 };
hudakz 0:e29bc8e0dddd 90
hudakz 0:e29bc8e0dddd 91 /** Inserter operator: Appends data (value) to CAN message
hudakz 0:e29bc8e0dddd 92 */
hudakz 0:e29bc8e0dddd 93 template<class T>
hudakz 0:e29bc8e0dddd 94 CANMessage &operator<<(const T val) {
hudakz 0:e29bc8e0dddd 95 if(len + sizeof(T) <= 8) {
hudakz 0:e29bc8e0dddd 96 *reinterpret_cast < T * > (&data[len]) = val;
hudakz 0:e29bc8e0dddd 97 len += sizeof(T);
hudakz 0:e29bc8e0dddd 98 }
hudakz 0:e29bc8e0dddd 99 #if DEBUG
hudakz 0:e29bc8e0dddd 100 else {
hudakz 25:353237492903 101 printf("Error: Cannot append data. Exceeding CAN data length!\r\n");
hudakz 0:e29bc8e0dddd 102 }
hudakz 0:e29bc8e0dddd 103 #endif
hudakz 0:e29bc8e0dddd 104 return *this;
hudakz 0:e29bc8e0dddd 105 }
hudakz 0:e29bc8e0dddd 106
hudakz 0:e29bc8e0dddd 107 /** Extractor operator: Extracts data (value) from CAN message
hudakz 0:e29bc8e0dddd 108 */
hudakz 0:e29bc8e0dddd 109 template<class T>
hudakz 0:e29bc8e0dddd 110 CANMessage &operator>>(T& val) {
hudakz 0:e29bc8e0dddd 111 if(sizeof(T) <= len) {
hudakz 0:e29bc8e0dddd 112 val = *reinterpret_cast < T * > (&data[0]);
hudakz 0:e29bc8e0dddd 113 len -= sizeof(T);
hudakz 0:e29bc8e0dddd 114 memcpy(data, data + sizeof(T), len);
hudakz 0:e29bc8e0dddd 115 }
hudakz 0:e29bc8e0dddd 116 #if DEBUG
hudakz 0:e29bc8e0dddd 117 else {
hudakz 25:353237492903 118 printf("Error: Cannot extract data. Exceeding CAN data length!\r\n");
hudakz 0:e29bc8e0dddd 119 }
hudakz 0:e29bc8e0dddd 120 #endif
hudakz 0:e29bc8e0dddd 121 return *this;
hudakz 0:e29bc8e0dddd 122 }
hudakz 0:e29bc8e0dddd 123
hudakz 0:e29bc8e0dddd 124 };
hudakz 0:e29bc8e0dddd 125
hudakz 0:e29bc8e0dddd 126 /** A can bus client, used for communicating with can devices
hudakz 0:e29bc8e0dddd 127 */
hudakz 0:e29bc8e0dddd 128 class CAN
hudakz 0:e29bc8e0dddd 129 {
hudakz 0:e29bc8e0dddd 130
hudakz 0:e29bc8e0dddd 131 public:
hudakz 0:e29bc8e0dddd 132 /** Creates an CAN interface connected to specific pins.
hudakz 0:e29bc8e0dddd 133 *
hudakz 0:e29bc8e0dddd 134 * @param rd read from transmitter
hudakz 0:e29bc8e0dddd 135 * @param td transmit to transmitter
hudakz 0:e29bc8e0dddd 136 *
hudakz 0:e29bc8e0dddd 137 * Example:
hudakz 0:e29bc8e0dddd 138 * @code
hudakz 0:e29bc8e0dddd 139 * #include "mbed.h"
hudakz 0:e29bc8e0dddd 140 * #include "CAN.h"
hudakz 0:e29bc8e0dddd 141 *
hudakz 0:e29bc8e0dddd 142 * Ticker ticker;
hudakz 0:e29bc8e0dddd 143 * DigitalOut led1(LED1);
hudakz 0:e29bc8e0dddd 144 * CAN can(PA_11, PA_12);
hudakz 0:e29bc8e0dddd 145 *
hudakz 0:e29bc8e0dddd 146 * char counter = 0;
hudakz 0:e29bc8e0dddd 147 *
hudakz 0:e29bc8e0dddd 148 * void send() {
hudakz 0:e29bc8e0dddd 149 * if(can.write(CANMessage(1337, &counter, 1))) {
hudakz 0:e29bc8e0dddd 150 * printf("Message sent: %d\n", counter);
hudakz 0:e29bc8e0dddd 151 * counter++;
hudakz 0:e29bc8e0dddd 152 * }
hudakz 0:e29bc8e0dddd 153 * led1 = !led1;
hudakz 0:e29bc8e0dddd 154 * }
hudakz 0:e29bc8e0dddd 155 *
hudakz 0:e29bc8e0dddd 156 * int main() {
hudakz 0:e29bc8e0dddd 157 * ticker.attach(&send, 1);
hudakz 0:e29bc8e0dddd 158 * CANMessage msg;
hudakz 0:e29bc8e0dddd 159 * while(1) {
hudakz 0:e29bc8e0dddd 160 * if(can.read(msg)) {
hudakz 0:e29bc8e0dddd 161 * printf("Message received: %d\n\n", msg.data[0]);
hudakz 0:e29bc8e0dddd 162 * led1 = !led1;
hudakz 0:e29bc8e0dddd 163 * }
hudakz 0:e29bc8e0dddd 164 * wait(0.2);
hudakz 0:e29bc8e0dddd 165 * }
hudakz 0:e29bc8e0dddd 166 * }
hudakz 0:e29bc8e0dddd 167 * @endcode
hudakz 0:e29bc8e0dddd 168 */
hudakz 6:c5a40d5fd9f1 169
hudakz 6:c5a40d5fd9f1 170 /** Constructor
hudakz 6:c5a40d5fd9f1 171 *
hudakz 6:c5a40d5fd9f1 172 * @param rd CAN receiver pin name
hudakz 6:c5a40d5fd9f1 173 * @param td CAN transmitter pin name
hudakz 6:c5a40d5fd9f1 174 * @param abom Automatic recovery from bus-off state (default value set to enabled)
hudakz 6:c5a40d5fd9f1 175 *
hudakz 6:c5a40d5fd9f1 176 */
hudakz 6:c5a40d5fd9f1 177 CAN(PinName rd, PinName td, FunctionalState abom = ENABLE);
hudakz 6:c5a40d5fd9f1 178
hudakz 0:e29bc8e0dddd 179 virtual ~CAN();
hudakz 0:e29bc8e0dddd 180
hudakz 0:e29bc8e0dddd 181 /** Set the frequency of the CAN interface
hudakz 0:e29bc8e0dddd 182 *
hudakz 0:e29bc8e0dddd 183 * @param hz The bus frequency in hertz
hudakz 0:e29bc8e0dddd 184 *
hudakz 0:e29bc8e0dddd 185 * @returns
hudakz 0:e29bc8e0dddd 186 * 1 if successful,
hudakz 0:e29bc8e0dddd 187 * 0 otherwise
hudakz 0:e29bc8e0dddd 188 */
hudakz 0:e29bc8e0dddd 189 int frequency(int hz);
hudakz 0:e29bc8e0dddd 190
hudakz 0:e29bc8e0dddd 191 /** Write a CANMessage to the bus.
hudakz 0:e29bc8e0dddd 192 *
hudakz 0:e29bc8e0dddd 193 * @param msg The CANMessage to write.
hudakz 0:e29bc8e0dddd 194 *
hudakz 0:e29bc8e0dddd 195 * @returns
hudakz 0:e29bc8e0dddd 196 * 0 if write failed,
hudakz 0:e29bc8e0dddd 197 * 1 if write was successful
hudakz 0:e29bc8e0dddd 198 */
hudakz 0:e29bc8e0dddd 199 int write(CANMessage msg);
hudakz 0:e29bc8e0dddd 200
hudakz 0:e29bc8e0dddd 201 /** Read a CANMessage from the bus.
hudakz 0:e29bc8e0dddd 202 *
hudakz 0:e29bc8e0dddd 203 * @param msg A CANMessage to read to.
hudakz 0:e29bc8e0dddd 204 * @param handle message filter handle (0 for any message)
hudakz 0:e29bc8e0dddd 205 *
hudakz 0:e29bc8e0dddd 206 * @returns
hudakz 0:e29bc8e0dddd 207 * 0 if no message arrived,
hudakz 0:e29bc8e0dddd 208 * 1 if message arrived
hudakz 0:e29bc8e0dddd 209 */
hudakz 0:e29bc8e0dddd 210 int read(CANMessage &msg, int handle = 0);
hudakz 0:e29bc8e0dddd 211
hudakz 0:e29bc8e0dddd 212 /** Reset CAN interface.
hudakz 0:e29bc8e0dddd 213 *
hudakz 0:e29bc8e0dddd 214 * To use after error overflow.
hudakz 0:e29bc8e0dddd 215 */
hudakz 0:e29bc8e0dddd 216 void reset();
hudakz 0:e29bc8e0dddd 217
hudakz 0:e29bc8e0dddd 218 /** Puts or removes the CAN interface into silent monitoring mode
hudakz 0:e29bc8e0dddd 219 *
hudakz 0:e29bc8e0dddd 220 * @param silent boolean indicating whether to go into silent mode or not
hudakz 0:e29bc8e0dddd 221 */
hudakz 0:e29bc8e0dddd 222 void monitor(bool silent);
hudakz 0:e29bc8e0dddd 223
hudakz 0:e29bc8e0dddd 224 enum Mode {
hudakz 0:e29bc8e0dddd 225 Reset = 0,
hudakz 0:e29bc8e0dddd 226 Normal,
hudakz 0:e29bc8e0dddd 227 Silent,
hudakz 0:e29bc8e0dddd 228 LocalTest,
hudakz 0:e29bc8e0dddd 229 GlobalTest,
hudakz 0:e29bc8e0dddd 230 SilentTest
hudakz 0:e29bc8e0dddd 231 };
hudakz 0:e29bc8e0dddd 232
hudakz 0:e29bc8e0dddd 233 /** Change CAN operation to the specified mode
hudakz 0:e29bc8e0dddd 234 *
hudakz 0:e29bc8e0dddd 235 * @param mode The new operation mode (CAN::Normal, CAN::Silent, CAN::LocalTest, CAN::GlobalTest, CAN::SilentTest)
hudakz 0:e29bc8e0dddd 236 *
hudakz 0:e29bc8e0dddd 237 * @returns
hudakz 0:e29bc8e0dddd 238 * 0 if mode change failed or unsupported,
hudakz 0:e29bc8e0dddd 239 * 1 if mode change was successful
hudakz 0:e29bc8e0dddd 240 */
hudakz 0:e29bc8e0dddd 241 int mode(Mode mode);
hudakz 0:e29bc8e0dddd 242
hudakz 0:e29bc8e0dddd 243 /** Filter out incomming messages
hudakz 0:e29bc8e0dddd 244 *
hudakz 0:e29bc8e0dddd 245 * @param id the id to filter on
hudakz 0:e29bc8e0dddd 246 * @param mask the mask applied to the id
hudakz 0:e29bc8e0dddd 247 * @param format format to filter on (Default CANAny)
hudakz 0:e29bc8e0dddd 248 * @param handle message filter handle (Optional)
hudakz 0:e29bc8e0dddd 249 *
hudakz 20:bcd8161f8f6c 250 * @retval 0 - successful
hudakz 8:5c90d6b9a382 251 * 1 - error
hudakz 8:5c90d6b9a382 252 * 2 - busy
hudakz 9:e9224f2c6d37 253 * 3 - time out
hudakz 0:e29bc8e0dddd 254 */
hudakz 0:e29bc8e0dddd 255 int filter(unsigned int id, unsigned int mask, CANFormat format = CANAny, int handle = 0);
hudakz 0:e29bc8e0dddd 256
hudakz 0:e29bc8e0dddd 257 /** Returns number of read errors to detect read overflow errors.
hudakz 0:e29bc8e0dddd 258 */
hudakz 0:e29bc8e0dddd 259 unsigned char rderror();
hudakz 0:e29bc8e0dddd 260
hudakz 0:e29bc8e0dddd 261 /** Returns number of write errors to detect write overflow errors.
hudakz 0:e29bc8e0dddd 262 */
hudakz 0:e29bc8e0dddd 263 unsigned char tderror();
hudakz 0:e29bc8e0dddd 264
hudakz 0:e29bc8e0dddd 265 enum IrqType {
hudakz 0:e29bc8e0dddd 266 RxIrq = 0,
hudakz 0:e29bc8e0dddd 267 TxIrq,
hudakz 0:e29bc8e0dddd 268 EwIrq,
hudakz 0:e29bc8e0dddd 269 DoIrq,
hudakz 0:e29bc8e0dddd 270 WuIrq,
hudakz 0:e29bc8e0dddd 271 EpIrq,
hudakz 0:e29bc8e0dddd 272 AlIrq,
hudakz 0:e29bc8e0dddd 273 BeIrq,
hudakz 0:e29bc8e0dddd 274 IdIrq
hudakz 0:e29bc8e0dddd 275 };
hudakz 0:e29bc8e0dddd 276
hudakz 0:e29bc8e0dddd 277 /** Attach a function to call whenever a CAN frame received interrupt is
hudakz 0:e29bc8e0dddd 278 * generated.
hudakz 0:e29bc8e0dddd 279 *
hudakz 25:353237492903 280 * @param func A pointer to a void function, or 0 to set as none
hudakz 25:353237492903 281 * @param event Which CAN interrupt to attach the member function to (only CAN::RxIrq for message received is supported)
hudakz 0:e29bc8e0dddd 282 */
hudakz 25:353237492903 283 void attach(mbed::Callback<void()> func, IrqType type=RxIrq);
hudakz 0:e29bc8e0dddd 284
hudakz 25:353237492903 285 /** Attach a member function to call whenever a CAN frame received interrupt
hudakz 25:353237492903 286 * is generated.
hudakz 25:353237492903 287 *
hudakz 25:353237492903 288 * @param obj pointer to the object to call the member function on
hudakz 25:353237492903 289 * @param method pointer to the member function to be called
hudakz 25:353237492903 290 * @param event Which CAN interrupt to attach the member function to (only CAN::RxIrq for message received is supported)
hudakz 25:353237492903 291 */
hudakz 0:e29bc8e0dddd 292 template<typename T>
hudakz 25:353237492903 293 void attach(T* obj, void (T::*method)(), IrqType type=RxIrq) {
hudakz 25:353237492903 294 // Underlying call thread safe
hudakz 25:353237492903 295 attach(Callback<void()>(obj, method), type);
hudakz 0:e29bc8e0dddd 296 }
hudakz 0:e29bc8e0dddd 297
hudakz 25:353237492903 298 /** Attach a member function to call whenever a CAN frame received interrupt
hudakz 25:353237492903 299 * is generated.
hudakz 25:353237492903 300 *
hudakz 25:353237492903 301 * @param obj pointer to the object to call the member function on
hudakz 25:353237492903 302 * @param method pointer to the member function to be called
hudakz 25:353237492903 303 * @param event Which CAN interrupt to attach the member function to (only CAN::RxIrq for message received is supported)
hudakz 25:353237492903 304 */
hudakz 25:353237492903 305 template<typename T>
hudakz 25:353237492903 306 void attach(T* obj, void (*method)(T*), IrqType type=RxIrq) {
hudakz 25:353237492903 307 // Underlying call thread safe
hudakz 25:353237492903 308 attach(Callback<void()>(obj, method), type);
hudakz 25:353237492903 309 }
hudakz 25:353237492903 310
hudakz 25:353237492903 311
hudakz 0:e29bc8e0dddd 312 static void _irq_handler(uint32_t id, CanIrqType type);
hudakz 0:e29bc8e0dddd 313
hudakz 0:e29bc8e0dddd 314 protected:
hudakz 25:353237492903 315 virtual void lock();
hudakz 25:353237492903 316 virtual void unlock();
hudakz 25:353237492903 317 mbed::Callback<void()> _irq[9];
hudakz 25:353237492903 318 PlatformMutex _mutex;
hudakz 0:e29bc8e0dddd 319 };
hudakz 0:e29bc8e0dddd 320
hudakz 23:ea766d08c9db 321 } // namespace CANnucleo
hudakz 0:e29bc8e0dddd 322
hudakz 23:ea766d08c9db 323 #endif // CAN_NUCLEO_H
hudakz 0:e29bc8e0dddd 324
hudakz 0:e29bc8e0dddd 325
hudakz 6:c5a40d5fd9f1 326
hudakz 8:5c90d6b9a382 327
hudakz 11:439f3a34c42e 328
hudakz 14:0344705e6fb8 329
hudakz 24:c5d348e65e24 330