mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Superseded

This library was superseded by mbed-dev - https://os.mbed.com/users/mbed_official/code/mbed-dev/.

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Committer:
mbed_official
Date:
Tue Dec 16 08:15:08 2014 +0000
Revision:
440:8a0b45cd594f
Parent:
227:7bd0639b8911
Child:
530:2939f5396008
Synchronized with git revision 67fbbf0b635d0c0d93fbe433306c537c2ad206aa

Full URL: https://github.com/mbedmicro/mbed/commit/67fbbf0b635d0c0d93fbe433306c537c2ad206aa/

Targets: nrf51 - updating app_timer.c from Norid'c SDKv7.1.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
emilmont 10:3bc89ef62ce7 1 /* mbed Microcontroller Library
emilmont 10:3bc89ef62ce7 2 * Copyright (c) 2006-2013 ARM Limited
emilmont 10:3bc89ef62ce7 3 *
emilmont 10:3bc89ef62ce7 4 * Licensed under the Apache License, Version 2.0 (the "License");
emilmont 10:3bc89ef62ce7 5 * you may not use this file except in compliance with the License.
emilmont 10:3bc89ef62ce7 6 * You may obtain a copy of the License at
emilmont 10:3bc89ef62ce7 7 *
emilmont 10:3bc89ef62ce7 8 * http://www.apache.org/licenses/LICENSE-2.0
emilmont 10:3bc89ef62ce7 9 *
emilmont 10:3bc89ef62ce7 10 * Unless required by applicable law or agreed to in writing, software
emilmont 10:3bc89ef62ce7 11 * distributed under the License is distributed on an "AS IS" BASIS,
emilmont 10:3bc89ef62ce7 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
emilmont 10:3bc89ef62ce7 13 * See the License for the specific language governing permissions and
emilmont 10:3bc89ef62ce7 14 * limitations under the License.
emilmont 10:3bc89ef62ce7 15 */
mbed_official 227:7bd0639b8911 16 #include "mbed_assert.h"
emilmont 10:3bc89ef62ce7 17 #include "can_api.h"
emilmont 10:3bc89ef62ce7 18
emilmont 10:3bc89ef62ce7 19 #include "cmsis.h"
emilmont 10:3bc89ef62ce7 20 #include "pinmap.h"
emilmont 10:3bc89ef62ce7 21
emilmont 10:3bc89ef62ce7 22 #include <math.h>
emilmont 10:3bc89ef62ce7 23 #include <string.h>
emilmont 10:3bc89ef62ce7 24
bogdanm 15:4892fe388435 25 #define CAN_NUM 2
bogdanm 15:4892fe388435 26
emilmont 10:3bc89ef62ce7 27 /* Acceptance filter mode in AFMR register */
emilmont 10:3bc89ef62ce7 28 #define ACCF_OFF 0x01
emilmont 10:3bc89ef62ce7 29 #define ACCF_BYPASS 0x02
emilmont 10:3bc89ef62ce7 30 #define ACCF_ON 0x00
emilmont 10:3bc89ef62ce7 31 #define ACCF_FULLCAN 0x04
emilmont 10:3bc89ef62ce7 32
emilmont 10:3bc89ef62ce7 33 /* There are several bit timing calculators on the internet.
emilmont 10:3bc89ef62ce7 34 http://www.port.de/engl/canprod/sv_req_form.html
emilmont 10:3bc89ef62ce7 35 http://www.kvaser.com/can/index.htm
emilmont 10:3bc89ef62ce7 36 */
emilmont 10:3bc89ef62ce7 37
emilmont 10:3bc89ef62ce7 38 static const PinMap PinMap_CAN_RD[] = {
emilmont 10:3bc89ef62ce7 39 {P0_0 , CAN_1, 1},
emilmont 10:3bc89ef62ce7 40 {P0_4 , CAN_2, 2},
emilmont 10:3bc89ef62ce7 41 {P0_21, CAN_1, 3},
emilmont 10:3bc89ef62ce7 42 {P2_7 , CAN_2, 1},
emilmont 10:3bc89ef62ce7 43 {NC , NC , 0}
emilmont 10:3bc89ef62ce7 44 };
emilmont 10:3bc89ef62ce7 45
emilmont 10:3bc89ef62ce7 46 static const PinMap PinMap_CAN_TD[] = {
emilmont 10:3bc89ef62ce7 47 {P0_1 , CAN_1, 1},
emilmont 10:3bc89ef62ce7 48 {P0_5 , CAN_2, 2},
emilmont 10:3bc89ef62ce7 49 {P0_22, CAN_1, 3},
emilmont 10:3bc89ef62ce7 50 {P2_8 , CAN_2, 1},
emilmont 10:3bc89ef62ce7 51 {NC , NC , 0}
emilmont 10:3bc89ef62ce7 52 };
emilmont 10:3bc89ef62ce7 53
emilmont 10:3bc89ef62ce7 54 // Type definition to hold a CAN message
emilmont 10:3bc89ef62ce7 55 struct CANMsg {
emilmont 10:3bc89ef62ce7 56 unsigned int reserved1 : 16;
emilmont 10:3bc89ef62ce7 57 unsigned int dlc : 4; // Bits 16..19: DLC - Data Length Counter
emilmont 10:3bc89ef62ce7 58 unsigned int reserved0 : 10;
emilmont 10:3bc89ef62ce7 59 unsigned int rtr : 1; // Bit 30: Set if this is a RTR message
emilmont 10:3bc89ef62ce7 60 unsigned int type : 1; // Bit 31: Set if this is a 29-bit ID message
emilmont 10:3bc89ef62ce7 61 unsigned int id; // CAN Message ID (11-bit or 29-bit)
emilmont 10:3bc89ef62ce7 62 unsigned char data[8]; // CAN Message Data Bytes 0-7
emilmont 10:3bc89ef62ce7 63 };
emilmont 10:3bc89ef62ce7 64 typedef struct CANMsg CANMsg;
emilmont 10:3bc89ef62ce7 65
bogdanm 15:4892fe388435 66 static uint32_t can_irq_ids[CAN_NUM] = {0};
bogdanm 15:4892fe388435 67 static can_irq_handler irq_handler;
bogdanm 15:4892fe388435 68
emilmont 10:3bc89ef62ce7 69 static uint32_t can_disable(can_t *obj) {
emilmont 10:3bc89ef62ce7 70 uint32_t sm = obj->dev->MOD;
emilmont 10:3bc89ef62ce7 71 obj->dev->MOD |= 1;
emilmont 10:3bc89ef62ce7 72 return sm;
emilmont 10:3bc89ef62ce7 73 }
emilmont 10:3bc89ef62ce7 74
emilmont 10:3bc89ef62ce7 75 static inline void can_enable(can_t *obj) {
emilmont 10:3bc89ef62ce7 76 if (obj->dev->MOD & 1) {
emilmont 10:3bc89ef62ce7 77 obj->dev->MOD &= ~(1);
emilmont 10:3bc89ef62ce7 78 }
emilmont 10:3bc89ef62ce7 79 }
emilmont 10:3bc89ef62ce7 80
mbed_official 41:e8b66477f5bf 81 int can_mode(can_t *obj, CanMode mode) {
mbed_official 41:e8b66477f5bf 82 return 0; // not implemented
mbed_official 41:e8b66477f5bf 83 }
mbed_official 41:e8b66477f5bf 84
mbed_official 41:e8b66477f5bf 85 int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle) {
bogdanm 15:4892fe388435 86 return 0; // not implemented
bogdanm 15:4892fe388435 87 }
bogdanm 15:4892fe388435 88
bogdanm 15:4892fe388435 89 static inline void can_irq(uint32_t icr, uint32_t index) {
bogdanm 15:4892fe388435 90 uint32_t i;
bogdanm 15:4892fe388435 91
bogdanm 15:4892fe388435 92 for(i = 0; i < 8; i++)
bogdanm 15:4892fe388435 93 {
bogdanm 15:4892fe388435 94 if((can_irq_ids[index] != 0) && (icr & (1 << i)))
bogdanm 15:4892fe388435 95 {
bogdanm 15:4892fe388435 96 switch (i) {
bogdanm 15:4892fe388435 97 case 0: irq_handler(can_irq_ids[index], IRQ_RX); break;
bogdanm 15:4892fe388435 98 case 1: irq_handler(can_irq_ids[index], IRQ_TX); break;
bogdanm 15:4892fe388435 99 case 2: irq_handler(can_irq_ids[index], IRQ_ERROR); break;
bogdanm 15:4892fe388435 100 case 3: irq_handler(can_irq_ids[index], IRQ_OVERRUN); break;
bogdanm 15:4892fe388435 101 case 4: irq_handler(can_irq_ids[index], IRQ_WAKEUP); break;
bogdanm 15:4892fe388435 102 case 5: irq_handler(can_irq_ids[index], IRQ_PASSIVE); break;
bogdanm 15:4892fe388435 103 case 6: irq_handler(can_irq_ids[index], IRQ_ARB); break;
bogdanm 15:4892fe388435 104 case 7: irq_handler(can_irq_ids[index], IRQ_BUS); break;
bogdanm 15:4892fe388435 105 case 8: irq_handler(can_irq_ids[index], IRQ_READY); break;
bogdanm 15:4892fe388435 106 }
bogdanm 15:4892fe388435 107 }
bogdanm 15:4892fe388435 108 }
bogdanm 15:4892fe388435 109 }
bogdanm 15:4892fe388435 110
bogdanm 15:4892fe388435 111 // Have to check that the CAN block is active before reading the Interrupt
bogdanm 15:4892fe388435 112 // Control Register, or the mbed hangs
bogdanm 15:4892fe388435 113 void can_irq_n() {
bogdanm 15:4892fe388435 114 uint32_t icr;
bogdanm 15:4892fe388435 115
bogdanm 15:4892fe388435 116 if(LPC_SC->PCONP & (1 << 13)) {
bogdanm 15:4892fe388435 117 icr = LPC_CAN1->ICR & 0x1FF;
bogdanm 15:4892fe388435 118 can_irq(icr, 0);
bogdanm 15:4892fe388435 119 }
bogdanm 15:4892fe388435 120
bogdanm 15:4892fe388435 121 if(LPC_SC->PCONP & (1 << 14)) {
bogdanm 15:4892fe388435 122 icr = LPC_CAN2->ICR & 0x1FF;
bogdanm 15:4892fe388435 123 can_irq(icr, 1);
bogdanm 15:4892fe388435 124 }
bogdanm 15:4892fe388435 125 }
bogdanm 15:4892fe388435 126
bogdanm 15:4892fe388435 127 // Register CAN object's irq handler
bogdanm 15:4892fe388435 128 void can_irq_init(can_t *obj, can_irq_handler handler, uint32_t id) {
bogdanm 15:4892fe388435 129 irq_handler = handler;
bogdanm 15:4892fe388435 130 can_irq_ids[obj->index] = id;
bogdanm 15:4892fe388435 131 }
bogdanm 15:4892fe388435 132
bogdanm 15:4892fe388435 133 // Unregister CAN object's irq handler
bogdanm 15:4892fe388435 134 void can_irq_free(can_t *obj) {
bogdanm 15:4892fe388435 135 obj->dev->IER &= ~(1);
bogdanm 15:4892fe388435 136 can_irq_ids[obj->index] = 0;
bogdanm 15:4892fe388435 137
bogdanm 15:4892fe388435 138 if ((can_irq_ids[0] == 0) && (can_irq_ids[1] == 0)) {
bogdanm 15:4892fe388435 139 NVIC_DisableIRQ(CAN_IRQn);
bogdanm 15:4892fe388435 140 }
bogdanm 15:4892fe388435 141 }
bogdanm 15:4892fe388435 142
bogdanm 15:4892fe388435 143 // Clear or set a irq
bogdanm 15:4892fe388435 144 void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable) {
bogdanm 15:4892fe388435 145 uint32_t ier;
bogdanm 15:4892fe388435 146
bogdanm 15:4892fe388435 147 switch (type) {
bogdanm 15:4892fe388435 148 case IRQ_RX: ier = (1 << 0); break;
bogdanm 15:4892fe388435 149 case IRQ_TX: ier = (1 << 1); break;
bogdanm 15:4892fe388435 150 case IRQ_ERROR: ier = (1 << 2); break;
bogdanm 15:4892fe388435 151 case IRQ_OVERRUN: ier = (1 << 3); break;
bogdanm 15:4892fe388435 152 case IRQ_WAKEUP: ier = (1 << 4); break;
bogdanm 15:4892fe388435 153 case IRQ_PASSIVE: ier = (1 << 5); break;
bogdanm 15:4892fe388435 154 case IRQ_ARB: ier = (1 << 6); break;
bogdanm 15:4892fe388435 155 case IRQ_BUS: ier = (1 << 7); break;
bogdanm 15:4892fe388435 156 case IRQ_READY: ier = (1 << 8); break;
bogdanm 15:4892fe388435 157 default: return;
bogdanm 15:4892fe388435 158 }
bogdanm 15:4892fe388435 159
bogdanm 15:4892fe388435 160 obj->dev->MOD |= 1;
bogdanm 15:4892fe388435 161 if(enable == 0) {
bogdanm 15:4892fe388435 162 obj->dev->IER &= ~ier;
bogdanm 15:4892fe388435 163 }
bogdanm 15:4892fe388435 164 else {
bogdanm 15:4892fe388435 165 obj->dev->IER |= ier;
bogdanm 15:4892fe388435 166 }
bogdanm 15:4892fe388435 167 obj->dev->MOD &= ~(1);
bogdanm 15:4892fe388435 168
bogdanm 15:4892fe388435 169 // Enable NVIC if at least 1 interrupt is active
bogdanm 20:4263a77256ae 170 if(((LPC_SC->PCONP & (1 << 13)) && LPC_CAN1->IER) || ((LPC_SC->PCONP & (1 << 14)) && LPC_CAN2->IER)) {
bogdanm 15:4892fe388435 171 NVIC_SetVector(CAN_IRQn, (uint32_t) &can_irq_n);
bogdanm 15:4892fe388435 172 NVIC_EnableIRQ(CAN_IRQn);
bogdanm 15:4892fe388435 173 }
bogdanm 15:4892fe388435 174 else {
bogdanm 15:4892fe388435 175 NVIC_DisableIRQ(CAN_IRQn);
bogdanm 15:4892fe388435 176 }
bogdanm 15:4892fe388435 177 }
bogdanm 15:4892fe388435 178
emilmont 10:3bc89ef62ce7 179 static int can_pclk(can_t *obj) {
emilmont 10:3bc89ef62ce7 180 int value = 0;
emilmont 10:3bc89ef62ce7 181 switch ((int)obj->dev) {
emilmont 10:3bc89ef62ce7 182 case CAN_1: value = (LPC_SC->PCLKSEL0 & (0x3 << 26)) >> 26; break;
emilmont 10:3bc89ef62ce7 183 case CAN_2: value = (LPC_SC->PCLKSEL0 & (0x3 << 28)) >> 28; break;
emilmont 10:3bc89ef62ce7 184 }
emilmont 10:3bc89ef62ce7 185
emilmont 10:3bc89ef62ce7 186 switch (value) {
emilmont 10:3bc89ef62ce7 187 case 1: return 1;
emilmont 10:3bc89ef62ce7 188 case 2: return 2;
emilmont 10:3bc89ef62ce7 189 case 3: return 6;
emilmont 10:3bc89ef62ce7 190 default: return 4;
emilmont 10:3bc89ef62ce7 191 }
emilmont 10:3bc89ef62ce7 192 }
emilmont 10:3bc89ef62ce7 193
emilmont 10:3bc89ef62ce7 194 // This table has the sampling points as close to 75% as possible. The first
emilmont 10:3bc89ef62ce7 195 // value is TSEG1, the second TSEG2.
emilmont 10:3bc89ef62ce7 196 static const int timing_pts[23][2] = {
emilmont 10:3bc89ef62ce7 197 {0x0, 0x0}, // 2, 50%
emilmont 10:3bc89ef62ce7 198 {0x1, 0x0}, // 3, 67%
emilmont 10:3bc89ef62ce7 199 {0x2, 0x0}, // 4, 75%
emilmont 10:3bc89ef62ce7 200 {0x3, 0x0}, // 5, 80%
emilmont 10:3bc89ef62ce7 201 {0x3, 0x1}, // 6, 67%
emilmont 10:3bc89ef62ce7 202 {0x4, 0x1}, // 7, 71%
emilmont 10:3bc89ef62ce7 203 {0x5, 0x1}, // 8, 75%
emilmont 10:3bc89ef62ce7 204 {0x6, 0x1}, // 9, 78%
emilmont 10:3bc89ef62ce7 205 {0x6, 0x2}, // 10, 70%
emilmont 10:3bc89ef62ce7 206 {0x7, 0x2}, // 11, 73%
emilmont 10:3bc89ef62ce7 207 {0x8, 0x2}, // 12, 75%
emilmont 10:3bc89ef62ce7 208 {0x9, 0x2}, // 13, 77%
emilmont 10:3bc89ef62ce7 209 {0x9, 0x3}, // 14, 71%
emilmont 10:3bc89ef62ce7 210 {0xA, 0x3}, // 15, 73%
emilmont 10:3bc89ef62ce7 211 {0xB, 0x3}, // 16, 75%
emilmont 10:3bc89ef62ce7 212 {0xC, 0x3}, // 17, 76%
emilmont 10:3bc89ef62ce7 213 {0xD, 0x3}, // 18, 78%
emilmont 10:3bc89ef62ce7 214 {0xD, 0x4}, // 19, 74%
emilmont 10:3bc89ef62ce7 215 {0xE, 0x4}, // 20, 75%
emilmont 10:3bc89ef62ce7 216 {0xF, 0x4}, // 21, 76%
emilmont 10:3bc89ef62ce7 217 {0xF, 0x5}, // 22, 73%
emilmont 10:3bc89ef62ce7 218 {0xF, 0x6}, // 23, 70%
emilmont 10:3bc89ef62ce7 219 {0xF, 0x7}, // 24, 67%
emilmont 10:3bc89ef62ce7 220 };
emilmont 10:3bc89ef62ce7 221
emilmont 10:3bc89ef62ce7 222 static unsigned int can_speed(unsigned int sclk, unsigned int pclk, unsigned int cclk, unsigned char psjw) {
emilmont 10:3bc89ef62ce7 223 uint32_t btr;
emilmont 10:3bc89ef62ce7 224 uint16_t brp = 0;
emilmont 10:3bc89ef62ce7 225 uint32_t calcbit;
emilmont 10:3bc89ef62ce7 226 uint32_t bitwidth;
emilmont 10:3bc89ef62ce7 227 int hit = 0;
emilmont 10:3bc89ef62ce7 228 int bits;
emilmont 10:3bc89ef62ce7 229
emilmont 10:3bc89ef62ce7 230 bitwidth = sclk / (pclk * cclk);
emilmont 10:3bc89ef62ce7 231
emilmont 10:3bc89ef62ce7 232 brp = bitwidth / 0x18;
emilmont 10:3bc89ef62ce7 233 while ((!hit) && (brp < bitwidth / 4)) {
emilmont 10:3bc89ef62ce7 234 brp++;
emilmont 10:3bc89ef62ce7 235 for (bits = 22; bits > 0; bits--) {
emilmont 10:3bc89ef62ce7 236 calcbit = (bits + 3) * (brp + 1);
emilmont 10:3bc89ef62ce7 237 if (calcbit == bitwidth) {
emilmont 10:3bc89ef62ce7 238 hit = 1;
emilmont 10:3bc89ef62ce7 239 break;
emilmont 10:3bc89ef62ce7 240 }
emilmont 10:3bc89ef62ce7 241 }
emilmont 10:3bc89ef62ce7 242 }
emilmont 10:3bc89ef62ce7 243
emilmont 10:3bc89ef62ce7 244 if (hit) {
emilmont 10:3bc89ef62ce7 245 btr = ((timing_pts[bits][1] << 20) & 0x00700000)
emilmont 10:3bc89ef62ce7 246 | ((timing_pts[bits][0] << 16) & 0x000F0000)
emilmont 10:3bc89ef62ce7 247 | ((psjw << 14) & 0x0000C000)
emilmont 10:3bc89ef62ce7 248 | ((brp << 0) & 0x000003FF);
emilmont 10:3bc89ef62ce7 249 } else {
emilmont 10:3bc89ef62ce7 250 btr = 0xFFFFFFFF;
emilmont 10:3bc89ef62ce7 251 }
emilmont 10:3bc89ef62ce7 252
emilmont 10:3bc89ef62ce7 253 return btr;
emilmont 10:3bc89ef62ce7 254
emilmont 10:3bc89ef62ce7 255 }
emilmont 10:3bc89ef62ce7 256
emilmont 10:3bc89ef62ce7 257 void can_init(can_t *obj, PinName rd, PinName td) {
emilmont 10:3bc89ef62ce7 258 CANName can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD);
emilmont 10:3bc89ef62ce7 259 CANName can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TD);
emilmont 10:3bc89ef62ce7 260 obj->dev = (LPC_CAN_TypeDef *)pinmap_merge(can_rd, can_td);
mbed_official 227:7bd0639b8911 261 MBED_ASSERT((int)obj->dev != NC);
emilmont 10:3bc89ef62ce7 262
emilmont 10:3bc89ef62ce7 263 switch ((int)obj->dev) {
emilmont 10:3bc89ef62ce7 264 case CAN_1: LPC_SC->PCONP |= 1 << 13; break;
emilmont 10:3bc89ef62ce7 265 case CAN_2: LPC_SC->PCONP |= 1 << 14; break;
emilmont 10:3bc89ef62ce7 266 }
emilmont 10:3bc89ef62ce7 267
emilmont 10:3bc89ef62ce7 268 pinmap_pinout(rd, PinMap_CAN_RD);
emilmont 10:3bc89ef62ce7 269 pinmap_pinout(td, PinMap_CAN_TD);
bogdanm 15:4892fe388435 270
bogdanm 15:4892fe388435 271 switch ((int)obj->dev) {
bogdanm 15:4892fe388435 272 case CAN_1: obj->index = 0; break;
bogdanm 15:4892fe388435 273 case CAN_2: obj->index = 1; break;
bogdanm 15:4892fe388435 274 }
bogdanm 15:4892fe388435 275
emilmont 10:3bc89ef62ce7 276 can_reset(obj);
emilmont 10:3bc89ef62ce7 277 obj->dev->IER = 0; // Disable Interrupts
emilmont 10:3bc89ef62ce7 278 can_frequency(obj, 100000);
emilmont 10:3bc89ef62ce7 279
emilmont 10:3bc89ef62ce7 280 LPC_CANAF->AFMR = ACCF_BYPASS; // Bypass Filter
emilmont 10:3bc89ef62ce7 281 }
emilmont 10:3bc89ef62ce7 282
emilmont 10:3bc89ef62ce7 283 void can_free(can_t *obj) {
emilmont 10:3bc89ef62ce7 284 switch ((int)obj->dev) {
emilmont 10:3bc89ef62ce7 285 case CAN_1: LPC_SC->PCONP &= ~(1 << 13); break;
emilmont 10:3bc89ef62ce7 286 case CAN_2: LPC_SC->PCONP &= ~(1 << 14); break;
emilmont 10:3bc89ef62ce7 287 }
emilmont 10:3bc89ef62ce7 288 }
emilmont 10:3bc89ef62ce7 289
emilmont 10:3bc89ef62ce7 290 int can_frequency(can_t *obj, int f) {
emilmont 10:3bc89ef62ce7 291 int pclk = can_pclk(obj);
emilmont 10:3bc89ef62ce7 292
emilmont 10:3bc89ef62ce7 293 int btr = can_speed(SystemCoreClock, pclk, (unsigned int)f, 1);
emilmont 10:3bc89ef62ce7 294
emilmont 10:3bc89ef62ce7 295 if (btr > 0) {
emilmont 10:3bc89ef62ce7 296 uint32_t modmask = can_disable(obj);
emilmont 10:3bc89ef62ce7 297 obj->dev->BTR = btr;
emilmont 10:3bc89ef62ce7 298 obj->dev->MOD = modmask;
emilmont 10:3bc89ef62ce7 299 return 1;
emilmont 10:3bc89ef62ce7 300 } else {
emilmont 10:3bc89ef62ce7 301 return 0;
emilmont 10:3bc89ef62ce7 302 }
emilmont 10:3bc89ef62ce7 303 }
emilmont 10:3bc89ef62ce7 304
emilmont 10:3bc89ef62ce7 305 int can_write(can_t *obj, CAN_Message msg, int cc) {
emilmont 10:3bc89ef62ce7 306 unsigned int CANStatus;
emilmont 10:3bc89ef62ce7 307 CANMsg m;
emilmont 10:3bc89ef62ce7 308
emilmont 10:3bc89ef62ce7 309 can_enable(obj);
emilmont 10:3bc89ef62ce7 310
emilmont 10:3bc89ef62ce7 311 m.id = msg.id ;
emilmont 10:3bc89ef62ce7 312 m.dlc = msg.len & 0xF;
emilmont 10:3bc89ef62ce7 313 m.rtr = msg.type;
emilmont 10:3bc89ef62ce7 314 m.type = msg.format;
emilmont 10:3bc89ef62ce7 315 memcpy(m.data, msg.data, msg.len);
emilmont 10:3bc89ef62ce7 316 const unsigned int *buf = (const unsigned int *)&m;
emilmont 10:3bc89ef62ce7 317
emilmont 10:3bc89ef62ce7 318 CANStatus = obj->dev->SR;
emilmont 10:3bc89ef62ce7 319 if (CANStatus & 0x00000004) {
emilmont 10:3bc89ef62ce7 320 obj->dev->TFI1 = buf[0] & 0xC00F0000;
emilmont 10:3bc89ef62ce7 321 obj->dev->TID1 = buf[1];
emilmont 10:3bc89ef62ce7 322 obj->dev->TDA1 = buf[2];
emilmont 10:3bc89ef62ce7 323 obj->dev->TDB1 = buf[3];
emilmont 10:3bc89ef62ce7 324 if(cc) {
emilmont 10:3bc89ef62ce7 325 obj->dev->CMR = 0x30;
emilmont 10:3bc89ef62ce7 326 } else {
emilmont 10:3bc89ef62ce7 327 obj->dev->CMR = 0x21;
emilmont 10:3bc89ef62ce7 328 }
emilmont 10:3bc89ef62ce7 329 return 1;
emilmont 10:3bc89ef62ce7 330
emilmont 10:3bc89ef62ce7 331 } else if (CANStatus & 0x00000400) {
emilmont 10:3bc89ef62ce7 332 obj->dev->TFI2 = buf[0] & 0xC00F0000;
emilmont 10:3bc89ef62ce7 333 obj->dev->TID2 = buf[1];
emilmont 10:3bc89ef62ce7 334 obj->dev->TDA2 = buf[2];
emilmont 10:3bc89ef62ce7 335 obj->dev->TDB2 = buf[3];
emilmont 10:3bc89ef62ce7 336 if (cc) {
emilmont 10:3bc89ef62ce7 337 obj->dev->CMR = 0x50;
emilmont 10:3bc89ef62ce7 338 } else {
emilmont 10:3bc89ef62ce7 339 obj->dev->CMR = 0x41;
emilmont 10:3bc89ef62ce7 340 }
emilmont 10:3bc89ef62ce7 341 return 1;
emilmont 10:3bc89ef62ce7 342
emilmont 10:3bc89ef62ce7 343 } else if (CANStatus & 0x00040000) {
emilmont 10:3bc89ef62ce7 344 obj->dev->TFI3 = buf[0] & 0xC00F0000;
emilmont 10:3bc89ef62ce7 345 obj->dev->TID3 = buf[1];
emilmont 10:3bc89ef62ce7 346 obj->dev->TDA3 = buf[2];
emilmont 10:3bc89ef62ce7 347 obj->dev->TDB3 = buf[3];
emilmont 10:3bc89ef62ce7 348 if (cc) {
emilmont 10:3bc89ef62ce7 349 obj->dev->CMR = 0x90;
emilmont 10:3bc89ef62ce7 350 } else {
emilmont 10:3bc89ef62ce7 351 obj->dev->CMR = 0x81;
emilmont 10:3bc89ef62ce7 352 }
emilmont 10:3bc89ef62ce7 353 return 1;
emilmont 10:3bc89ef62ce7 354 }
emilmont 10:3bc89ef62ce7 355
emilmont 10:3bc89ef62ce7 356 return 0;
emilmont 10:3bc89ef62ce7 357 }
emilmont 10:3bc89ef62ce7 358
mbed_official 41:e8b66477f5bf 359 int can_read(can_t *obj, CAN_Message *msg, int handle) {
emilmont 10:3bc89ef62ce7 360 CANMsg x;
emilmont 10:3bc89ef62ce7 361 unsigned int *i = (unsigned int *)&x;
emilmont 10:3bc89ef62ce7 362
emilmont 10:3bc89ef62ce7 363 can_enable(obj);
emilmont 10:3bc89ef62ce7 364
emilmont 10:3bc89ef62ce7 365 if (obj->dev->GSR & 0x1) {
emilmont 10:3bc89ef62ce7 366 *i++ = obj->dev->RFS; // Frame
emilmont 10:3bc89ef62ce7 367 *i++ = obj->dev->RID; // ID
emilmont 10:3bc89ef62ce7 368 *i++ = obj->dev->RDA; // Data A
emilmont 10:3bc89ef62ce7 369 *i++ = obj->dev->RDB; // Data B
emilmont 10:3bc89ef62ce7 370 obj->dev->CMR = 0x04; // release receive buffer
emilmont 10:3bc89ef62ce7 371
emilmont 10:3bc89ef62ce7 372 msg->id = x.id;
emilmont 10:3bc89ef62ce7 373 msg->len = x.dlc;
emilmont 10:3bc89ef62ce7 374 msg->format = (x.type)? CANExtended : CANStandard;
emilmont 10:3bc89ef62ce7 375 msg->type = (x.rtr)? CANRemote: CANData;
emilmont 10:3bc89ef62ce7 376 memcpy(msg->data,x.data,x.dlc);
emilmont 10:3bc89ef62ce7 377 return 1;
emilmont 10:3bc89ef62ce7 378 }
emilmont 10:3bc89ef62ce7 379
emilmont 10:3bc89ef62ce7 380 return 0;
emilmont 10:3bc89ef62ce7 381 }
emilmont 10:3bc89ef62ce7 382
emilmont 10:3bc89ef62ce7 383 void can_reset(can_t *obj) {
emilmont 10:3bc89ef62ce7 384 can_disable(obj);
emilmont 10:3bc89ef62ce7 385 obj->dev->GSR = 0; // Reset error counter when CAN1MOD is in reset
emilmont 10:3bc89ef62ce7 386 }
emilmont 10:3bc89ef62ce7 387
emilmont 10:3bc89ef62ce7 388 unsigned char can_rderror(can_t *obj) {
emilmont 10:3bc89ef62ce7 389 return (obj->dev->GSR >> 16) & 0xFF;
emilmont 10:3bc89ef62ce7 390 }
emilmont 10:3bc89ef62ce7 391
emilmont 10:3bc89ef62ce7 392 unsigned char can_tderror(can_t *obj) {
emilmont 10:3bc89ef62ce7 393 return (obj->dev->GSR >> 24) & 0xFF;
emilmont 10:3bc89ef62ce7 394 }
emilmont 10:3bc89ef62ce7 395
emilmont 10:3bc89ef62ce7 396 void can_monitor(can_t *obj, int silent) {
emilmont 10:3bc89ef62ce7 397 uint32_t mod_mask = can_disable(obj);
emilmont 10:3bc89ef62ce7 398 if (silent) {
emilmont 10:3bc89ef62ce7 399 obj->dev->MOD |= (1 << 1);
emilmont 10:3bc89ef62ce7 400 } else {
emilmont 10:3bc89ef62ce7 401 obj->dev->MOD &= ~(1 << 1);
emilmont 10:3bc89ef62ce7 402 }
emilmont 10:3bc89ef62ce7 403 if (!(mod_mask & 1)) {
emilmont 10:3bc89ef62ce7 404 can_enable(obj);
emilmont 10:3bc89ef62ce7 405 }
emilmont 10:3bc89ef62ce7 406 }