Skip to content

Commit

Permalink
Make USB virtual COM thread-safe
Browse files Browse the repository at this point in the history
  • Loading branch information
ReservedField committed Oct 24, 2016
1 parent e7644c7 commit 1a214f7
Showing 1 changed file with 20 additions and 21 deletions.
41 changes: 20 additions & 21 deletions src/usb/USB_VirtualCOM.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <M451Series.h>
#include <USB_VirtualCOM.h>
#include <USB.h>
#include <Thread.h>

/* Endpoints */
#define USB_VCOM_CTRL_IN_EP EP0
Expand Down Expand Up @@ -350,6 +351,11 @@ static volatile USB_VirtualCOM_RxCallback_t USB_VirtualCOM_rxCallbackPtr;
*/
static uint8_t USB_VirtualCOM_isAsync;

/**
* Virtual COM mutex.
*/
static Thread_Mutex_t USB_VirtualCOM_mutex;

/**
* Write data to the RX ring buffer.
* If the data size exceeds current buffer capacity, excess
Expand Down Expand Up @@ -679,15 +685,12 @@ static void USB_VirtualCOM_SendSync(const uint8_t *buf, uint32_t size) {
*/
static void USB_VirtualCOM_SendAsync(const uint8_t *buf, uint32_t size) {
USB_VirtualCOM_TxTransfer_t *transfer;
uint32_t partialSize;
uint32_t primask, partialSize;

if(size == 0) {
return;
}

// Enter critical section
__set_PRIMASK(1);

partialSize = 0;
if(USB_VirtualCOM_bulkInWaiting) {
// Transfer first packet right away
Expand All @@ -700,7 +703,6 @@ static void USB_VirtualCOM_SendAsync(const uint8_t *buf, uint32_t size) {

if(partialSize != 0 && partialSize < USB_VCOM_BULK_IN_MAX_PKT_SIZE) {
// We already transferred the whole packet
__set_PRIMASK(0);
return;
}

Expand All @@ -710,7 +712,6 @@ static void USB_VirtualCOM_SendAsync(const uint8_t *buf, uint32_t size) {
// allocated for the bulk IN handler to send the zero packet.
transfer = (USB_VirtualCOM_TxTransfer_t *) malloc(sizeof(USB_VirtualCOM_TxTransfer_t) + size);
if(transfer == NULL) {
__set_PRIMASK(0);
return;
}

Expand All @@ -723,27 +724,24 @@ static void USB_VirtualCOM_SendAsync(const uint8_t *buf, uint32_t size) {
}

// Append transfer to queue
primask = Thread_IrqDisable();
if(USB_VirtualCOM_txQueue.head == NULL) {
USB_VirtualCOM_txQueue.head = USB_VirtualCOM_txQueue.tail = transfer;
}
else {
USB_VirtualCOM_txQueue.tail->next = transfer;
USB_VirtualCOM_txQueue.tail = transfer;
}

// Exit critical section
__set_PRIMASK(0);
Thread_IrqRestore(primask);
}

void USB_VirtualCOM_Init() {
// Initialize state
USB_VirtualCOM_lineState = 0;
USB_VirtualCOM_txQueue.head = USB_VirtualCOM_txQueue.tail = NULL;
USB_VirtualCOM_bulkInWaiting = 1;
USB_VirtualCOM_rxBuffer.readIndex = USB_VirtualCOM_rxBuffer.writeIndex = 0;
USB_VirtualCOM_rxBuffer.dataSize = 0;
USB_VirtualCOM_rxCallbackPtr = NULL;
USB_VirtualCOM_isAsync = 0;

if(Thread_MutexCreate(&USB_VirtualCOM_mutex) != TD_SUCCESS) {
// No user code has run yet, the heap is messed up
asm volatile ("udf");
}

// Open USB
USBD_Open(&USB_VirtualCOM_UsbdInfo, USB_VirtualCOM_HandleClassRequest, NULL);
Expand Down Expand Up @@ -783,12 +781,14 @@ void USB_VirtualCOM_Send(const uint8_t *buf, uint32_t size) {
return;
}

Thread_MutexLock(USB_VirtualCOM_mutex);
if(USB_VirtualCOM_isAsync) {
USB_VirtualCOM_SendAsync(buf, size);
}
else {
USB_VirtualCOM_SendSync(buf, size);
}
Thread_MutexUnlock(USB_VirtualCOM_mutex);
}

void USB_VirtualCOM_SendString(const char *str) {
Expand All @@ -801,17 +801,16 @@ uint16_t USB_VirtualCOM_GetAvailableSize() {

uint16_t USB_VirtualCOM_Read(uint8_t *buf, uint16_t size) {
uint16_t readSize;
uint32_t primask;

// Read in critical section
__set_PRIMASK(1);
primask = Thread_IrqDisable();
readSize = USB_VirtualCOM_RxBuffer_Read(buf, size);
__set_PRIMASK(0);
Thread_IrqRestore(primask);

return readSize;
}

void USB_VirtualCOM_SetRxCallback(USB_VirtualCOM_RxCallback_t callbackPtr) {
// Atomic
USB_VirtualCOM_rxCallbackPtr = callbackPtr;
}

Expand Down Expand Up @@ -839,4 +838,4 @@ void USBD_IRQHandler() {
// This handler should be fast.
// Be careful with display debugging in here, as it may throw off USB timing.
USB_VirtualCOM_IRQHandler();
}
}

0 comments on commit 1a214f7

Please sign in to comment.