Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
can_arch.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2012 Piotr Esden-Tempski <piotr@esden.net>
3 *
4 * This file is part of paparazzi.
5 *
6 * paparazzi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * paparazzi is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with paparazzi; see the file COPYING. If not, write to
18 * the Free Software Foundation, 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 *
21 */
22
30#include <stdint.h>
31#include <string.h>
32
33#include "mcu_periph/can_arch.h"
34#include "mcu_periph/can.h"
35
36#include <libopencm3/stm32/rcc.h>
37#include <libopencm3/stm32/gpio.h>
38#include <libopencm3/stm32/can.h>
39#include <libopencm3/cm3/nvic.h>
40
41#include "led.h"
42
43
44#ifdef RTOS_PRIO
45#define NVIC_USB_LP_CAN_RX0_IRQ_PRIO RTOS_PRIO+1
46#else
47#define NVIC_USB_LP_CAN_RX0_IRQ_PRIO 1
48#define NVIC_CAN1_RX_IRQ_PRIO 1
49#endif
50
52
53struct can_arch_periph {
59};
60
62 .canport = CAN1,
63 .can_initialized = false,
64 .addr = {.can_ifindex = 1},
65 .rxframe = {0},
66 .new_rxframe = false;
67};
68
69
70void can_hw_init(void)
71{
72 can1.arch_struct = &can1_arch_s;
73
74#ifdef STM32F1
75 /* Enable peripheral clocks. */
79
80 /* Remap the gpio pin if necessary. */
82
83 /* Configure CAN pin: RX (input pull-up). */
87
88 /* Configure CAN pin: TX (output push-pull). */
91
92 /* NVIC setup. */
95
96#elif STM32F4
97
98 /* Enable peripheral clocks. */
101
102 /* set up pins for CAN1TX & CAN1RX alternate function */
105
106 /* enable interrupts on RX0 FIFO */
109
110#endif
111 /* Reset CAN. */
113
114 /* CAN cell init.
115 * For time quanta calculation see STM32 reference manual
116 * section 24.7.7 "Bit timing" page 645
117 *
118 * To talk to CSC using LPC mcu we need a baud rate of 375kHz
119 * The APB1 runs at 36MHz therefor we select a prescaler of 12
120 * resulting in time quanta frequency of 36MHz / 12 = 3MHz
121 *
122 * As the Bit time is combined of 1tq for SYNC_SEG, TS1tq for bit
123 * segment 1 and TS2tq for bit segment 2:
124 * BITtq = 1tq + TS1tq + TS2tq
125 *
126 * We can choose to use TS1 = 3 and TS2 = 4 getting
127 * 1tq + 3tq + 4tq = 8tq per bit therefor a bit frequency is
128 * 3MHZ / 8 = 375kHz
129 *
130 * Maximum baud rate of CAN is 1MHz so we can choose to use
131 * prescaler of 2 resulting in a quanta frequency of 36MHz / 2 = 18Mhz
132 *
133 * So we need to devide the frequency by 18. This can be accomplished
134 * using TS1 = 10 and TS2 = 7 resulting in:
135 * 1tq + 10tq + 7tq = 18tq
136 *
137 * NOTE: Although it is out of spec I managed to have CAN run at 2MBit
138 * Just decrease the prescaler to 1. It worked for me(tm) (esden)
139 */
141 false, /* TTCM: Time triggered comm mode? */
142 true, /* ABOM: Automatic bus-off management? */
143 false, /* AWUM: Automatic wakeup mode? */
144 false, /* NART: No automatic retransmission? */
145 false, /* RFLM: Receive FIFO locked mode? */
146 false, /* TXFP: Transmit FIFO priority? */
155#endif
156 2, /* BRP+1: Baud rate prescaler */
157 false, /* loopback mode */
158 false)) { /* silent mode */
159 /* TODO we need something somewhere where we can leave a note
160 * that CAN was unable to initialize. Just like any other
161 * driver should...
162 */
163
165
166 return;
167 }
168
169 /* CAN filter 0 init. */
170 can_filter_id_mask_32bit_init(0, /* Filter ID */
171 0, /* CAN ID */
172 0, /* CAN ID mask */
173 0, /* FIFO assignment (here: FIFO0) */
174 true); /* Enable the filter. */
175
176 /* Enable CAN RX interrupt. */
178
179 /* Remember that we succeeded to initialize. */
181}
182
183
186 return -2;
187 }
188
189 if(txframe->len > 8) {
190 return -1; //does not currently support CANFD
191 }
192
195 txframe->can_id & CAN_EID_MASK,
196 true, /* IDE: CAN ID extended */
197#else
198 txframe->can_id & CAN_SID_MASK,
199 false, /* IDE: CAN ID standard */
200#endif
201 txframe->can_id & CAN_FRAME_RTR, /* RTR: Request transmit? */
202 can_len_to_dlc(txframe->len), /* DLC: Data length */
203 (uint8_t *)txframe->data);
204
205}
206
207#ifdef STM32F1
208void usb_lp_can_rx0_isr(void)
209#elif STM32F4
210void can1_rx0_isr(void)
211#else
212#error "CAN unsuported on this MCU!"
214#endif
215{
216 uint32_t id;
217 uint8_t fmi;
218 bool ext, rtr;
219 uint8_t dlc;
220 struct pprzcan_frame* rxframe = &can1_arch_s.rxframe;
221
222
224 0, /* FIFO: 0 */
225 false, /* Release */
226 &rxframe->can_id,
227 &ext,
228 &rtr,
229 &fmi,
230 &dlc,
231 rxframe->data,
232 &rxframe->timestamp);
233
234 rxframe->len = can_dlc_to_len(dlc);
235
236 if(ext) {
237 rxframe->can_id |= CAN_FRAME_EFF;
238 }
239
240 if(rtr) {
241 rxframe->can_id |= CAN_FRAME_RTR;
242 }
243
245
247}
248
249
250void can_event() {
252 for(int i=0; i<CAN_NB_CALLBACKS_MAX; i++) {
253 if(can1.callbacks[i] != NULL) {
254 can1.callbacks[i](&can1_arch_s.rxframe, &can1_arch_s.addr, can1.callback_user_data[i]);
255 }
256 }
257 can1_arch_s.new_rxframe = false;
258 }
259}
uint8_t can_dlc_to_len(uint8_t dlc)
Definition can.c:39
uint8_t can_len_to_dlc(uint8_t len)
Definition can.c:46
uint32_t timestamp
Definition can.h:76
uint8_t len
Definition can.h:74
uint8_t data[SOCKETCAN_MAX_DLEN]
Definition can.h:77
#define CAN_NB_CALLBACKS_MAX
Definition can.h:40
socketcan_id_t can_id
Definition can.h:73
#define CAN_FRAME_EFF
Definition can.h:62
#define CAN_EID_MASK
Definition can.h:64
#define CAN_SID_MASK
Definition can.h:65
#define CAN_FRAME_RTR
Definition can.h:60
void can_hw_init()
Definition can_arch.c:68
int can_transmit_frame(struct pprzcan_frame *txframe, struct pprzaddr_can *addr)
Definition can_arch.c:137
static void gpio_set(ioportid_t port, uint16_t pin)
Set a gpio output to high level.
Definition gpio_arch.h:104
#define GPIO_AF9
Definition gpio_def.h:73
#define GPIO8
Definition gpio_def.h:39
#define GPIO9
Definition gpio_def.h:40
arch independent LED (Light Emitting Diodes) API
uint16_t foo
Definition main_demo5.c:58
#define GPIOB
Definition gpio_arch.h:35
void _can_run_rx_callback(uint32_t id, uint8_t *buf, uint8_t len)
#define NVIC_CAN1_RX_IRQ_PRIO
Definition can_arch.c:48
uint32_t canport
Definition can_arch.c:54
struct pprzcan_frame rxframe
Definition can_arch.c:56
struct can_arch_periph can1_arch_s
Definition can_arch.c:61
#define NVIC_USB_LP_CAN_RX0_IRQ_PRIO
Definition can_arch.c:47
bool can_initialized
Definition can_arch.c:55
struct pprzaddr_can addr
Definition can_arch.c:58
void can_event()
Definition can_arch.c:250
void __unsupported_isr(void)
Definition can_arch.c:213
void can_init(void)
Definition uavcan.c:94
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.