mirror of
https://github.com/paparazzi/paparazzi.git
synced 2026-05-09 22:49:53 +08:00
[stm32] usb_serial: CDC USB Device driver for STM32F1/4
add usb_serial implementation and using that for telemetry_usb closes #998
This commit is contained in:
@@ -11,8 +11,15 @@ ap.srcs += $(SRC_FIRMWARE)/datalink.c
|
||||
ap.srcs += $(SRC_ARCH)/usb_ser_hw.c $(SRC_ARCH)/lpcusb/usbhw_lpc.c $(SRC_ARCH)/lpcusb/usbcontrol.c
|
||||
ap.srcs += $(SRC_ARCH)/lpcusb/usbstdreq.c $(SRC_ARCH)/lpcusb/usbinit.c
|
||||
else
|
||||
ifeq ($(ARCH), stm32)
|
||||
ap.CFLAGS += -DDOWNLINK -DPERIODIC_TELEMETRY -DDOWNLINK_DEVICE=usb_serial -DPPRZ_UART=UsbS
|
||||
ap.CFLAGS += -DDOWNLINK_TRANSPORT=pprz_tp -DDATALINK=PPRZ -DUSE_USB_SERIAL
|
||||
ap.srcs += subsystems/datalink/downlink.c subsystems/datalink/pprz_transport.c
|
||||
ap.srcs += $(SRC_FIRMWARE)/datalink.c
|
||||
ap.srcs += $(SRC_ARCH)/usb_ser_hw.c
|
||||
else
|
||||
ifneq ($(ARCH), sim)
|
||||
$(error telemetry_transparent_usb currently only implemented for the lpc21)
|
||||
$(error telemetry_transparent_usb currently only implemented for the lpc21 and stm32)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
@@ -9,8 +9,15 @@ ap.srcs += $(SRC_FIRMWARE)/datalink.c $(SRC_FIRMWARE)/rotorcraft_telemetry.c
|
||||
ap.srcs += $(SRC_ARCH)/usb_ser_hw.c $(SRC_ARCH)/lpcusb/usbhw_lpc.c $(SRC_ARCH)/lpcusb/usbcontrol.c
|
||||
ap.srcs += $(SRC_ARCH)/lpcusb/usbstdreq.c $(SRC_ARCH)/lpcusb/usbinit.c
|
||||
else
|
||||
ifeq ($(ARCH), stm32)
|
||||
ap.CFLAGS += -DDOWNLINK -DPERIODIC_TELEMETRY -DDOWNLINK_DEVICE=usb_serial -DPPRZ_UART=UsbS
|
||||
ap.CFLAGS += -DDOWNLINK_TRANSPORT=pprz_tp -DDATALINK=PPRZ -DUSE_USB_SERIAL -DDefaultPeriodic='&telemetry_Main'
|
||||
ap.srcs += subsystems/datalink/downlink.c subsystems/datalink/pprz_transport.c subsystems/datalink/telemetry.c
|
||||
ap.srcs += $(SRC_FIRMWARE)/datalink.c $(SRC_FIRMWARE)/rotorcraft_telemetry.c
|
||||
ap.srcs += $(SRC_ARCH)/usb_ser_hw.c
|
||||
else
|
||||
ifneq ($(ARCH), sim)
|
||||
$(error telemetry_transparent_usb currently only implemented for the lpc21)
|
||||
$(error telemetry_transparent_usb currently only implemented for the lpc21 and stm32)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<!DOCTYPE module SYSTEM "module.dtd">
|
||||
|
||||
<module name="usb_serial_stm32_example1" dir="com">
|
||||
<doc>
|
||||
<description>
|
||||
Serial-over-USB console on STM32.
|
||||
Example of USB-serial module on STM32 architecture, using libopencm3 library.
|
||||
This example emulates a console - i.e. user can send commands to Paparazzi and get response
|
||||
To be used with Lisa M/MX 2.1
|
||||
</description>
|
||||
</doc>
|
||||
|
||||
<header>
|
||||
<file name="usb_serial_stm32.h"/>
|
||||
</header>
|
||||
|
||||
<init fun="init_usb_serial()"/>
|
||||
<event fun="event_usb_serial()"/>
|
||||
|
||||
<makefile target="ap">
|
||||
<raw>
|
||||
ap.srcs += $(SRC_ARCH)/usb_ser_hw.c
|
||||
</raw>
|
||||
<define name="USE_USB_SERIAL"/>
|
||||
<file name="usb_serial_stm32_example1.c"/>
|
||||
</makefile>
|
||||
</module>
|
||||
@@ -0,0 +1,30 @@
|
||||
<!DOCTYPE module SYSTEM "module.dtd">
|
||||
|
||||
<module name="usb_serial_stm32_example1" dir="com">
|
||||
<doc>
|
||||
<description>
|
||||
STM32 USB-serial example.
|
||||
Example of USB-serial module on STM32 architecture, using libopencm3 library.
|
||||
This example tests the capability of USB-serial port by sending a lots of data.
|
||||
To be used with Lisa M/MX 2.1
|
||||
</description>
|
||||
</doc>
|
||||
|
||||
<header>
|
||||
<file name="usb_serial_stm32.h"/>
|
||||
</header>
|
||||
|
||||
<init fun="init_usb_serial()"/>
|
||||
|
||||
<periodic fun="periodic_usb_serial()" freq="10." autorun="TRUE"/>
|
||||
|
||||
<event fun="event_usb_serial()"/>
|
||||
|
||||
<makefile target="ap">
|
||||
<raw>
|
||||
ap.srcs += $(SRC_ARCH)/usb_ser_hw.c
|
||||
</raw>
|
||||
<define name="USE_USB_SERIAL"/>
|
||||
<file name="usb_serial_stm32_example2.c"/>
|
||||
</makefile>
|
||||
</module>
|
||||
@@ -565,6 +565,12 @@ static void usb_serial_transmit(struct usb_serial_periph* p __attribute__((unuse
|
||||
|
||||
static void usb_serial_send(struct usb_serial_periph* p __attribute__((unused))) { }
|
||||
|
||||
// Empty for lpc21
|
||||
void VCOM_event(void) {}
|
||||
|
||||
// Empty for lpc21
|
||||
void VCOM_transmit_message(void) {}
|
||||
|
||||
void VCOM_init(void) {
|
||||
// initialise stack
|
||||
USBInit();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -656,6 +656,10 @@ void event_task_ap( void ) {
|
||||
uart_event();
|
||||
#endif
|
||||
|
||||
#if USE_USB_SERIAL
|
||||
VCOM_event();
|
||||
#endif
|
||||
|
||||
#if USE_AHRS && USE_IMU
|
||||
ImuEvent(on_gyro_event, on_accel_event, on_mag_event);
|
||||
#endif
|
||||
|
||||
@@ -83,6 +83,10 @@ PRINT_CONFIG_MSG_VALUE("USE_BARO_BOARD is TRUE, reading onboard baro: ", BARO_BO
|
||||
#include "generated/modules.h"
|
||||
#include "subsystems/abi.h"
|
||||
|
||||
#ifdef USE_USB_SERIAL
|
||||
#include "mcu_periph/usb_serial.h"
|
||||
#endif
|
||||
|
||||
|
||||
/* if PRINT_CONFIG is defined, print some config options */
|
||||
PRINT_CONFIG_VAR(PERIODIC_FREQUENCY)
|
||||
@@ -283,6 +287,10 @@ STATIC_INLINE void main_event( void ) {
|
||||
udp_event();
|
||||
#endif
|
||||
|
||||
#ifdef USE_USB_SERIAL
|
||||
VCOM_event();
|
||||
#endif
|
||||
|
||||
DatalinkEvent();
|
||||
|
||||
if (autopilot_rc) {
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include <inttypes.h>
|
||||
#include "std.h"
|
||||
#include "mcu_periph/link_device.h"
|
||||
//#include "usb_serial_hw.h"
|
||||
|
||||
struct usb_serial_periph {
|
||||
/** Generic device interface */
|
||||
@@ -47,13 +46,18 @@ bool_t VCOM_check_free_space(uint8_t len);
|
||||
int VCOM_check_available(void);
|
||||
void VCOM_set_linecoding(uint8_t mode);
|
||||
void VCOM_allow_linecoding(uint8_t mode);
|
||||
void VCOM_transmit_message(void);
|
||||
void VCOM_event(void);
|
||||
|
||||
/*
|
||||
* Macros can be used in subsystems that normally work with serial ports
|
||||
* e.g. use UsbS instead of UART1
|
||||
*/
|
||||
#define UsbSInit() VCOM_init()
|
||||
#define UsbSCheckFreeSpace(_x) VCOM_check_free_space(_x)
|
||||
#define UsbSTransmit(_x) VCOM_putchar(_x)
|
||||
#define UsbSSendMessage() {}
|
||||
#define UsbSSendMessage() VCOM_transmit_message()
|
||||
#define UsbSGetch() VCOM_getchar()
|
||||
#define UsbSChAvailable() VCOM_check_available()
|
||||
|
||||
|
||||
#endif /* USB_S_H */
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Michal Podhradsky
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file modules/com/usb_serial_stm32.h
|
||||
* header for serial over USB modules
|
||||
*/
|
||||
|
||||
#ifndef USB_SERIAL_STM32_H
|
||||
#define USB_SERIAL_STM32_H
|
||||
|
||||
#include "mcu_periph/usb_serial.h"
|
||||
|
||||
void init_usb_serial(void);
|
||||
void periodic_usb_serial(void);
|
||||
void event_usb_serial(void);
|
||||
|
||||
void usb_serial_parse_packet(int c);
|
||||
|
||||
#endif // USB_SERIAL_STM32_H
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Michal Podhradsky
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file modules/com/usb_serial_stm32_example1.c
|
||||
*
|
||||
* USB_SERIAL_STM32 example 1 - a template for a console to autopilot
|
||||
*
|
||||
*/
|
||||
|
||||
#include "modules/com/usb_serial_stm32.h"
|
||||
#include <string.h>
|
||||
|
||||
void send_command(void);
|
||||
void cmd_execute(void);
|
||||
|
||||
char cmd_buf[64];
|
||||
uint8_t cmd_idx;
|
||||
bool_t cmd_avail;
|
||||
uint8_t prompt = '$';
|
||||
|
||||
/**
|
||||
* Init module, call VCOM_init() from here
|
||||
*/
|
||||
void init_usb_serial(void)
|
||||
{
|
||||
VCOM_init();
|
||||
cmd_idx = 0;
|
||||
cmd_avail = FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse data from buffer
|
||||
* Note that the function receives int, not char
|
||||
* Because we want to be able to catch -1 in case no
|
||||
* more data were available
|
||||
*/
|
||||
void usb_serial_parse_packet(int data)
|
||||
{
|
||||
if (data == -1) { return; }
|
||||
char c = (char)data;
|
||||
|
||||
if (c == '\r' || c == '\n') {
|
||||
// command complete
|
||||
cmd_avail = TRUE;
|
||||
// add termination characters and the prompt into buffer
|
||||
VCOM_putchar('\r');
|
||||
VCOM_putchar('\n');
|
||||
VCOM_putchar(prompt);
|
||||
} else {
|
||||
// buffer command
|
||||
cmd_buf[cmd_idx++] = c;
|
||||
// echo char back and transmit immediately
|
||||
VCOM_putchar((uint8_t)c);
|
||||
VCOM_transmit_message();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function
|
||||
*/
|
||||
static inline void ReadUsbBuffer(void)
|
||||
{
|
||||
while (UsbSChAvailable() && !cmd_avail) {
|
||||
usb_serial_parse_packet(UsbSGetch());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute command from user
|
||||
* use strncmp
|
||||
*/
|
||||
void cmd_execute(void)
|
||||
{
|
||||
// copy command into tx buffer for user feedback
|
||||
for (int i = 0; i < cmd_idx; i++) {
|
||||
VCOM_putchar(cmd_buf[i]);
|
||||
}
|
||||
|
||||
if (strncmp("help", cmd_buf, cmd_idx) == 0) {
|
||||
uint8_t response[] = " - user asked for help";
|
||||
for (uint16_t i = 0; i < sizeof(response); i++) {
|
||||
VCOM_putchar(response[i]);
|
||||
}
|
||||
} else {
|
||||
uint8_t response[] = " Command not recognized";
|
||||
for (uint16_t i = 0; i < sizeof(response); i++) {
|
||||
VCOM_putchar(response[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// add termination characters and the prompt into buffer
|
||||
VCOM_putchar('\r');
|
||||
VCOM_putchar('\n');
|
||||
VCOM_putchar(prompt);
|
||||
|
||||
// reset counter
|
||||
cmd_idx = 0;
|
||||
// transmit message
|
||||
VCOM_transmit_message();
|
||||
}
|
||||
|
||||
/**
|
||||
* Call VCOM_poll() from module event function
|
||||
*/
|
||||
void event_usb_serial(void)
|
||||
{
|
||||
VCOM_event();
|
||||
if (UsbSChAvailable()) {
|
||||
ReadUsbBuffer();
|
||||
}
|
||||
if (cmd_avail) {
|
||||
cmd_execute();
|
||||
cmd_avail = FALSE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Michal Podhradsky
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file modules/com/usb_serial_stm32_example2.c
|
||||
*
|
||||
* USB_SERIAL_STM32 example 2 - sends lot of data through serial port. User can control
|
||||
* the flow by pressing "S" for stop and "R" for run.
|
||||
*/
|
||||
|
||||
#include "modules/com/usb_serial_stm32.h"
|
||||
|
||||
void send_command(void);
|
||||
|
||||
uint8_t run;
|
||||
uint8_t prompt = '$';
|
||||
|
||||
/* A lot of text */
|
||||
uint8_t big_buffer[] = " ASCII stands for American Standard Code for Information Interchange. Computers can only understand numbers, so an ASCII code is the numerical representation of a character such as 'a' or '@' or an action of some sort. ASCII was developed a long time ago and now the non-printing characters are rarely used for their original purpose. Below is the ASCII character table and this includes descriptions of the first 32 non-printing characters. ASCII was actually designed for use with teletypes and so the descriptions are somewhat obscure. If someone says they want your CV however in ASCII format, all this means is they want 'plain' text with no formatting such as tabs, bold or underscoring - the raw format that any computer can understand. This is usually so they can easily import the file into their own applications without issues. Notepad.exe creates ASCII text, or in MS Word you can save a file as 'text only' ";
|
||||
|
||||
/**
|
||||
* Init module, call VCOM_init() from here
|
||||
*/
|
||||
void init_usb_serial(void)
|
||||
{
|
||||
VCOM_init();
|
||||
run = FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Periodic function in case you needed to send data periodically
|
||||
* like telemetry
|
||||
* Note that the data are sent once the buffer is full, not immediately
|
||||
*/
|
||||
void periodic_usb_serial(void)
|
||||
{
|
||||
if (run) {
|
||||
for (uint16_t i = 0; i < sizeof(big_buffer); i++) {
|
||||
VCOM_putchar(big_buffer[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse data from buffer
|
||||
* Note that the function receives int, not char
|
||||
* Because we want to be able to catch -1 in case no
|
||||
* more data were available
|
||||
*/
|
||||
void usb_serial_parse_packet(int data)
|
||||
{
|
||||
if (data == -1) { return; }
|
||||
uint8_t c = (uint8_t)data;
|
||||
VCOM_putchar(prompt);
|
||||
VCOM_putchar(data);
|
||||
VCOM_putchar('\r');
|
||||
VCOM_putchar('\n');
|
||||
|
||||
if (c == 'S') {
|
||||
run = FALSE;
|
||||
}
|
||||
if (c == 'R') {
|
||||
run = TRUE;
|
||||
}
|
||||
VCOM_transmit_message();
|
||||
}
|
||||
|
||||
/**
|
||||
* Call VCOM_poll() from module event function
|
||||
*/
|
||||
void event_usb_serial(void)
|
||||
{
|
||||
VCOM_event();
|
||||
if (UsbSChAvailable()) {
|
||||
usb_serial_parse_packet(UsbSGetch());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user