[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_rc_spektrum" board="lisa_m_2.0"/>
<target name="test_baro" 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_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_imu" board="lisa_m_2.0"/>
<target name="test_rc_ppm" board="lisa_m_2.0"/> <target name="test_rc_ppm" board="lisa_m_2.0"/>
<target name="test_adc" 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_SUBSYSTEMS)/radio_control/spektrum.c
#test_manual.srcs += $(SRC_ARCH)/subsystems/radio_control/spektrum_arch.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. * This file is part of paparazzi.
* *
@@ -26,128 +26,123 @@
#include "mcu_periph/can_arch.h" #include "mcu_periph/can_arch.h"
#include "mcu_periph/can.h" #include "mcu_periph/can.h"
#include <stm32/rcc.h> #include <libopencm3/stm32/f1/rcc.h>
#include <stm32/gpio.h> #include <libopencm3/stm32/f1/gpio.h>
#include <stm32/flash.h> #include <libopencm3/stm32/can.h>
#include <stm32/misc.h> #include <libopencm3/cm3/nvic.h>
#include <stm32/can.h>
#include "led.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); void _can_run_rx_callback(uint32_t id, uint8_t *buf, uint8_t len);
bool can_initialized = false;
void can_hw_init(void) void can_hw_init(void)
{ {
GPIO_InitTypeDef gpio;
NVIC_InitTypeDef nvic;
CAN_InitTypeDef can;
CAN_FilterInitTypeDef can_filter;
/* Enable peripheral clocks */ /* Enable peripheral clocks. */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_AFIOEN);
RCC_APB2Periph_GPIOA, ENABLE); rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_CAN1EN);
/* Configure CAN pin: RX */ /* Remap the gpio pin if necessary. */
gpio.GPIO_Pin = GPIO_Pin_11; AFIO_MAPR |= AFIO_MAPR_CAN1_REMAP_PORTB;
gpio.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &gpio);
/* Configure CAN pin: TX */ /* Configure CAN pin: RX (input pull-up). */
gpio.GPIO_Pin = GPIO_Pin_12; gpio_set_mode(GPIO_BANK_CAN1_PB_RX, GPIO_MODE_INPUT,
gpio.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_CNF_INPUT_PULL_UPDOWN, GPIO_CAN1_PB_RX);
gpio.GPIO_Speed = GPIO_Speed_50MHz; gpio_set(GPIO_BANK_CAN1_PB_RX, GPIO_CAN1_PB_RX);
GPIO_Init(GPIOA, &gpio);
/* NVIC configuration */ /* Configure CAN pin: TX (output push-pull). */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); 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 setup. */
nvic.NVIC_IRQChannelPreemptionPriority = 0x00; nvic_enable_irq(NVIC_USB_LP_CAN_RX0_IRQ);
nvic.NVIC_IRQChannelSubPriority = 0x00; nvic_set_priority(NVIC_USB_LP_CAN_RX0_IRQ, 1);
nvic.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic);
/* CAN register init */ /* Reset CAN. */
CAN_DeInit(CAN1); can_reset(CAN1);
CAN_StructInit(&can);
/* CAN cell init */ /* CAN cell init. */
can.CAN_TTCM = DISABLE; if (can_init(CAN1,
can.CAN_ABOM = CAN_ERR_RESUME; false, /* TTCM: Time triggered comm mode? */
can.CAN_AWUM = DISABLE; true, /* ABOM: Automatic bus-off management? */
can.CAN_NART = DISABLE; false, /* AWUM: Automatic wakeup mode? */
can.CAN_RFLM = DISABLE; false, /* NART: No automatic retransmission? */
can.CAN_TXFP = DISABLE; false, /* RFLM: Receive FIFO locked mode? */
can.CAN_Mode = CAN_Mode_Normal; false, /* TXFP: Transmit FIFO priority? */
can.CAN_SJW = CAN_SJW_TQ; CAN_BTR_SJW_1TQ,
can.CAN_BS1 = CAN_BS1_TQ; CAN_BTR_TS1_3TQ,
can.CAN_BS2 = CAN_BS2_TQ; CAN_BTR_TS2_4TQ,
can.CAN_Prescaler = CAN_PRESCALER; 12)) /* BRP+1: Baud rate prescaler */
can.CAN_ABOM = ENABLE; {
CAN_Init(CAN1, &can); /* 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_reset(CAN1);
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);
/* transmit struct init */ return;
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;
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) int can_hw_transmit(uint32_t id, const uint8_t *buf, uint8_t len)
{ {
if (!can_initialized) {
return -2;
}
if(len > 8){ if(len > 8){
return -1; return -1;
} }
return can_transmit(CAN1,
id, /* (EX/ST)ID: CAN ID */
#ifdef USE_CAN_EXT_ID #ifdef USE_CAN_EXT_ID
can_tx_msg.ExtId = id; true, /* IDE: CAN ID extended */
#else #else
can_tx_msg.StdId = id; false, /* IDE: CAN ID not extended */
#endif #endif
can_tx_msg.DLC = len; false, /* RTR: Request transmit? */
len, /* DLC: Data length */
memcpy(can_tx_msg.Data, buf, len); buf);
CAN_Transmit(CAN1, &can_tx_msg);
return 0;
} }
void usb_lp_can1_rx0_irq_handler(void) void usb_lp_can_rx0_isr(void)
{ {
CAN_Receive(CAN1, CAN_FIFO0, &can_rx_msg); u32 id, fmi;
#ifdef USE_CAN_EXT_ID bool ext, rtr;
_can_run_rx_callback(can_rx_msg.ExtId, can_rx_msg.Data, can_rx_msg.DLC); u8 length, data[8];
#else
_can_run_rx_callback(can_rx_msg.StdId, can_rx_msg.Data, can_rx_msg.DLC); can_receive(CAN1,
#endif 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. * 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_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_rx_callback = callback;
can_hw_init(); 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); 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. * This file is part of paparazzi.
* *
@@ -25,7 +25,7 @@
typedef void(* can_rx_callback_t)(uint32_t id, uint8_t *buf, int len); typedef void(* can_rx_callback_t)(uint32_t id, uint8_t *buf, int len);
void can_init(can_rx_callback_t callback); void ppz_can_init(can_rx_callback_t callback);
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);
#endif /* CAN_H */ #endif /* CAN_H */