[stm32][can] Ported the can driver to locm3. Added a simple test firmware.

This commit is contained in:
Piotr Esden-Tempski
2012-11-08 20:30:01 -08:00
parent a1bd7dd5bc
commit 90ca384e00
6 changed files with 244 additions and 99 deletions
+1
View File
@@ -224,6 +224,7 @@
<target name="test_rc_spektrum" board="lisa_m_2.0"/>
<target name="test_baro" board="lisa_m_2.0"/>
<target name="test_imu_b2" board="lisa_m_2.0"/>
<target name="test_can" board="lisa_m_2.0"/>
<!--<target name="test_imu" board="lisa_m_2.0"/>
<target name="test_rc_ppm" board="lisa_m_2.0"/>
<target name="test_adc" board="lisa_m_2.0"/>
+13
View File
@@ -564,3 +564,16 @@ test_actuators_asctecv1.srcs += mcu_periph/i2c.c $(SRC_ARCH)/mcu_periph/i2c_ar
#test_manual.srcs += $(SRC_SUBSYSTEMS)/radio_control/spektrum.c
#test_manual.srcs += $(SRC_ARCH)/subsystems/radio_control/spektrum_arch.c
##
## test can interface
##
test_can.ARCHDIR = $(ARCH)
test_can.CFLAGS = $(COMMON_TEST_CFLAGS)
test_can.srcs = $(COMMON_TEST_SRCS)
test_can.CFLAGS += $(COMMON_TELEMETRY_CFLAGS)
test_can.srcs += $(COMMON_TELEMETRY_SRCS)
test_can.CFLAGS += -I$(SRC_LISA) -I$(SRC_BOARD)
test_can.CFLAGS += -I$(SRC_LISA)
test_can.srcs += lisa/test_can.c
test_can.srcs += mcu_periph/can.c $(SRC_ARCH)/mcu_periph/can_arch.c
+88 -93
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
* Copyright (C) 2012 Piotr Esden-Tempski <piotr@esden.net>
*
* This file is part of paparazzi.
*
@@ -26,128 +26,123 @@
#include "mcu_periph/can_arch.h"
#include "mcu_periph/can.h"
#include <stm32/rcc.h>
#include <stm32/gpio.h>
#include <stm32/flash.h>
#include <stm32/misc.h>
#include <stm32/can.h>
#include <libopencm3/stm32/f1/rcc.h>
#include <libopencm3/stm32/f1/gpio.h>
#include <libopencm3/stm32/can.h>
#include <libopencm3/cm3/nvic.h>
#include "led.h"
#define RCC_APB2Periph_GPIO_CAN RCC_APB2Periph_GPIOA
#define GPIO_CAN GPIOA
#define GPIO_Pin_CAN_RX GPIO_Pin_11
#define GPIO_Pin_CAN_TX GPIO_Pin_12
CanTxMsg can_tx_msg;
CanRxMsg can_rx_msg;
void _can_run_rx_callback(uint32_t id, uint8_t *buf, uint8_t len);
bool can_initialized = false;
void can_hw_init(void)
{
GPIO_InitTypeDef gpio;
NVIC_InitTypeDef nvic;
CAN_InitTypeDef can;
CAN_FilterInitTypeDef can_filter;
/* Enable peripheral clocks */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO |
RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
/* Enable peripheral clocks. */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_AFIOEN);
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN);
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_CAN1EN);
/* Configure CAN pin: RX */
gpio.GPIO_Pin = GPIO_Pin_11;
gpio.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &gpio);
/* Remap the gpio pin if necessary. */
AFIO_MAPR |= AFIO_MAPR_CAN1_REMAP_PORTB;
/* Configure CAN pin: TX */
gpio.GPIO_Pin = GPIO_Pin_12;
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &gpio);
/* Configure CAN pin: RX (input pull-up). */
gpio_set_mode(GPIO_BANK_CAN1_PB_RX, GPIO_MODE_INPUT,
GPIO_CNF_INPUT_PULL_UPDOWN, GPIO_CAN1_PB_RX);
gpio_set(GPIO_BANK_CAN1_PB_RX, GPIO_CAN1_PB_RX);
/* NVIC configuration */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
/* Configure CAN pin: TX (output push-pull). */
gpio_set_mode(GPIO_BANK_CAN1_PB_TX, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_CAN1_PB_TX);
nvic.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
nvic.NVIC_IRQChannelPreemptionPriority = 0x00;
nvic.NVIC_IRQChannelSubPriority = 0x00;
nvic.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic);
/* NVIC setup. */
nvic_enable_irq(NVIC_USB_LP_CAN_RX0_IRQ);
nvic_set_priority(NVIC_USB_LP_CAN_RX0_IRQ, 1);
/* CAN register init */
CAN_DeInit(CAN1);
CAN_StructInit(&can);
/* Reset CAN. */
can_reset(CAN1);
/* CAN cell init */
can.CAN_TTCM = DISABLE;
can.CAN_ABOM = CAN_ERR_RESUME;
can.CAN_AWUM = DISABLE;
can.CAN_NART = DISABLE;
can.CAN_RFLM = DISABLE;
can.CAN_TXFP = DISABLE;
can.CAN_Mode = CAN_Mode_Normal;
can.CAN_SJW = CAN_SJW_TQ;
can.CAN_BS1 = CAN_BS1_TQ;
can.CAN_BS2 = CAN_BS2_TQ;
can.CAN_Prescaler = CAN_PRESCALER;
can.CAN_ABOM = ENABLE;
CAN_Init(CAN1, &can);
/* CAN cell init. */
if (can_init(CAN1,
false, /* TTCM: Time triggered comm mode? */
true, /* ABOM: Automatic bus-off management? */
false, /* AWUM: Automatic wakeup mode? */
false, /* NART: No automatic retransmission? */
false, /* RFLM: Receive FIFO locked mode? */
false, /* TXFP: Transmit FIFO priority? */
CAN_BTR_SJW_1TQ,
CAN_BTR_TS1_3TQ,
CAN_BTR_TS2_4TQ,
12)) /* BRP+1: Baud rate prescaler */
{
/* TODO we need something somewhere where we can leave a note
* that CAN was unable to initialize. Just like any other
* driver should...
*/
/* CAN filter init */
can_filter.CAN_FilterNumber = 0;
can_filter.CAN_FilterMode = CAN_FilterMode_IdMask;
can_filter.CAN_FilterScale = CAN_FilterScale_32bit;
can_filter.CAN_FilterIdHigh = 0x0000;
can_filter.CAN_FilterIdLow = 0x0000;
can_filter.CAN_FilterMaskIdHigh = 0x0000;
can_filter.CAN_FilterMaskIdLow = 0x0000;
can_filter.CAN_FilterFIFOAssignment = 0;
can_filter.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&can_filter);
can_reset(CAN1);
/* transmit struct init */
can_tx_msg.StdId = 0x0;
can_tx_msg.ExtId = 0x0;
can_tx_msg.RTR = CAN_RTR_DATA;
#ifdef USE_CAN_EXT_ID
can_tx_msg.IDE = CAN_ID_EXT;
#else
can_tx_msg.IDE = CAN_ID_STD;
#endif
can_tx_msg.DLC = 1;
return;
}
CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
/* CAN filter 0 init. */
can_filter_id_mask_32bit_init(CAN1,
0, /* Filter ID */
0, /* CAN ID */
0, /* CAN ID mask */
0, /* FIFO assignment (here: FIFO0) */
true); /* Enable the filter. */
/* Enable CAN RX interrupt. */
can_enable_irq(CAN1, CAN_IER_FMPIE0);
/* Remember that we succeeded to initialize. */
can_initialized = true;
}
int can_hw_transmit(uint32_t id, const uint8_t *buf, uint8_t len)
{
if (!can_initialized) {
return -2;
}
if(len > 8){
return -1;
}
return can_transmit(CAN1,
id, /* (EX/ST)ID: CAN ID */
#ifdef USE_CAN_EXT_ID
can_tx_msg.ExtId = id;
true, /* IDE: CAN ID extended */
#else
can_tx_msg.StdId = id;
false, /* IDE: CAN ID not extended */
#endif
can_tx_msg.DLC = len;
memcpy(can_tx_msg.Data, buf, len);
CAN_Transmit(CAN1, &can_tx_msg);
return 0;
false, /* RTR: Request transmit? */
len, /* DLC: Data length */
buf);
}
void usb_lp_can1_rx0_irq_handler(void)
void usb_lp_can_rx0_isr(void)
{
CAN_Receive(CAN1, CAN_FIFO0, &can_rx_msg);
#ifdef USE_CAN_EXT_ID
_can_run_rx_callback(can_rx_msg.ExtId, can_rx_msg.Data, can_rx_msg.DLC);
#else
_can_run_rx_callback(can_rx_msg.StdId, can_rx_msg.Data, can_rx_msg.DLC);
#endif
u32 id, fmi;
bool ext, rtr;
u8 length, data[8];
can_receive(CAN1,
0, /* FIFO: 0 */
false, /* Release */
&id,
&ext,
&rtr,
&fmi,
&length,
data);
_can_run_rx_callback(id, data, length);
can_fifo_release(CAN1, 0);
}
+136
View File
@@ -0,0 +1,136 @@
/*
* $Id:$
*
* Copyright (C) 2012 Piotr Esden-Tempski <piotr@esden.net>
*
* This file is part of paparazzi.
*
* paparazzi is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* paparazzi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with paparazzi; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "mcu.h"
#include "mcu_periph/sys_time.h"
#include "led.h"
#include "subsystems/datalink/downlink.h"
#include "mcu_periph/uart.h"
#include "mcu_periph/can.h"
static inline void main_init( void );
static inline void main_periodic_task( void );
static inline void main_event_task( void );
void main_on_can_msg(uint32_t id, uint8_t *data, int len);
uint8_t tx_data[8];
uint8_t rx_data[8];
bool new_can_data = false;
int main(void) {
main_init();
tx_data[0] = 0;
tx_data[1] = 0;
tx_data[2] = 0;
tx_data[3] = 0;
tx_data[4] = 0;
tx_data[5] = 0;
tx_data[6] = 0;
tx_data[7] = 0;
new_can_data = false;
while(1) {
if (sys_time_check_and_ack_timer(0))
main_periodic_task();
main_event_task();
}
return 0;
}
static inline void main_init( void ) {
mcu_init();
sys_time_register_timer((1./PERIODIC_FREQUENCY), NULL);
ppz_can_init(main_on_can_msg);
}
static inline void main_periodic_task( void ) {
static int delay = 0;
DOWNLINK_SEND_ALIVE(DefaultChannel, DefaultDevice, 16, MD5SUM);
LED_PERIODIC();
if (delay < 100) {
delay++;
return;
}
delay = 0;
tx_data[0]+=1;
ppz_can_transmit(0, tx_data, 8);
}
static inline void main_event_task( void ) {
if (new_can_data) {
if (rx_data[0] & 1) {
LED_ON(2);
} else {
LED_OFF(2);
}
}
if (new_can_data) {
if (rx_data[0] & 2) {
LED_ON(3);
} else {
LED_OFF(3);
}
}
if (new_can_data) {
if (rx_data[0] & 4) {
LED_ON(4);
} else {
LED_OFF(4);
}
}
if (new_can_data) {
if (rx_data[0] & 8) {
LED_ON(5);
} else {
LED_OFF(5);
}
}
}
void main_on_can_msg(uint32_t id, uint8_t *data, int len)
{
for (int i = 0; i<8; i++) {
rx_data[i] = data[i];
}
new_can_data = true;
}
+3 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
* Copyright (C) 2012 Piotr Esden-Tempski <piotr@esden.net>
*
* This file is part of paparazzi.
*
@@ -29,13 +29,13 @@ can_rx_callback_t can_rx_callback;
void _can_run_rx_callback(uint32_t id, uint8_t *buf, uint8_t len);
void can_init(can_rx_callback_t callback)
void ppz_can_init(can_rx_callback_t callback)
{
can_rx_callback = callback;
can_hw_init();
}
int can_transmit(uint32_t id, const uint8_t *buf, uint8_t len)
int ppz_can_transmit(uint32_t id, const uint8_t *buf, uint8_t len)
{
return can_hw_transmit(id, buf, len);
}
+3 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
* Copyright (C) 2012 Piotr Esden-Tempski <piotr@esden.net>
*
* This file is part of paparazzi.
*
@@ -25,7 +25,7 @@
typedef void(* can_rx_callback_t)(uint32_t id, uint8_t *buf, int len);
void can_init(can_rx_callback_t callback);
int can_transmit(uint32_t id, const uint8_t *buf, uint8_t len);
void ppz_can_init(can_rx_callback_t callback);
int ppz_can_transmit(uint32_t id, const uint8_t *buf, uint8_t len);
#endif /* CAN_H */