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