Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-dev by
targets/TARGET_STM/can_api.c@182:57724642e740, 2018-02-16 (annotated)
- Committer:
- AnnaBridge
- Date:
- Fri Feb 16 16:09:33 2018 +0000
- Revision:
- 182:57724642e740
- Parent:
- 181:96ed750bd169
mbed-dev library. Release version 159.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
<> | 160:d5399cc887bb | 1 | /* mbed Microcontroller Library |
<> | 160:d5399cc887bb | 2 | * Copyright (c) 2006-2017 ARM Limited |
<> | 160:d5399cc887bb | 3 | * |
<> | 160:d5399cc887bb | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
<> | 160:d5399cc887bb | 5 | * you may not use this file except in compliance with the License. |
<> | 160:d5399cc887bb | 6 | * You may obtain a copy of the License at |
<> | 160:d5399cc887bb | 7 | * |
<> | 160:d5399cc887bb | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
<> | 160:d5399cc887bb | 9 | * |
<> | 160:d5399cc887bb | 10 | * Unless required by applicable law or agreed to in writing, software |
<> | 160:d5399cc887bb | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
<> | 160:d5399cc887bb | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
<> | 160:d5399cc887bb | 13 | * See the License for the specific language governing permissions and |
<> | 160:d5399cc887bb | 14 | * limitations under the License. |
<> | 160:d5399cc887bb | 15 | */ |
<> | 160:d5399cc887bb | 16 | #include "can_api.h" |
<> | 160:d5399cc887bb | 17 | |
<> | 160:d5399cc887bb | 18 | #if DEVICE_CAN |
<> | 160:d5399cc887bb | 19 | |
<> | 160:d5399cc887bb | 20 | #include "cmsis.h" |
<> | 160:d5399cc887bb | 21 | #include "pinmap.h" |
<> | 160:d5399cc887bb | 22 | #include "PeripheralPins.h" |
<> | 160:d5399cc887bb | 23 | #include "mbed_error.h" |
<> | 160:d5399cc887bb | 24 | #include "can_device.h" // Specific to STM32 serie |
<> | 160:d5399cc887bb | 25 | #include <math.h> |
<> | 160:d5399cc887bb | 26 | #include <string.h> |
<> | 160:d5399cc887bb | 27 | |
<> | 160:d5399cc887bb | 28 | static uint32_t can_irq_ids[CAN_NUM] = {0}; |
<> | 160:d5399cc887bb | 29 | static can_irq_handler irq_handler; |
<> | 160:d5399cc887bb | 30 | |
AnnaBridge | 175:b96e65c34a4d | 31 | static void can_registers_init(can_t *obj) |
AnnaBridge | 175:b96e65c34a4d | 32 | { |
AnnaBridge | 175:b96e65c34a4d | 33 | if (HAL_CAN_Init(&obj->CanHandle) != HAL_OK) { |
AnnaBridge | 175:b96e65c34a4d | 34 | error("Cannot initialize CAN"); |
AnnaBridge | 175:b96e65c34a4d | 35 | } |
AnnaBridge | 175:b96e65c34a4d | 36 | |
AnnaBridge | 175:b96e65c34a4d | 37 | // Set initial CAN frequency to specified frequency |
AnnaBridge | 175:b96e65c34a4d | 38 | if (can_frequency(obj, obj->hz) != 1) { |
AnnaBridge | 175:b96e65c34a4d | 39 | error("Can frequency could not be set\n"); |
AnnaBridge | 175:b96e65c34a4d | 40 | } |
AnnaBridge | 175:b96e65c34a4d | 41 | } |
AnnaBridge | 175:b96e65c34a4d | 42 | |
<> | 160:d5399cc887bb | 43 | void can_init(can_t *obj, PinName rd, PinName td) |
<> | 160:d5399cc887bb | 44 | { |
AnnaBridge | 167:e84263d55307 | 45 | can_init_freq(obj, rd, td, 100000); |
AnnaBridge | 167:e84263d55307 | 46 | } |
AnnaBridge | 167:e84263d55307 | 47 | |
AnnaBridge | 167:e84263d55307 | 48 | void can_init_freq (can_t *obj, PinName rd, PinName td, int hz) |
AnnaBridge | 167:e84263d55307 | 49 | { |
<> | 160:d5399cc887bb | 50 | CANName can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD); |
<> | 160:d5399cc887bb | 51 | CANName can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TD); |
AnnaBridge | 175:b96e65c34a4d | 52 | CANName can = (CANName)pinmap_merge(can_rd, can_td); |
<> | 160:d5399cc887bb | 53 | |
AnnaBridge | 175:b96e65c34a4d | 54 | MBED_ASSERT((int)can != NC); |
<> | 160:d5399cc887bb | 55 | |
AnnaBridge | 175:b96e65c34a4d | 56 | if (can == CAN_1) { |
<> | 160:d5399cc887bb | 57 | __HAL_RCC_CAN1_CLK_ENABLE(); |
<> | 160:d5399cc887bb | 58 | obj->index = 0; |
<> | 160:d5399cc887bb | 59 | } |
Anna Bridge |
181:96ed750bd169 | 60 | #if defined(CAN2_BASE) && (CAN_NUM > 1) |
AnnaBridge | 175:b96e65c34a4d | 61 | else if (can == CAN_2) { |
<> | 160:d5399cc887bb | 62 | __HAL_RCC_CAN1_CLK_ENABLE(); // needed to set filters |
<> | 160:d5399cc887bb | 63 | __HAL_RCC_CAN2_CLK_ENABLE(); |
<> | 160:d5399cc887bb | 64 | obj->index = 1; |
<> | 160:d5399cc887bb | 65 | } |
<> | 160:d5399cc887bb | 66 | #endif |
Anna Bridge |
181:96ed750bd169 | 67 | #if defined(CAN3_BASE) && (CAN_NUM > 2) |
AnnaBridge | 179:79309dc6340a | 68 | else if (can == CAN_3) { |
AnnaBridge | 179:79309dc6340a | 69 | __HAL_RCC_CAN3_CLK_ENABLE(); |
AnnaBridge | 179:79309dc6340a | 70 | obj->index = 2; |
AnnaBridge | 179:79309dc6340a | 71 | } |
AnnaBridge | 179:79309dc6340a | 72 | #endif |
<> | 160:d5399cc887bb | 73 | else { |
<> | 160:d5399cc887bb | 74 | return; |
<> | 160:d5399cc887bb | 75 | } |
<> | 160:d5399cc887bb | 76 | |
<> | 160:d5399cc887bb | 77 | // Configure the CAN pins |
<> | 160:d5399cc887bb | 78 | pinmap_pinout(rd, PinMap_CAN_RD); |
<> | 160:d5399cc887bb | 79 | pinmap_pinout(td, PinMap_CAN_TD); |
<> | 160:d5399cc887bb | 80 | if (rd != NC) { |
<> | 160:d5399cc887bb | 81 | pin_mode(rd, PullUp); |
<> | 160:d5399cc887bb | 82 | } |
<> | 160:d5399cc887bb | 83 | if (td != NC) { |
<> | 160:d5399cc887bb | 84 | pin_mode(td, PullUp); |
<> | 160:d5399cc887bb | 85 | } |
<> | 160:d5399cc887bb | 86 | |
AnnaBridge | 175:b96e65c34a4d | 87 | /* Use default values for rist init */ |
AnnaBridge | 175:b96e65c34a4d | 88 | obj->CanHandle.Instance = (CAN_TypeDef *)can; |
AnnaBridge | 175:b96e65c34a4d | 89 | obj->CanHandle.Init.TTCM = DISABLE; |
AnnaBridge | 175:b96e65c34a4d | 90 | obj->CanHandle.Init.ABOM = DISABLE; |
AnnaBridge | 175:b96e65c34a4d | 91 | obj->CanHandle.Init.AWUM = DISABLE; |
AnnaBridge | 175:b96e65c34a4d | 92 | obj->CanHandle.Init.NART = DISABLE; |
AnnaBridge | 175:b96e65c34a4d | 93 | obj->CanHandle.Init.RFLM = DISABLE; |
AnnaBridge | 175:b96e65c34a4d | 94 | obj->CanHandle.Init.TXFP = DISABLE; |
AnnaBridge | 175:b96e65c34a4d | 95 | obj->CanHandle.Init.Mode = CAN_MODE_NORMAL; |
AnnaBridge | 175:b96e65c34a4d | 96 | obj->CanHandle.Init.SJW = CAN_SJW_1TQ; |
AnnaBridge | 175:b96e65c34a4d | 97 | obj->CanHandle.Init.BS1 = CAN_BS1_6TQ; |
AnnaBridge | 175:b96e65c34a4d | 98 | obj->CanHandle.Init.BS2 = CAN_BS2_8TQ; |
AnnaBridge | 175:b96e65c34a4d | 99 | obj->CanHandle.Init.Prescaler = 2; |
<> | 160:d5399cc887bb | 100 | |
AnnaBridge | 175:b96e65c34a4d | 101 | /* Store frequency to be restored in case of reset */ |
AnnaBridge | 175:b96e65c34a4d | 102 | obj->hz = hz; |
<> | 160:d5399cc887bb | 103 | |
AnnaBridge | 175:b96e65c34a4d | 104 | can_registers_init(obj); |
<> | 160:d5399cc887bb | 105 | |
Anna Bridge |
181:96ed750bd169 | 106 | /* Bits 27:14 are available for dual CAN configuration and are reserved for |
Anna Bridge |
181:96ed750bd169 | 107 | single CAN configuration: */ |
Anna Bridge |
181:96ed750bd169 | 108 | #if defined(CAN3_BASE) && (CAN_NUM > 2) |
Anna Bridge |
181:96ed750bd169 | 109 | uint32_t filter_number = (can == CAN_1 || can == CAN_3) ? 0 : 14; |
Anna Bridge |
181:96ed750bd169 | 110 | #else |
AnnaBridge | 175:b96e65c34a4d | 111 | uint32_t filter_number = (can == CAN_1) ? 0 : 14; |
Anna Bridge |
181:96ed750bd169 | 112 | #endif |
<> | 160:d5399cc887bb | 113 | can_filter(obj, 0, 0, CANStandard, filter_number); |
<> | 160:d5399cc887bb | 114 | } |
<> | 160:d5399cc887bb | 115 | |
AnnaBridge | 175:b96e65c34a4d | 116 | |
<> | 160:d5399cc887bb | 117 | void can_irq_init(can_t *obj, can_irq_handler handler, uint32_t id) |
<> | 160:d5399cc887bb | 118 | { |
<> | 160:d5399cc887bb | 119 | irq_handler = handler; |
<> | 160:d5399cc887bb | 120 | can_irq_ids[obj->index] = id; |
<> | 160:d5399cc887bb | 121 | } |
<> | 160:d5399cc887bb | 122 | |
<> | 160:d5399cc887bb | 123 | void can_irq_free(can_t *obj) |
<> | 160:d5399cc887bb | 124 | { |
AnnaBridge | 175:b96e65c34a4d | 125 | CAN_TypeDef *can = obj->CanHandle.Instance; |
<> | 160:d5399cc887bb | 126 | |
<> | 160:d5399cc887bb | 127 | can->IER &= ~(CAN_IT_FMP0 | CAN_IT_FMP1 | CAN_IT_TME | \ |
<> | 160:d5399cc887bb | 128 | CAN_IT_ERR | CAN_IT_EPV | CAN_IT_BOF); |
AnnaBridge | 167:e84263d55307 | 129 | can_irq_ids[obj->index] = 0; |
<> | 160:d5399cc887bb | 130 | } |
<> | 160:d5399cc887bb | 131 | |
<> | 160:d5399cc887bb | 132 | void can_free(can_t *obj) |
<> | 160:d5399cc887bb | 133 | { |
AnnaBridge | 175:b96e65c34a4d | 134 | CANName can = (CANName) obj->CanHandle.Instance; |
<> | 160:d5399cc887bb | 135 | // Reset CAN and disable clock |
AnnaBridge | 175:b96e65c34a4d | 136 | if (can == CAN_1) { |
<> | 160:d5399cc887bb | 137 | __HAL_RCC_CAN1_FORCE_RESET(); |
<> | 160:d5399cc887bb | 138 | __HAL_RCC_CAN1_RELEASE_RESET(); |
<> | 160:d5399cc887bb | 139 | __HAL_RCC_CAN1_CLK_DISABLE(); |
<> | 160:d5399cc887bb | 140 | } |
Anna Bridge |
181:96ed750bd169 | 141 | #if defined(CAN2_BASE) && (CAN_NUM > 1) |
AnnaBridge | 175:b96e65c34a4d | 142 | if (can == CAN_2) { |
<> | 160:d5399cc887bb | 143 | __HAL_RCC_CAN2_FORCE_RESET(); |
<> | 160:d5399cc887bb | 144 | __HAL_RCC_CAN2_RELEASE_RESET(); |
<> | 160:d5399cc887bb | 145 | __HAL_RCC_CAN2_CLK_DISABLE(); |
<> | 160:d5399cc887bb | 146 | } |
<> | 160:d5399cc887bb | 147 | #endif |
Anna Bridge |
181:96ed750bd169 | 148 | #if defined(CAN3_BASE) && (CAN_NUM > 2) |
AnnaBridge | 179:79309dc6340a | 149 | if (can == CAN_3) { |
AnnaBridge | 179:79309dc6340a | 150 | __HAL_RCC_CAN3_FORCE_RESET(); |
AnnaBridge | 179:79309dc6340a | 151 | __HAL_RCC_CAN3_RELEASE_RESET(); |
AnnaBridge | 179:79309dc6340a | 152 | __HAL_RCC_CAN3_CLK_DISABLE(); |
AnnaBridge | 179:79309dc6340a | 153 | } |
AnnaBridge | 179:79309dc6340a | 154 | #endif |
<> | 160:d5399cc887bb | 155 | } |
<> | 160:d5399cc887bb | 156 | |
<> | 160:d5399cc887bb | 157 | // The following table is used to program bit_timing. It is an adjustment of the sample |
<> | 160:d5399cc887bb | 158 | // point by synchronizing on the start-bit edge and resynchronizing on the following edges. |
<> | 160:d5399cc887bb | 159 | // This table has the sampling points as close to 75% as possible (most commonly used). |
<> | 160:d5399cc887bb | 160 | // The first value is TSEG1, the second TSEG2. |
<> | 160:d5399cc887bb | 161 | static const int timing_pts[23][2] = { |
<> | 160:d5399cc887bb | 162 | {0x0, 0x0}, // 2, 50% |
<> | 160:d5399cc887bb | 163 | {0x1, 0x0}, // 3, 67% |
<> | 160:d5399cc887bb | 164 | {0x2, 0x0}, // 4, 75% |
<> | 160:d5399cc887bb | 165 | {0x3, 0x0}, // 5, 80% |
<> | 160:d5399cc887bb | 166 | {0x3, 0x1}, // 6, 67% |
<> | 160:d5399cc887bb | 167 | {0x4, 0x1}, // 7, 71% |
<> | 160:d5399cc887bb | 168 | {0x5, 0x1}, // 8, 75% |
<> | 160:d5399cc887bb | 169 | {0x6, 0x1}, // 9, 78% |
<> | 160:d5399cc887bb | 170 | {0x6, 0x2}, // 10, 70% |
<> | 160:d5399cc887bb | 171 | {0x7, 0x2}, // 11, 73% |
<> | 160:d5399cc887bb | 172 | {0x8, 0x2}, // 12, 75% |
<> | 160:d5399cc887bb | 173 | {0x9, 0x2}, // 13, 77% |
<> | 160:d5399cc887bb | 174 | {0x9, 0x3}, // 14, 71% |
<> | 160:d5399cc887bb | 175 | {0xA, 0x3}, // 15, 73% |
<> | 160:d5399cc887bb | 176 | {0xB, 0x3}, // 16, 75% |
<> | 160:d5399cc887bb | 177 | {0xC, 0x3}, // 17, 76% |
<> | 160:d5399cc887bb | 178 | {0xD, 0x3}, // 18, 78% |
<> | 160:d5399cc887bb | 179 | {0xD, 0x4}, // 19, 74% |
<> | 160:d5399cc887bb | 180 | {0xE, 0x4}, // 20, 75% |
<> | 160:d5399cc887bb | 181 | {0xF, 0x4}, // 21, 76% |
<> | 160:d5399cc887bb | 182 | {0xF, 0x5}, // 22, 73% |
<> | 160:d5399cc887bb | 183 | {0xF, 0x6}, // 23, 70% |
<> | 160:d5399cc887bb | 184 | {0xF, 0x7}, // 24, 67% |
<> | 160:d5399cc887bb | 185 | }; |
<> | 160:d5399cc887bb | 186 | |
<> | 160:d5399cc887bb | 187 | static unsigned int can_speed(unsigned int pclk, unsigned int cclk, unsigned char psjw) |
<> | 160:d5399cc887bb | 188 | { |
<> | 160:d5399cc887bb | 189 | uint32_t btr; |
<> | 160:d5399cc887bb | 190 | uint16_t brp = 0; |
<> | 160:d5399cc887bb | 191 | uint32_t calcbit; |
<> | 160:d5399cc887bb | 192 | uint32_t bitwidth; |
<> | 160:d5399cc887bb | 193 | int hit = 0; |
<> | 160:d5399cc887bb | 194 | int bits; |
<> | 160:d5399cc887bb | 195 | |
<> | 160:d5399cc887bb | 196 | bitwidth = (pclk / cclk); |
<> | 160:d5399cc887bb | 197 | |
<> | 160:d5399cc887bb | 198 | brp = bitwidth / 0x18; |
<> | 160:d5399cc887bb | 199 | while ((!hit) && (brp < bitwidth / 4)) { |
<> | 160:d5399cc887bb | 200 | brp++; |
<> | 160:d5399cc887bb | 201 | for (bits = 22; bits > 0; bits--) { |
<> | 160:d5399cc887bb | 202 | calcbit = (bits + 3) * (brp + 1); |
<> | 160:d5399cc887bb | 203 | if (calcbit == bitwidth) { |
<> | 160:d5399cc887bb | 204 | hit = 1; |
<> | 160:d5399cc887bb | 205 | break; |
<> | 160:d5399cc887bb | 206 | } |
<> | 160:d5399cc887bb | 207 | } |
<> | 160:d5399cc887bb | 208 | } |
<> | 160:d5399cc887bb | 209 | |
<> | 160:d5399cc887bb | 210 | if (hit) { |
AnnaBridge | 173:7d866c31b3c5 | 211 | btr = ((timing_pts[bits][1] << CAN_BTR_TS2_Pos) & CAN_BTR_TS2) | |
AnnaBridge | 173:7d866c31b3c5 | 212 | ((timing_pts[bits][0] << CAN_BTR_TS1_Pos) & CAN_BTR_TS1) | |
AnnaBridge | 173:7d866c31b3c5 | 213 | ((psjw << CAN_BTR_SJW_Pos) & CAN_BTR_SJW) | |
AnnaBridge | 173:7d866c31b3c5 | 214 | ((brp << CAN_BTR_BRP_Pos) & CAN_BTR_BRP); |
<> | 160:d5399cc887bb | 215 | } else { |
<> | 160:d5399cc887bb | 216 | btr = 0xFFFFFFFF; |
<> | 160:d5399cc887bb | 217 | } |
<> | 160:d5399cc887bb | 218 | |
<> | 160:d5399cc887bb | 219 | return btr; |
<> | 160:d5399cc887bb | 220 | |
<> | 160:d5399cc887bb | 221 | } |
<> | 160:d5399cc887bb | 222 | |
<> | 160:d5399cc887bb | 223 | int can_frequency(can_t *obj, int f) |
<> | 160:d5399cc887bb | 224 | { |
<> | 160:d5399cc887bb | 225 | int pclk = HAL_RCC_GetPCLK1Freq(); |
<> | 160:d5399cc887bb | 226 | int btr = can_speed(pclk, (unsigned int)f, 1); |
AnnaBridge | 175:b96e65c34a4d | 227 | CAN_TypeDef *can = obj->CanHandle.Instance; |
AnnaBridge | 167:e84263d55307 | 228 | uint32_t tickstart = 0; |
AnnaBridge | 167:e84263d55307 | 229 | int status = 1; |
<> | 160:d5399cc887bb | 230 | |
<> | 160:d5399cc887bb | 231 | if (btr > 0) { |
<> | 160:d5399cc887bb | 232 | can->MCR |= CAN_MCR_INRQ ; |
AnnaBridge | 167:e84263d55307 | 233 | /* Get tick */ |
AnnaBridge | 167:e84263d55307 | 234 | tickstart = HAL_GetTick(); |
<> | 160:d5399cc887bb | 235 | while ((can->MSR & CAN_MSR_INAK) != CAN_MSR_INAK) { |
AnnaBridge | 167:e84263d55307 | 236 | if ((HAL_GetTick() - tickstart) > 2) { |
AnnaBridge | 167:e84263d55307 | 237 | status = 0; |
AnnaBridge | 167:e84263d55307 | 238 | break; |
AnnaBridge | 167:e84263d55307 | 239 | } |
<> | 160:d5399cc887bb | 240 | } |
AnnaBridge | 167:e84263d55307 | 241 | if (status != 0) { |
AnnaBridge | 175:b96e65c34a4d | 242 | /* Do not erase all BTR registers (e.g. silent mode), only the |
AnnaBridge | 175:b96e65c34a4d | 243 | * ones calculated in can_speed */ |
AnnaBridge | 175:b96e65c34a4d | 244 | can->BTR &= ~(CAN_BTR_TS2 | CAN_BTR_TS1 | CAN_BTR_SJW | CAN_BTR_BRP); |
AnnaBridge | 175:b96e65c34a4d | 245 | can->BTR |= btr; |
AnnaBridge | 175:b96e65c34a4d | 246 | |
AnnaBridge | 167:e84263d55307 | 247 | can->MCR &= ~(uint32_t)CAN_MCR_INRQ; |
AnnaBridge | 167:e84263d55307 | 248 | /* Get tick */ |
AnnaBridge | 167:e84263d55307 | 249 | tickstart = HAL_GetTick(); |
AnnaBridge | 167:e84263d55307 | 250 | while ((can->MSR & CAN_MSR_INAK) == CAN_MSR_INAK) { |
AnnaBridge | 167:e84263d55307 | 251 | if ((HAL_GetTick() - tickstart) > 2) { |
AnnaBridge | 167:e84263d55307 | 252 | status = 0; |
AnnaBridge | 167:e84263d55307 | 253 | break; |
AnnaBridge | 167:e84263d55307 | 254 | } |
AnnaBridge | 167:e84263d55307 | 255 | } |
AnnaBridge | 167:e84263d55307 | 256 | if (status == 0) { |
AnnaBridge | 167:e84263d55307 | 257 | error("can ESR 0x%04x.%04x + timeout status %d", (can->ESR & 0xFFFF0000) >> 16, (can->ESR & 0xFFFF), status); |
AnnaBridge | 167:e84263d55307 | 258 | } |
AnnaBridge | 167:e84263d55307 | 259 | } else { |
AnnaBridge | 167:e84263d55307 | 260 | error("can init request timeout\n"); |
<> | 160:d5399cc887bb | 261 | } |
<> | 160:d5399cc887bb | 262 | } else { |
AnnaBridge | 167:e84263d55307 | 263 | status = 0; |
<> | 160:d5399cc887bb | 264 | } |
AnnaBridge | 167:e84263d55307 | 265 | return status; |
<> | 160:d5399cc887bb | 266 | } |
<> | 160:d5399cc887bb | 267 | |
<> | 160:d5399cc887bb | 268 | int can_write(can_t *obj, CAN_Message msg, int cc) |
<> | 160:d5399cc887bb | 269 | { |
<> | 160:d5399cc887bb | 270 | uint32_t transmitmailbox = CAN_TXSTATUS_NOMAILBOX; |
AnnaBridge | 175:b96e65c34a4d | 271 | CAN_TypeDef *can = obj->CanHandle.Instance; |
<> | 160:d5399cc887bb | 272 | |
<> | 160:d5399cc887bb | 273 | /* Select one empty transmit mailbox */ |
<> | 160:d5399cc887bb | 274 | if ((can->TSR & CAN_TSR_TME0) == CAN_TSR_TME0) { |
<> | 160:d5399cc887bb | 275 | transmitmailbox = 0; |
<> | 160:d5399cc887bb | 276 | } else if ((can->TSR & CAN_TSR_TME1) == CAN_TSR_TME1) { |
<> | 160:d5399cc887bb | 277 | transmitmailbox = 1; |
<> | 160:d5399cc887bb | 278 | } else if ((can->TSR & CAN_TSR_TME2) == CAN_TSR_TME2) { |
<> | 160:d5399cc887bb | 279 | transmitmailbox = 2; |
<> | 160:d5399cc887bb | 280 | } else { |
<> | 160:d5399cc887bb | 281 | return 0; |
<> | 160:d5399cc887bb | 282 | } |
<> | 160:d5399cc887bb | 283 | |
<> | 160:d5399cc887bb | 284 | can->sTxMailBox[transmitmailbox].TIR &= CAN_TI0R_TXRQ; |
<> | 160:d5399cc887bb | 285 | if (!(msg.format)) { |
Anna Bridge |
181:96ed750bd169 | 286 | can->sTxMailBox[transmitmailbox].TIR |= ((msg.id << 21) | (msg.type << 1)); |
<> | 160:d5399cc887bb | 287 | } else { |
Anna Bridge |
181:96ed750bd169 | 288 | can->sTxMailBox[transmitmailbox].TIR |= ((msg.id << 3) | CAN_ID_EXT | (msg.type << 1)); |
<> | 160:d5399cc887bb | 289 | } |
AnnaBridge | 167:e84263d55307 | 290 | |
<> | 160:d5399cc887bb | 291 | /* Set up the DLC */ |
<> | 160:d5399cc887bb | 292 | can->sTxMailBox[transmitmailbox].TDTR &= (uint32_t)0xFFFFFFF0; |
<> | 160:d5399cc887bb | 293 | can->sTxMailBox[transmitmailbox].TDTR |= (msg.len & (uint8_t)0x0000000F); |
AnnaBridge | 167:e84263d55307 | 294 | |
<> | 160:d5399cc887bb | 295 | /* Set up the data field */ |
<> | 160:d5399cc887bb | 296 | can->sTxMailBox[transmitmailbox].TDLR = (((uint32_t)msg.data[3] << 24) | |
AnnaBridge | 167:e84263d55307 | 297 | ((uint32_t)msg.data[2] << 16) | |
AnnaBridge | 167:e84263d55307 | 298 | ((uint32_t)msg.data[1] << 8) | |
AnnaBridge | 167:e84263d55307 | 299 | ((uint32_t)msg.data[0])); |
<> | 160:d5399cc887bb | 300 | can->sTxMailBox[transmitmailbox].TDHR = (((uint32_t)msg.data[7] << 24) | |
AnnaBridge | 167:e84263d55307 | 301 | ((uint32_t)msg.data[6] << 16) | |
AnnaBridge | 167:e84263d55307 | 302 | ((uint32_t)msg.data[5] << 8) | |
<> | 160:d5399cc887bb | 303 | ((uint32_t)msg.data[4])); |
<> | 160:d5399cc887bb | 304 | /* Request transmission */ |
<> | 160:d5399cc887bb | 305 | can->sTxMailBox[transmitmailbox].TIR |= CAN_TI0R_TXRQ; |
<> | 160:d5399cc887bb | 306 | |
<> | 160:d5399cc887bb | 307 | return 1; |
<> | 160:d5399cc887bb | 308 | } |
<> | 160:d5399cc887bb | 309 | |
<> | 160:d5399cc887bb | 310 | int can_read(can_t *obj, CAN_Message *msg, int handle) |
<> | 160:d5399cc887bb | 311 | { |
<> | 160:d5399cc887bb | 312 | //handle is the FIFO number |
<> | 160:d5399cc887bb | 313 | |
AnnaBridge | 175:b96e65c34a4d | 314 | CAN_TypeDef *can = obj->CanHandle.Instance; |
<> | 160:d5399cc887bb | 315 | |
<> | 160:d5399cc887bb | 316 | // check FPM0 which holds the pending message count in FIFO 0 |
<> | 160:d5399cc887bb | 317 | // if no message is pending, return 0 |
<> | 160:d5399cc887bb | 318 | if ((can->RF0R & CAN_RF0R_FMP0) == 0) { |
<> | 160:d5399cc887bb | 319 | return 0; |
<> | 160:d5399cc887bb | 320 | } |
<> | 160:d5399cc887bb | 321 | |
<> | 160:d5399cc887bb | 322 | /* Get the Id */ |
<> | 160:d5399cc887bb | 323 | msg->format = (CANFormat)(((uint8_t)0x04 & can->sFIFOMailBox[handle].RIR) >> 2); |
<> | 160:d5399cc887bb | 324 | if (!msg->format) { |
<> | 160:d5399cc887bb | 325 | msg->id = (uint32_t)0x000007FF & (can->sFIFOMailBox[handle].RIR >> 21); |
<> | 160:d5399cc887bb | 326 | } else { |
<> | 160:d5399cc887bb | 327 | msg->id = (uint32_t)0x1FFFFFFF & (can->sFIFOMailBox[handle].RIR >> 3); |
<> | 160:d5399cc887bb | 328 | } |
<> | 160:d5399cc887bb | 329 | |
<> | 160:d5399cc887bb | 330 | msg->type = (CANType)(((uint8_t)0x02 & can->sFIFOMailBox[handle].RIR) >> 1); |
<> | 160:d5399cc887bb | 331 | /* Get the DLC */ |
<> | 160:d5399cc887bb | 332 | msg->len = (uint8_t)0x0F & can->sFIFOMailBox[handle].RDTR; |
<> | 160:d5399cc887bb | 333 | /* Get the FMI */ |
<> | 160:d5399cc887bb | 334 | // msg->FMI = (uint8_t)0xFF & (can->sFIFOMailBox[handle].RDTR >> 8); |
<> | 160:d5399cc887bb | 335 | /* Get the data field */ |
<> | 160:d5399cc887bb | 336 | msg->data[0] = (uint8_t)0xFF & can->sFIFOMailBox[handle].RDLR; |
<> | 160:d5399cc887bb | 337 | msg->data[1] = (uint8_t)0xFF & (can->sFIFOMailBox[handle].RDLR >> 8); |
<> | 160:d5399cc887bb | 338 | msg->data[2] = (uint8_t)0xFF & (can->sFIFOMailBox[handle].RDLR >> 16); |
<> | 160:d5399cc887bb | 339 | msg->data[3] = (uint8_t)0xFF & (can->sFIFOMailBox[handle].RDLR >> 24); |
<> | 160:d5399cc887bb | 340 | msg->data[4] = (uint8_t)0xFF & can->sFIFOMailBox[handle].RDHR; |
<> | 160:d5399cc887bb | 341 | msg->data[5] = (uint8_t)0xFF & (can->sFIFOMailBox[handle].RDHR >> 8); |
<> | 160:d5399cc887bb | 342 | msg->data[6] = (uint8_t)0xFF & (can->sFIFOMailBox[handle].RDHR >> 16); |
<> | 160:d5399cc887bb | 343 | msg->data[7] = (uint8_t)0xFF & (can->sFIFOMailBox[handle].RDHR >> 24); |
<> | 160:d5399cc887bb | 344 | |
<> | 160:d5399cc887bb | 345 | /* Release the FIFO */ |
<> | 160:d5399cc887bb | 346 | if (handle == CAN_FIFO0) { |
<> | 160:d5399cc887bb | 347 | /* Release FIFO0 */ |
<> | 160:d5399cc887bb | 348 | can->RF0R |= CAN_RF0R_RFOM0; |
<> | 160:d5399cc887bb | 349 | } else { /* FIFONumber == CAN_FIFO1 */ |
<> | 160:d5399cc887bb | 350 | /* Release FIFO1 */ |
<> | 160:d5399cc887bb | 351 | can->RF1R |= CAN_RF1R_RFOM1; |
<> | 160:d5399cc887bb | 352 | } |
<> | 160:d5399cc887bb | 353 | |
<> | 160:d5399cc887bb | 354 | return 1; |
<> | 160:d5399cc887bb | 355 | } |
<> | 160:d5399cc887bb | 356 | |
<> | 160:d5399cc887bb | 357 | void can_reset(can_t *obj) |
<> | 160:d5399cc887bb | 358 | { |
AnnaBridge | 175:b96e65c34a4d | 359 | CAN_TypeDef *can = obj->CanHandle.Instance; |
AnnaBridge | 175:b96e65c34a4d | 360 | |
AnnaBridge | 175:b96e65c34a4d | 361 | /* Reset IP and delete errors */ |
<> | 160:d5399cc887bb | 362 | can->MCR |= CAN_MCR_RESET; |
<> | 160:d5399cc887bb | 363 | can->ESR = 0x0; |
AnnaBridge | 175:b96e65c34a4d | 364 | |
AnnaBridge | 175:b96e65c34a4d | 365 | /* restore registers state as saved in obj context */ |
AnnaBridge | 175:b96e65c34a4d | 366 | can_registers_init(obj); |
<> | 160:d5399cc887bb | 367 | } |
<> | 160:d5399cc887bb | 368 | |
<> | 160:d5399cc887bb | 369 | unsigned char can_rderror(can_t *obj) |
<> | 160:d5399cc887bb | 370 | { |
AnnaBridge | 175:b96e65c34a4d | 371 | CAN_TypeDef *can = obj->CanHandle.Instance; |
<> | 160:d5399cc887bb | 372 | return (can->ESR >> 24) & 0xFF; |
<> | 160:d5399cc887bb | 373 | } |
<> | 160:d5399cc887bb | 374 | |
<> | 160:d5399cc887bb | 375 | unsigned char can_tderror(can_t *obj) |
<> | 160:d5399cc887bb | 376 | { |
AnnaBridge | 175:b96e65c34a4d | 377 | CAN_TypeDef *can = obj->CanHandle.Instance; |
<> | 160:d5399cc887bb | 378 | return (can->ESR >> 16) & 0xFF; |
<> | 160:d5399cc887bb | 379 | } |
<> | 160:d5399cc887bb | 380 | |
<> | 160:d5399cc887bb | 381 | void can_monitor(can_t *obj, int silent) |
<> | 160:d5399cc887bb | 382 | { |
AnnaBridge | 175:b96e65c34a4d | 383 | CanMode mode = MODE_NORMAL; |
AnnaBridge | 175:b96e65c34a4d | 384 | /* Update current state w/ or w/o silent */ |
AnnaBridge | 175:b96e65c34a4d | 385 | if(silent) { |
AnnaBridge | 175:b96e65c34a4d | 386 | switch (obj->CanHandle.Init.Mode) { |
AnnaBridge | 175:b96e65c34a4d | 387 | case CAN_MODE_LOOPBACK: |
AnnaBridge | 175:b96e65c34a4d | 388 | case CAN_MODE_SILENT_LOOPBACK: |
AnnaBridge | 175:b96e65c34a4d | 389 | mode = MODE_TEST_SILENT; |
AnnaBridge | 175:b96e65c34a4d | 390 | break; |
AnnaBridge | 175:b96e65c34a4d | 391 | default: |
AnnaBridge | 175:b96e65c34a4d | 392 | mode = MODE_SILENT; |
AnnaBridge | 175:b96e65c34a4d | 393 | break; |
AnnaBridge | 175:b96e65c34a4d | 394 | } |
AnnaBridge | 175:b96e65c34a4d | 395 | } else { |
AnnaBridge | 175:b96e65c34a4d | 396 | switch (obj->CanHandle.Init.Mode) { |
AnnaBridge | 175:b96e65c34a4d | 397 | case CAN_MODE_LOOPBACK: |
AnnaBridge | 175:b96e65c34a4d | 398 | case CAN_MODE_SILENT_LOOPBACK: |
AnnaBridge | 175:b96e65c34a4d | 399 | mode = MODE_TEST_LOCAL; |
AnnaBridge | 175:b96e65c34a4d | 400 | break; |
AnnaBridge | 175:b96e65c34a4d | 401 | default: |
AnnaBridge | 175:b96e65c34a4d | 402 | mode = MODE_NORMAL; |
AnnaBridge | 175:b96e65c34a4d | 403 | break; |
AnnaBridge | 175:b96e65c34a4d | 404 | } |
<> | 160:d5399cc887bb | 405 | } |
<> | 160:d5399cc887bb | 406 | |
AnnaBridge | 175:b96e65c34a4d | 407 | can_mode(obj, mode); |
<> | 160:d5399cc887bb | 408 | } |
<> | 160:d5399cc887bb | 409 | |
<> | 160:d5399cc887bb | 410 | int can_mode(can_t *obj, CanMode mode) |
<> | 160:d5399cc887bb | 411 | { |
<> | 160:d5399cc887bb | 412 | int success = 0; |
AnnaBridge | 175:b96e65c34a4d | 413 | CAN_TypeDef *can = obj->CanHandle.Instance; |
<> | 160:d5399cc887bb | 414 | |
<> | 160:d5399cc887bb | 415 | can->MCR |= CAN_MCR_INRQ ; |
<> | 160:d5399cc887bb | 416 | while ((can->MSR & CAN_MSR_INAK) != CAN_MSR_INAK) { |
<> | 160:d5399cc887bb | 417 | } |
<> | 160:d5399cc887bb | 418 | |
<> | 160:d5399cc887bb | 419 | switch (mode) { |
<> | 160:d5399cc887bb | 420 | case MODE_NORMAL: |
AnnaBridge | 175:b96e65c34a4d | 421 | obj->CanHandle.Init.Mode = CAN_MODE_NORMAL; |
<> | 160:d5399cc887bb | 422 | can->BTR &= ~(CAN_BTR_SILM | CAN_BTR_LBKM); |
<> | 160:d5399cc887bb | 423 | success = 1; |
<> | 160:d5399cc887bb | 424 | break; |
<> | 160:d5399cc887bb | 425 | case MODE_SILENT: |
AnnaBridge | 175:b96e65c34a4d | 426 | obj->CanHandle.Init.Mode = CAN_MODE_SILENT; |
<> | 160:d5399cc887bb | 427 | can->BTR |= CAN_BTR_SILM; |
<> | 160:d5399cc887bb | 428 | can->BTR &= ~CAN_BTR_LBKM; |
<> | 160:d5399cc887bb | 429 | success = 1; |
<> | 160:d5399cc887bb | 430 | break; |
<> | 160:d5399cc887bb | 431 | case MODE_TEST_GLOBAL: |
<> | 160:d5399cc887bb | 432 | case MODE_TEST_LOCAL: |
AnnaBridge | 175:b96e65c34a4d | 433 | obj->CanHandle.Init.Mode = CAN_MODE_LOOPBACK; |
<> | 160:d5399cc887bb | 434 | can->BTR |= CAN_BTR_LBKM; |
<> | 160:d5399cc887bb | 435 | can->BTR &= ~CAN_BTR_SILM; |
<> | 160:d5399cc887bb | 436 | success = 1; |
<> | 160:d5399cc887bb | 437 | break; |
<> | 160:d5399cc887bb | 438 | case MODE_TEST_SILENT: |
AnnaBridge | 175:b96e65c34a4d | 439 | obj->CanHandle.Init.Mode = CAN_MODE_SILENT_LOOPBACK; |
<> | 160:d5399cc887bb | 440 | can->BTR |= (CAN_BTR_SILM | CAN_BTR_LBKM); |
<> | 160:d5399cc887bb | 441 | success = 1; |
<> | 160:d5399cc887bb | 442 | break; |
<> | 160:d5399cc887bb | 443 | default: |
<> | 160:d5399cc887bb | 444 | success = 0; |
<> | 160:d5399cc887bb | 445 | break; |
<> | 160:d5399cc887bb | 446 | } |
<> | 160:d5399cc887bb | 447 | |
<> | 160:d5399cc887bb | 448 | can->MCR &= ~(uint32_t)CAN_MCR_INRQ; |
<> | 160:d5399cc887bb | 449 | while ((can->MSR & CAN_MSR_INAK) == CAN_MSR_INAK) { |
<> | 160:d5399cc887bb | 450 | } |
<> | 160:d5399cc887bb | 451 | |
<> | 160:d5399cc887bb | 452 | return success; |
<> | 160:d5399cc887bb | 453 | } |
<> | 160:d5399cc887bb | 454 | |
<> | 160:d5399cc887bb | 455 | int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle) |
<> | 160:d5399cc887bb | 456 | { |
<> | 160:d5399cc887bb | 457 | int retval = 0; |
<> | 160:d5399cc887bb | 458 | |
<> | 160:d5399cc887bb | 459 | // filter for CANAny format cannot be configured for STM32 |
<> | 160:d5399cc887bb | 460 | if ((format == CANStandard) || (format == CANExtended)) { |
<> | 160:d5399cc887bb | 461 | CAN_FilterConfTypeDef sFilterConfig; |
<> | 160:d5399cc887bb | 462 | sFilterConfig.FilterNumber = handle; |
<> | 160:d5399cc887bb | 463 | sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; |
<> | 160:d5399cc887bb | 464 | sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; |
<> | 160:d5399cc887bb | 465 | |
<> | 160:d5399cc887bb | 466 | if (format == CANStandard) { |
<> | 160:d5399cc887bb | 467 | sFilterConfig.FilterIdHigh = id << 5; |
<> | 160:d5399cc887bb | 468 | sFilterConfig.FilterIdLow = 0x0; |
<> | 160:d5399cc887bb | 469 | sFilterConfig.FilterMaskIdHigh = mask << 5; |
<> | 160:d5399cc887bb | 470 | sFilterConfig.FilterMaskIdLow = 0x0; // allows both remote and data frames |
AnnaBridge | 182:57724642e740 | 471 | } else { // format == CANExtended |
<> | 160:d5399cc887bb | 472 | sFilterConfig.FilterIdHigh = id >> 13; // EXTID[28:13] |
AnnaBridge | 182:57724642e740 | 473 | sFilterConfig.FilterIdLow = (0xFFFF & (id << 3)) | (1 << 2); // EXTID[12:0] + IDE |
<> | 160:d5399cc887bb | 474 | sFilterConfig.FilterMaskIdHigh = mask >> 13; |
AnnaBridge | 182:57724642e740 | 475 | sFilterConfig.FilterMaskIdLow = (0xFFFF & (mask << 3)) | (1 << 2); |
<> | 160:d5399cc887bb | 476 | } |
<> | 160:d5399cc887bb | 477 | |
<> | 160:d5399cc887bb | 478 | sFilterConfig.FilterFIFOAssignment = 0; |
<> | 160:d5399cc887bb | 479 | sFilterConfig.FilterActivation = ENABLE; |
<> | 160:d5399cc887bb | 480 | sFilterConfig.BankNumber = 14 + handle; |
<> | 160:d5399cc887bb | 481 | |
AnnaBridge | 175:b96e65c34a4d | 482 | HAL_CAN_ConfigFilter(&obj->CanHandle, &sFilterConfig); |
<> | 160:d5399cc887bb | 483 | retval = handle; |
<> | 160:d5399cc887bb | 484 | } |
<> | 160:d5399cc887bb | 485 | return retval; |
<> | 160:d5399cc887bb | 486 | } |
<> | 160:d5399cc887bb | 487 | |
<> | 160:d5399cc887bb | 488 | static void can_irq(CANName name, int id) |
<> | 160:d5399cc887bb | 489 | { |
<> | 160:d5399cc887bb | 490 | uint32_t tmp1 = 0, tmp2 = 0, tmp3 = 0; |
AnnaBridge | 175:b96e65c34a4d | 491 | CAN_HandleTypeDef CanHandle; |
<> | 160:d5399cc887bb | 492 | CanHandle.Instance = (CAN_TypeDef *)name; |
<> | 160:d5399cc887bb | 493 | |
<> | 160:d5399cc887bb | 494 | if (__HAL_CAN_GET_IT_SOURCE(&CanHandle, CAN_IT_TME)) { |
<> | 160:d5399cc887bb | 495 | tmp1 = __HAL_CAN_TRANSMIT_STATUS(&CanHandle, CAN_TXMAILBOX_0); |
<> | 160:d5399cc887bb | 496 | tmp2 = __HAL_CAN_TRANSMIT_STATUS(&CanHandle, CAN_TXMAILBOX_1); |
<> | 160:d5399cc887bb | 497 | tmp3 = __HAL_CAN_TRANSMIT_STATUS(&CanHandle, CAN_TXMAILBOX_2); |
<> | 160:d5399cc887bb | 498 | if (tmp1) { |
<> | 160:d5399cc887bb | 499 | __HAL_CAN_CLEAR_FLAG(&CanHandle, CAN_FLAG_RQCP0); |
<> | 160:d5399cc887bb | 500 | } |
<> | 160:d5399cc887bb | 501 | if (tmp2) { |
<> | 160:d5399cc887bb | 502 | __HAL_CAN_CLEAR_FLAG(&CanHandle, CAN_FLAG_RQCP1); |
<> | 160:d5399cc887bb | 503 | } |
<> | 160:d5399cc887bb | 504 | if (tmp3) { |
<> | 160:d5399cc887bb | 505 | __HAL_CAN_CLEAR_FLAG(&CanHandle, CAN_FLAG_RQCP2); |
<> | 160:d5399cc887bb | 506 | } |
<> | 160:d5399cc887bb | 507 | if (tmp1 || tmp2 || tmp3) { |
<> | 160:d5399cc887bb | 508 | irq_handler(can_irq_ids[id], IRQ_TX); |
<> | 160:d5399cc887bb | 509 | } |
<> | 160:d5399cc887bb | 510 | } |
<> | 160:d5399cc887bb | 511 | |
<> | 160:d5399cc887bb | 512 | tmp1 = __HAL_CAN_MSG_PENDING(&CanHandle, CAN_FIFO0); |
<> | 160:d5399cc887bb | 513 | tmp2 = __HAL_CAN_GET_IT_SOURCE(&CanHandle, CAN_IT_FMP0); |
<> | 160:d5399cc887bb | 514 | |
<> | 160:d5399cc887bb | 515 | if ((tmp1 != 0) && tmp2) { |
<> | 160:d5399cc887bb | 516 | irq_handler(can_irq_ids[id], IRQ_RX); |
<> | 160:d5399cc887bb | 517 | } |
<> | 160:d5399cc887bb | 518 | |
<> | 160:d5399cc887bb | 519 | tmp1 = __HAL_CAN_GET_FLAG(&CanHandle, CAN_FLAG_EPV); |
<> | 160:d5399cc887bb | 520 | tmp2 = __HAL_CAN_GET_IT_SOURCE(&CanHandle, CAN_IT_EPV); |
<> | 160:d5399cc887bb | 521 | tmp3 = __HAL_CAN_GET_IT_SOURCE(&CanHandle, CAN_IT_ERR); |
<> | 160:d5399cc887bb | 522 | |
<> | 160:d5399cc887bb | 523 | if (tmp1 && tmp2 && tmp3) { |
<> | 160:d5399cc887bb | 524 | irq_handler(can_irq_ids[id], IRQ_PASSIVE); |
<> | 160:d5399cc887bb | 525 | } |
<> | 160:d5399cc887bb | 526 | |
<> | 160:d5399cc887bb | 527 | tmp1 = __HAL_CAN_GET_FLAG(&CanHandle, CAN_FLAG_BOF); |
<> | 160:d5399cc887bb | 528 | tmp2 = __HAL_CAN_GET_IT_SOURCE(&CanHandle, CAN_IT_BOF); |
<> | 160:d5399cc887bb | 529 | tmp3 = __HAL_CAN_GET_IT_SOURCE(&CanHandle, CAN_IT_ERR); |
<> | 160:d5399cc887bb | 530 | if (tmp1 && tmp2 && tmp3) { |
<> | 160:d5399cc887bb | 531 | irq_handler(can_irq_ids[id], IRQ_BUS); |
<> | 160:d5399cc887bb | 532 | } |
<> | 160:d5399cc887bb | 533 | |
<> | 160:d5399cc887bb | 534 | tmp3 = __HAL_CAN_GET_IT_SOURCE(&CanHandle, CAN_IT_ERR); |
<> | 160:d5399cc887bb | 535 | if (tmp1 && tmp2 && tmp3) { |
<> | 160:d5399cc887bb | 536 | irq_handler(can_irq_ids[id], IRQ_ERROR); |
<> | 160:d5399cc887bb | 537 | } |
<> | 160:d5399cc887bb | 538 | } |
<> | 160:d5399cc887bb | 539 | |
<> | 160:d5399cc887bb | 540 | #if defined(TARGET_STM32F0) |
<> | 160:d5399cc887bb | 541 | void CAN_IRQHandler(void) |
<> | 160:d5399cc887bb | 542 | { |
<> | 160:d5399cc887bb | 543 | can_irq(CAN_1, 0); |
<> | 160:d5399cc887bb | 544 | } |
<> | 160:d5399cc887bb | 545 | #elif defined(TARGET_STM32F3) |
<> | 160:d5399cc887bb | 546 | void CAN_RX0_IRQHandler(void) |
<> | 160:d5399cc887bb | 547 | { |
<> | 160:d5399cc887bb | 548 | can_irq(CAN_1, 0); |
<> | 160:d5399cc887bb | 549 | } |
<> | 160:d5399cc887bb | 550 | void CAN_TX_IRQHandler(void) |
<> | 160:d5399cc887bb | 551 | { |
<> | 160:d5399cc887bb | 552 | can_irq(CAN_1, 0); |
<> | 160:d5399cc887bb | 553 | } |
<> | 160:d5399cc887bb | 554 | void CAN_SCE_IRQHandler(void) |
<> | 160:d5399cc887bb | 555 | { |
<> | 160:d5399cc887bb | 556 | can_irq(CAN_1, 0); |
<> | 160:d5399cc887bb | 557 | } |
<> | 160:d5399cc887bb | 558 | #else |
<> | 160:d5399cc887bb | 559 | void CAN1_RX0_IRQHandler(void) |
<> | 160:d5399cc887bb | 560 | { |
<> | 160:d5399cc887bb | 561 | can_irq(CAN_1, 0); |
<> | 160:d5399cc887bb | 562 | } |
<> | 160:d5399cc887bb | 563 | void CAN1_TX_IRQHandler(void) |
<> | 160:d5399cc887bb | 564 | { |
<> | 160:d5399cc887bb | 565 | can_irq(CAN_1, 0); |
<> | 160:d5399cc887bb | 566 | } |
<> | 160:d5399cc887bb | 567 | void CAN1_SCE_IRQHandler(void) |
<> | 160:d5399cc887bb | 568 | { |
<> | 160:d5399cc887bb | 569 | can_irq(CAN_1, 0); |
<> | 160:d5399cc887bb | 570 | } |
Anna Bridge |
181:96ed750bd169 | 571 | #if defined(CAN2_BASE) && (CAN_NUM > 1) |
<> | 160:d5399cc887bb | 572 | void CAN2_RX0_IRQHandler(void) |
<> | 160:d5399cc887bb | 573 | { |
<> | 160:d5399cc887bb | 574 | can_irq(CAN_2, 1); |
<> | 160:d5399cc887bb | 575 | } |
<> | 160:d5399cc887bb | 576 | void CAN2_TX_IRQHandler(void) |
<> | 160:d5399cc887bb | 577 | { |
<> | 160:d5399cc887bb | 578 | can_irq(CAN_2, 1); |
<> | 160:d5399cc887bb | 579 | } |
<> | 160:d5399cc887bb | 580 | void CAN2_SCE_IRQHandler(void) |
<> | 160:d5399cc887bb | 581 | { |
<> | 160:d5399cc887bb | 582 | can_irq(CAN_2, 1); |
<> | 160:d5399cc887bb | 583 | } |
AnnaBridge | 179:79309dc6340a | 584 | #endif |
Anna Bridge |
181:96ed750bd169 | 585 | #if defined(CAN3_BASE) && (CAN_NUM > 2) |
AnnaBridge | 179:79309dc6340a | 586 | void CAN3_RX0_IRQHandler(void) |
AnnaBridge | 179:79309dc6340a | 587 | { |
Anna Bridge |
181:96ed750bd169 | 588 | can_irq(CAN_3, 2); |
AnnaBridge | 179:79309dc6340a | 589 | } |
AnnaBridge | 179:79309dc6340a | 590 | void CAN3_TX_IRQHandler(void) |
AnnaBridge | 179:79309dc6340a | 591 | { |
Anna Bridge |
181:96ed750bd169 | 592 | can_irq(CAN_3, 2); |
AnnaBridge | 179:79309dc6340a | 593 | } |
AnnaBridge | 179:79309dc6340a | 594 | void CAN3_SCE_IRQHandler(void) |
AnnaBridge | 179:79309dc6340a | 595 | { |
Anna Bridge |
181:96ed750bd169 | 596 | can_irq(CAN_3, 2); |
AnnaBridge | 179:79309dc6340a | 597 | } |
AnnaBridge | 179:79309dc6340a | 598 | #endif |
<> | 160:d5399cc887bb | 599 | #endif // else |
<> | 160:d5399cc887bb | 600 | |
<> | 160:d5399cc887bb | 601 | void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable) |
<> | 160:d5399cc887bb | 602 | { |
AnnaBridge | 175:b96e65c34a4d | 603 | CAN_TypeDef *can = obj->CanHandle.Instance; |
<> | 160:d5399cc887bb | 604 | IRQn_Type irq_n = (IRQn_Type)0; |
<> | 160:d5399cc887bb | 605 | uint32_t vector = 0; |
<> | 160:d5399cc887bb | 606 | uint32_t ier; |
<> | 160:d5399cc887bb | 607 | |
AnnaBridge | 175:b96e65c34a4d | 608 | if ((CANName) can == CAN_1) { |
<> | 160:d5399cc887bb | 609 | switch (type) { |
<> | 160:d5399cc887bb | 610 | case IRQ_RX: |
<> | 160:d5399cc887bb | 611 | ier = CAN_IT_FMP0; |
<> | 160:d5399cc887bb | 612 | irq_n = CAN1_IRQ_RX_IRQN; |
<> | 160:d5399cc887bb | 613 | vector = (uint32_t)&CAN1_IRQ_RX_VECT; |
<> | 160:d5399cc887bb | 614 | break; |
<> | 160:d5399cc887bb | 615 | case IRQ_TX: |
<> | 160:d5399cc887bb | 616 | ier = CAN_IT_TME; |
<> | 160:d5399cc887bb | 617 | irq_n = CAN1_IRQ_TX_IRQN; |
<> | 160:d5399cc887bb | 618 | vector = (uint32_t)&CAN1_IRQ_TX_VECT; |
<> | 160:d5399cc887bb | 619 | break; |
<> | 160:d5399cc887bb | 620 | case IRQ_ERROR: |
<> | 160:d5399cc887bb | 621 | ier = CAN_IT_ERR; |
<> | 160:d5399cc887bb | 622 | irq_n = CAN1_IRQ_ERROR_IRQN; |
<> | 160:d5399cc887bb | 623 | vector = (uint32_t)&CAN1_IRQ_ERROR_VECT; |
<> | 160:d5399cc887bb | 624 | break; |
<> | 160:d5399cc887bb | 625 | case IRQ_PASSIVE: |
<> | 160:d5399cc887bb | 626 | ier = CAN_IT_EPV; |
<> | 160:d5399cc887bb | 627 | irq_n = CAN1_IRQ_PASSIVE_IRQN; |
<> | 160:d5399cc887bb | 628 | vector = (uint32_t)&CAN1_IRQ_PASSIVE_VECT; |
<> | 160:d5399cc887bb | 629 | break; |
<> | 160:d5399cc887bb | 630 | case IRQ_BUS: |
<> | 160:d5399cc887bb | 631 | ier = CAN_IT_BOF; |
<> | 160:d5399cc887bb | 632 | irq_n = CAN1_IRQ_BUS_IRQN; |
<> | 160:d5399cc887bb | 633 | vector = (uint32_t)&CAN1_IRQ_BUS_VECT; |
<> | 160:d5399cc887bb | 634 | break; |
<> | 160:d5399cc887bb | 635 | default: |
<> | 160:d5399cc887bb | 636 | return; |
<> | 160:d5399cc887bb | 637 | } |
<> | 160:d5399cc887bb | 638 | } |
Anna Bridge |
181:96ed750bd169 | 639 | #if defined(CAN2_BASE) && (CAN_NUM > 1) |
AnnaBridge | 175:b96e65c34a4d | 640 | else if ((CANName) can == CAN_2) { |
<> | 160:d5399cc887bb | 641 | switch (type) { |
<> | 160:d5399cc887bb | 642 | case IRQ_RX: |
<> | 160:d5399cc887bb | 643 | ier = CAN_IT_FMP0; |
<> | 160:d5399cc887bb | 644 | irq_n = CAN2_IRQ_RX_IRQN; |
<> | 160:d5399cc887bb | 645 | vector = (uint32_t)&CAN2_IRQ_RX_VECT; |
<> | 160:d5399cc887bb | 646 | break; |
<> | 160:d5399cc887bb | 647 | case IRQ_TX: |
<> | 160:d5399cc887bb | 648 | ier = CAN_IT_TME; |
<> | 160:d5399cc887bb | 649 | irq_n = CAN2_IRQ_TX_IRQN; |
<> | 160:d5399cc887bb | 650 | vector = (uint32_t)&CAN2_IRQ_TX_VECT; |
<> | 160:d5399cc887bb | 651 | break; |
<> | 160:d5399cc887bb | 652 | case IRQ_ERROR: |
<> | 160:d5399cc887bb | 653 | ier = CAN_IT_ERR; |
<> | 160:d5399cc887bb | 654 | irq_n = CAN2_IRQ_ERROR_IRQN; |
<> | 160:d5399cc887bb | 655 | vector = (uint32_t)&CAN2_IRQ_ERROR_VECT; |
<> | 160:d5399cc887bb | 656 | break; |
<> | 160:d5399cc887bb | 657 | case IRQ_PASSIVE: |
<> | 160:d5399cc887bb | 658 | ier = CAN_IT_EPV; |
<> | 160:d5399cc887bb | 659 | irq_n = CAN2_IRQ_PASSIVE_IRQN; |
<> | 160:d5399cc887bb | 660 | vector = (uint32_t)&CAN2_IRQ_PASSIVE_VECT; |
<> | 160:d5399cc887bb | 661 | break; |
<> | 160:d5399cc887bb | 662 | case IRQ_BUS: |
<> | 160:d5399cc887bb | 663 | ier = CAN_IT_BOF; |
<> | 160:d5399cc887bb | 664 | irq_n = CAN2_IRQ_BUS_IRQN; |
<> | 160:d5399cc887bb | 665 | vector = (uint32_t)&CAN2_IRQ_BUS_VECT; |
<> | 160:d5399cc887bb | 666 | break; |
<> | 160:d5399cc887bb | 667 | default: |
<> | 160:d5399cc887bb | 668 | return; |
<> | 160:d5399cc887bb | 669 | } |
<> | 160:d5399cc887bb | 670 | } |
<> | 160:d5399cc887bb | 671 | #endif |
Anna Bridge |
181:96ed750bd169 | 672 | #if defined(CAN3_BASE) && (CAN_NUM > 2) |
AnnaBridge | 179:79309dc6340a | 673 | else if ((CANName) can == CAN_3) { |
AnnaBridge | 179:79309dc6340a | 674 | switch (type) { |
AnnaBridge | 179:79309dc6340a | 675 | case IRQ_RX: |
AnnaBridge | 179:79309dc6340a | 676 | ier = CAN_IT_FMP0; |
AnnaBridge | 179:79309dc6340a | 677 | irq_n = CAN3_IRQ_RX_IRQN; |
AnnaBridge | 179:79309dc6340a | 678 | vector = (uint32_t)&CAN3_IRQ_RX_VECT; |
AnnaBridge | 179:79309dc6340a | 679 | break; |
AnnaBridge | 179:79309dc6340a | 680 | case IRQ_TX: |
AnnaBridge | 179:79309dc6340a | 681 | ier = CAN_IT_TME; |
AnnaBridge | 179:79309dc6340a | 682 | irq_n = CAN3_IRQ_TX_IRQN; |
AnnaBridge | 179:79309dc6340a | 683 | vector = (uint32_t)&CAN3_IRQ_TX_VECT; |
AnnaBridge | 179:79309dc6340a | 684 | break; |
AnnaBridge | 179:79309dc6340a | 685 | case IRQ_ERROR: |
AnnaBridge | 179:79309dc6340a | 686 | ier = CAN_IT_ERR; |
AnnaBridge | 179:79309dc6340a | 687 | irq_n = CAN3_IRQ_ERROR_IRQN; |
AnnaBridge | 179:79309dc6340a | 688 | vector = (uint32_t)&CAN3_IRQ_ERROR_VECT; |
AnnaBridge | 179:79309dc6340a | 689 | break; |
AnnaBridge | 179:79309dc6340a | 690 | case IRQ_PASSIVE: |
AnnaBridge | 179:79309dc6340a | 691 | ier = CAN_IT_EPV; |
AnnaBridge | 179:79309dc6340a | 692 | irq_n = CAN3_IRQ_PASSIVE_IRQN; |
AnnaBridge | 179:79309dc6340a | 693 | vector = (uint32_t)&CAN3_IRQ_PASSIVE_VECT; |
AnnaBridge | 179:79309dc6340a | 694 | break; |
AnnaBridge | 179:79309dc6340a | 695 | case IRQ_BUS: |
AnnaBridge | 179:79309dc6340a | 696 | ier = CAN_IT_BOF; |
AnnaBridge | 179:79309dc6340a | 697 | irq_n = CAN3_IRQ_BUS_IRQN; |
AnnaBridge | 179:79309dc6340a | 698 | vector = (uint32_t)&CAN3_IRQ_BUS_VECT; |
AnnaBridge | 179:79309dc6340a | 699 | break; |
AnnaBridge | 179:79309dc6340a | 700 | default: |
AnnaBridge | 179:79309dc6340a | 701 | return; |
AnnaBridge | 179:79309dc6340a | 702 | } |
AnnaBridge | 179:79309dc6340a | 703 | } |
AnnaBridge | 179:79309dc6340a | 704 | #endif |
<> | 160:d5399cc887bb | 705 | else { |
<> | 160:d5399cc887bb | 706 | return; |
<> | 160:d5399cc887bb | 707 | } |
<> | 160:d5399cc887bb | 708 | |
<> | 160:d5399cc887bb | 709 | if (enable) { |
<> | 160:d5399cc887bb | 710 | can->IER |= ier; |
<> | 160:d5399cc887bb | 711 | } else { |
<> | 160:d5399cc887bb | 712 | can->IER &= ~ier; |
<> | 160:d5399cc887bb | 713 | } |
<> | 160:d5399cc887bb | 714 | |
<> | 160:d5399cc887bb | 715 | NVIC_SetVector(irq_n, vector); |
<> | 160:d5399cc887bb | 716 | NVIC_EnableIRQ(irq_n); |
<> | 160:d5399cc887bb | 717 | } |
<> | 160:d5399cc887bb | 718 | |
<> | 160:d5399cc887bb | 719 | #endif // DEVICE_CAN |