mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-13 03:20:00 +03:00
* PICO: Initial multicore (using it for IRQs) * Updated so any function can be pushed. * Corrected includes * Move to queues * Removed header * Adding check on command - correcting core reset return * Updates based on feedback * Whitespace * making static * Removing comment
212 lines
4.7 KiB
C
212 lines
4.7 KiB
C
/*
|
|
* This file is part of Betaflight.
|
|
*
|
|
* Betaflight is free software. You can redistribute this software
|
|
* and/or modify this software under the terms of the GNU General
|
|
* Public License as published by the Free Software Foundation,
|
|
* either version 3 of the License, or (at your option) any later
|
|
* version.
|
|
*
|
|
* Betaflight 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 this software.
|
|
*
|
|
* If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
|
|
#include "platform.h"
|
|
|
|
#ifdef USE_VCP
|
|
|
|
#include "build/build_config.h"
|
|
|
|
#include "common/utils.h"
|
|
|
|
#include "drivers/io.h"
|
|
|
|
#include "pg/usb.h"
|
|
|
|
#include "usb/usb_cdc.h"
|
|
|
|
#include "drivers/time.h"
|
|
#include "drivers/serial.h"
|
|
#include "drivers/serial_usb_vcp.h"
|
|
#include "platform/multicore.h"
|
|
|
|
static vcpPort_t vcpPort = { 0 };
|
|
|
|
static void usbVcpSetBaudRate(serialPort_t *instance, uint32_t baudRate)
|
|
{
|
|
UNUSED(instance);
|
|
UNUSED(baudRate);
|
|
}
|
|
|
|
static void usbVcpSetMode(serialPort_t *instance, portMode_e mode)
|
|
{
|
|
UNUSED(instance);
|
|
UNUSED(mode);
|
|
}
|
|
|
|
static void usbVcpSetCtrlLineStateCb(serialPort_t *instance, void (*cb)(void *context, uint16_t ctrlLineState), void *context)
|
|
{
|
|
UNUSED(instance);
|
|
UNUSED(cb);
|
|
UNUSED(context);
|
|
}
|
|
|
|
static void usbVcpSetBaudRateCb(serialPort_t *instance, void (*cb)(serialPort_t *context, uint32_t baud), serialPort_t *context)
|
|
{
|
|
UNUSED(instance);
|
|
UNUSED(cb);
|
|
UNUSED(context);
|
|
}
|
|
|
|
static bool isUsbVcpTransmitBufferEmpty(const serialPort_t *instance)
|
|
{
|
|
UNUSED(instance);
|
|
return true;
|
|
}
|
|
|
|
static uint32_t usbVcpRxBytesAvailable(const serialPort_t *instance)
|
|
{
|
|
UNUSED(instance);
|
|
return cdc_usb_bytes_available();
|
|
}
|
|
|
|
static uint8_t usbVcpRead(serialPort_t *instance)
|
|
{
|
|
UNUSED(instance);
|
|
|
|
uint8_t buf[1];
|
|
|
|
while (true) {
|
|
if (cdc_usb_read(buf, 1)) {
|
|
return buf[0];
|
|
}
|
|
}
|
|
}
|
|
|
|
static void usbVcpWriteBuf(serialPort_t *instance, const void *data, int count)
|
|
{
|
|
UNUSED(instance);
|
|
|
|
if (!(cdc_usb_connected() && cdc_usb_configured())) {
|
|
return;
|
|
}
|
|
|
|
const uint8_t *p = data;
|
|
while (count > 0) {
|
|
int txed = cdc_usb_write(p, count);
|
|
|
|
if (txed <= 0) {
|
|
break;
|
|
}
|
|
count -= txed;
|
|
p += txed;
|
|
}
|
|
}
|
|
|
|
static bool usbVcpFlush(vcpPort_t *port)
|
|
{
|
|
uint32_t count = port->txAt;
|
|
port->txAt = 0;
|
|
|
|
if (count == 0) {
|
|
return true;
|
|
}
|
|
|
|
if (!cdc_usb_connected() || !cdc_usb_configured()) {
|
|
return false;
|
|
}
|
|
|
|
const uint8_t *p = port->txBuf;
|
|
while (count > 0) {
|
|
int txed = cdc_usb_write(p, count);
|
|
|
|
if (txed <= 0) {
|
|
break;
|
|
}
|
|
count -= txed;
|
|
p += txed;
|
|
}
|
|
return count == 0;
|
|
}
|
|
|
|
static void usbVcpWrite(serialPort_t *instance, uint8_t c)
|
|
{
|
|
vcpPort_t *port = container_of(instance, vcpPort_t, port);
|
|
|
|
port->txBuf[port->txAt++] = c;
|
|
if (!port->buffering || port->txAt >= ARRAYLEN(port->txBuf)) {
|
|
usbVcpFlush(port);
|
|
}
|
|
}
|
|
|
|
static void usbVcpBeginWrite(serialPort_t *instance)
|
|
{
|
|
vcpPort_t *port = container_of(instance, vcpPort_t, port);
|
|
port->buffering = true;
|
|
}
|
|
|
|
static uint32_t usbTxBytesFree(const serialPort_t *instance)
|
|
{
|
|
UNUSED(instance);
|
|
return cdc_usb_tx_bytes_free();
|
|
}
|
|
|
|
static void usbVcpEndWrite(serialPort_t *instance)
|
|
{
|
|
vcpPort_t *port = container_of(instance, vcpPort_t, port);
|
|
port->buffering = false;
|
|
usbVcpFlush(port);
|
|
}
|
|
|
|
static const struct serialPortVTable usbVTable[] = {
|
|
{
|
|
.serialWrite = usbVcpWrite,
|
|
.serialTotalRxWaiting = usbVcpRxBytesAvailable,
|
|
.serialTotalTxFree = usbTxBytesFree,
|
|
.serialRead = usbVcpRead,
|
|
.serialSetBaudRate = usbVcpSetBaudRate,
|
|
.isSerialTransmitBufferEmpty = isUsbVcpTransmitBufferEmpty,
|
|
.setMode = usbVcpSetMode,
|
|
.setCtrlLineStateCb = usbVcpSetCtrlLineStateCb,
|
|
.setBaudRateCb = usbVcpSetBaudRateCb,
|
|
.writeBuf = usbVcpWriteBuf,
|
|
.beginWrite = usbVcpBeginWrite,
|
|
.endWrite = usbVcpEndWrite
|
|
}
|
|
};
|
|
|
|
serialPort_t *usbVcpOpen(void)
|
|
{
|
|
// initialise the USB CDC interface
|
|
// potentially this could be done in a multicore task
|
|
//multicoreExecuteBlocking(&cdc_usb_init);
|
|
cdc_usb_init();
|
|
|
|
vcpPort_t *s = &vcpPort;
|
|
s->port.vTable = usbVTable;
|
|
return &s->port;
|
|
}
|
|
|
|
uint32_t usbVcpGetBaudRate(serialPort_t *instance)
|
|
{
|
|
UNUSED(instance);
|
|
return cdc_usb_baud_rate();
|
|
}
|
|
|
|
uint8_t usbVcpIsConnected(void)
|
|
{
|
|
return cdc_usb_connected();
|
|
}
|
|
|
|
#endif // USE_VCP
|