mirror of
https://github.com/paparazzi/paparazzi.git
synced 2026-06-05 15:12:09 +08:00
[stm32][can] Ported the can driver to locm3. Added a simple test firmware.
This commit is contained in:
@@ -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"/>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user