Paparazzi UAS  v5.2.2_stable-0-gd6b9f29
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures 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 #ifndef STM32F1
44 #error "CAN is currently only implemented for STM32F1"
45 #endif
46 
47 #ifdef RTOS_PRIO
48 #define NVIC_USB_LP_CAN_RX0_IRQ_PRIO RTOS_PRIO+1
49 #else
50 #define NVIC_USB_LP_CAN_RX0_IRQ_PRIO 1
51 #endif
52 
54 
55 bool can_initialized = false;
56 
57 void can_hw_init(void)
58 {
59 
60  /* Enable peripheral clocks. */
61  rcc_periph_clock_enable(RCC_AFIO);
62  rcc_periph_clock_enable(RCC_GPIOB);
63  rcc_periph_clock_enable(RCC_CAN1);
64 
65  /* Remap the gpio pin if necessary. */
66  AFIO_MAPR |= AFIO_MAPR_CAN1_REMAP_PORTB;
67 
68  /* Configure CAN pin: RX (input pull-up). */
69  gpio_set_mode(GPIO_BANK_CAN1_PB_RX, GPIO_MODE_INPUT,
70  GPIO_CNF_INPUT_PULL_UPDOWN, GPIO_CAN1_PB_RX);
71  gpio_set(GPIO_BANK_CAN1_PB_RX, GPIO_CAN1_PB_RX);
72 
73  /* Configure CAN pin: TX (output push-pull). */
74  gpio_set_mode(GPIO_BANK_CAN1_PB_TX, GPIO_MODE_OUTPUT_50_MHZ,
75  GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_CAN1_PB_TX);
76 
77  /* NVIC setup. */
78  nvic_enable_irq(NVIC_USB_LP_CAN_RX0_IRQ);
79  nvic_set_priority(NVIC_USB_LP_CAN_RX0_IRQ, NVIC_USB_LP_CAN_RX0_IRQ_PRIO);
80 
81  /* Reset CAN. */
82  can_reset(CAN1);
83 
84  /* CAN cell init.
85  * For time quanta calculation see STM32 reference manual
86  * section 24.7.7 "Bit timing" page 645
87  *
88  * To talk to CSC using LPC mcu we need a baud rate of 375kHz
89  * The APB1 runs at 36MHz therefor we select a prescaler of 12
90  * resulting in time quanta frequency of 36MHz / 12 = 3MHz
91  *
92  * As the Bit time is combined of 1tq for SYNC_SEG, TS1tq for bit
93  * segment 1 and TS2tq for bit segment 2:
94  * BITtq = 1tq + TS1tq + TS2tq
95  *
96  * We can choose to use TS1 = 3 and TS2 = 4 getting
97  * 1tq + 3tq + 4tq = 8tq per bit therefor a bit frequency is
98  * 3MHZ / 8 = 375kHz
99  *
100  * Maximum baud rate of CAN is 1MHz so we can choose to use
101  * prescaler of 2 resulting in a quanta frequency of 36MHz / 2 = 18Mhz
102  *
103  * So we need to devide the frequency by 18. This can be accomplished
104  * using TS1 = 10 and TS2 = 7 resulting in:
105  * 1tq + 10tq + 7tq = 18tq
106  *
107  * NOTE: Although it is out of spec I managed to have CAN run at 2MBit
108  * Just decrease the prescaler to 1. It worked for me(tm) (esden)
109  */
110  if (can_init(CAN1,
111  false, /* TTCM: Time triggered comm mode? */
112  true, /* ABOM: Automatic bus-off management? */
113  false, /* AWUM: Automatic wakeup mode? */
114  false, /* NART: No automatic retransmission? */
115  false, /* RFLM: Receive FIFO locked mode? */
116  false, /* TXFP: Transmit FIFO priority? */
117  CAN_BTR_SJW_1TQ,
118  CAN_BTR_TS1_10TQ,
119  CAN_BTR_TS2_7TQ,
120  2, /* BRP+1: Baud rate prescaler */
121  false, /* loopback mode */
122  false)) /* silent mode */
123  {
124  /* TODO we need something somewhere where we can leave a note
125  * that CAN was unable to initialize. Just like any other
126  * driver should...
127  */
128 
129  can_reset(CAN1);
130 
131  return;
132  }
133 
134  /* CAN filter 0 init. */
135  can_filter_id_mask_32bit_init(CAN1,
136  0, /* Filter ID */
137  0, /* CAN ID */
138  0, /* CAN ID mask */
139  0, /* FIFO assignment (here: FIFO0) */
140  true); /* Enable the filter. */
141 
142  /* Enable CAN RX interrupt. */
143  can_enable_irq(CAN1, CAN_IER_FMPIE0);
144 
145  /* Remember that we succeeded to initialize. */
146  can_initialized = true;
147 }
148 
150 {
151 
152  if (!can_initialized) {
153  return -2;
154  }
155 
156  if(len > 8){
157  return -1;
158  }
159 
160 
161  /* FIXME: we are discarding the const qualifier for buf here.
162  * We should probably fix libopencm3 to actually have the
163  * const qualifier too...
164  */
165  return can_transmit(CAN1,
166  id, /* (EX/ST)ID: CAN ID */
167 #ifdef USE_CAN_EXT_ID
168  true, /* IDE: CAN ID extended */
169 #else
170  false, /* IDE: CAN ID not extended */
171 #endif
172  false, /* RTR: Request transmit? */
173  len, /* DLC: Data length */
174  (uint8_t *)buf);
175 }
176 
178 {
179  uint32_t id, fmi;
180  bool ext, rtr;
181  uint8_t length, data[8];
182 
183  can_receive(CAN1,
184  0, /* FIFO: 0 */
185  false, /* Release */
186  &id,
187  &ext,
188  &rtr,
189  &fmi,
190  &length,
191  data);
192 
193  _can_run_rx_callback(id, data, length);
194 
195  can_fifo_release(CAN1, 0);
196 }
197 
Handling of CAN hardware for STM32.
#define CAN1
Definition: LPC21xx.h:484
void _can_run_rx_callback(uint32_t id, uint8_t *buf, uint8_t len)
Definition: can.c:43
void gpio_set(uint32_t port, uint16_t pin)
Set a gpio output to high level.
#define NVIC_USB_LP_CAN_RX0_IRQ_PRIO
Definition: can_arch.c:50
unsigned long uint32_t
Definition: types.h:18
void usb_lp_can_rx0_isr(void)
Definition: can_arch.c:177
int can_hw_transmit(uint32_t id, const uint8_t *buf, uint8_t len)
Definition: can_arch.c:149
struct adc_buf * buf
Definition: adc_arch.c:586
unsigned char uint8_t
Definition: types.h:14
void can_hw_init(void)
Definition: can_arch.c:57
arch independent LED (Light Emitting Diodes) API
bool can_initialized
Definition: can_arch.c:55