mirror of
https://github.com/LNH-team/dspico-usb-examples.git
synced 2026-06-02 01:06:52 +02:00
Initial commit
This commit is contained in:
29
platform/DSPicoUsb.h
Normal file
29
platform/DSPicoUsb.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
#include <libtwl/card/card.h>
|
||||
|
||||
#define DSPICO_CMD_USB_COMMAND(command, arguments) (0xE800000000000000ull | ((u64)(command) << 48) | (arguments))
|
||||
#define DSPICO_CMD_USB_COMMAND_INIT DSPICO_CMD_USB_COMMAND(1, 0)
|
||||
#define DSPICO_CMD_USB_COMMAND_BEGIN_SET_ADDRESS DSPICO_CMD_USB_COMMAND(2, 0)
|
||||
#define DSPICO_CMD_USB_COMMAND_REMOTE_WAKEUP DSPICO_CMD_USB_COMMAND(3, 0)
|
||||
#define DSPICO_CMD_USB_COMMAND_CONNECT DSPICO_CMD_USB_COMMAND(4, 0)
|
||||
#define DSPICO_CMD_USB_COMMAND_DISCONNECT DSPICO_CMD_USB_COMMAND(5, 0)
|
||||
#define DSPICO_CMD_USB_COMMAND_SOF_ENABLE DSPICO_CMD_USB_COMMAND(6, 0)
|
||||
#define DSPICO_CMD_USB_COMMAND_SOF_DISABLE DSPICO_CMD_USB_COMMAND(7, 0)
|
||||
#define DSPICO_CMD_USB_COMMAND_EP_CLOSE_ALL DSPICO_CMD_USB_COMMAND(8, 0)
|
||||
#define DSPICO_CMD_USB_COMMAND_EP_STALL(ep) DSPICO_CMD_USB_COMMAND(9, (u64)(ep) << 40)
|
||||
#define DSPICO_CMD_USB_COMMAND_EP_CLEAR_STALL(ep) DSPICO_CMD_USB_COMMAND(10, (u64)(ep) << 40)
|
||||
#define DSPICO_CMD_USB_COMMAND_EP_CLOSE(ep) DSPICO_CMD_USB_COMMAND(11, (u64)(ep) << 40)
|
||||
#define DSPICO_CMD_USB_COMMAND_FINISH_SET_ADDRESS(addr) DSPICO_CMD_USB_COMMAND(12, (u64)(addr) << 40)
|
||||
#define DSPICO_CMD_USB_COMMAND_EP_OPEN(ep, maxPktSize, xfer) DSPICO_CMD_USB_COMMAND(13, ((u64)(ep) << 40) | ((u64)((xfer) & 3) << 32) | ((u64)((maxPktSize) & 0x7FF)))
|
||||
#define DSPICO_CMD_USB_COMMAND_CLEAR_EVENT_QUEUE DSPICO_CMD_USB_COMMAND(14, 0)
|
||||
#define DSPICO_CMD_USB_COMMAND_DEINIT DSPICO_CMD_USB_COMMAND(15, 0)
|
||||
#define DSPICO_CMD_USB_COMMAND_BEGIN_TRANSFER(ep, offset, length) DSPICO_CMD_USB_COMMAND(16, ((u64)(ep) << 40) | ((u64)(offset) << 32) | (length))
|
||||
#define DSPICO_CMD_USB_COMMAND_INTERRUPT_ENABLE DSPICO_CMD_USB_COMMAND(17, 0)
|
||||
#define DSPICO_CMD_USB_COMMAND_INTERRUPT_DISABLE DSPICO_CMD_USB_COMMAND(18, 0)
|
||||
|
||||
#define DSPICO_CMD_USB_WRITE_DATA(offset, endpoint, isLast, totalLength) (0xE900000000000000ull | ((u64)(offset) << 48) | ((u64)(endpoint) << 40) | ((u64)(isLast) << 32) | (totalLength))
|
||||
#define DSPICO_CMD_USB_READ_DATA(offset, endpoint) (0xEA00000000000000ull | ((u64)(offset) << 32) | ((u64)(endpoint) << 40))
|
||||
#define DSPICO_CMD_USB_GET_EVENT 0xEB00000000000000ull
|
||||
|
||||
#define DSPICO_USB_DEFAULT_COMMAND_SETTINGS (MCCNT1_DIR_READ | MCCNT1_RESET_OFF | MCCNT1_CLK_6_7_MHZ | MCCNT1_LEN_0 | MCCNT1_CMD_SCRAMBLE |\
|
||||
MCCNT1_LATENCY2(0) | MCCNT1_CLOCK_SCRAMBLER | MCCNT1_READ_DATA_DESCRAMBLE | MCCNT1_LATENCY1(0))
|
||||
100
platform/DSPicoUsbInEndpoint.cpp
Normal file
100
platform/DSPicoUsbInEndpoint.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
#include "common.h"
|
||||
#include "libtwl/dma/dmaNitro.h"
|
||||
#include "tusb.h"
|
||||
#include "device/dcd.h"
|
||||
#include "DSPicoUsb.h"
|
||||
#include "DSPicoUsbInEndpoint.h"
|
||||
|
||||
void DSPicoUsbInEndpoint::BeginTransfer(const u8* buffer, u32 length)
|
||||
{
|
||||
rtos_lockMutex(&_mutex);
|
||||
{
|
||||
_buffer = buffer;
|
||||
_bufferLength = length;
|
||||
_remaining = length;
|
||||
_bufferOffset = 0;
|
||||
_currentDSPicoBuffer = 0;
|
||||
_transferActive = true;
|
||||
SendUsbBlock(true);
|
||||
SendUsbBlock(false);
|
||||
}
|
||||
rtos_unlockMutex(&_mutex);
|
||||
}
|
||||
|
||||
void DSPicoUsbInEndpoint::ProcessTransferCompleteEvent(u32 transferredBytes)
|
||||
{
|
||||
rtos_lockMutex(&_mutex);
|
||||
{
|
||||
if (_transferActive)
|
||||
{
|
||||
_remaining -= transferredBytes;
|
||||
if (_remaining == 0)
|
||||
{
|
||||
dcd_event_xfer_complete(0, _endpointAddress, _bufferLength, XFER_RESULT_SUCCESS, true);
|
||||
_transferActive = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 length = _remaining;
|
||||
if (length > 512)
|
||||
{
|
||||
length = 512;
|
||||
}
|
||||
rtos_lockMutex(&gCardMutex);
|
||||
{
|
||||
card_romSetCmd(DSPICO_CMD_USB_COMMAND_BEGIN_TRANSFER(_endpointAddress, 1 - _currentDSPicoBuffer, length));
|
||||
card_romStartXfer(DSPICO_USB_DEFAULT_COMMAND_SETTINGS, false);
|
||||
card_romWaitBusy();
|
||||
}
|
||||
rtos_unlockMutex(&gCardMutex);
|
||||
|
||||
SendUsbBlock(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This seems to happen only once on the control endpoint. Idk why.
|
||||
dcd_event_xfer_complete(0, _endpointAddress, transferredBytes, XFER_RESULT_SUCCESS, true);
|
||||
}
|
||||
}
|
||||
rtos_unlockMutex(&_mutex);
|
||||
}
|
||||
|
||||
void DSPicoUsbInEndpoint::SendUsbBlock(bool startTransfer)
|
||||
{
|
||||
u32 length = _bufferLength - _bufferOffset;
|
||||
if (length > 0)
|
||||
{
|
||||
if (length > 512)
|
||||
{
|
||||
length = 512;
|
||||
}
|
||||
|
||||
rtos_lockMutex(&gCardMutex);
|
||||
{
|
||||
REG_DMA3SAD = (u32)(_buffer + _bufferOffset);
|
||||
REG_DMA3DAD = (u32)®_MCD1;
|
||||
REG_DMA3CNT = 0xA6400001;
|
||||
card_romSetCmd(DSPICO_CMD_USB_WRITE_DATA(_currentDSPicoBuffer, _endpointAddress, startTransfer, length));
|
||||
card_romStartXfer(MCCNT1_DIR_WRITE | MCCNT1_RESET_OFF | MCCNT1_CLK_6_7_MHZ | MCCNT1_LEN_512 | MCCNT1_CMD_SCRAMBLE |
|
||||
MCCNT1_LATENCY2(8) | MCCNT1_CLOCK_SCRAMBLER | MCCNT1_READ_DATA_DESCRAMBLE | MCCNT1_LATENCY1(0), false);
|
||||
card_romWaitBusy();
|
||||
REG_DMA3CNT = 0;
|
||||
}
|
||||
rtos_unlockMutex(&gCardMutex);
|
||||
|
||||
_bufferOffset += length;
|
||||
_currentDSPicoBuffer = 1 - _currentDSPicoBuffer;
|
||||
}
|
||||
else if (startTransfer)
|
||||
{
|
||||
// zero length transfer
|
||||
rtos_lockMutex(&gCardMutex);
|
||||
{
|
||||
card_romSetCmd(DSPICO_CMD_USB_WRITE_DATA(_currentDSPicoBuffer, _endpointAddress, true, 0));
|
||||
card_romStartXfer(DSPICO_USB_DEFAULT_COMMAND_SETTINGS, false);
|
||||
card_romWaitBusy();
|
||||
}
|
||||
rtos_unlockMutex(&gCardMutex);
|
||||
}
|
||||
}
|
||||
28
platform/DSPicoUsbInEndpoint.h
Normal file
28
platform/DSPicoUsbInEndpoint.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
#include "libtwl/rtos/rtosMutex.h"
|
||||
|
||||
class DSPicoUsbInEndpoint
|
||||
{
|
||||
public:
|
||||
explicit DSPicoUsbInEndpoint(u8 endpointAddress)
|
||||
: _endpointAddress(endpointAddress), _currentDSPicoBuffer(0), _buffer(nullptr)
|
||||
, _bufferLength(0), _remaining(0), _bufferOffset(0), _transferActive(false)
|
||||
{
|
||||
rtos_createMutex(&_mutex);
|
||||
}
|
||||
|
||||
void BeginTransfer(const u8* buffer, u32 length);
|
||||
void ProcessTransferCompleteEvent(u32 transferredBytes);
|
||||
|
||||
private:
|
||||
u8 _endpointAddress;
|
||||
u8 _currentDSPicoBuffer;
|
||||
const u8* _buffer;
|
||||
u32 _bufferLength;
|
||||
u32 _remaining;
|
||||
u32 _bufferOffset;
|
||||
rtos_mutex_t _mutex;
|
||||
bool _transferActive;
|
||||
|
||||
void SendUsbBlock(bool startTransfer);
|
||||
};
|
||||
141
platform/DSPicoUsbOutEndpoint.cpp
Normal file
141
platform/DSPicoUsbOutEndpoint.cpp
Normal file
@@ -0,0 +1,141 @@
|
||||
#include "common.h"
|
||||
#include "libtwl/dma/dmaNitro.h"
|
||||
#include "tusb.h"
|
||||
#include "device/dcd.h"
|
||||
#include "DSPicoUsb.h"
|
||||
#include "DSPicoUsbOutEndpoint.h"
|
||||
|
||||
void DSPicoUsbOutEndpoint::BeginTransfer(u8* buffer, u32 length)
|
||||
{
|
||||
rtos_lockMutex(&_mutex);
|
||||
{
|
||||
_buffer = buffer;
|
||||
_bufferLength = length;
|
||||
_bufferOffset = 0;
|
||||
_totalReceived = 0;
|
||||
_currentDSPicoBuffer = 0;
|
||||
_transferActive = true;
|
||||
u32 firstReceiveLength = _bufferLength;
|
||||
if (firstReceiveLength > 512)
|
||||
{
|
||||
firstReceiveLength = 512;
|
||||
}
|
||||
rtos_lockMutex(&gCardMutex);
|
||||
{
|
||||
card_romSetCmd(DSPICO_CMD_USB_COMMAND_BEGIN_TRANSFER(_endpointAddress, _currentDSPicoBuffer, firstReceiveLength));
|
||||
card_romStartXfer(DSPICO_USB_DEFAULT_COMMAND_SETTINGS, false);
|
||||
card_romWaitBusy();
|
||||
}
|
||||
rtos_unlockMutex(&gCardMutex);
|
||||
}
|
||||
rtos_unlockMutex(&_mutex);
|
||||
}
|
||||
|
||||
void DSPicoUsbOutEndpoint::ProcessTransferCompleteEvent(u32 transferredBytes)
|
||||
{
|
||||
rtos_lockMutex(&_mutex);
|
||||
{
|
||||
if (_transferActive)
|
||||
{
|
||||
_totalReceived += transferredBytes;
|
||||
int length = _bufferLength - _bufferOffset - 512;
|
||||
if (length > 512)
|
||||
{
|
||||
length = 512;
|
||||
}
|
||||
if (transferredBytes == 512)
|
||||
{
|
||||
if (length > 0)
|
||||
{
|
||||
rtos_lockMutex(&gCardMutex);
|
||||
{
|
||||
card_romSetCmd(DSPICO_CMD_USB_COMMAND_BEGIN_TRANSFER(_endpointAddress, 1 - _currentDSPicoBuffer, length));
|
||||
card_romStartXfer(DSPICO_USB_DEFAULT_COMMAND_SETTINGS, false);
|
||||
card_romWaitBusy();
|
||||
}
|
||||
rtos_unlockMutex(&gCardMutex);
|
||||
}
|
||||
}
|
||||
|
||||
ReceiveUsbBlock();
|
||||
|
||||
if (transferredBytes < 512 || length == 0)
|
||||
{
|
||||
dcd_event_xfer_complete(0, _endpointAddress, _bufferOffset, XFER_RESULT_SUCCESS, true);
|
||||
_transferActive = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// idk
|
||||
dcd_event_xfer_complete(0, _endpointAddress, transferredBytes, XFER_RESULT_SUCCESS, true);
|
||||
}
|
||||
}
|
||||
rtos_unlockMutex(&_mutex);
|
||||
}
|
||||
|
||||
void DSPicoUsbOutEndpoint::ReceiveUsbBlock()
|
||||
{
|
||||
u32 length = _totalReceived - _bufferOffset;
|
||||
if (length > 0)
|
||||
{
|
||||
if (length > 512)
|
||||
{
|
||||
length = 512;
|
||||
}
|
||||
rtos_lockMutex(&gCardMutex);
|
||||
{
|
||||
if (length == 512)
|
||||
{
|
||||
REG_DMA3SAD = (u32)®_MCD1;
|
||||
REG_DMA3DAD = (u32)(_buffer + _bufferOffset);
|
||||
REG_DMA3CNT = 0xA7000001;
|
||||
}
|
||||
card_romSetCmd(DSPICO_CMD_USB_READ_DATA(_currentDSPicoBuffer, _endpointAddress));
|
||||
card_romStartXfer(MCCNT1_DIR_READ | MCCNT1_RESET_OFF | MCCNT1_CLK_6_7_MHZ | MCCNT1_LEN_512 | MCCNT1_CMD_SCRAMBLE |
|
||||
MCCNT1_LATENCY2(4) | MCCNT1_CLOCK_SCRAMBLER | MCCNT1_LATENCY1(0), false);
|
||||
if (length == 512)
|
||||
{
|
||||
card_romWaitBusy();
|
||||
REG_DMA3CNT = 0;
|
||||
}
|
||||
else if (length & 3)
|
||||
{
|
||||
u8* target = _buffer + _bufferOffset + length;
|
||||
u8* dst = _buffer + _bufferOffset;
|
||||
do
|
||||
{
|
||||
// Read data if available
|
||||
if (card_romIsDataReady())
|
||||
{
|
||||
u32 data = card_romGetData();
|
||||
if (dst + 3 < target)
|
||||
{
|
||||
*(u32*)dst = data;
|
||||
dst += 4;
|
||||
}
|
||||
else if (dst < target)
|
||||
{
|
||||
*dst++ = data & 0xFF;
|
||||
if (dst < target)
|
||||
{
|
||||
*dst++ = (data >> 8) & 0xFF;
|
||||
if (dst < target)
|
||||
{
|
||||
*dst++ = (data >> 16) & 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (card_romIsBusy());
|
||||
}
|
||||
else
|
||||
{
|
||||
card_romCpuRead((u32*)(_buffer + _bufferOffset), length >> 2);
|
||||
}
|
||||
}
|
||||
rtos_unlockMutex(&gCardMutex);
|
||||
_bufferOffset += length;
|
||||
_currentDSPicoBuffer = 1 - _currentDSPicoBuffer;
|
||||
}
|
||||
}
|
||||
26
platform/DSPicoUsbOutEndpoint.h
Normal file
26
platform/DSPicoUsbOutEndpoint.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
class DSPicoUsbOutEndpoint
|
||||
{
|
||||
public:
|
||||
explicit DSPicoUsbOutEndpoint(u8 endpointAddress)
|
||||
: _endpointAddress(endpointAddress), _currentDSPicoBuffer(0), _buffer(nullptr)
|
||||
, _bufferLength(0), _bufferOffset(0), _totalReceived(0), _transferActive(false)
|
||||
{
|
||||
rtos_createMutex(&_mutex);
|
||||
}
|
||||
|
||||
void BeginTransfer(u8* buffer, u32 length);
|
||||
void ProcessTransferCompleteEvent(u32 transferredBytes);
|
||||
private:
|
||||
u8 _endpointAddress;
|
||||
u8 _currentDSPicoBuffer;
|
||||
u8* _buffer;
|
||||
u32 _bufferLength;
|
||||
u32 _bufferOffset;
|
||||
u32 _totalReceived;
|
||||
bool _transferActive;
|
||||
rtos_mutex_t _mutex;
|
||||
|
||||
void ReceiveUsbBlock();
|
||||
};
|
||||
25
platform/UsbStringDescriptor.h
Normal file
25
platform/UsbStringDescriptor.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#include "tusb.h"
|
||||
|
||||
template<std::size_t N>
|
||||
struct UsbStringDescriptor
|
||||
{
|
||||
u8 length = 2 * N;
|
||||
u8 descriptorType = TUSB_DESC_STRING;
|
||||
char16_t string[N - 1];
|
||||
|
||||
explicit constexpr UsbStringDescriptor(const char16_t(&str)[N])
|
||||
{
|
||||
for (size_t i = 0; i < N - 1; i++)
|
||||
{
|
||||
string[i] = str[i];
|
||||
}
|
||||
}
|
||||
|
||||
explicit constexpr UsbStringDescriptor(u16 languageId)
|
||||
{
|
||||
string[0] = languageId;
|
||||
}
|
||||
};
|
||||
|
||||
#define USB_STRING_DESCRIPTOR(str) ({ static const UsbStringDescriptor descriptor(str); (const u16*)&descriptor; })
|
||||
315
platform/dcd_dspico.cpp
Normal file
315
platform/dcd_dspico.cpp
Normal file
@@ -0,0 +1,315 @@
|
||||
#include "common.h"
|
||||
#include <libtwl/card/card.h>
|
||||
#include <libtwl/rtos/rtosIrq.h>
|
||||
#include <libtwl/rtos/rtosEvent.h>
|
||||
#include <libtwl/rtos/rtosThread.h>
|
||||
#include "tusb_option.h"
|
||||
#include "tusb.h"
|
||||
|
||||
#if CFG_TUD_ENABLED && CFG_TUSB_MCU == OPT_MCU_DSPICO
|
||||
|
||||
#include "device/dcd.h"
|
||||
#include "DSPicoUsb.h"
|
||||
#include "DSPicoUsbInEndpoint.h"
|
||||
#include "DSPicoUsbOutEndpoint.h"
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
static rtos_event_t sCardIrqEvent;
|
||||
static rtos_thread_t sUsbThread;
|
||||
static u32 sUsbThreadStack[512];
|
||||
|
||||
static DSPicoUsbInEndpoint sInEndpoints[16] =
|
||||
{
|
||||
DSPicoUsbInEndpoint(TUSB_DIR_IN_MASK | 0),
|
||||
DSPicoUsbInEndpoint(TUSB_DIR_IN_MASK | 1),
|
||||
DSPicoUsbInEndpoint(TUSB_DIR_IN_MASK | 2),
|
||||
DSPicoUsbInEndpoint(TUSB_DIR_IN_MASK | 3),
|
||||
DSPicoUsbInEndpoint(TUSB_DIR_IN_MASK | 4),
|
||||
DSPicoUsbInEndpoint(TUSB_DIR_IN_MASK | 5),
|
||||
DSPicoUsbInEndpoint(TUSB_DIR_IN_MASK | 6),
|
||||
DSPicoUsbInEndpoint(TUSB_DIR_IN_MASK | 7),
|
||||
DSPicoUsbInEndpoint(TUSB_DIR_IN_MASK | 8),
|
||||
DSPicoUsbInEndpoint(TUSB_DIR_IN_MASK | 9),
|
||||
DSPicoUsbInEndpoint(TUSB_DIR_IN_MASK | 10),
|
||||
DSPicoUsbInEndpoint(TUSB_DIR_IN_MASK | 11),
|
||||
DSPicoUsbInEndpoint(TUSB_DIR_IN_MASK | 12),
|
||||
DSPicoUsbInEndpoint(TUSB_DIR_IN_MASK | 13),
|
||||
DSPicoUsbInEndpoint(TUSB_DIR_IN_MASK | 14),
|
||||
DSPicoUsbInEndpoint(TUSB_DIR_IN_MASK | 15)
|
||||
};
|
||||
|
||||
static DSPicoUsbOutEndpoint sOutEndpoints[16] =
|
||||
{
|
||||
DSPicoUsbOutEndpoint(0),
|
||||
DSPicoUsbOutEndpoint(1),
|
||||
DSPicoUsbOutEndpoint(2),
|
||||
DSPicoUsbOutEndpoint(3),
|
||||
DSPicoUsbOutEndpoint(4),
|
||||
DSPicoUsbOutEndpoint(5),
|
||||
DSPicoUsbOutEndpoint(6),
|
||||
DSPicoUsbOutEndpoint(7),
|
||||
DSPicoUsbOutEndpoint(8),
|
||||
DSPicoUsbOutEndpoint(9),
|
||||
DSPicoUsbOutEndpoint(10),
|
||||
DSPicoUsbOutEndpoint(11),
|
||||
DSPicoUsbOutEndpoint(12),
|
||||
DSPicoUsbOutEndpoint(13),
|
||||
DSPicoUsbOutEndpoint(14),
|
||||
DSPicoUsbOutEndpoint(15)
|
||||
};
|
||||
|
||||
static void sendCommand(u64 command)
|
||||
{
|
||||
rtos_lockMutex(&gCardMutex);
|
||||
card_romSetCmd(command);
|
||||
card_romStartXfer(DSPICO_USB_DEFAULT_COMMAND_SETTINGS, false);
|
||||
card_romWaitBusy();
|
||||
rtos_unlockMutex(&gCardMutex);
|
||||
}
|
||||
|
||||
static void cardIrq(u32 irqMask)
|
||||
{
|
||||
rtos_signalEvent(&sCardIrqEvent);
|
||||
}
|
||||
|
||||
static void usbThreadMain(void* arg)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
rtos_waitEvent(&sCardIrqEvent, false, true);
|
||||
|
||||
u32 event;
|
||||
bool lastEvent;
|
||||
do
|
||||
{
|
||||
rtos_lockMutex(&gCardMutex);
|
||||
card_romSetCmd(DSPICO_CMD_USB_GET_EVENT);
|
||||
card_romStartXfer(MCCNT1_DIR_READ | MCCNT1_RESET_OFF | MCCNT1_CLK_6_7_MHZ | MCCNT1_LEN_4 | MCCNT1_CMD_SCRAMBLE |
|
||||
MCCNT1_LATENCY2(4) | MCCNT1_CLOCK_SCRAMBLER | MCCNT1_READ_DATA_DESCRAMBLE | MCCNT1_LATENCY1(0), false);
|
||||
card_romCpuRead(&event, 1);
|
||||
rtos_unlockMutex(&gCardMutex);
|
||||
lastEvent = (event >> 31) != 0;
|
||||
event &= ~(1 << 31);
|
||||
if (event == 0)
|
||||
{
|
||||
// USB_EVENT_NONE
|
||||
break;
|
||||
}
|
||||
else if ((event >> 30) == 1)
|
||||
{
|
||||
// USB_EVENT_SETUP_RECEIVED
|
||||
tusb_control_request_t setup;
|
||||
setup.wLength = (event >> 16) & 0x1FFF;
|
||||
u32 direction = (event >> 29) & 1;
|
||||
setup.wIndex = event & 0xFFFF;
|
||||
|
||||
rtos_lockMutex(&gCardMutex);
|
||||
card_romSetCmd(DSPICO_CMD_USB_GET_EVENT);
|
||||
card_romStartXfer(MCCNT1_DIR_READ | MCCNT1_RESET_OFF | MCCNT1_CLK_6_7_MHZ | MCCNT1_LEN_4 | MCCNT1_CMD_SCRAMBLE |
|
||||
MCCNT1_LATENCY2(4) | MCCNT1_CLOCK_SCRAMBLER | MCCNT1_READ_DATA_DESCRAMBLE | MCCNT1_LATENCY1(0), false);
|
||||
card_romCpuRead(&event, 1);
|
||||
rtos_unlockMutex(&gCardMutex);
|
||||
lastEvent = (event >> 31) != 0;
|
||||
event &= ~(1 << 31);
|
||||
setup.wValue = event & 0xFFFF;
|
||||
setup.bRequest = (event >> 16) & 0xFF;
|
||||
setup.bmRequestType = (event >> 24) & 0x7F;
|
||||
setup.bmRequestType_bit.direction = direction;
|
||||
dcd_event_setup_received(0, (const u8*)&setup, true);
|
||||
}
|
||||
else if ((event >> 28) == 2)
|
||||
{
|
||||
// USB_EVENT_SOF
|
||||
dcd_event_sof(0, event & 0x7FF, true);
|
||||
}
|
||||
else if ((event >> 28) == 3)
|
||||
{
|
||||
// USB_EVENT_XFER_COMPLETE
|
||||
u32 endpoint = event & 0xFF;
|
||||
u32 transferredBytes = (event >> 8) & 0x1FFF;
|
||||
if (tu_edpt_dir(endpoint) == TUSB_DIR_IN)
|
||||
{
|
||||
sInEndpoints[endpoint & ~0x80].ProcessTransferCompleteEvent(transferredBytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
sOutEndpoints[endpoint & ~0x80].ProcessTransferCompleteEvent(transferredBytes);
|
||||
}
|
||||
}
|
||||
else if (event == 1)
|
||||
{
|
||||
// USB_EVENT_BUS_RESET
|
||||
dcd_event_bus_reset(0, TUSB_SPEED_FULL, true);
|
||||
}
|
||||
else if (event == 2)
|
||||
{
|
||||
// USB_EVENT_UNPLUGGED
|
||||
dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true);
|
||||
}
|
||||
else if (event == 3)
|
||||
{
|
||||
// USB_EVENT_SUSPEND
|
||||
dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true);
|
||||
}
|
||||
else if (event == 4)
|
||||
{
|
||||
// USB_EVENT_RESUME
|
||||
dcd_event_bus_signal(0, DCD_EVENT_RESUME, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// invalid
|
||||
}
|
||||
} while (!lastEvent);
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Device API
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
// Initialize controller to device mode
|
||||
bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init)
|
||||
{
|
||||
(void) rhport;
|
||||
(void) rh_init;
|
||||
rtos_createEvent(&sCardIrqEvent);
|
||||
rtos_disableIrqMask(RTOS_IRQ_DS_SLOTA_IREQ);
|
||||
rtos_setIrqFunc(RTOS_IRQ_DS_SLOTA_IREQ, cardIrq);
|
||||
rtos_ackIrqMask(RTOS_IRQ_DS_SLOTA_IREQ);
|
||||
rtos_createThread(&sUsbThread, 2, usbThreadMain, NULL, sUsbThreadStack, sizeof(sUsbThreadStack));
|
||||
rtos_wakeupThread(&sUsbThread);
|
||||
sendCommand(DSPICO_CMD_USB_COMMAND_INIT);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dcd_deinit(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
rtos_disableIrqMask(RTOS_IRQ_DS_SLOTA_IREQ);
|
||||
rtos_setIrqFunc(RTOS_IRQ_DS_SLOTA_IREQ, NULL);
|
||||
rtos_ackIrqMask(RTOS_IRQ_DS_SLOTA_IREQ);
|
||||
sendCommand(DSPICO_CMD_USB_COMMAND_DEINIT);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Enable device interrupt
|
||||
void dcd_int_enable(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
sendCommand(DSPICO_CMD_USB_COMMAND_INTERRUPT_ENABLE);
|
||||
rtos_enableIrqMask(RTOS_IRQ_DS_SLOTA_IREQ);
|
||||
}
|
||||
|
||||
// Disable device interrupt
|
||||
void dcd_int_disable(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
rtos_disableIrqMask(RTOS_IRQ_DS_SLOTA_IREQ);
|
||||
sendCommand(DSPICO_CMD_USB_COMMAND_INTERRUPT_DISABLE);
|
||||
}
|
||||
|
||||
// Receive Set Address request, mcu port must also include status IN response
|
||||
void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
|
||||
{
|
||||
(void) rhport;
|
||||
(void) dev_addr;
|
||||
sendCommand(DSPICO_CMD_USB_COMMAND_BEGIN_SET_ADDRESS);
|
||||
}
|
||||
|
||||
// Wake up host
|
||||
void dcd_remote_wakeup(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
sendCommand(DSPICO_CMD_USB_COMMAND_REMOTE_WAKEUP);
|
||||
}
|
||||
|
||||
// Connect by enabling internal pull-up resistor on D+/D-
|
||||
void dcd_connect(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
sendCommand(DSPICO_CMD_USB_COMMAND_CONNECT);
|
||||
}
|
||||
|
||||
// Disconnect by disabling internal pull-up resistor on D+/D-
|
||||
void dcd_disconnect(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
sendCommand(DSPICO_CMD_USB_COMMAND_DISCONNECT);
|
||||
}
|
||||
|
||||
void dcd_sof_enable(uint8_t rhport, bool en)
|
||||
{
|
||||
(void) rhport;
|
||||
sendCommand(en ? DSPICO_CMD_USB_COMMAND_SOF_ENABLE : DSPICO_CMD_USB_COMMAND_SOF_DISABLE);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Endpoint API
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const* request)
|
||||
{
|
||||
(void) rhport;
|
||||
if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE &&
|
||||
request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD &&
|
||||
request->bRequest == TUSB_REQ_SET_ADDRESS)
|
||||
{
|
||||
sendCommand(DSPICO_CMD_USB_COMMAND_FINISH_SET_ADDRESS((u8)request->wValue));
|
||||
}
|
||||
}
|
||||
|
||||
// Configure endpoint's registers according to descriptor
|
||||
bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc)
|
||||
{
|
||||
(void) rhport;
|
||||
sendCommand(DSPICO_CMD_USB_COMMAND_EP_OPEN(
|
||||
ep_desc->bEndpointAddress, ep_desc->wMaxPacketSize, ep_desc->bmAttributes.xfer));
|
||||
return true;
|
||||
}
|
||||
|
||||
void dcd_edpt_close_all(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
sendCommand(DSPICO_CMD_USB_COMMAND_EP_CLOSE_ALL);
|
||||
}
|
||||
|
||||
// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack
|
||||
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes)
|
||||
{
|
||||
(void) rhport;
|
||||
if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN)
|
||||
{
|
||||
sInEndpoints[ep_addr & ~0x80].BeginTransfer(buffer, total_bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
sOutEndpoints[ep_addr & ~0x80].BeginTransfer(buffer, total_bytes);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Stall endpoint
|
||||
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
|
||||
{
|
||||
(void) rhport;
|
||||
sendCommand(DSPICO_CMD_USB_COMMAND_EP_STALL(ep_addr));
|
||||
}
|
||||
|
||||
// clear stall, data toggle is also reset to DATA0
|
||||
void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
|
||||
{
|
||||
(void) rhport;
|
||||
sendCommand(DSPICO_CMD_USB_COMMAND_EP_CLEAR_STALL(ep_addr));
|
||||
}
|
||||
|
||||
void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr)
|
||||
{
|
||||
(void) rhport;
|
||||
sendCommand(DSPICO_CMD_USB_COMMAND_EP_CLOSE(ep_addr));
|
||||
}
|
||||
|
||||
#endif
|
||||
161
platform/tusb_os_custom.h
Normal file
161
platform/tusb_os_custom.h
Normal file
@@ -0,0 +1,161 @@
|
||||
#pragma once
|
||||
#include "common.h"
|
||||
#include "libtwl/rtos/rtosMutex.h"
|
||||
#include "libtwl/rtos/rtosEvent.h"
|
||||
|
||||
typedef rtos_event_t osal_semaphore_def_t;
|
||||
typedef rtos_event_t* osal_semaphore_t;
|
||||
|
||||
static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef)
|
||||
{
|
||||
rtos_createEvent(semdef);
|
||||
return semdef;
|
||||
}
|
||||
|
||||
static inline bool osal_semaphore_delete(osal_semaphore_t semd_hdl)
|
||||
{
|
||||
(void) semd_hdl;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr)
|
||||
{
|
||||
rtos_signalEvent(sem_hdl);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec)
|
||||
{
|
||||
(void) msec;
|
||||
rtos_waitEvent(sem_hdl, false, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl)
|
||||
{
|
||||
rtos_clearEvent(sem_hdl);
|
||||
}
|
||||
|
||||
typedef rtos_mutex_t osal_mutex_def_t;
|
||||
typedef rtos_mutex_t* osal_mutex_t;
|
||||
|
||||
static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef)
|
||||
{
|
||||
rtos_createMutex(mdef);
|
||||
return mdef;
|
||||
}
|
||||
|
||||
static inline bool osal_mutex_delete(osal_mutex_t mutex_hdl)
|
||||
{
|
||||
(void) mutex_hdl;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec)
|
||||
{
|
||||
if (msec == OSAL_TIMEOUT_NOTIMEOUT)
|
||||
{
|
||||
return rtos_tryLockMutex(mutex_hdl);
|
||||
}
|
||||
else
|
||||
{
|
||||
rtos_lockMutex(mutex_hdl);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl)
|
||||
{
|
||||
rtos_unlockMutex(mutex_hdl);
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
rtos_event_t event;
|
||||
volatile uint32_t readPtr;
|
||||
volatile uint32_t writePtr;
|
||||
uint32_t elementSize;
|
||||
uint32_t bufferSize;
|
||||
uint8_t* buffer;
|
||||
} osal_queue_def_t;
|
||||
|
||||
typedef osal_queue_def_t* osal_queue_t;
|
||||
|
||||
#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \
|
||||
uint8_t _name##_buf[(_depth + 1)*sizeof(_type)]; \
|
||||
osal_queue_def_t _name = { \
|
||||
.readPtr = 0, \
|
||||
.writePtr = 0, \
|
||||
.elementSize = sizeof(_type), \
|
||||
.bufferSize = (_depth + 1)*sizeof(_type), \
|
||||
.buffer = _name##_buf \
|
||||
}
|
||||
|
||||
static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef)
|
||||
{
|
||||
rtos_createEvent(&qdef->event);
|
||||
qdef->readPtr = 0;
|
||||
qdef->writePtr = 0;
|
||||
return qdef;
|
||||
}
|
||||
|
||||
static inline bool osal_queue_delete(osal_queue_t qhdl)
|
||||
{
|
||||
(void) qhdl;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec)
|
||||
{
|
||||
do
|
||||
{
|
||||
uint32_t readPtr = qhdl->readPtr;
|
||||
uint32_t writePtr = qhdl->writePtr;
|
||||
if (readPtr != writePtr)
|
||||
{
|
||||
memcpy(data, &qhdl->buffer[readPtr], qhdl->elementSize);
|
||||
readPtr += qhdl->elementSize;
|
||||
if (readPtr == qhdl->bufferSize)
|
||||
{
|
||||
readPtr = 0;
|
||||
}
|
||||
qhdl->readPtr = readPtr;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (msec == OSAL_TIMEOUT_NOTIMEOUT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
rtos_waitEvent(&qhdl->event, false, true);
|
||||
} while (true);
|
||||
}
|
||||
|
||||
static inline bool osal_queue_send(osal_queue_t qhdl, const void* data, bool in_isr)
|
||||
{
|
||||
uint32_t readPtr = qhdl->readPtr;
|
||||
uint32_t writePtr = qhdl->writePtr;
|
||||
uint32_t newWritePtr = writePtr + qhdl->elementSize;
|
||||
if (newWritePtr == qhdl->bufferSize)
|
||||
{
|
||||
newWritePtr = 0;
|
||||
}
|
||||
if (newWritePtr == readPtr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(&qhdl->buffer[writePtr], data, qhdl->elementSize);
|
||||
qhdl->writePtr = newWritePtr;
|
||||
rtos_signalEvent(&qhdl->event);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool osal_queue_empty(osal_queue_t qhdl)
|
||||
{
|
||||
qhdl->readPtr = 0;
|
||||
qhdl->writePtr = 0;
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user