- ACM fixed, thread added, wakeup() removed
This commit is contained in:
parent
a977b32471
commit
983c8a8840
75
class/acm.c
75
class/acm.c
@ -9,12 +9,15 @@
|
|||||||
#include "acm.h"
|
#include "acm.h"
|
||||||
|
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "../usb.h"
|
#include "../usb.h"
|
||||||
#include "../usb_device_types.h"
|
#include "../usb_device_types.h"
|
||||||
|
#include "cmsis_os2.h"
|
||||||
|
|
||||||
#include <blocking_io/blocking_fifo.h>
|
#include <blocking_io/blocking_fifo.h>
|
||||||
|
#include <strings.h>
|
||||||
|
|
||||||
// -------------------------
|
// -------------------------
|
||||||
|
|
||||||
@ -22,6 +25,42 @@ static Usb_AcmState acms = {0}; ///< ACM module state
|
|||||||
static uint8_t tx_buffer[USB_ACM_PCKT_BUFSIZE]; ///< Transmit buffer
|
static uint8_t tx_buffer[USB_ACM_PCKT_BUFSIZE]; ///< Transmit buffer
|
||||||
static uint8_t fifo_mem[USB_ACM_FIFO_MEM_SIZE]; ///< Memory assigned to the TX BFifo
|
static uint8_t fifo_mem[USB_ACM_FIFO_MEM_SIZE]; ///< Memory assigned to the TX BFifo
|
||||||
static BFifo fifo; ///< TX Blocking FIFO
|
static BFifo fifo; ///< TX Blocking FIFO
|
||||||
|
static osThreadId_t th; ///< ACM thread
|
||||||
|
static osEventFlagsId_t flags; ///< Event flags
|
||||||
|
|
||||||
|
#define USB_ACM_DATA_IN_DONE (0x01) ///< IN transfer done flag
|
||||||
|
#define USB_ACM_COMM_INIT (0x02) ///< Communication has been initialized
|
||||||
|
#define USB_ACM_HOSTBOUND_DATA_AVAIL (0x04) ///< Hostbound data is available
|
||||||
|
|
||||||
|
#define USB_ACM_LOOP_TIMEOUT_TICKS (100) ///< Main loop timeout for interrupt status transmission
|
||||||
|
|
||||||
|
// -------------------------
|
||||||
|
|
||||||
|
static void thread_usb_acm(void *arg) {
|
||||||
|
osEventFlagsWait(flags, USB_ACM_COMM_INIT, 0, osWaitForever); // wait for communication to become initialized
|
||||||
|
|
||||||
|
osEventFlagsSet(flags, USB_ACM_DATA_IN_DONE); // assume we can write to the data endpoint
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
uint32_t signals = osEventFlagsWait(flags, USB_ACM_HOSTBOUND_DATA_AVAIL, osFlagsWaitAny, USB_ACM_LOOP_TIMEOUT_TICKS);
|
||||||
|
|
||||||
|
if (signals != osErrorTimeout) { // check timeout
|
||||||
|
if (signals & USB_ACM_HOSTBOUND_DATA_AVAIL) { // data hostbound available
|
||||||
|
do {
|
||||||
|
osEventFlagsWait(flags, USB_ACM_DATA_IN_DONE, osFlagsWaitAny, 1000); // wait for the IN DONE flag
|
||||||
|
uint32_t readSize = bfifo_read(&fifo, tx_buffer, USB_ACM_PCKT_BUFSIZE); // read from the fifo
|
||||||
|
if (readSize > 0) {
|
||||||
|
uint32_t writeSize = usbcore_schedule_transmission(acms.ep_assignments.data_ep, tx_buffer, readSize); // write data acquired from the buffer
|
||||||
|
bfifo_pop(&fifo, writeSize, 0); // pop with no blocking
|
||||||
|
}
|
||||||
|
} while (bfifo_get_used(&fifo) > 0);
|
||||||
|
}
|
||||||
|
} else { // timeout
|
||||||
|
// send an all-zero interrupt
|
||||||
|
usbcore_schedule_transmission(acms.ep_assignments.control_ep, (const uint8_t *)&(acms.interrupt_data), sizeof(uint16_t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// -------------------------
|
// -------------------------
|
||||||
|
|
||||||
@ -42,11 +81,20 @@ void usb_acm_init(const Usb_Acm_EpAssignments *as) {
|
|||||||
|
|
||||||
// initialize an all-0 interrupt
|
// initialize an all-0 interrupt
|
||||||
acms.interrupt_data = 0;
|
acms.interrupt_data = 0;
|
||||||
acms.interrupt_pending = true;
|
|
||||||
|
|
||||||
// communication parameters have not been set
|
// communication parameters have not been set
|
||||||
acms.commInit = false;
|
acms.commInit = false;
|
||||||
|
|
||||||
|
// create flags
|
||||||
|
flags = osEventFlagsNew(NULL);
|
||||||
|
|
||||||
|
// create thread
|
||||||
|
osThreadAttr_t attr;
|
||||||
|
memset(&attr, 0, sizeof(osThreadAttr_t));
|
||||||
|
attr.stack_size = 1024;
|
||||||
|
attr.name = "acm";
|
||||||
|
th = osThreadNew(thread_usb_acm, NULL, &attr);
|
||||||
|
|
||||||
// from now on CDC module is considered initialized
|
// from now on CDC module is considered initialized
|
||||||
acms.moduleInit = true;
|
acms.moduleInit = true;
|
||||||
}
|
}
|
||||||
@ -61,6 +109,9 @@ static void usb_cdc_review_comm_init() {
|
|||||||
|
|
||||||
// combine the above criteria
|
// combine the above criteria
|
||||||
acms.commInit = lcOk && clsOk;
|
acms.commInit = lcOk && clsOk;
|
||||||
|
|
||||||
|
// signal the processing thread
|
||||||
|
osEventFlagsSet(flags, USB_ACM_COMM_INIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
int usb_acm_process_and_return(Usb_CallbackEvent *cbevt) {
|
int usb_acm_process_and_return(Usb_CallbackEvent *cbevt) {
|
||||||
@ -108,24 +159,11 @@ int usb_acm_process_and_return(Usb_CallbackEvent *cbevt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case USB_CBEVT_IN: {
|
case USB_CBEVT_IN: {
|
||||||
if (cbevt->ep == acms.ep_assignments.control_ep) { // if notification feeding is requested
|
if (cbevt->ep == acms.ep_assignments.data_ep) {
|
||||||
if (acms.interrupt_pending) {
|
osEventFlagsSet(flags, USB_ACM_DATA_IN_DONE);
|
||||||
usbcore_schedule_transmission(acms.ep_assignments.control_ep, (const uint8_t *)&(acms.interrupt_data), sizeof(uint16_t)); // send ZLP
|
|
||||||
acms.interrupt_pending = false;
|
|
||||||
}
|
}
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else if (cbevt->ep == acms.ep_assignments.data_ep) { // if data are requested
|
break;
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
// read from the fifo
|
|
||||||
if (acms.commInit) {
|
|
||||||
uint32_t readSize = bfifo_read(&fifo, tx_buffer, USB_ACM_PCKT_BUFSIZE);
|
|
||||||
if (readSize > 0) {
|
|
||||||
uint32_t writeSize = usbcore_schedule_transmission(acms.ep_assignments.data_ep, tx_buffer, readSize); // write data acquired from the buffer
|
|
||||||
bfifo_pop(&fifo, writeSize, 0); // pop with no blocking
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -138,11 +176,10 @@ int usb_acm_process_and_return(Usb_CallbackEvent *cbevt) {
|
|||||||
void usb_acm_write(const uint8_t *data, uint32_t size) {
|
void usb_acm_write(const uint8_t *data, uint32_t size) {
|
||||||
if (acms.moduleInit) {
|
if (acms.moduleInit) {
|
||||||
bfifo_push_all(&fifo, data, size);
|
bfifo_push_all(&fifo, data, size);
|
||||||
usbcore_wake_up_endpoint(acms.ep_assignments.data_ep, USB_IN);
|
osEventFlagsSet(flags, USB_ACM_HOSTBOUND_DATA_AVAIL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @fn void usb_acm_read_callback(const uint8_t *data, uint32_t size)
|
* @fn void usb_acm_read_callback(const uint8_t *data, uint32_t size)
|
||||||
* Callback function prototype for data reception. This function is
|
* Callback function prototype for data reception. This function is
|
||||||
|
@ -82,7 +82,6 @@ typedef struct {
|
|||||||
Usb_Acm_LineCodingStruct line_coding; ///< Line Coding
|
Usb_Acm_LineCodingStruct line_coding; ///< Line Coding
|
||||||
Usb_Acm_ControlLineStateStruct control_line_state; ///< Control Line State
|
Usb_Acm_ControlLineStateStruct control_line_state; ///< Control Line State
|
||||||
uint16_t interrupt_data; ///< Data sent though the next transfer on the notification element
|
uint16_t interrupt_data; ///< Data sent though the next transfer on the notification element
|
||||||
bool interrupt_pending; ///< Interrupt data is valid and should be send in the next cycle
|
|
||||||
bool moduleInit; ///< CDC module is initialized
|
bool moduleInit; ///< CDC module is initialized
|
||||||
bool commInit; ///< Communication protocol is initialized
|
bool commInit; ///< Communication protocol is initialized
|
||||||
} Usb_AcmState;
|
} Usb_AcmState;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user