mbed library sources. Supersedes mbed-src.
Dependents: Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more
targets/TARGET_GigaDevice/TARGET_GD32E10X/can_api.c@189:f392fc9709a3, 2019-02-20 (annotated)
- Committer:
- AnnaBridge
- Date:
- Wed Feb 20 22:31:08 2019 +0000
- Revision:
- 189:f392fc9709a3
mbed library release version 165
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
AnnaBridge | 189:f392fc9709a3 | 1 | /* mbed Microcontroller Library |
AnnaBridge | 189:f392fc9709a3 | 2 | * Copyright (c) 2018 GigaDevice Semiconductor Inc. |
AnnaBridge | 189:f392fc9709a3 | 3 | * |
AnnaBridge | 189:f392fc9709a3 | 4 | * SPDX-License-Identifier: Apache-2.0 |
AnnaBridge | 189:f392fc9709a3 | 5 | * |
AnnaBridge | 189:f392fc9709a3 | 6 | * Licensed under the Apache License, Version 2.0 (the "License"); |
AnnaBridge | 189:f392fc9709a3 | 7 | * you may not use this file except in compliance with the License. |
AnnaBridge | 189:f392fc9709a3 | 8 | * You may obtain a copy of the License at |
AnnaBridge | 189:f392fc9709a3 | 9 | * |
AnnaBridge | 189:f392fc9709a3 | 10 | * http://www.apache.org/licenses/LICENSE-2.0 |
AnnaBridge | 189:f392fc9709a3 | 11 | * |
AnnaBridge | 189:f392fc9709a3 | 12 | * Unless required by applicable law or agreed to in writing, software |
AnnaBridge | 189:f392fc9709a3 | 13 | * distributed under the License is distributed on an "AS IS" BASIS, |
AnnaBridge | 189:f392fc9709a3 | 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
AnnaBridge | 189:f392fc9709a3 | 15 | * See the License for the specific language governing permissions and |
AnnaBridge | 189:f392fc9709a3 | 16 | * limitations under the License. |
AnnaBridge | 189:f392fc9709a3 | 17 | */ |
AnnaBridge | 189:f392fc9709a3 | 18 | |
AnnaBridge | 189:f392fc9709a3 | 19 | #include "can_api.h" |
AnnaBridge | 189:f392fc9709a3 | 20 | #include "pinmap.h" |
AnnaBridge | 189:f392fc9709a3 | 21 | #include "PeripheralPins.h" |
AnnaBridge | 189:f392fc9709a3 | 22 | #include "mbed_error.h" |
AnnaBridge | 189:f392fc9709a3 | 23 | |
AnnaBridge | 189:f392fc9709a3 | 24 | #if DEVICE_CAN |
AnnaBridge | 189:f392fc9709a3 | 25 | |
AnnaBridge | 189:f392fc9709a3 | 26 | /* BS1[3:0] + 1 + BS2[2:0] + 1 */ |
AnnaBridge | 189:f392fc9709a3 | 27 | #define DEV_CAN_BT_SEG_MAX 24 |
AnnaBridge | 189:f392fc9709a3 | 28 | #define DEV_CAN_BT_SEG_MIN 4 |
AnnaBridge | 189:f392fc9709a3 | 29 | |
AnnaBridge | 189:f392fc9709a3 | 30 | /* CAN related register mask */ |
AnnaBridge | 189:f392fc9709a3 | 31 | #define DEV_CAN_BS1_MASK 0x000F0000 |
AnnaBridge | 189:f392fc9709a3 | 32 | #define DEV_CAN_BS2_MASK 0x00700000 |
AnnaBridge | 189:f392fc9709a3 | 33 | #define DEV_CAN_BAUDPSC_MASK 0x000003FF |
AnnaBridge | 189:f392fc9709a3 | 34 | #define DEV_CAN_SJW_MASK 0x03000000 |
AnnaBridge | 189:f392fc9709a3 | 35 | /* CAN0 interrupt vector number */ |
AnnaBridge | 189:f392fc9709a3 | 36 | #define CAN0_IRQ_BASE_NUM 19 |
AnnaBridge | 189:f392fc9709a3 | 37 | |
AnnaBridge | 189:f392fc9709a3 | 38 | /* CAN1 interrupt vector number */ |
AnnaBridge | 189:f392fc9709a3 | 39 | #define CAN1_IRQ_BASE_NUM 63 |
AnnaBridge | 189:f392fc9709a3 | 40 | |
AnnaBridge | 189:f392fc9709a3 | 41 | static uint32_t can_irq_ids[2] = {0}; |
AnnaBridge | 189:f392fc9709a3 | 42 | static can_irq_handler irq_callback; |
AnnaBridge | 189:f392fc9709a3 | 43 | |
AnnaBridge | 189:f392fc9709a3 | 44 | /** CAN interrupt handle . |
AnnaBridge | 189:f392fc9709a3 | 45 | * |
AnnaBridge | 189:f392fc9709a3 | 46 | * @param can_periph CAN0 or CAN1. |
AnnaBridge | 189:f392fc9709a3 | 47 | * @param id the CANx index . |
AnnaBridge | 189:f392fc9709a3 | 48 | */ |
AnnaBridge | 189:f392fc9709a3 | 49 | static void dev_can_irq_handle(uint32_t periph, int id) |
AnnaBridge | 189:f392fc9709a3 | 50 | { |
AnnaBridge | 189:f392fc9709a3 | 51 | uint32_t flag0 = 0, flag1 = 0, flag2 = 0; |
AnnaBridge | 189:f392fc9709a3 | 52 | |
AnnaBridge | 189:f392fc9709a3 | 53 | flag0 = can_interrupt_flag_get(periph, CAN_INT_FLAG_MTF0); |
AnnaBridge | 189:f392fc9709a3 | 54 | flag1 = can_interrupt_flag_get(periph, CAN_INT_FLAG_MTF1); |
AnnaBridge | 189:f392fc9709a3 | 55 | flag2 = can_interrupt_flag_get(periph, CAN_INT_FLAG_MTF2); |
AnnaBridge | 189:f392fc9709a3 | 56 | |
AnnaBridge | 189:f392fc9709a3 | 57 | if (flag0) { |
AnnaBridge | 189:f392fc9709a3 | 58 | can_flag_clear(periph, CAN_FLAG_MTF0); |
AnnaBridge | 189:f392fc9709a3 | 59 | } |
AnnaBridge | 189:f392fc9709a3 | 60 | if (flag1) { |
AnnaBridge | 189:f392fc9709a3 | 61 | can_flag_clear(periph, CAN_FLAG_MTF1); |
AnnaBridge | 189:f392fc9709a3 | 62 | } |
AnnaBridge | 189:f392fc9709a3 | 63 | if (flag2) { |
AnnaBridge | 189:f392fc9709a3 | 64 | can_flag_clear(periph, CAN_FLAG_MTF2); |
AnnaBridge | 189:f392fc9709a3 | 65 | } |
AnnaBridge | 189:f392fc9709a3 | 66 | |
AnnaBridge | 189:f392fc9709a3 | 67 | /* CAN transmit complete interrupt handle */ |
AnnaBridge | 189:f392fc9709a3 | 68 | if (flag0 || flag1 || flag2) { |
AnnaBridge | 189:f392fc9709a3 | 69 | irq_callback(can_irq_ids[id], IRQ_TX); |
AnnaBridge | 189:f392fc9709a3 | 70 | } |
AnnaBridge | 189:f392fc9709a3 | 71 | |
AnnaBridge | 189:f392fc9709a3 | 72 | /* CAN receive complete interrupt handle */ |
AnnaBridge | 189:f392fc9709a3 | 73 | if (CAN_INTEN_RFNEIE0 == (CAN_INTEN(periph) & CAN_INTEN_RFNEIE0)) { |
AnnaBridge | 189:f392fc9709a3 | 74 | if (0 != can_receive_message_length_get(periph, CAN_FIFO0)) { |
AnnaBridge | 189:f392fc9709a3 | 75 | irq_callback(can_irq_ids[id], IRQ_RX); |
AnnaBridge | 189:f392fc9709a3 | 76 | } |
AnnaBridge | 189:f392fc9709a3 | 77 | } |
AnnaBridge | 189:f392fc9709a3 | 78 | |
AnnaBridge | 189:f392fc9709a3 | 79 | /* CAN error interrupt handle */ |
AnnaBridge | 189:f392fc9709a3 | 80 | if (SET == can_interrupt_flag_get(periph, CAN_INT_FLAG_ERRIF)) { |
AnnaBridge | 189:f392fc9709a3 | 81 | /* passive error interrupt handle */ |
AnnaBridge | 189:f392fc9709a3 | 82 | if (CAN_INTEN_PERRIE == (CAN_INTEN(periph) & CAN_INTEN_PERRIE)) { |
AnnaBridge | 189:f392fc9709a3 | 83 | if (SET == can_flag_get(periph, CAN_FLAG_PERR)) { |
AnnaBridge | 189:f392fc9709a3 | 84 | irq_callback(can_irq_ids[id], IRQ_PASSIVE); |
AnnaBridge | 189:f392fc9709a3 | 85 | } |
AnnaBridge | 189:f392fc9709a3 | 86 | } |
AnnaBridge | 189:f392fc9709a3 | 87 | |
AnnaBridge | 189:f392fc9709a3 | 88 | /* bus-off interrupt handle */ |
AnnaBridge | 189:f392fc9709a3 | 89 | if (CAN_INTEN_BOIE == (CAN_INTEN(periph) & CAN_INTEN_BOIE)) { |
AnnaBridge | 189:f392fc9709a3 | 90 | if (SET == can_flag_get(periph, CAN_FLAG_BOERR)) { |
AnnaBridge | 189:f392fc9709a3 | 91 | irq_callback(can_irq_ids[id], IRQ_BUS); |
AnnaBridge | 189:f392fc9709a3 | 92 | } |
AnnaBridge | 189:f392fc9709a3 | 93 | } |
AnnaBridge | 189:f392fc9709a3 | 94 | |
AnnaBridge | 189:f392fc9709a3 | 95 | irq_callback(can_irq_ids[id], IRQ_ERROR); |
AnnaBridge | 189:f392fc9709a3 | 96 | } |
AnnaBridge | 189:f392fc9709a3 | 97 | } |
AnnaBridge | 189:f392fc9709a3 | 98 | |
AnnaBridge | 189:f392fc9709a3 | 99 | /** CAN1 Interrupt Request entry . |
AnnaBridge | 189:f392fc9709a3 | 100 | * |
AnnaBridge | 189:f392fc9709a3 | 101 | */ |
AnnaBridge | 189:f392fc9709a3 | 102 | static void dev_can0_irq_entry(void) |
AnnaBridge | 189:f392fc9709a3 | 103 | { |
AnnaBridge | 189:f392fc9709a3 | 104 | dev_can_irq_handle(CAN0, 0); |
AnnaBridge | 189:f392fc9709a3 | 105 | } |
AnnaBridge | 189:f392fc9709a3 | 106 | |
AnnaBridge | 189:f392fc9709a3 | 107 | /** CAN1 Interrupt Request entry . |
AnnaBridge | 189:f392fc9709a3 | 108 | * |
AnnaBridge | 189:f392fc9709a3 | 109 | */ |
AnnaBridge | 189:f392fc9709a3 | 110 | static void dev_can1_irq_entry(void) |
AnnaBridge | 189:f392fc9709a3 | 111 | { |
AnnaBridge | 189:f392fc9709a3 | 112 | dev_can_irq_handle(CAN1, 1); |
AnnaBridge | 189:f392fc9709a3 | 113 | } |
AnnaBridge | 189:f392fc9709a3 | 114 | |
AnnaBridge | 189:f392fc9709a3 | 115 | /** Config the CAN mode . |
AnnaBridge | 189:f392fc9709a3 | 116 | * |
AnnaBridge | 189:f392fc9709a3 | 117 | * @param can_periph CAN0 or CAN1. |
AnnaBridge | 189:f392fc9709a3 | 118 | * @param mode the mode to be set. |
AnnaBridge | 189:f392fc9709a3 | 119 | */ |
AnnaBridge | 189:f392fc9709a3 | 120 | static void dev_can_mode_config(uint32_t can_periph, uint32_t mode) |
AnnaBridge | 189:f392fc9709a3 | 121 | { |
AnnaBridge | 189:f392fc9709a3 | 122 | /* enter the initialization mode, only in initialization mode CAN register can be configured */ |
AnnaBridge | 189:f392fc9709a3 | 123 | can_working_mode_set(can_periph, CAN_MODE_INITIALIZE); |
AnnaBridge | 189:f392fc9709a3 | 124 | |
AnnaBridge | 189:f392fc9709a3 | 125 | CAN_BT(can_periph) &= ~BT_MODE(3); |
AnnaBridge | 189:f392fc9709a3 | 126 | CAN_BT(can_periph) |= BT_MODE(mode); |
AnnaBridge | 189:f392fc9709a3 | 127 | |
AnnaBridge | 189:f392fc9709a3 | 128 | /* enter the normal mode */ |
AnnaBridge | 189:f392fc9709a3 | 129 | can_working_mode_set(can_periph, CAN_MODE_NORMAL); |
AnnaBridge | 189:f392fc9709a3 | 130 | } |
AnnaBridge | 189:f392fc9709a3 | 131 | |
AnnaBridge | 189:f392fc9709a3 | 132 | /** Config the interrupt . |
AnnaBridge | 189:f392fc9709a3 | 133 | * |
AnnaBridge | 189:f392fc9709a3 | 134 | * @param can_periph CAN0 or CAN1. |
AnnaBridge | 189:f392fc9709a3 | 135 | * @param interrupt The interrupt type. |
AnnaBridge | 189:f392fc9709a3 | 136 | * @param enable enable or disable. |
AnnaBridge | 189:f392fc9709a3 | 137 | */ |
AnnaBridge | 189:f392fc9709a3 | 138 | static void dev_can_interrupt_config(uint32_t can_periph, uint32_t interrupt, uint32_t enable) |
AnnaBridge | 189:f392fc9709a3 | 139 | { |
AnnaBridge | 189:f392fc9709a3 | 140 | if (enable) { |
AnnaBridge | 189:f392fc9709a3 | 141 | can_interrupt_enable(can_periph, interrupt); |
AnnaBridge | 189:f392fc9709a3 | 142 | } else { |
AnnaBridge | 189:f392fc9709a3 | 143 | can_interrupt_disable(can_periph, interrupt); |
AnnaBridge | 189:f392fc9709a3 | 144 | } |
AnnaBridge | 189:f392fc9709a3 | 145 | } |
AnnaBridge | 189:f392fc9709a3 | 146 | |
AnnaBridge | 189:f392fc9709a3 | 147 | /* This table can be used to calculate bit time |
AnnaBridge | 189:f392fc9709a3 | 148 | The first value is bit segment 1(BS1[3:0]), the second is bit segment 2(BS2[2:0]) */ |
AnnaBridge | 189:f392fc9709a3 | 149 | static const int sampling_points[23][2] = { |
AnnaBridge | 189:f392fc9709a3 | 150 | {0x0, 0x0}, /* 2, 50% */ |
AnnaBridge | 189:f392fc9709a3 | 151 | {0x1, 0x0}, /* 3, 67% */ |
AnnaBridge | 189:f392fc9709a3 | 152 | {0x2, 0x0}, /* 4, 75% */ |
AnnaBridge | 189:f392fc9709a3 | 153 | {0x3, 0x0}, /* 5, 80% */ |
AnnaBridge | 189:f392fc9709a3 | 154 | {0x3, 0x1}, /* 6, 67% */ |
AnnaBridge | 189:f392fc9709a3 | 155 | {0x4, 0x1}, /* 7, 71% */ |
AnnaBridge | 189:f392fc9709a3 | 156 | {0x5, 0x1}, /* 8, 75% */ |
AnnaBridge | 189:f392fc9709a3 | 157 | {0x6, 0x1}, /* 9, 78% */ |
AnnaBridge | 189:f392fc9709a3 | 158 | {0x6, 0x2}, /* 10, 70% */ |
AnnaBridge | 189:f392fc9709a3 | 159 | {0x7, 0x2}, /* 11, 73% */ |
AnnaBridge | 189:f392fc9709a3 | 160 | {0x8, 0x2}, /* 12, 75% */ |
AnnaBridge | 189:f392fc9709a3 | 161 | {0x9, 0x2}, /* 13, 77% */ |
AnnaBridge | 189:f392fc9709a3 | 162 | {0x9, 0x3}, /* 14, 71% */ |
AnnaBridge | 189:f392fc9709a3 | 163 | {0xA, 0x3}, /* 15, 73% */ |
AnnaBridge | 189:f392fc9709a3 | 164 | {0xB, 0x3}, /* 16, 75% */ |
AnnaBridge | 189:f392fc9709a3 | 165 | {0xC, 0x3}, /* 17, 76% */ |
AnnaBridge | 189:f392fc9709a3 | 166 | {0xD, 0x3}, /* 18, 78% */ |
AnnaBridge | 189:f392fc9709a3 | 167 | {0xD, 0x4}, /* 19, 74% */ |
AnnaBridge | 189:f392fc9709a3 | 168 | {0xE, 0x4}, /* 20, 75% */ |
AnnaBridge | 189:f392fc9709a3 | 169 | {0xF, 0x4}, /* 21, 76% */ |
AnnaBridge | 189:f392fc9709a3 | 170 | {0xF, 0x5}, /* 22, 73% */ |
AnnaBridge | 189:f392fc9709a3 | 171 | {0xF, 0x6}, /* 23, 70% */ |
AnnaBridge | 189:f392fc9709a3 | 172 | {0xF, 0x7}, /* 24, 67% */ |
AnnaBridge | 189:f392fc9709a3 | 173 | }; |
AnnaBridge | 189:f392fc9709a3 | 174 | |
AnnaBridge | 189:f392fc9709a3 | 175 | /** Set the baudrate. |
AnnaBridge | 189:f392fc9709a3 | 176 | * |
AnnaBridge | 189:f392fc9709a3 | 177 | * @param freq The frequency value to be set. |
AnnaBridge | 189:f392fc9709a3 | 178 | * |
AnnaBridge | 189:f392fc9709a3 | 179 | * @returns |
AnnaBridge | 189:f392fc9709a3 | 180 | * CAN_BT register value |
AnnaBridge | 189:f392fc9709a3 | 181 | */ |
AnnaBridge | 189:f392fc9709a3 | 182 | static unsigned int dev_can_baudrate_set(int freq) |
AnnaBridge | 189:f392fc9709a3 | 183 | { |
AnnaBridge | 189:f392fc9709a3 | 184 | uint32_t reval; |
AnnaBridge | 189:f392fc9709a3 | 185 | uint16_t baud_psc; |
AnnaBridge | 189:f392fc9709a3 | 186 | uint16_t baud_psc_max; |
AnnaBridge | 189:f392fc9709a3 | 187 | uint32_t temp; |
AnnaBridge | 189:f392fc9709a3 | 188 | uint32_t bt_reg_config; |
AnnaBridge | 189:f392fc9709a3 | 189 | uint8_t flag; |
AnnaBridge | 189:f392fc9709a3 | 190 | int bits; |
AnnaBridge | 189:f392fc9709a3 | 191 | |
AnnaBridge | 189:f392fc9709a3 | 192 | flag = 0; |
AnnaBridge | 189:f392fc9709a3 | 193 | |
AnnaBridge | 189:f392fc9709a3 | 194 | /* computes the value that the CAN_BT register needs to be configured */ |
AnnaBridge | 189:f392fc9709a3 | 195 | /* (BAUDPSC[9:0] + 1) * ((BS1[3:0] + 1) + (BS2[2:0] + 1) + SJW(always 1)) */ |
AnnaBridge | 189:f392fc9709a3 | 196 | bt_reg_config = (rcu_clock_freq_get(CK_APB1) / freq); |
AnnaBridge | 189:f392fc9709a3 | 197 | /* BAUDPSC[9:0] minimum value */ |
AnnaBridge | 189:f392fc9709a3 | 198 | baud_psc = bt_reg_config / DEV_CAN_BT_SEG_MAX; |
AnnaBridge | 189:f392fc9709a3 | 199 | /* BAUDPSC[9:0] maximum value */ |
AnnaBridge | 189:f392fc9709a3 | 200 | baud_psc_max = bt_reg_config / DEV_CAN_BT_SEG_MIN; |
AnnaBridge | 189:f392fc9709a3 | 201 | |
AnnaBridge | 189:f392fc9709a3 | 202 | while ((!flag) && (baud_psc < baud_psc_max)) { |
AnnaBridge | 189:f392fc9709a3 | 203 | baud_psc++; |
AnnaBridge | 189:f392fc9709a3 | 204 | for (bits = 22; bits > 0; bits--) { |
AnnaBridge | 189:f392fc9709a3 | 205 | temp = (bits + 3) * (baud_psc + 1); |
AnnaBridge | 189:f392fc9709a3 | 206 | if (temp == bt_reg_config) { |
AnnaBridge | 189:f392fc9709a3 | 207 | flag = 1; |
AnnaBridge | 189:f392fc9709a3 | 208 | break; |
AnnaBridge | 189:f392fc9709a3 | 209 | } |
AnnaBridge | 189:f392fc9709a3 | 210 | } |
AnnaBridge | 189:f392fc9709a3 | 211 | } |
AnnaBridge | 189:f392fc9709a3 | 212 | |
AnnaBridge | 189:f392fc9709a3 | 213 | if (flag) { |
AnnaBridge | 189:f392fc9709a3 | 214 | reval = ((sampling_points[bits][1] << 20) & DEV_CAN_BS2_MASK) |
AnnaBridge | 189:f392fc9709a3 | 215 | | ((sampling_points[bits][0] << 16) & DEV_CAN_BS1_MASK) |
AnnaBridge | 189:f392fc9709a3 | 216 | | ((1 << 24) & DEV_CAN_SJW_MASK) |
AnnaBridge | 189:f392fc9709a3 | 217 | | ((baud_psc << 0) & DEV_CAN_BAUDPSC_MASK); |
AnnaBridge | 189:f392fc9709a3 | 218 | } else { |
AnnaBridge | 189:f392fc9709a3 | 219 | /* CAN_BT register reset value */ |
AnnaBridge | 189:f392fc9709a3 | 220 | reval = 0x01230000; |
AnnaBridge | 189:f392fc9709a3 | 221 | } |
AnnaBridge | 189:f392fc9709a3 | 222 | |
AnnaBridge | 189:f392fc9709a3 | 223 | return reval; |
AnnaBridge | 189:f392fc9709a3 | 224 | } |
AnnaBridge | 189:f392fc9709a3 | 225 | |
AnnaBridge | 189:f392fc9709a3 | 226 | /** init the CAN. |
AnnaBridge | 189:f392fc9709a3 | 227 | * |
AnnaBridge | 189:f392fc9709a3 | 228 | */ |
AnnaBridge | 189:f392fc9709a3 | 229 | void can_init(can_t *obj, PinName rd, PinName td) |
AnnaBridge | 189:f392fc9709a3 | 230 | { |
AnnaBridge | 189:f392fc9709a3 | 231 | can_init_freq(obj, rd, td, 500000); |
AnnaBridge | 189:f392fc9709a3 | 232 | } |
AnnaBridge | 189:f392fc9709a3 | 233 | |
AnnaBridge | 189:f392fc9709a3 | 234 | /** init the CAN frequency. |
AnnaBridge | 189:f392fc9709a3 | 235 | * |
AnnaBridge | 189:f392fc9709a3 | 236 | * @param rd receive pin. |
AnnaBridge | 189:f392fc9709a3 | 237 | * @param td transmit pin. |
AnnaBridge | 189:f392fc9709a3 | 238 | * @param hz The bus frequency in hertz. |
AnnaBridge | 189:f392fc9709a3 | 239 | */ |
AnnaBridge | 189:f392fc9709a3 | 240 | void can_init_freq(can_t *obj, PinName rd, PinName td, int hz) |
AnnaBridge | 189:f392fc9709a3 | 241 | { |
AnnaBridge | 189:f392fc9709a3 | 242 | CANName can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD); |
AnnaBridge | 189:f392fc9709a3 | 243 | CANName can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TD); |
AnnaBridge | 189:f392fc9709a3 | 244 | obj->can = (CANName)pinmap_merge(can_rd, can_td); |
AnnaBridge | 189:f392fc9709a3 | 245 | |
AnnaBridge | 189:f392fc9709a3 | 246 | MBED_ASSERT((int)obj->can != NC); |
AnnaBridge | 189:f392fc9709a3 | 247 | |
AnnaBridge | 189:f392fc9709a3 | 248 | if (obj->can == CAN_0) { |
AnnaBridge | 189:f392fc9709a3 | 249 | rcu_periph_clock_enable(RCU_CAN0); |
AnnaBridge | 189:f392fc9709a3 | 250 | can_deinit(obj->can); |
AnnaBridge | 189:f392fc9709a3 | 251 | obj->index = 0; |
AnnaBridge | 189:f392fc9709a3 | 252 | } else if (obj->can == CAN_1) { |
AnnaBridge | 189:f392fc9709a3 | 253 | rcu_periph_clock_enable(RCU_CAN0); |
AnnaBridge | 189:f392fc9709a3 | 254 | rcu_periph_clock_enable(RCU_CAN1); |
AnnaBridge | 189:f392fc9709a3 | 255 | can_deinit(obj->can); |
AnnaBridge | 189:f392fc9709a3 | 256 | obj->index = 1; |
AnnaBridge | 189:f392fc9709a3 | 257 | } else { |
AnnaBridge | 189:f392fc9709a3 | 258 | return; |
AnnaBridge | 189:f392fc9709a3 | 259 | } |
AnnaBridge | 189:f392fc9709a3 | 260 | |
AnnaBridge | 189:f392fc9709a3 | 261 | /* Configure the CAN pins */ |
AnnaBridge | 189:f392fc9709a3 | 262 | pinmap_pinout(rd, PinMap_CAN_RD); |
AnnaBridge | 189:f392fc9709a3 | 263 | pinmap_pinout(td, PinMap_CAN_TD); |
AnnaBridge | 189:f392fc9709a3 | 264 | if (rd != NC) { |
AnnaBridge | 189:f392fc9709a3 | 265 | pin_mode(rd, PullUp); |
AnnaBridge | 189:f392fc9709a3 | 266 | } |
AnnaBridge | 189:f392fc9709a3 | 267 | if (td != NC) { |
AnnaBridge | 189:f392fc9709a3 | 268 | pin_mode(td, PullUp); |
AnnaBridge | 189:f392fc9709a3 | 269 | } |
AnnaBridge | 189:f392fc9709a3 | 270 | |
AnnaBridge | 189:f392fc9709a3 | 271 | dev_can_mode_config(obj->can, CAN_NORMAL_MODE); |
AnnaBridge | 189:f392fc9709a3 | 272 | |
AnnaBridge | 189:f392fc9709a3 | 273 | can_frequency(obj, hz); |
AnnaBridge | 189:f392fc9709a3 | 274 | |
AnnaBridge | 189:f392fc9709a3 | 275 | if (obj->can == CAN_0) { |
AnnaBridge | 189:f392fc9709a3 | 276 | can_filter(obj, 0, 0, CANStandard, 0); |
AnnaBridge | 189:f392fc9709a3 | 277 | } else { |
AnnaBridge | 189:f392fc9709a3 | 278 | can_filter(obj, 0, 0, CANStandard, 14); |
AnnaBridge | 189:f392fc9709a3 | 279 | } |
AnnaBridge | 189:f392fc9709a3 | 280 | } |
AnnaBridge | 189:f392fc9709a3 | 281 | |
AnnaBridge | 189:f392fc9709a3 | 282 | /** disable CAN. |
AnnaBridge | 189:f392fc9709a3 | 283 | * |
AnnaBridge | 189:f392fc9709a3 | 284 | */ |
AnnaBridge | 189:f392fc9709a3 | 285 | void can_free(can_t *obj) |
AnnaBridge | 189:f392fc9709a3 | 286 | { |
AnnaBridge | 189:f392fc9709a3 | 287 | can_deinit(obj->can); |
AnnaBridge | 189:f392fc9709a3 | 288 | |
AnnaBridge | 189:f392fc9709a3 | 289 | if (obj->can == CAN0) { |
AnnaBridge | 189:f392fc9709a3 | 290 | rcu_periph_clock_disable(RCU_CAN0); |
AnnaBridge | 189:f392fc9709a3 | 291 | } |
AnnaBridge | 189:f392fc9709a3 | 292 | |
AnnaBridge | 189:f392fc9709a3 | 293 | if (obj->can == CAN1) { |
AnnaBridge | 189:f392fc9709a3 | 294 | rcu_periph_clock_disable(RCU_CAN1); |
AnnaBridge | 189:f392fc9709a3 | 295 | } |
AnnaBridge | 189:f392fc9709a3 | 296 | } |
AnnaBridge | 189:f392fc9709a3 | 297 | |
AnnaBridge | 189:f392fc9709a3 | 298 | /** Set the frequency of the CAN interface. |
AnnaBridge | 189:f392fc9709a3 | 299 | * |
AnnaBridge | 189:f392fc9709a3 | 300 | * @param hz The bus frequency in hertz. |
AnnaBridge | 189:f392fc9709a3 | 301 | * |
AnnaBridge | 189:f392fc9709a3 | 302 | * @returns |
AnnaBridge | 189:f392fc9709a3 | 303 | * 1 if successful, |
AnnaBridge | 189:f392fc9709a3 | 304 | * 0 otherwise |
AnnaBridge | 189:f392fc9709a3 | 305 | */ |
AnnaBridge | 189:f392fc9709a3 | 306 | int can_frequency(can_t *obj, int hz) |
AnnaBridge | 189:f392fc9709a3 | 307 | { |
AnnaBridge | 189:f392fc9709a3 | 308 | int reval; |
AnnaBridge | 189:f392fc9709a3 | 309 | |
AnnaBridge | 189:f392fc9709a3 | 310 | /* The maximum baud rate support to 1M */ |
AnnaBridge | 189:f392fc9709a3 | 311 | if (hz <= 1000000) { |
AnnaBridge | 189:f392fc9709a3 | 312 | if (SUCCESS == can_working_mode_set(obj->can, CAN_MODE_INITIALIZE)) { |
AnnaBridge | 189:f392fc9709a3 | 313 | CAN_BT(obj->can) = dev_can_baudrate_set(hz); |
AnnaBridge | 189:f392fc9709a3 | 314 | } else { |
AnnaBridge | 189:f392fc9709a3 | 315 | error("the configuration of can frequency is out of range \r\n"); |
AnnaBridge | 189:f392fc9709a3 | 316 | } |
AnnaBridge | 189:f392fc9709a3 | 317 | |
AnnaBridge | 189:f392fc9709a3 | 318 | if (SUCCESS == can_working_mode_set(obj->can, CAN_MODE_NORMAL)) { |
AnnaBridge | 189:f392fc9709a3 | 319 | reval = 1; |
AnnaBridge | 189:f392fc9709a3 | 320 | } else { |
AnnaBridge | 189:f392fc9709a3 | 321 | reval = 0; |
AnnaBridge | 189:f392fc9709a3 | 322 | } |
AnnaBridge | 189:f392fc9709a3 | 323 | } |
AnnaBridge | 189:f392fc9709a3 | 324 | |
AnnaBridge | 189:f392fc9709a3 | 325 | return reval; |
AnnaBridge | 189:f392fc9709a3 | 326 | } |
AnnaBridge | 189:f392fc9709a3 | 327 | |
AnnaBridge | 189:f392fc9709a3 | 328 | /** init the interrupt. |
AnnaBridge | 189:f392fc9709a3 | 329 | * |
AnnaBridge | 189:f392fc9709a3 | 330 | * @param handler the interrupt callback. |
AnnaBridge | 189:f392fc9709a3 | 331 | * @param id the CANx index. |
AnnaBridge | 189:f392fc9709a3 | 332 | */ |
AnnaBridge | 189:f392fc9709a3 | 333 | void can_irq_init(can_t *obj, can_irq_handler handler, uint32_t id) |
AnnaBridge | 189:f392fc9709a3 | 334 | { |
AnnaBridge | 189:f392fc9709a3 | 335 | irq_callback = handler; |
AnnaBridge | 189:f392fc9709a3 | 336 | can_irq_ids[obj->index] = id; |
AnnaBridge | 189:f392fc9709a3 | 337 | } |
AnnaBridge | 189:f392fc9709a3 | 338 | |
AnnaBridge | 189:f392fc9709a3 | 339 | /** disable the interrupt. |
AnnaBridge | 189:f392fc9709a3 | 340 | * |
AnnaBridge | 189:f392fc9709a3 | 341 | */ |
AnnaBridge | 189:f392fc9709a3 | 342 | void can_irq_free(can_t *obj) |
AnnaBridge | 189:f392fc9709a3 | 343 | { |
AnnaBridge | 189:f392fc9709a3 | 344 | if (CAN0 == obj->can) { |
AnnaBridge | 189:f392fc9709a3 | 345 | can_interrupt_disable(obj->can, CAN_INTEN_TMEIE | CAN_INTEN_RFNEIE0 | CAN_INTEN_RFNEIE1 | \ |
AnnaBridge | 189:f392fc9709a3 | 346 | CAN_INTEN_PERRIE | CAN_INTEN_BOIE | CAN_INTEN_ERRIE); |
AnnaBridge | 189:f392fc9709a3 | 347 | } |
AnnaBridge | 189:f392fc9709a3 | 348 | |
AnnaBridge | 189:f392fc9709a3 | 349 | if (CAN1 == obj->can) { |
AnnaBridge | 189:f392fc9709a3 | 350 | can_interrupt_disable(obj->can, CAN_INTEN_TMEIE | CAN_INTEN_RFNEIE0 | CAN_INTEN_RFNEIE1 | \ |
AnnaBridge | 189:f392fc9709a3 | 351 | CAN_INTEN_PERRIE | CAN_INTEN_BOIE | CAN_INTEN_ERRIE); |
AnnaBridge | 189:f392fc9709a3 | 352 | } |
AnnaBridge | 189:f392fc9709a3 | 353 | |
AnnaBridge | 189:f392fc9709a3 | 354 | can_irq_ids[obj->index] = 0; |
AnnaBridge | 189:f392fc9709a3 | 355 | } |
AnnaBridge | 189:f392fc9709a3 | 356 | |
AnnaBridge | 189:f392fc9709a3 | 357 | /** Set the interrupt handle. |
AnnaBridge | 189:f392fc9709a3 | 358 | * |
AnnaBridge | 189:f392fc9709a3 | 359 | * @param type The interrupt type. |
AnnaBridge | 189:f392fc9709a3 | 360 | * @param enable enable or disable. |
AnnaBridge | 189:f392fc9709a3 | 361 | */ |
AnnaBridge | 189:f392fc9709a3 | 362 | void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable) |
AnnaBridge | 189:f392fc9709a3 | 363 | { |
AnnaBridge | 189:f392fc9709a3 | 364 | uint32_t irq_num; |
AnnaBridge | 189:f392fc9709a3 | 365 | uint32_t vector = 0; |
AnnaBridge | 189:f392fc9709a3 | 366 | |
AnnaBridge | 189:f392fc9709a3 | 367 | if (obj->can == CAN_0) { |
AnnaBridge | 189:f392fc9709a3 | 368 | vector = (uint32_t)dev_can0_irq_entry; |
AnnaBridge | 189:f392fc9709a3 | 369 | irq_num = CAN0_IRQ_BASE_NUM; |
AnnaBridge | 189:f392fc9709a3 | 370 | } |
AnnaBridge | 189:f392fc9709a3 | 371 | |
AnnaBridge | 189:f392fc9709a3 | 372 | else if (obj->can == CAN_1) { |
AnnaBridge | 189:f392fc9709a3 | 373 | vector = (uint32_t)dev_can1_irq_entry; |
AnnaBridge | 189:f392fc9709a3 | 374 | irq_num = CAN1_IRQ_BASE_NUM; |
AnnaBridge | 189:f392fc9709a3 | 375 | } |
AnnaBridge | 189:f392fc9709a3 | 376 | |
AnnaBridge | 189:f392fc9709a3 | 377 | switch (type) { |
AnnaBridge | 189:f392fc9709a3 | 378 | case IRQ_RX: |
AnnaBridge | 189:f392fc9709a3 | 379 | dev_can_interrupt_config(obj->can, CAN_INT_RFNE0, enable); |
AnnaBridge | 189:f392fc9709a3 | 380 | break; |
AnnaBridge | 189:f392fc9709a3 | 381 | case IRQ_TX: |
AnnaBridge | 189:f392fc9709a3 | 382 | dev_can_interrupt_config(obj->can, CAN_INT_TME, enable); |
AnnaBridge | 189:f392fc9709a3 | 383 | irq_num += 1; |
AnnaBridge | 189:f392fc9709a3 | 384 | break; |
AnnaBridge | 189:f392fc9709a3 | 385 | case IRQ_ERROR: |
AnnaBridge | 189:f392fc9709a3 | 386 | dev_can_interrupt_config(obj->can, CAN_INT_ERR | CAN_INT_ERRN, enable); |
AnnaBridge | 189:f392fc9709a3 | 387 | irq_num += 3; |
AnnaBridge | 189:f392fc9709a3 | 388 | break; |
AnnaBridge | 189:f392fc9709a3 | 389 | case IRQ_PASSIVE: |
AnnaBridge | 189:f392fc9709a3 | 390 | dev_can_interrupt_config(obj->can, CAN_INT_ERR | CAN_INT_PERR, enable); |
AnnaBridge | 189:f392fc9709a3 | 391 | irq_num += 3; |
AnnaBridge | 189:f392fc9709a3 | 392 | break; |
AnnaBridge | 189:f392fc9709a3 | 393 | case IRQ_BUS: |
AnnaBridge | 189:f392fc9709a3 | 394 | dev_can_interrupt_config(obj->can, CAN_INT_ERR | CAN_INT_BO, enable); |
AnnaBridge | 189:f392fc9709a3 | 395 | irq_num += 3; |
AnnaBridge | 189:f392fc9709a3 | 396 | break; |
AnnaBridge | 189:f392fc9709a3 | 397 | default: |
AnnaBridge | 189:f392fc9709a3 | 398 | return; |
AnnaBridge | 189:f392fc9709a3 | 399 | } |
AnnaBridge | 189:f392fc9709a3 | 400 | |
AnnaBridge | 189:f392fc9709a3 | 401 | NVIC_SetVector((IRQn_Type)irq_num, vector); |
AnnaBridge | 189:f392fc9709a3 | 402 | NVIC_EnableIRQ((IRQn_Type)irq_num); |
AnnaBridge | 189:f392fc9709a3 | 403 | } |
AnnaBridge | 189:f392fc9709a3 | 404 | |
AnnaBridge | 189:f392fc9709a3 | 405 | /** Write a CANMessage to the bus. |
AnnaBridge | 189:f392fc9709a3 | 406 | * |
AnnaBridge | 189:f392fc9709a3 | 407 | * @param msg The CANMessage to write. |
AnnaBridge | 189:f392fc9709a3 | 408 | * |
AnnaBridge | 189:f392fc9709a3 | 409 | * @returns |
AnnaBridge | 189:f392fc9709a3 | 410 | * 0 if write failed, |
AnnaBridge | 189:f392fc9709a3 | 411 | * 1 if write was successful |
AnnaBridge | 189:f392fc9709a3 | 412 | */ |
AnnaBridge | 189:f392fc9709a3 | 413 | int can_write(can_t *obj, CAN_Message msg, int cc) |
AnnaBridge | 189:f392fc9709a3 | 414 | { |
AnnaBridge | 189:f392fc9709a3 | 415 | can_trasnmit_message_struct transmit_message; |
AnnaBridge | 189:f392fc9709a3 | 416 | uint32_t i; |
AnnaBridge | 189:f392fc9709a3 | 417 | |
AnnaBridge | 189:f392fc9709a3 | 418 | can_struct_para_init(CAN_TX_MESSAGE_STRUCT, &transmit_message); |
AnnaBridge | 189:f392fc9709a3 | 419 | /* configure frame type: data or remote */ |
AnnaBridge | 189:f392fc9709a3 | 420 | if (CANData == msg.type) { |
AnnaBridge | 189:f392fc9709a3 | 421 | transmit_message.tx_ft = CAN_FT_DATA; |
AnnaBridge | 189:f392fc9709a3 | 422 | } else if (CANRemote == msg.type) { |
AnnaBridge | 189:f392fc9709a3 | 423 | transmit_message.tx_ft = CAN_FT_REMOTE; |
AnnaBridge | 189:f392fc9709a3 | 424 | } else { |
AnnaBridge | 189:f392fc9709a3 | 425 | error("frame type of transmit message is invalid \r\n"); |
AnnaBridge | 189:f392fc9709a3 | 426 | } |
AnnaBridge | 189:f392fc9709a3 | 427 | |
AnnaBridge | 189:f392fc9709a3 | 428 | /* configure frame format: standard or extended */ |
AnnaBridge | 189:f392fc9709a3 | 429 | if (CANStandard == msg.format) { |
AnnaBridge | 189:f392fc9709a3 | 430 | transmit_message.tx_ff = CAN_FF_STANDARD; |
AnnaBridge | 189:f392fc9709a3 | 431 | transmit_message.tx_sfid = msg.id; |
AnnaBridge | 189:f392fc9709a3 | 432 | } else if (CANExtended == msg.format) { |
AnnaBridge | 189:f392fc9709a3 | 433 | transmit_message.tx_ff = CAN_FF_EXTENDED; |
AnnaBridge | 189:f392fc9709a3 | 434 | transmit_message.tx_efid = msg.id; |
AnnaBridge | 189:f392fc9709a3 | 435 | } else { |
AnnaBridge | 189:f392fc9709a3 | 436 | error("frame format of transmit message is invalid \r\n"); |
AnnaBridge | 189:f392fc9709a3 | 437 | } |
AnnaBridge | 189:f392fc9709a3 | 438 | |
AnnaBridge | 189:f392fc9709a3 | 439 | transmit_message.tx_dlen = msg.len; |
AnnaBridge | 189:f392fc9709a3 | 440 | |
AnnaBridge | 189:f392fc9709a3 | 441 | for (i = 0; i < msg.len; i++) { |
AnnaBridge | 189:f392fc9709a3 | 442 | transmit_message.tx_data[i] = msg.data[i]; |
AnnaBridge | 189:f392fc9709a3 | 443 | } |
AnnaBridge | 189:f392fc9709a3 | 444 | |
AnnaBridge | 189:f392fc9709a3 | 445 | can_message_transmit(obj->can, &transmit_message); |
AnnaBridge | 189:f392fc9709a3 | 446 | |
AnnaBridge | 189:f392fc9709a3 | 447 | return 1; |
AnnaBridge | 189:f392fc9709a3 | 448 | } |
AnnaBridge | 189:f392fc9709a3 | 449 | |
AnnaBridge | 189:f392fc9709a3 | 450 | /** Read a CANMessage from the bus. |
AnnaBridge | 189:f392fc9709a3 | 451 | * |
AnnaBridge | 189:f392fc9709a3 | 452 | * @param msg A CANMessage to read to. |
AnnaBridge | 189:f392fc9709a3 | 453 | * @param handle message filter handle (0 for any message). |
AnnaBridge | 189:f392fc9709a3 | 454 | * |
AnnaBridge | 189:f392fc9709a3 | 455 | * @returns |
AnnaBridge | 189:f392fc9709a3 | 456 | * 0 if no message arrived, |
AnnaBridge | 189:f392fc9709a3 | 457 | * 1 if message arrived |
AnnaBridge | 189:f392fc9709a3 | 458 | */ |
AnnaBridge | 189:f392fc9709a3 | 459 | int can_read(can_t *obj, CAN_Message *msg, int handle) |
AnnaBridge | 189:f392fc9709a3 | 460 | { |
AnnaBridge | 189:f392fc9709a3 | 461 | uint8_t i; |
AnnaBridge | 189:f392fc9709a3 | 462 | uint8_t fifo_number; |
AnnaBridge | 189:f392fc9709a3 | 463 | |
AnnaBridge | 189:f392fc9709a3 | 464 | fifo_number = (uint8_t)handle; |
AnnaBridge | 189:f392fc9709a3 | 465 | can_receive_message_struct receive_message; |
AnnaBridge | 189:f392fc9709a3 | 466 | |
AnnaBridge | 189:f392fc9709a3 | 467 | /* if the frame is not received, retrun 0 */ |
AnnaBridge | 189:f392fc9709a3 | 468 | if (0 == can_receive_message_length_get(obj->can, CAN_FIFO0)) { |
AnnaBridge | 189:f392fc9709a3 | 469 | return 0; |
AnnaBridge | 189:f392fc9709a3 | 470 | } |
AnnaBridge | 189:f392fc9709a3 | 471 | |
AnnaBridge | 189:f392fc9709a3 | 472 | can_message_receive(obj->can, fifo_number, &receive_message); |
AnnaBridge | 189:f392fc9709a3 | 473 | |
AnnaBridge | 189:f392fc9709a3 | 474 | if (receive_message.rx_ff == CAN_RFIFOMI_FF) { |
AnnaBridge | 189:f392fc9709a3 | 475 | msg->format = CANExtended; |
AnnaBridge | 189:f392fc9709a3 | 476 | } else { |
AnnaBridge | 189:f392fc9709a3 | 477 | msg->format = CANStandard; |
AnnaBridge | 189:f392fc9709a3 | 478 | } |
AnnaBridge | 189:f392fc9709a3 | 479 | |
AnnaBridge | 189:f392fc9709a3 | 480 | if (0 == msg->format) { |
AnnaBridge | 189:f392fc9709a3 | 481 | msg->id = (uint32_t)0x000007FF & (receive_message.rx_sfid); |
AnnaBridge | 189:f392fc9709a3 | 482 | } else { |
AnnaBridge | 189:f392fc9709a3 | 483 | msg->id = (uint32_t)0x1FFFFFFF & (receive_message.rx_efid); |
AnnaBridge | 189:f392fc9709a3 | 484 | } |
AnnaBridge | 189:f392fc9709a3 | 485 | |
AnnaBridge | 189:f392fc9709a3 | 486 | if (receive_message.rx_ft == CAN_RFIFOMI_FT) { |
AnnaBridge | 189:f392fc9709a3 | 487 | msg->type = CANRemote; |
AnnaBridge | 189:f392fc9709a3 | 488 | } else { |
AnnaBridge | 189:f392fc9709a3 | 489 | msg->type = CANData; |
AnnaBridge | 189:f392fc9709a3 | 490 | } |
AnnaBridge | 189:f392fc9709a3 | 491 | |
AnnaBridge | 189:f392fc9709a3 | 492 | msg->len = (uint8_t)receive_message.rx_dlen; |
AnnaBridge | 189:f392fc9709a3 | 493 | |
AnnaBridge | 189:f392fc9709a3 | 494 | for (i = 0; i < msg->len; i++) { |
AnnaBridge | 189:f392fc9709a3 | 495 | msg->data[i] = (uint8_t)receive_message.rx_data[i]; |
AnnaBridge | 189:f392fc9709a3 | 496 | } |
AnnaBridge | 189:f392fc9709a3 | 497 | /* If the frame is received successfully, retrun 1 */ |
AnnaBridge | 189:f392fc9709a3 | 498 | return 1; |
AnnaBridge | 189:f392fc9709a3 | 499 | } |
AnnaBridge | 189:f392fc9709a3 | 500 | |
AnnaBridge | 189:f392fc9709a3 | 501 | /** Change CAN operation to the specified mode. |
AnnaBridge | 189:f392fc9709a3 | 502 | * |
AnnaBridge | 189:f392fc9709a3 | 503 | * @param mode The new operation mode (CAN::Normal, CAN::Silent, CAN::LocalTest, CAN::GlobalTest, CAN::SilentTest). |
AnnaBridge | 189:f392fc9709a3 | 504 | * |
AnnaBridge | 189:f392fc9709a3 | 505 | * @returns |
AnnaBridge | 189:f392fc9709a3 | 506 | * 0 if mode change failed or unsupported, |
AnnaBridge | 189:f392fc9709a3 | 507 | * 1 if mode change was successful |
AnnaBridge | 189:f392fc9709a3 | 508 | */ |
AnnaBridge | 189:f392fc9709a3 | 509 | int can_mode(can_t *obj, CanMode mode) |
AnnaBridge | 189:f392fc9709a3 | 510 | { |
AnnaBridge | 189:f392fc9709a3 | 511 | switch (mode) { |
AnnaBridge | 189:f392fc9709a3 | 512 | case MODE_NORMAL: |
AnnaBridge | 189:f392fc9709a3 | 513 | dev_can_mode_config(obj->can, CAN_NORMAL_MODE); |
AnnaBridge | 189:f392fc9709a3 | 514 | break; |
AnnaBridge | 189:f392fc9709a3 | 515 | case MODE_SILENT: |
AnnaBridge | 189:f392fc9709a3 | 516 | dev_can_mode_config(obj->can, CAN_SILENT_MODE); |
AnnaBridge | 189:f392fc9709a3 | 517 | break; |
AnnaBridge | 189:f392fc9709a3 | 518 | case MODE_TEST_GLOBAL: |
AnnaBridge | 189:f392fc9709a3 | 519 | case MODE_TEST_LOCAL: |
AnnaBridge | 189:f392fc9709a3 | 520 | dev_can_mode_config(obj->can, CAN_LOOPBACK_MODE); |
AnnaBridge | 189:f392fc9709a3 | 521 | break; |
AnnaBridge | 189:f392fc9709a3 | 522 | case MODE_TEST_SILENT: |
AnnaBridge | 189:f392fc9709a3 | 523 | dev_can_mode_config(obj->can, CAN_SILENT_LOOPBACK_MODE); |
AnnaBridge | 189:f392fc9709a3 | 524 | break; |
AnnaBridge | 189:f392fc9709a3 | 525 | default: |
AnnaBridge | 189:f392fc9709a3 | 526 | return 0; |
AnnaBridge | 189:f392fc9709a3 | 527 | } |
AnnaBridge | 189:f392fc9709a3 | 528 | |
AnnaBridge | 189:f392fc9709a3 | 529 | return 1; |
AnnaBridge | 189:f392fc9709a3 | 530 | } |
AnnaBridge | 189:f392fc9709a3 | 531 | |
AnnaBridge | 189:f392fc9709a3 | 532 | /** Filter out incomming messages. |
AnnaBridge | 189:f392fc9709a3 | 533 | * |
AnnaBridge | 189:f392fc9709a3 | 534 | * @param id the id to filter on. |
AnnaBridge | 189:f392fc9709a3 | 535 | * @param mask the mask applied to the id. |
AnnaBridge | 189:f392fc9709a3 | 536 | * @param format format to filter on (Default CANAny). |
AnnaBridge | 189:f392fc9709a3 | 537 | * @param handle message filter handle (Optional). |
AnnaBridge | 189:f392fc9709a3 | 538 | * |
AnnaBridge | 189:f392fc9709a3 | 539 | * @returns |
AnnaBridge | 189:f392fc9709a3 | 540 | * 0 if filter change failed or unsupported, |
AnnaBridge | 189:f392fc9709a3 | 541 | * new filter handle if successful |
AnnaBridge | 189:f392fc9709a3 | 542 | */ |
AnnaBridge | 189:f392fc9709a3 | 543 | int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle) |
AnnaBridge | 189:f392fc9709a3 | 544 | { |
AnnaBridge | 189:f392fc9709a3 | 545 | can_filter_parameter_struct can_filter; |
AnnaBridge | 189:f392fc9709a3 | 546 | |
AnnaBridge | 189:f392fc9709a3 | 547 | can_filter.filter_number = handle; |
AnnaBridge | 189:f392fc9709a3 | 548 | can_filter.filter_mode = CAN_FILTERMODE_MASK; |
AnnaBridge | 189:f392fc9709a3 | 549 | can_filter.filter_bits = CAN_FILTERBITS_32BIT; |
AnnaBridge | 189:f392fc9709a3 | 550 | can_filter.filter_fifo_number = CAN_FIFO0; |
AnnaBridge | 189:f392fc9709a3 | 551 | can_filter.filter_enable = ENABLE; |
AnnaBridge | 189:f392fc9709a3 | 552 | |
AnnaBridge | 189:f392fc9709a3 | 553 | switch (format) { |
AnnaBridge | 189:f392fc9709a3 | 554 | case CANStandard: |
AnnaBridge | 189:f392fc9709a3 | 555 | /* configure SFID[10:0] */ |
AnnaBridge | 189:f392fc9709a3 | 556 | can_filter.filter_list_high = id << 5; |
AnnaBridge | 189:f392fc9709a3 | 557 | can_filter.filter_list_low = 0x0; |
AnnaBridge | 189:f392fc9709a3 | 558 | /* configure SFID[10:0] mask */ |
AnnaBridge | 189:f392fc9709a3 | 559 | can_filter.filter_mask_high = mask << 5; |
AnnaBridge | 189:f392fc9709a3 | 560 | /* both data and remote frames can be received */ |
AnnaBridge | 189:f392fc9709a3 | 561 | can_filter.filter_mask_low = 0x0; |
AnnaBridge | 189:f392fc9709a3 | 562 | |
AnnaBridge | 189:f392fc9709a3 | 563 | break; |
AnnaBridge | 189:f392fc9709a3 | 564 | |
AnnaBridge | 189:f392fc9709a3 | 565 | case CANExtended: |
AnnaBridge | 189:f392fc9709a3 | 566 | /* configure EFID[28:13] */ |
AnnaBridge | 189:f392fc9709a3 | 567 | can_filter.filter_list_high = id >> 13; |
AnnaBridge | 189:f392fc9709a3 | 568 | /* configure EFID[12:0] and frame format bit set */ |
AnnaBridge | 189:f392fc9709a3 | 569 | can_filter.filter_list_low = (id << 3) | (1 << 2); |
AnnaBridge | 189:f392fc9709a3 | 570 | /* configure EFID[28:13] mask */ |
AnnaBridge | 189:f392fc9709a3 | 571 | can_filter.filter_mask_high = mask >> 13; |
AnnaBridge | 189:f392fc9709a3 | 572 | /* configure EFID[12:0] and frame format bit mask */ |
AnnaBridge | 189:f392fc9709a3 | 573 | /* both data and remote frames can be received */ |
AnnaBridge | 189:f392fc9709a3 | 574 | can_filter.filter_mask_low = (mask << 3) | (1 << 2); |
AnnaBridge | 189:f392fc9709a3 | 575 | |
AnnaBridge | 189:f392fc9709a3 | 576 | break; |
AnnaBridge | 189:f392fc9709a3 | 577 | |
AnnaBridge | 189:f392fc9709a3 | 578 | case CANAny: |
AnnaBridge | 189:f392fc9709a3 | 579 | error("CANAny mode is not supported \r\n"); |
AnnaBridge | 189:f392fc9709a3 | 580 | return 0; |
AnnaBridge | 189:f392fc9709a3 | 581 | |
AnnaBridge | 189:f392fc9709a3 | 582 | default: |
AnnaBridge | 189:f392fc9709a3 | 583 | error("parameter is not supported \r\n"); |
AnnaBridge | 189:f392fc9709a3 | 584 | return 0; |
AnnaBridge | 189:f392fc9709a3 | 585 | } |
AnnaBridge | 189:f392fc9709a3 | 586 | |
AnnaBridge | 189:f392fc9709a3 | 587 | can_filter_init(&can_filter); |
AnnaBridge | 189:f392fc9709a3 | 588 | can1_filter_start_bank(handle); |
AnnaBridge | 189:f392fc9709a3 | 589 | |
AnnaBridge | 189:f392fc9709a3 | 590 | return handle; |
AnnaBridge | 189:f392fc9709a3 | 591 | } |
AnnaBridge | 189:f392fc9709a3 | 592 | |
AnnaBridge | 189:f392fc9709a3 | 593 | /** Reset CAN interface. |
AnnaBridge | 189:f392fc9709a3 | 594 | * |
AnnaBridge | 189:f392fc9709a3 | 595 | * To use after error overflow. |
AnnaBridge | 189:f392fc9709a3 | 596 | */ |
AnnaBridge | 189:f392fc9709a3 | 597 | void can_reset(can_t *obj) |
AnnaBridge | 189:f392fc9709a3 | 598 | { |
AnnaBridge | 189:f392fc9709a3 | 599 | can_deinit(obj->can); |
AnnaBridge | 189:f392fc9709a3 | 600 | } |
AnnaBridge | 189:f392fc9709a3 | 601 | |
AnnaBridge | 189:f392fc9709a3 | 602 | /** Detects read errors - Used to detect read overflow errors. |
AnnaBridge | 189:f392fc9709a3 | 603 | * |
AnnaBridge | 189:f392fc9709a3 | 604 | * @returns number of read errors |
AnnaBridge | 189:f392fc9709a3 | 605 | */ |
AnnaBridge | 189:f392fc9709a3 | 606 | unsigned char can_rderror(can_t *obj) |
AnnaBridge | 189:f392fc9709a3 | 607 | { |
AnnaBridge | 189:f392fc9709a3 | 608 | return can_receive_error_number_get(obj->can); |
AnnaBridge | 189:f392fc9709a3 | 609 | } |
AnnaBridge | 189:f392fc9709a3 | 610 | |
AnnaBridge | 189:f392fc9709a3 | 611 | /** Detects write errors - Used to detect write overflow errors. |
AnnaBridge | 189:f392fc9709a3 | 612 | * |
AnnaBridge | 189:f392fc9709a3 | 613 | * @returns number of write errors |
AnnaBridge | 189:f392fc9709a3 | 614 | */ |
AnnaBridge | 189:f392fc9709a3 | 615 | unsigned char can_tderror(can_t *obj) |
AnnaBridge | 189:f392fc9709a3 | 616 | { |
AnnaBridge | 189:f392fc9709a3 | 617 | return can_transmit_error_number_get(obj->can); |
AnnaBridge | 189:f392fc9709a3 | 618 | } |
AnnaBridge | 189:f392fc9709a3 | 619 | |
AnnaBridge | 189:f392fc9709a3 | 620 | /** Puts or removes the CAN interface into silent monitoring mode. |
AnnaBridge | 189:f392fc9709a3 | 621 | * |
AnnaBridge | 189:f392fc9709a3 | 622 | * @param silent boolean indicating whether to go into silent mode or not. |
AnnaBridge | 189:f392fc9709a3 | 623 | */ |
AnnaBridge | 189:f392fc9709a3 | 624 | void can_monitor(can_t *obj, int silent) |
AnnaBridge | 189:f392fc9709a3 | 625 | { |
AnnaBridge | 189:f392fc9709a3 | 626 | if (silent) { |
AnnaBridge | 189:f392fc9709a3 | 627 | dev_can_mode_config(obj->can, CAN_SILENT_MODE); |
AnnaBridge | 189:f392fc9709a3 | 628 | } else { |
AnnaBridge | 189:f392fc9709a3 | 629 | dev_can_mode_config(obj->can, CAN_NORMAL_MODE); |
AnnaBridge | 189:f392fc9709a3 | 630 | } |
AnnaBridge | 189:f392fc9709a3 | 631 | } |
AnnaBridge | 189:f392fc9709a3 | 632 | |
AnnaBridge | 189:f392fc9709a3 | 633 | #endif |