mbed SDK library sources

Fork of mbed-src by mbed official

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:
Fri Oct 25 15:00:04 2013 +0100
Revision:
41:e8b66477f5bf
Synchronized with git revision 317a1f66d2a2d4efe5544d3bf6c2aaf1d147a968

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 41:e8b66477f5bf 1 /* mbed Microcontroller Library
mbed_official 41:e8b66477f5bf 2 * Copyright (c) 2006-2013 ARM Limited
mbed_official 41:e8b66477f5bf 3 *
mbed_official 41:e8b66477f5bf 4 * Licensed under the Apache License, Version 2.0 (the "License");
mbed_official 41:e8b66477f5bf 5 * you may not use this file except in compliance with the License.
mbed_official 41:e8b66477f5bf 6 * You may obtain a copy of the License at
mbed_official 41:e8b66477f5bf 7 *
mbed_official 41:e8b66477f5bf 8 * http://www.apache.org/licenses/LICENSE-2.0
mbed_official 41:e8b66477f5bf 9 *
mbed_official 41:e8b66477f5bf 10 * Unless required by applicable law or agreed to in writing, software
mbed_official 41:e8b66477f5bf 11 * distributed under the License is distributed on an "AS IS" BASIS,
mbed_official 41:e8b66477f5bf 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
mbed_official 41:e8b66477f5bf 13 * See the License for the specific language governing permissions and
mbed_official 41:e8b66477f5bf 14 * limitations under the License.
mbed_official 41:e8b66477f5bf 15 */
mbed_official 41:e8b66477f5bf 16 #include "can_api.h"
mbed_official 41:e8b66477f5bf 17
mbed_official 41:e8b66477f5bf 18 #include "cmsis.h"
mbed_official 41:e8b66477f5bf 19 #include "error.h"
mbed_official 41:e8b66477f5bf 20
mbed_official 41:e8b66477f5bf 21 #include <math.h>
mbed_official 41:e8b66477f5bf 22 #include <string.h>
mbed_official 41:e8b66477f5bf 23
mbed_official 41:e8b66477f5bf 24 /* Handy defines */
mbed_official 41:e8b66477f5bf 25 #define MSG_OBJ_MAX 32
mbed_official 41:e8b66477f5bf 26 #define DLC_MAX 8
mbed_official 41:e8b66477f5bf 27
mbed_official 41:e8b66477f5bf 28 #define ID_STD_MASK 0x07FF
mbed_official 41:e8b66477f5bf 29 #define ID_EXT_MASK 0x1FFFFFFF
mbed_official 41:e8b66477f5bf 30 #define DLC_MASK 0x0F
mbed_official 41:e8b66477f5bf 31
mbed_official 41:e8b66477f5bf 32 static uint32_t can_irq_id = 0;
mbed_official 41:e8b66477f5bf 33 static can_irq_handler irq_handler;
mbed_official 41:e8b66477f5bf 34
mbed_official 41:e8b66477f5bf 35 static uint32_t can_disable(can_t *obj) {
mbed_official 41:e8b66477f5bf 36 uint32_t sm = LPC_CAN->CNTL;
mbed_official 41:e8b66477f5bf 37 LPC_CAN->CNTL |= CANCNTL_INIT;
mbed_official 41:e8b66477f5bf 38 return sm;
mbed_official 41:e8b66477f5bf 39 }
mbed_official 41:e8b66477f5bf 40
mbed_official 41:e8b66477f5bf 41 static inline void can_enable(can_t *obj) {
mbed_official 41:e8b66477f5bf 42 if (LPC_CAN->CNTL & CANCNTL_INIT) {
mbed_official 41:e8b66477f5bf 43 LPC_CAN->CNTL &= ~CANCNTL_INIT;
mbed_official 41:e8b66477f5bf 44 }
mbed_official 41:e8b66477f5bf 45 }
mbed_official 41:e8b66477f5bf 46
mbed_official 41:e8b66477f5bf 47 int can_mode(can_t *obj, CanMode mode) {
mbed_official 41:e8b66477f5bf 48 return 0; // not implemented
mbed_official 41:e8b66477f5bf 49 }
mbed_official 41:e8b66477f5bf 50
mbed_official 41:e8b66477f5bf 51 int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle) {
mbed_official 41:e8b66477f5bf 52 uint16_t i;
mbed_official 41:e8b66477f5bf 53
mbed_official 41:e8b66477f5bf 54 // Find first free message object
mbed_official 41:e8b66477f5bf 55 if(handle == 0) {
mbed_official 41:e8b66477f5bf 56 uint32_t msgval = LPC_CAN->MSGV1 | (LPC_CAN->MSGV2 << 16);
mbed_official 41:e8b66477f5bf 57 // Find first free messagebox
mbed_official 41:e8b66477f5bf 58 for(i = 0; i < 32; i++) {
mbed_official 41:e8b66477f5bf 59 if((msgval & (1 << i)) == 0) {
mbed_official 41:e8b66477f5bf 60 handle = i+1;
mbed_official 41:e8b66477f5bf 61 break;
mbed_official 41:e8b66477f5bf 62 }
mbed_official 41:e8b66477f5bf 63 }
mbed_official 41:e8b66477f5bf 64 }
mbed_official 41:e8b66477f5bf 65
mbed_official 41:e8b66477f5bf 66 if(handle > 0 && handle < 32) {
mbed_official 41:e8b66477f5bf 67 if(format == CANExtended) {
mbed_official 41:e8b66477f5bf 68 // Mark message valid, Direction = TX, Extended Frame, Set Identifier and mask everything
mbed_official 41:e8b66477f5bf 69 LPC_CAN->IF1_ARB1 = BFN_PREP(id, CANIFn_ARB1_ID);
mbed_official 41:e8b66477f5bf 70 LPC_CAN->IF1_ARB2 = CANIFn_ARB2_MSGVAL | CANIFn_ARB2_XTD | BFN_PREP(id >> 16, CANIFn_ARB2_ID);
mbed_official 41:e8b66477f5bf 71 LPC_CAN->IF1_MSK1 = BFN_PREP(mask, CANIFn_MSK1_MSK);
mbed_official 41:e8b66477f5bf 72 LPC_CAN->IF1_MSK2 = CANIFn_MSK2_MXTD | CANIFn_MSK2_MDIR | BFN_PREP(mask >> 16, CANIFn_MSK2_MSK);
mbed_official 41:e8b66477f5bf 73 }
mbed_official 41:e8b66477f5bf 74 else {
mbed_official 41:e8b66477f5bf 75 // Mark message valid, Direction = TX, Set Identifier and mask everything
mbed_official 41:e8b66477f5bf 76 LPC_CAN->IF1_ARB2 = CANIFn_ARB2_MSGVAL | BFN_PREP(id << 2, CANIFn_ARB2_ID);
mbed_official 41:e8b66477f5bf 77 LPC_CAN->IF1_MSK2 = CANIFn_MSK2_MDIR | BFN_PREP(mask << 2, CANIFn_MSK2_MSK);
mbed_official 41:e8b66477f5bf 78 }
mbed_official 41:e8b66477f5bf 79
mbed_official 41:e8b66477f5bf 80 // Use mask, single message object and set DLC
mbed_official 41:e8b66477f5bf 81 LPC_CAN->IF1_MCTRL = CANIFn_MCTRL_UMASK | CANIFn_MCTRL_EOB | CANIFn_MCTRL_RXIE | BFN_PREP(DLC_MAX, CANIFn_MCTRL_DLC);
mbed_official 41:e8b66477f5bf 82
mbed_official 41:e8b66477f5bf 83 // Transfer all fields to message object
mbed_official 41:e8b66477f5bf 84 LPC_CAN->IF1_CMDMSK = CANIFn_CMDMSK_WR | CANIFn_CMDMSK_MASK | CANIFn_CMDMSK_ARB | CANIFn_CMDMSK_CTRL;
mbed_official 41:e8b66477f5bf 85
mbed_official 41:e8b66477f5bf 86 // Start Transfer to given message number
mbed_official 41:e8b66477f5bf 87 LPC_CAN->IF1_CMDREQ = BFN_PREP(handle, CANIFn_CMDREQ_MN);
mbed_official 41:e8b66477f5bf 88
mbed_official 41:e8b66477f5bf 89 // Wait until transfer to message ram complete - TODO: maybe not block??
mbed_official 41:e8b66477f5bf 90 while( LPC_CAN->IF1_CMDREQ & CANIFn_CMDREQ_BUSY );
mbed_official 41:e8b66477f5bf 91 }
mbed_official 41:e8b66477f5bf 92
mbed_official 41:e8b66477f5bf 93 return handle;
mbed_official 41:e8b66477f5bf 94 }
mbed_official 41:e8b66477f5bf 95
mbed_official 41:e8b66477f5bf 96 static inline void can_irq() {
mbed_official 41:e8b66477f5bf 97 irq_handler(can_irq_id, IRQ_RX);
mbed_official 41:e8b66477f5bf 98 }
mbed_official 41:e8b66477f5bf 99
mbed_official 41:e8b66477f5bf 100 // Register CAN object's irq handler
mbed_official 41:e8b66477f5bf 101 void can_irq_init(can_t *obj, can_irq_handler handler, uint32_t id) {
mbed_official 41:e8b66477f5bf 102 irq_handler = handler;
mbed_official 41:e8b66477f5bf 103 can_irq_id = id;
mbed_official 41:e8b66477f5bf 104 }
mbed_official 41:e8b66477f5bf 105
mbed_official 41:e8b66477f5bf 106 // Unregister CAN object's irq handler
mbed_official 41:e8b66477f5bf 107 void can_irq_free(can_t *obj) {
mbed_official 41:e8b66477f5bf 108 LPC_CAN->CNTL &= ~CANCNTL_IE; // Disable Interrupts :)
mbed_official 41:e8b66477f5bf 109
mbed_official 41:e8b66477f5bf 110 can_irq_id = 0;
mbed_official 41:e8b66477f5bf 111 NVIC_DisableIRQ(CAN_IRQn);
mbed_official 41:e8b66477f5bf 112 }
mbed_official 41:e8b66477f5bf 113
mbed_official 41:e8b66477f5bf 114 // Clear or set a irq
mbed_official 41:e8b66477f5bf 115 void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable) {
mbed_official 41:e8b66477f5bf 116 // Put CAN in Reset Mode and enable interrupt
mbed_official 41:e8b66477f5bf 117 can_disable(obj);
mbed_official 41:e8b66477f5bf 118 if(enable == 0) {
mbed_official 41:e8b66477f5bf 119 LPC_CAN->CNTL &= ~(CANCNTL_IE | CANCNTL_SIE);
mbed_official 41:e8b66477f5bf 120 }
mbed_official 41:e8b66477f5bf 121 else {
mbed_official 41:e8b66477f5bf 122 LPC_CAN->CNTL |= CANCNTL_IE | CANCNTL_SIE;
mbed_official 41:e8b66477f5bf 123 }
mbed_official 41:e8b66477f5bf 124 // Take it out of reset...
mbed_official 41:e8b66477f5bf 125 can_enable(obj);
mbed_official 41:e8b66477f5bf 126
mbed_official 41:e8b66477f5bf 127 // Enable NVIC if at least 1 interrupt is active
mbed_official 41:e8b66477f5bf 128 NVIC_SetVector(CAN_IRQn, (uint32_t) &can_irq);
mbed_official 41:e8b66477f5bf 129 NVIC_EnableIRQ(CAN_IRQn);
mbed_official 41:e8b66477f5bf 130 }
mbed_official 41:e8b66477f5bf 131
mbed_official 41:e8b66477f5bf 132 // This table has the sampling points as close to 75% as possible. The first
mbed_official 41:e8b66477f5bf 133 // value is TSEG1, the second TSEG2.
mbed_official 41:e8b66477f5bf 134 static const int timing_pts[23][2] = {
mbed_official 41:e8b66477f5bf 135 {0x0, 0x0}, // 2, 50%
mbed_official 41:e8b66477f5bf 136 {0x1, 0x0}, // 3, 67%
mbed_official 41:e8b66477f5bf 137 {0x2, 0x0}, // 4, 75%
mbed_official 41:e8b66477f5bf 138 {0x3, 0x0}, // 5, 80%
mbed_official 41:e8b66477f5bf 139 {0x3, 0x1}, // 6, 67%
mbed_official 41:e8b66477f5bf 140 {0x4, 0x1}, // 7, 71%
mbed_official 41:e8b66477f5bf 141 {0x5, 0x1}, // 8, 75%
mbed_official 41:e8b66477f5bf 142 {0x6, 0x1}, // 9, 78%
mbed_official 41:e8b66477f5bf 143 {0x6, 0x2}, // 10, 70%
mbed_official 41:e8b66477f5bf 144 {0x7, 0x2}, // 11, 73%
mbed_official 41:e8b66477f5bf 145 {0x8, 0x2}, // 12, 75%
mbed_official 41:e8b66477f5bf 146 {0x9, 0x2}, // 13, 77%
mbed_official 41:e8b66477f5bf 147 {0x9, 0x3}, // 14, 71%
mbed_official 41:e8b66477f5bf 148 {0xA, 0x3}, // 15, 73%
mbed_official 41:e8b66477f5bf 149 {0xB, 0x3}, // 16, 75%
mbed_official 41:e8b66477f5bf 150 {0xC, 0x3}, // 17, 76%
mbed_official 41:e8b66477f5bf 151 {0xD, 0x3}, // 18, 78%
mbed_official 41:e8b66477f5bf 152 {0xD, 0x4}, // 19, 74%
mbed_official 41:e8b66477f5bf 153 {0xE, 0x4}, // 20, 75%
mbed_official 41:e8b66477f5bf 154 {0xF, 0x4}, // 21, 76%
mbed_official 41:e8b66477f5bf 155 {0xF, 0x5}, // 22, 73%
mbed_official 41:e8b66477f5bf 156 {0xF, 0x6}, // 23, 70%
mbed_official 41:e8b66477f5bf 157 {0xF, 0x7}, // 24, 67%
mbed_official 41:e8b66477f5bf 158 };
mbed_official 41:e8b66477f5bf 159
mbed_official 41:e8b66477f5bf 160 static unsigned int can_speed(unsigned int sclk, unsigned int cclk, unsigned char psjw) {
mbed_official 41:e8b66477f5bf 161 uint32_t btr;
mbed_official 41:e8b66477f5bf 162 uint32_t clkdiv = 1;
mbed_official 41:e8b66477f5bf 163 uint16_t brp = 0;
mbed_official 41:e8b66477f5bf 164 uint32_t calcbit;
mbed_official 41:e8b66477f5bf 165 uint32_t bitwidth;
mbed_official 41:e8b66477f5bf 166 int hit = 0;
mbed_official 41:e8b66477f5bf 167 int bits = 0;
mbed_official 41:e8b66477f5bf 168
mbed_official 41:e8b66477f5bf 169 bitwidth = sclk / cclk;
mbed_official 41:e8b66477f5bf 170
mbed_official 41:e8b66477f5bf 171 brp = bitwidth / 0x18;
mbed_official 41:e8b66477f5bf 172 while ((!hit) && (brp < bitwidth / 4)) {
mbed_official 41:e8b66477f5bf 173 brp++;
mbed_official 41:e8b66477f5bf 174 for (bits = 22; bits > 0; bits--) {
mbed_official 41:e8b66477f5bf 175 calcbit = (bits + 3) * (brp + 1);
mbed_official 41:e8b66477f5bf 176 if (calcbit == bitwidth) {
mbed_official 41:e8b66477f5bf 177 hit = 1;
mbed_official 41:e8b66477f5bf 178 break;
mbed_official 41:e8b66477f5bf 179 }
mbed_official 41:e8b66477f5bf 180 }
mbed_official 41:e8b66477f5bf 181 }
mbed_official 41:e8b66477f5bf 182
mbed_official 41:e8b66477f5bf 183 /* This might be funky
mbed_official 41:e8b66477f5bf 184 while(btr > 63 && clkdiv < 16) {
mbed_official 41:e8b66477f5bf 185 btr = btr / 2;
mbed_official 41:e8b66477f5bf 186 clkdiv = clkdiv * 2;
mbed_official 41:e8b66477f5bf 187 }
mbed_official 41:e8b66477f5bf 188 */
mbed_official 41:e8b66477f5bf 189 clkdiv = clkdiv - 1;
mbed_official 41:e8b66477f5bf 190
mbed_official 41:e8b66477f5bf 191 if (hit) {
mbed_official 41:e8b66477f5bf 192 btr = BFN_PREP(timing_pts[bits][1], CANBT_TSEG2)
mbed_official 41:e8b66477f5bf 193 | BFN_PREP(timing_pts[bits][0], CANBT_TSEG1)
mbed_official 41:e8b66477f5bf 194 | BFN_PREP(psjw, CANBT_SJW)
mbed_official 41:e8b66477f5bf 195 | BFN_PREP(brp, CANBT_BRP);
mbed_official 41:e8b66477f5bf 196 btr = btr | (clkdiv << 16);
mbed_official 41:e8b66477f5bf 197
mbed_official 41:e8b66477f5bf 198 } else {
mbed_official 41:e8b66477f5bf 199 btr = 0;
mbed_official 41:e8b66477f5bf 200 }
mbed_official 41:e8b66477f5bf 201
mbed_official 41:e8b66477f5bf 202 return btr;
mbed_official 41:e8b66477f5bf 203 }
mbed_official 41:e8b66477f5bf 204
mbed_official 41:e8b66477f5bf 205
mbed_official 41:e8b66477f5bf 206 int can_config_rxmsgobj(can_t *obj) {
mbed_official 41:e8b66477f5bf 207 uint16_t i = 0;
mbed_official 41:e8b66477f5bf 208
mbed_official 41:e8b66477f5bf 209 // Make sure the interface is available
mbed_official 41:e8b66477f5bf 210 //while( LPC_CAN->IF1_CMDREQ & CANIFn_CMDREQ_BUSY );
mbed_official 41:e8b66477f5bf 211
mbed_official 41:e8b66477f5bf 212 // Mark message valid, Direction = RX, Don't care about anything else
mbed_official 41:e8b66477f5bf 213 LPC_CAN->IF1_ARB1 = 0;
mbed_official 41:e8b66477f5bf 214 LPC_CAN->IF1_ARB2 = 0;
mbed_official 41:e8b66477f5bf 215 LPC_CAN->IF1_MCTRL = 0;
mbed_official 41:e8b66477f5bf 216
mbed_official 41:e8b66477f5bf 217 for ( i = 0; i < MSG_OBJ_MAX; i++ )
mbed_official 41:e8b66477f5bf 218 {
mbed_official 41:e8b66477f5bf 219 // Transfer arb and control fields to message object
mbed_official 41:e8b66477f5bf 220 LPC_CAN->IF1_CMDMSK = CANIFn_CMDMSK_WR | CANIFn_CMDMSK_ARB | CANIFn_CMDMSK_CTRL | CANIFn_CMDMSK_TXRQST;
mbed_official 41:e8b66477f5bf 221
mbed_official 41:e8b66477f5bf 222 // Start Transfer to given message number
mbed_official 41:e8b66477f5bf 223 LPC_CAN->IF1_CMDREQ = BFN_PREP(i, CANIFn_CMDREQ_MN);
mbed_official 41:e8b66477f5bf 224
mbed_official 41:e8b66477f5bf 225 // Wait until transfer to message ram complete - TODO: maybe not block??
mbed_official 41:e8b66477f5bf 226 while( LPC_CAN->IF1_CMDREQ & CANIFn_CMDREQ_BUSY );
mbed_official 41:e8b66477f5bf 227 }
mbed_official 41:e8b66477f5bf 228
mbed_official 41:e8b66477f5bf 229 // Accept all messages
mbed_official 41:e8b66477f5bf 230 can_filter(obj, 0, 0, CANStandard, 1);
mbed_official 41:e8b66477f5bf 231
mbed_official 41:e8b66477f5bf 232 return 1;
mbed_official 41:e8b66477f5bf 233 }
mbed_official 41:e8b66477f5bf 234
mbed_official 41:e8b66477f5bf 235
mbed_official 41:e8b66477f5bf 236 void can_init(can_t *obj, PinName rd, PinName td) {
mbed_official 41:e8b66477f5bf 237 // Enable power and clock
mbed_official 41:e8b66477f5bf 238 LPC_SYSCON->PRESETCTRL |= PRESETCTRL_CAN_RST_N;
mbed_official 41:e8b66477f5bf 239 LPC_SYSCON->SYSAHBCLKCTRL |= SYSAHBCLKCTRL_CAN;
mbed_official 41:e8b66477f5bf 240
mbed_official 41:e8b66477f5bf 241 // Enable Initialization mode
mbed_official 41:e8b66477f5bf 242 if (!(LPC_CAN->CNTL & CANCNTL_INIT)) {
mbed_official 41:e8b66477f5bf 243 LPC_CAN->CNTL |= CANCNTL_INIT;
mbed_official 41:e8b66477f5bf 244 }
mbed_official 41:e8b66477f5bf 245
mbed_official 41:e8b66477f5bf 246 can_frequency(obj, 125000);
mbed_official 41:e8b66477f5bf 247
mbed_official 41:e8b66477f5bf 248 // Resume operation
mbed_official 41:e8b66477f5bf 249 LPC_CAN->CNTL &= ~CANCNTL_INIT;
mbed_official 41:e8b66477f5bf 250 while ( LPC_CAN->CNTL & CANCNTL_INIT );
mbed_official 41:e8b66477f5bf 251
mbed_official 41:e8b66477f5bf 252 // Initialize RX message object
mbed_official 41:e8b66477f5bf 253 can_config_rxmsgobj(obj);
mbed_official 41:e8b66477f5bf 254 }
mbed_official 41:e8b66477f5bf 255
mbed_official 41:e8b66477f5bf 256 void can_free(can_t *obj) {
mbed_official 41:e8b66477f5bf 257 LPC_SYSCON->SYSAHBCLKCTRL &= ~(SYSAHBCLKCTRL_CAN);
mbed_official 41:e8b66477f5bf 258 LPC_SYSCON->PRESETCTRL &= ~(PRESETCTRL_CAN_RST_N);
mbed_official 41:e8b66477f5bf 259 }
mbed_official 41:e8b66477f5bf 260
mbed_official 41:e8b66477f5bf 261 int can_frequency(can_t *obj, int f) {
mbed_official 41:e8b66477f5bf 262 int btr = can_speed(SystemCoreClock, (unsigned int)f, 1);
mbed_official 41:e8b66477f5bf 263 int clkdiv = (btr >> 16) & 0x0F;
mbed_official 41:e8b66477f5bf 264 btr = btr & 0xFFFF;
mbed_official 41:e8b66477f5bf 265
mbed_official 41:e8b66477f5bf 266 if (btr > 0) {
mbed_official 41:e8b66477f5bf 267 // Set the bit clock
mbed_official 41:e8b66477f5bf 268 LPC_CAN->CNTL |= CANCNTL_CCE;
mbed_official 41:e8b66477f5bf 269 LPC_CAN->CLKDIV = clkdiv;
mbed_official 41:e8b66477f5bf 270 LPC_CAN->BT = btr;
mbed_official 41:e8b66477f5bf 271 LPC_CAN->BRPE = 0x0000;
mbed_official 41:e8b66477f5bf 272 LPC_CAN->CNTL &= ~CANCNTL_CCE;
mbed_official 41:e8b66477f5bf 273 return 1;
mbed_official 41:e8b66477f5bf 274 }
mbed_official 41:e8b66477f5bf 275 return 0;
mbed_official 41:e8b66477f5bf 276 }
mbed_official 41:e8b66477f5bf 277
mbed_official 41:e8b66477f5bf 278 int can_write(can_t *obj, CAN_Message msg, int cc) {
mbed_official 41:e8b66477f5bf 279 uint16_t msgnum = 0;
mbed_official 41:e8b66477f5bf 280
mbed_official 41:e8b66477f5bf 281 // Make sure controller is enabled
mbed_official 41:e8b66477f5bf 282 can_enable(obj);
mbed_official 41:e8b66477f5bf 283
mbed_official 41:e8b66477f5bf 284 // Make sure the interface is available
mbed_official 41:e8b66477f5bf 285 while( LPC_CAN->IF1_CMDREQ & CANIFn_CMDREQ_BUSY );
mbed_official 41:e8b66477f5bf 286
mbed_official 41:e8b66477f5bf 287 if(msg.format == CANExtended) {
mbed_official 41:e8b66477f5bf 288 // Mark message valid, Direction = TX, Extended Frame, Set Identifier and mask everything
mbed_official 41:e8b66477f5bf 289 LPC_CAN->IF1_ARB1 = BFN_PREP(msg.id, CANIFn_ARB1_ID);
mbed_official 41:e8b66477f5bf 290 LPC_CAN->IF1_ARB2 = CANIFn_ARB2_MSGVAL | CANIFn_ARB2_XTD | CANIFn_ARB2_DIR | BFN_PREP(msg.id >> 16, CANIFn_ARB2_ID);
mbed_official 41:e8b66477f5bf 291 LPC_CAN->IF1_MSK1 = BFN_PREP(ID_EXT_MASK, CANIFn_MSK1_MSK);
mbed_official 41:e8b66477f5bf 292 LPC_CAN->IF1_MSK2 = CANIFn_MSK2_MXTD | CANIFn_MSK2_MDIR | BFN_PREP(ID_EXT_MASK >> 16, CANIFn_MSK2_MSK);
mbed_official 41:e8b66477f5bf 293 }
mbed_official 41:e8b66477f5bf 294 else {
mbed_official 41:e8b66477f5bf 295 // Mark message valid, Direction = TX, Set Identifier and mask everything
mbed_official 41:e8b66477f5bf 296 LPC_CAN->IF1_ARB2 = CANIFn_ARB2_MSGVAL | CANIFn_ARB2_DIR | BFN_PREP(msg.id << 2, CANIFn_ARB2_ID);
mbed_official 41:e8b66477f5bf 297 LPC_CAN->IF1_MSK2 = CANIFn_MSK2_MDIR | BFN_PREP(ID_STD_MASK << 2, CANIFn_MSK2_MSK);
mbed_official 41:e8b66477f5bf 298 }
mbed_official 41:e8b66477f5bf 299
mbed_official 41:e8b66477f5bf 300 // Use mask, request transmission, single message object and set DLC
mbed_official 41:e8b66477f5bf 301 LPC_CAN->IF1_MCTRL = CANIFn_MCTRL_UMASK | CANIFn_MCTRL_TXRQST | CANIFn_MCTRL_EOB | BFN_PREP(msg.len, CANIFn_MCTRL_DLC);
mbed_official 41:e8b66477f5bf 302
mbed_official 41:e8b66477f5bf 303 LPC_CAN->IF1_DA1 = BFN_PREP(msg.data[1], CANIFn_DA1_DATA1) | BFN_PREP(msg.data[0], CANIFn_DA1_DATA0);
mbed_official 41:e8b66477f5bf 304 LPC_CAN->IF1_DA2 = BFN_PREP(msg.data[3], CANIFn_DA2_DATA3) | BFN_PREP(msg.data[2], CANIFn_DA2_DATA2);
mbed_official 41:e8b66477f5bf 305 LPC_CAN->IF1_DB1 = BFN_PREP(msg.data[5], CANIFn_DB1_DATA5) | BFN_PREP(msg.data[4], CANIFn_DB1_DATA4);
mbed_official 41:e8b66477f5bf 306 LPC_CAN->IF1_DB2 = BFN_PREP(msg.data[7], CANIFn_DB2_DATA7) | BFN_PREP(msg.data[6], CANIFn_DB2_DATA6);
mbed_official 41:e8b66477f5bf 307
mbed_official 41:e8b66477f5bf 308 // Transfer all fields to message object
mbed_official 41:e8b66477f5bf 309 LPC_CAN->IF1_CMDMSK = CANIFn_CMDMSK_WR | CANIFn_CMDMSK_MASK | CANIFn_CMDMSK_ARB | CANIFn_CMDMSK_CTRL | CANIFn_CMDMSK_TXRQST | CANIFn_CMDMSK_DATA_A | CANIFn_CMDMSK_DATA_B;
mbed_official 41:e8b66477f5bf 310
mbed_official 41:e8b66477f5bf 311 // Start Transfer to given message number
mbed_official 41:e8b66477f5bf 312 LPC_CAN->IF1_CMDREQ = BFN_PREP(msgnum, CANIFn_CMDREQ_MN);
mbed_official 41:e8b66477f5bf 313
mbed_official 41:e8b66477f5bf 314 // Wait until transfer to message ram complete - TODO: maybe not block??
mbed_official 41:e8b66477f5bf 315 while( LPC_CAN->IF1_CMDREQ & CANIFn_CMDREQ_BUSY);
mbed_official 41:e8b66477f5bf 316
mbed_official 41:e8b66477f5bf 317 // Wait until TXOK is set, then clear it - TODO: maybe not block
mbed_official 41:e8b66477f5bf 318 //while( !(LPC_CAN->STAT & CANSTAT_TXOK) );
mbed_official 41:e8b66477f5bf 319 LPC_CAN->STAT &= ~(CANSTAT_TXOK);
mbed_official 41:e8b66477f5bf 320
mbed_official 41:e8b66477f5bf 321 return 1;
mbed_official 41:e8b66477f5bf 322 }
mbed_official 41:e8b66477f5bf 323
mbed_official 41:e8b66477f5bf 324 int can_read(can_t *obj, CAN_Message *msg, int handle) {
mbed_official 41:e8b66477f5bf 325 uint16_t i;
mbed_official 41:e8b66477f5bf 326
mbed_official 41:e8b66477f5bf 327 // Make sure controller is enabled
mbed_official 41:e8b66477f5bf 328 can_enable(obj);
mbed_official 41:e8b66477f5bf 329
mbed_official 41:e8b66477f5bf 330 // Find first message object with new data
mbed_official 41:e8b66477f5bf 331 if(handle == 0) {
mbed_official 41:e8b66477f5bf 332 uint32_t newdata = LPC_CAN->ND1 | (LPC_CAN->ND2 << 16);
mbed_official 41:e8b66477f5bf 333 // Find first free messagebox
mbed_official 41:e8b66477f5bf 334 for(i = 0; i < 32; i++) {
mbed_official 41:e8b66477f5bf 335 if(newdata & (1 << i)) {
mbed_official 41:e8b66477f5bf 336 handle = i+1;
mbed_official 41:e8b66477f5bf 337 break;
mbed_official 41:e8b66477f5bf 338 }
mbed_official 41:e8b66477f5bf 339 }
mbed_official 41:e8b66477f5bf 340 }
mbed_official 41:e8b66477f5bf 341
mbed_official 41:e8b66477f5bf 342 if(handle > 0 && handle < 32) {
mbed_official 41:e8b66477f5bf 343 // Wait until message interface is free
mbed_official 41:e8b66477f5bf 344 while( LPC_CAN->IF2_CMDREQ & CANIFn_CMDREQ_BUSY );
mbed_official 41:e8b66477f5bf 345
mbed_official 41:e8b66477f5bf 346 // Transfer all fields to message object
mbed_official 41:e8b66477f5bf 347 LPC_CAN->IF2_CMDMSK = CANIFn_CMDMSK_RD | CANIFn_CMDMSK_MASK | CANIFn_CMDMSK_ARB | CANIFn_CMDMSK_CTRL | CANIFn_CMDMSK_CLRINTPND | CANIFn_CMDMSK_TXRQST | CANIFn_CMDMSK_DATA_A | CANIFn_CMDMSK_DATA_B;
mbed_official 41:e8b66477f5bf 348
mbed_official 41:e8b66477f5bf 349 // Start Transfer from given message number
mbed_official 41:e8b66477f5bf 350 LPC_CAN->IF2_CMDREQ = BFN_PREP(handle, CANIFn_CMDREQ_MN);
mbed_official 41:e8b66477f5bf 351
mbed_official 41:e8b66477f5bf 352 // Wait until transfer to message ram complete
mbed_official 41:e8b66477f5bf 353 while( LPC_CAN->IF2_CMDREQ & CANIFn_CMDREQ_BUSY );
mbed_official 41:e8b66477f5bf 354
mbed_official 41:e8b66477f5bf 355 if (LPC_CAN->IF2_ARB2 & CANIFn_ARB2_XTD) {
mbed_official 41:e8b66477f5bf 356 msg->format = CANExtended;
mbed_official 41:e8b66477f5bf 357 msg->id = (LPC_CAN->IF2_ARB1 & CANIFn_ARB2_ID_MASK) << 16;
mbed_official 41:e8b66477f5bf 358 msg->id |= (LPC_CAN->IF2_ARB2 & CANIFn_ARB2_ID_MASK);
mbed_official 41:e8b66477f5bf 359 }
mbed_official 41:e8b66477f5bf 360 else {
mbed_official 41:e8b66477f5bf 361 msg->format = CANStandard;
mbed_official 41:e8b66477f5bf 362 msg->id = (LPC_CAN->IF2_ARB2 & CANIFn_ARB2_ID_MASK) >> 2;
mbed_official 41:e8b66477f5bf 363 }
mbed_official 41:e8b66477f5bf 364
mbed_official 41:e8b66477f5bf 365 // TODO: Remote frame support
mbed_official 41:e8b66477f5bf 366 msg->type = CANData;
mbed_official 41:e8b66477f5bf 367 msg->len = BFN_GET(LPC_CAN->IF2_MCTRL, CANIFn_MCTRL_DLC); // TODO: If > 8, len = 8
mbed_official 41:e8b66477f5bf 368 msg->data[0] = BFN_GET(LPC_CAN->IF2_DA1, CANIFn_DA1_DATA0);
mbed_official 41:e8b66477f5bf 369 msg->data[1] = BFN_GET(LPC_CAN->IF2_DA1, CANIFn_DA1_DATA1);
mbed_official 41:e8b66477f5bf 370 msg->data[2] = BFN_GET(LPC_CAN->IF2_DA2, CANIFn_DA2_DATA2);
mbed_official 41:e8b66477f5bf 371 msg->data[3] = BFN_GET(LPC_CAN->IF2_DA2, CANIFn_DA2_DATA3);
mbed_official 41:e8b66477f5bf 372 msg->data[4] = BFN_GET(LPC_CAN->IF2_DB1, CANIFn_DB1_DATA4);
mbed_official 41:e8b66477f5bf 373 msg->data[5] = BFN_GET(LPC_CAN->IF2_DB1, CANIFn_DB1_DATA5);
mbed_official 41:e8b66477f5bf 374 msg->data[6] = BFN_GET(LPC_CAN->IF2_DB2, CANIFn_DB2_DATA6);
mbed_official 41:e8b66477f5bf 375 msg->data[7] = BFN_GET(LPC_CAN->IF2_DB2, CANIFn_DB2_DATA7);
mbed_official 41:e8b66477f5bf 376
mbed_official 41:e8b66477f5bf 377 LPC_CAN->STAT &= ~(CANSTAT_RXOK);
mbed_official 41:e8b66477f5bf 378 return 1;
mbed_official 41:e8b66477f5bf 379 }
mbed_official 41:e8b66477f5bf 380
mbed_official 41:e8b66477f5bf 381 return 0;
mbed_official 41:e8b66477f5bf 382 }
mbed_official 41:e8b66477f5bf 383
mbed_official 41:e8b66477f5bf 384 void can_reset(can_t *obj) {
mbed_official 41:e8b66477f5bf 385 LPC_SYSCON->PRESETCTRL &= ~PRESETCTRL_CAN_RST_N;
mbed_official 41:e8b66477f5bf 386 LPC_CAN->STAT = 0;
mbed_official 41:e8b66477f5bf 387
mbed_official 41:e8b66477f5bf 388 can_config_rxmsgobj(obj);
mbed_official 41:e8b66477f5bf 389 }
mbed_official 41:e8b66477f5bf 390
mbed_official 41:e8b66477f5bf 391 unsigned char can_rderror(can_t *obj) {
mbed_official 41:e8b66477f5bf 392 return BFN_GET(LPC_CAN->EC, CANEC_REC);
mbed_official 41:e8b66477f5bf 393 }
mbed_official 41:e8b66477f5bf 394
mbed_official 41:e8b66477f5bf 395 unsigned char can_tderror(can_t *obj) {
mbed_official 41:e8b66477f5bf 396 return BFN_GET(LPC_CAN->EC, CANEC_TEC);
mbed_official 41:e8b66477f5bf 397 }
mbed_official 41:e8b66477f5bf 398
mbed_official 41:e8b66477f5bf 399 void can_monitor(can_t *obj, int silent) {
mbed_official 41:e8b66477f5bf 400 if (silent) {
mbed_official 41:e8b66477f5bf 401 LPC_CAN->CNTL |= CANCNTL_TEST;
mbed_official 41:e8b66477f5bf 402 LPC_CAN->TEST |= CANTEST_SILENT;
mbed_official 41:e8b66477f5bf 403 } else {
mbed_official 41:e8b66477f5bf 404 LPC_CAN->CNTL &= ~(CANCNTL_TEST);
mbed_official 41:e8b66477f5bf 405 LPC_CAN->TEST &= ~CANTEST_SILENT;
mbed_official 41:e8b66477f5bf 406 }
mbed_official 41:e8b66477f5bf 407
mbed_official 41:e8b66477f5bf 408 if (!(LPC_CAN->CNTL & CANCNTL_INIT)) {
mbed_official 41:e8b66477f5bf 409 LPC_CAN->CNTL |= CANCNTL_INIT;
mbed_official 41:e8b66477f5bf 410 }
mbed_official 41:e8b66477f5bf 411 }