mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-02-05 21:52:10 +01:00
Merge remote-tracking branch 'origin/amorale/OP-980_revolution_usb_reconnect' into next
This commit is contained in:
commit
107b930573
@ -37,4 +37,33 @@
|
|||||||
#define NELEMENTS(x) (sizeof(x) / sizeof((x)[0]))
|
#define NELEMENTS(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compiler barrier: Disables compiler load/store reordering across the barrier
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define COMPILER_BARRIER() asm volatile ("" ::: "memory")
|
||||||
|
|
||||||
|
// Memory barriers:
|
||||||
|
// Note that on single core Cortex M3 & M4, the is generally no need to use a processor memory barrier instruction such as DMB.
|
||||||
|
// See http://infocenter.arm.com/help/topic/com.arm.doc.dai0321a/DAI0321A_programming_guide_memory_barriers_for_m_profile.pdf
|
||||||
|
// However, it makes sense to use these if we want to reduce issues if we ever port to a multicore processor in the future.
|
||||||
|
// An important exception for STM32 is when setting up the DMA engine - see the above reference for details.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read Acquire memory barrier
|
||||||
|
*/
|
||||||
|
#define READ_MEMORY_BARRIER() COMPILER_BARRIER()
|
||||||
|
/**
|
||||||
|
* @brief Write Release memory barrier
|
||||||
|
*/
|
||||||
|
#define WRITE_MEMORY_BARRIER() COMPILER_BARRIER()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Full fence memory barrier
|
||||||
|
*/
|
||||||
|
#define MEMORY_BARRIER() COMPILER_BARRIER()
|
||||||
|
|
||||||
|
// For future multicore ARM v7 or later:
|
||||||
|
// The above three macros would be replaced with: asm volatile("dmb":::"memory")
|
||||||
|
|
||||||
#endif // PIOS_HELPERS_H
|
#endif // PIOS_HELPERS_H
|
||||||
|
@ -37,7 +37,7 @@ extern int32_t PIOS_USB_Reenumerate();
|
|||||||
extern int32_t PIOS_USB_ChangeConnectionState(bool connected);
|
extern int32_t PIOS_USB_ChangeConnectionState(bool connected);
|
||||||
extern bool PIOS_USB_CableConnected(uint8_t id);
|
extern bool PIOS_USB_CableConnected(uint8_t id);
|
||||||
extern bool PIOS_USB_CheckAvailable(uint32_t id);
|
extern bool PIOS_USB_CheckAvailable(uint32_t id);
|
||||||
|
extern void PIOS_USB_RegisterDisconnectionCallback(void (*disconnectionCB)(void));
|
||||||
#endif /* PIOS_USB_H */
|
#endif /* PIOS_USB_H */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,12 +34,14 @@
|
|||||||
|
|
||||||
#include "usb_core.h"
|
#include "usb_core.h"
|
||||||
#include "pios_usb_board_data.h"
|
#include "pios_usb_board_data.h"
|
||||||
#include "pios_usb_priv.h"
|
#include <pios_usb_priv.h>
|
||||||
|
#include <pios_helpers.h>
|
||||||
|
|
||||||
/* Rx/Tx status */
|
/* Rx/Tx status */
|
||||||
static uint8_t transfer_possible = 0;
|
static uint8_t transfer_possible = 0;
|
||||||
|
|
||||||
|
static void(*disconnection_cb_list[3]) (void);
|
||||||
|
|
||||||
enum pios_usb_dev_magic {
|
enum pios_usb_dev_magic {
|
||||||
PIOS_USB_DEV_MAGIC = 0x17365904,
|
PIOS_USB_DEV_MAGIC = 0x17365904,
|
||||||
};
|
};
|
||||||
@ -47,8 +49,13 @@ enum pios_usb_dev_magic {
|
|||||||
struct pios_usb_dev {
|
struct pios_usb_dev {
|
||||||
enum pios_usb_dev_magic magic;
|
enum pios_usb_dev_magic magic;
|
||||||
const struct pios_usb_cfg *cfg;
|
const struct pios_usb_cfg *cfg;
|
||||||
|
#ifdef PIOS_INCLUDE_FREERTOS
|
||||||
|
xSemaphoreHandle statusCheckSemaphore;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void raiseDisconnectionCallbacks(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Validate the usb device structure
|
* @brief Validate the usb device structure
|
||||||
* @returns true if valid device or false otherwise
|
* @returns true if valid device or false otherwise
|
||||||
@ -67,7 +74,8 @@ static struct pios_usb_dev *PIOS_USB_alloc(void)
|
|||||||
if (!usb_dev) {
|
if (!usb_dev) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
vSemaphoreCreateBinary(usb_dev->statusCheckSemaphore);
|
||||||
|
xSemaphoreGive(usb_dev->statusCheckSemaphore);
|
||||||
usb_dev->magic = PIOS_USB_DEV_MAGIC;
|
usb_dev->magic = PIOS_USB_DEV_MAGIC;
|
||||||
return usb_dev;
|
return usb_dev;
|
||||||
}
|
}
|
||||||
@ -162,15 +170,56 @@ uint32_t usb_found;
|
|||||||
bool PIOS_USB_CheckAvailable(__attribute__((unused)) uint32_t id)
|
bool PIOS_USB_CheckAvailable(__attribute__((unused)) uint32_t id)
|
||||||
{
|
{
|
||||||
struct pios_usb_dev *usb_dev = (struct pios_usb_dev *)pios_usb_id;
|
struct pios_usb_dev *usb_dev = (struct pios_usb_dev *)pios_usb_id;
|
||||||
|
static bool lastStatus = false;
|
||||||
|
|
||||||
if (!PIOS_USB_validate(usb_dev)) {
|
if (!PIOS_USB_validate(usb_dev)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
usb_found = ((usb_dev->cfg->vsense.gpio->IDR & usb_dev->cfg->vsense.init.GPIO_Pin) != 0) ^ usb_dev->cfg->vsense_active_low;
|
usb_found = ((usb_dev->cfg->vsense.gpio->IDR & usb_dev->cfg->vsense.init.GPIO_Pin) != 0) ^ usb_dev->cfg->vsense_active_low;
|
||||||
return usb_found;
|
|
||||||
|
|
||||||
return usb_found != 0 && transfer_possible ? 1 : 0;
|
bool status = usb_found != 0 && transfer_possible ? 1 : 0;
|
||||||
|
|
||||||
|
#ifdef PIOS_INCLUDE_FREERTOS
|
||||||
|
while (xSemaphoreTakeFromISR(usb_dev->statusCheckSemaphore, NULL) != pdTRUE) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
bool reconnect = (lastStatus && !status);
|
||||||
|
lastStatus = status;
|
||||||
|
#ifdef PIOS_INCLUDE_FREERTOS
|
||||||
|
xSemaphoreGiveFromISR(usb_dev->statusCheckSemaphore, NULL);
|
||||||
|
#endif
|
||||||
|
if (reconnect) {
|
||||||
|
raiseDisconnectionCallbacks();
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Register a physical disconnection callback
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void PIOS_USB_RegisterDisconnectionCallback(void (*disconnectionCB)(void))
|
||||||
|
{
|
||||||
|
PIOS_Assert(disconnectionCB);
|
||||||
|
for (uint32_t i = 0; i < NELEMENTS(disconnection_cb_list); i++) {
|
||||||
|
if (disconnection_cb_list[i] == NULL) {
|
||||||
|
disconnection_cb_list[i] = disconnectionCB;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PIOS_Assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void raiseDisconnectionCallbacks(void)
|
||||||
|
{
|
||||||
|
uint32_t i = 0;
|
||||||
|
|
||||||
|
while (i < NELEMENTS(disconnection_cb_list) && disconnection_cb_list[i] != NULL) {
|
||||||
|
(disconnection_cb_list[i++])();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -29,14 +29,14 @@
|
|||||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pios.h"
|
#include <pios.h>
|
||||||
|
|
||||||
#ifdef PIOS_INCLUDE_USB_HID
|
#ifdef PIOS_INCLUDE_USB_HID
|
||||||
|
|
||||||
#include "pios_usb_hid_priv.h"
|
#include <pios_usb_hid_priv.h>
|
||||||
#include "pios_usb_board_data.h" /* PIOS_BOARD_*_DATA_LENGTH */
|
#include "pios_usb_board_data.h" /* PIOS_BOARD_*_DATA_LENGTH */
|
||||||
#include "pios_usbhook.h" /* PIOS_USBHOOK_* */
|
#include <pios_usbhook.h> /* PIOS_USBHOOK_* */
|
||||||
|
#include <pios_delay.h>
|
||||||
static void PIOS_USB_HID_RegisterTxCallback(uint32_t usbhid_id, pios_com_callback tx_out_cb, uint32_t context);
|
static void PIOS_USB_HID_RegisterTxCallback(uint32_t usbhid_id, pios_com_callback tx_out_cb, uint32_t context);
|
||||||
static void PIOS_USB_HID_RegisterRxCallback(uint32_t usbhid_id, pios_com_callback rx_in_cb, uint32_t context);
|
static void PIOS_USB_HID_RegisterRxCallback(uint32_t usbhid_id, pios_com_callback rx_in_cb, uint32_t context);
|
||||||
static void PIOS_USB_HID_TxStart(uint32_t usbhid_id, uint16_t tx_bytes_avail);
|
static void PIOS_USB_HID_TxStart(uint32_t usbhid_id, uint16_t tx_bytes_avail);
|
||||||
@ -68,10 +68,10 @@ struct pios_usb_hid_dev {
|
|||||||
bool usb_if_enabled;
|
bool usb_if_enabled;
|
||||||
|
|
||||||
uint8_t rx_packet_buffer[PIOS_USB_BOARD_HID_DATA_LENGTH] __attribute__((aligned(4)));
|
uint8_t rx_packet_buffer[PIOS_USB_BOARD_HID_DATA_LENGTH] __attribute__((aligned(4)));
|
||||||
bool rx_active;
|
volatile bool rx_active;
|
||||||
|
|
||||||
uint8_t tx_packet_buffer[PIOS_USB_BOARD_HID_DATA_LENGTH] __attribute__((aligned(4)));
|
uint8_t tx_packet_buffer[PIOS_USB_BOARD_HID_DATA_LENGTH] __attribute__((aligned(4)));
|
||||||
bool tx_active;
|
volatile bool tx_active;
|
||||||
|
|
||||||
uint32_t rx_dropped;
|
uint32_t rx_dropped;
|
||||||
uint32_t rx_oversize;
|
uint32_t rx_oversize;
|
||||||
@ -187,7 +187,7 @@ static bool PIOS_USB_HID_SendReport(struct pios_usb_hid_dev *usb_hid_dev)
|
|||||||
if (!usb_hid_dev->tx_out_cb) {
|
if (!usb_hid_dev->tx_out_cb) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
READ_MEMORY_BARRIER();
|
||||||
bool need_yield = false;
|
bool need_yield = false;
|
||||||
#ifdef PIOS_USB_BOARD_BL_HID_HAS_NO_LENGTH_BYTE
|
#ifdef PIOS_USB_BOARD_BL_HID_HAS_NO_LENGTH_BYTE
|
||||||
bytes_to_tx = (usb_hid_dev->tx_out_cb)(usb_hid_dev->tx_out_context,
|
bytes_to_tx = (usb_hid_dev->tx_out_cb)(usb_hid_dev->tx_out_context,
|
||||||
@ -252,6 +252,12 @@ static void PIOS_USB_HID_RxStart(uint32_t usbhid_id, uint16_t rx_bytes_avail)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add a timeout to prevent connection drops
|
||||||
|
static uint32_t last_rx_time_raw = 0;
|
||||||
|
if (PIOS_DELAY_DiffuS(last_rx_time_raw) > 1000000) {
|
||||||
|
usb_hid_dev->rx_active = false;
|
||||||
|
}
|
||||||
|
|
||||||
// If endpoint was stalled and there is now space make it valid
|
// If endpoint was stalled and there is now space make it valid
|
||||||
#ifdef PIOS_USB_BOARD_BL_HID_HAS_NO_LENGTH_BYTE
|
#ifdef PIOS_USB_BOARD_BL_HID_HAS_NO_LENGTH_BYTE
|
||||||
uint16_t max_payload_length = PIOS_USB_BOARD_HID_DATA_LENGTH - 1;
|
uint16_t max_payload_length = PIOS_USB_BOARD_HID_DATA_LENGTH - 1;
|
||||||
@ -260,6 +266,7 @@ static void PIOS_USB_HID_RxStart(uint32_t usbhid_id, uint16_t rx_bytes_avail)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!usb_hid_dev->rx_active && (rx_bytes_avail >= max_payload_length)) {
|
if (!usb_hid_dev->rx_active && (rx_bytes_avail >= max_payload_length)) {
|
||||||
|
last_rx_time_raw = PIOS_DELAY_GetRaw();
|
||||||
PIOS_USBHOOK_EndpointRx(usb_hid_dev->cfg->data_rx_ep,
|
PIOS_USBHOOK_EndpointRx(usb_hid_dev->cfg->data_rx_ep,
|
||||||
usb_hid_dev->rx_packet_buffer,
|
usb_hid_dev->rx_packet_buffer,
|
||||||
sizeof(usb_hid_dev->rx_packet_buffer));
|
sizeof(usb_hid_dev->rx_packet_buffer));
|
||||||
@ -303,6 +310,7 @@ static void PIOS_USB_HID_RegisterRxCallback(uint32_t usbhid_id, pios_com_callbac
|
|||||||
* field to determine if it's ok to dereference _cb and _context
|
* field to determine if it's ok to dereference _cb and _context
|
||||||
*/
|
*/
|
||||||
usb_hid_dev->rx_in_context = context;
|
usb_hid_dev->rx_in_context = context;
|
||||||
|
WRITE_MEMORY_BARRIER();
|
||||||
usb_hid_dev->rx_in_cb = rx_in_cb;
|
usb_hid_dev->rx_in_cb = rx_in_cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,6 +327,7 @@ static void PIOS_USB_HID_RegisterTxCallback(uint32_t usbhid_id, pios_com_callbac
|
|||||||
* field to determine if it's ok to dereference _cb and _context
|
* field to determine if it's ok to dereference _cb and _context
|
||||||
*/
|
*/
|
||||||
usb_hid_dev->tx_out_context = context;
|
usb_hid_dev->tx_out_context = context;
|
||||||
|
WRITE_MEMORY_BARRIER();
|
||||||
usb_hid_dev->tx_out_cb = tx_out_cb;
|
usb_hid_dev->tx_out_cb = tx_out_cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -340,6 +349,8 @@ static void PIOS_USB_HID_IF_Init(uint32_t usb_hid_id)
|
|||||||
PIOS_USB_HID_EP_OUT_Callback,
|
PIOS_USB_HID_EP_OUT_Callback,
|
||||||
(uint32_t)usb_hid_dev);
|
(uint32_t)usb_hid_dev);
|
||||||
usb_hid_dev->usb_if_enabled = true;
|
usb_hid_dev->usb_if_enabled = true;
|
||||||
|
usb_hid_dev->tx_active = false;
|
||||||
|
usb_hid_dev->rx_active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PIOS_USB_HID_IF_DeInit(uint32_t usb_hid_id)
|
static void PIOS_USB_HID_IF_DeInit(uint32_t usb_hid_id)
|
||||||
@ -352,6 +363,8 @@ static void PIOS_USB_HID_IF_DeInit(uint32_t usb_hid_id)
|
|||||||
|
|
||||||
/* DeRegister endpoint specific callbacks with the USBHOOK layer */
|
/* DeRegister endpoint specific callbacks with the USBHOOK layer */
|
||||||
usb_hid_dev->usb_if_enabled = false;
|
usb_hid_dev->usb_if_enabled = false;
|
||||||
|
usb_hid_dev->tx_active = false;
|
||||||
|
usb_hid_dev->rx_active = false;
|
||||||
PIOS_USBHOOK_DeRegisterEpInCallback(usb_hid_dev->cfg->data_tx_ep);
|
PIOS_USBHOOK_DeRegisterEpInCallback(usb_hid_dev->cfg->data_tx_ep);
|
||||||
PIOS_USBHOOK_DeRegisterEpOutCallback(usb_hid_dev->cfg->data_rx_ep);
|
PIOS_USBHOOK_DeRegisterEpOutCallback(usb_hid_dev->cfg->data_rx_ep);
|
||||||
}
|
}
|
||||||
@ -497,7 +510,7 @@ static bool PIOS_USB_HID_EP_OUT_Callback(uint32_t usb_hid_id, __attribute__((unu
|
|||||||
usb_hid_dev->rx_active = false;
|
usb_hid_dev->rx_active = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
READ_MEMORY_BARRIER();
|
||||||
/* The first byte is report ID (not checked), the second byte is the valid data length */
|
/* The first byte is report ID (not checked), the second byte is the valid data length */
|
||||||
uint16_t headroom;
|
uint16_t headroom;
|
||||||
bool need_yield = false;
|
bool need_yield = false;
|
||||||
|
@ -46,6 +46,8 @@
|
|||||||
#include "usbd_req.h" /* USBD_CtlError */
|
#include "usbd_req.h" /* USBD_CtlError */
|
||||||
#include "usb_dcd_int.h" /* USBD_OTG_ISR_Handler */
|
#include "usb_dcd_int.h" /* USBD_OTG_ISR_Handler */
|
||||||
|
|
||||||
|
static void reconnect(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* External API
|
* External API
|
||||||
*/
|
*/
|
||||||
@ -82,6 +84,8 @@ static USBD_Usr_cb_TypeDef user_callbacks;
|
|||||||
|
|
||||||
void PIOS_USBHOOK_Activate(void)
|
void PIOS_USBHOOK_Activate(void)
|
||||||
{
|
{
|
||||||
|
PIOS_USB_RegisterDisconnectionCallback(&reconnect);
|
||||||
|
|
||||||
USBD_Init(&pios_usb_otg_core_handle,
|
USBD_Init(&pios_usb_otg_core_handle,
|
||||||
USB_OTG_FS_CORE_ID,
|
USB_OTG_FS_CORE_ID,
|
||||||
&device_callbacks,
|
&device_callbacks,
|
||||||
@ -271,12 +275,7 @@ static USBD_DEVICE device_callbacks = {
|
|||||||
static void PIOS_USBHOOK_USR_Init(void)
|
static void PIOS_USBHOOK_USR_Init(void)
|
||||||
{
|
{
|
||||||
PIOS_USB_ChangeConnectionState(false);
|
PIOS_USB_ChangeConnectionState(false);
|
||||||
|
reconnect();
|
||||||
#if 1
|
|
||||||
/* Force a physical disconnect/reconnect */
|
|
||||||
DCD_DevDisconnect(&pios_usb_otg_core_handle);
|
|
||||||
DCD_DevConnect(&pios_usb_otg_core_handle);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PIOS_USBHOOK_USR_DeviceReset(__attribute__((unused)) uint8_t speed)
|
static void PIOS_USBHOOK_USR_DeviceReset(__attribute__((unused)) uint8_t speed)
|
||||||
@ -483,4 +482,11 @@ static USBD_Class_cb_TypeDef class_callbacks = {
|
|||||||
#endif /* USB_SUPPORT_USER_STRING_DESC */
|
#endif /* USB_SUPPORT_USER_STRING_DESC */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void reconnect(void)
|
||||||
|
{
|
||||||
|
/* Force a physical disconnect/reconnect */
|
||||||
|
DCD_DevDisconnect(&pios_usb_otg_core_handle);
|
||||||
|
DCD_DevConnect(&pios_usb_otg_core_handle);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* PIOS_INCLUDE_USB */
|
#endif /* PIOS_INCLUDE_USB */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user