git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4273 35acf78f-673a-0410-8e92-d51de3d6d3f4
parent
93ed653e57
commit
f620f29e0a
|
@ -275,7 +275,7 @@ typedef struct {
|
|||
/** @brief No pending conditions.*/
|
||||
#define CHN_NO_ERROR 0
|
||||
/** @brief Connection happened.*/
|
||||
#define ICHN_CONNECTED 1
|
||||
#define CHN_CONNECTED 1
|
||||
/** @brief Disconnection happened.*/
|
||||
#define CHN_DISCONNECTED 2
|
||||
/** @brief Data available in the input queue.*/
|
||||
|
|
|
@ -160,6 +160,7 @@ extern "C" {
|
|||
void sduObjectInit(SerialUSBDriver *sdp);
|
||||
void sduStart(SerialUSBDriver *sdup, const SerialUSBConfig *config);
|
||||
void sduStop(SerialUSBDriver *sdup);
|
||||
void sduConfigureHookI(USBDriver *usbp);
|
||||
bool_t sduRequestsHook(USBDriver *usbp);
|
||||
void sduDataTransmitted(USBDriver *usbp, usbep_t ep);
|
||||
void sduDataReceived(USBDriver *usbp, usbep_t ep);
|
||||
|
|
|
@ -321,9 +321,21 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp,
|
|||
* @name Macro Functions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief Returns the sriver state.
|
||||
*
|
||||
* @param[in] usbp pointer to the @p USBDriver object
|
||||
* @return The driver state.
|
||||
*
|
||||
* @iclass
|
||||
*/
|
||||
#define usbGetDriverStateI(usbp) ((usbp)->state)
|
||||
|
||||
/**
|
||||
* @brief Connects the USB device.
|
||||
*
|
||||
* @param[in] usbp pointer to the @p USBDriver object
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
#define usbConnectBus(usbp) usb_lld_connect_bus(usbp)
|
||||
|
@ -331,6 +343,8 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp,
|
|||
/**
|
||||
* @brief Disconnect the USB device.
|
||||
*
|
||||
* @param[in] usbp pointer to the @p USBDriver object
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
#define usbDisconnectBus(usbp) usb_lld_disconnect_bus(usbp)
|
||||
|
|
|
@ -144,7 +144,7 @@ static void otg_rxfifo_flush(void) {
|
|||
OTG->GRSTCTL = GRSTCTL_RXFFLSH;
|
||||
while ((OTG->GRSTCTL & GRSTCTL_RXFFLSH) != 0)
|
||||
;
|
||||
/* Wait for 3 PHY Clocks*/
|
||||
/* Wait for 3 PHY Clocks.*/
|
||||
halPolledDelay(12);
|
||||
}
|
||||
|
||||
|
@ -153,7 +153,7 @@ static void otg_txfifo_flush(uint32_t fifo) {
|
|||
OTG->GRSTCTL = GRSTCTL_TXFNUM(fifo) | GRSTCTL_TXFFLSH;
|
||||
while ((OTG->GRSTCTL & GRSTCTL_TXFFLSH) != 0)
|
||||
;
|
||||
/* Wait for 3 PHY Clocks*/
|
||||
/* Wait for 3 PHY Clocks.*/
|
||||
halPolledDelay(12);
|
||||
}
|
||||
|
||||
|
@ -186,6 +186,84 @@ static uint32_t otg_ram_alloc(USBDriver *usbp, size_t size) {
|
|||
"otg_fifo_alloc(), #1", "FIFO memory overflow");
|
||||
return next;
|
||||
}
|
||||
/**
|
||||
* @brief Prepares for a transmit transaction on an IN endpoint.
|
||||
* @post The endpoint is ready for @p usbStartTransmitI().
|
||||
* @note The transmit transaction size is equal to the data contained
|
||||
* in the queue.
|
||||
*
|
||||
* @param[in] usbp pointer to the @p USBDriver object
|
||||
* @param[in] ep endpoint number
|
||||
* @param[in] n maximum number of bytes to copy
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
static void otg_prepare_transmit(USBDriver *usbp, usbep_t ep, size_t n) {
|
||||
uint32_t pcnt;
|
||||
USBInEndpointState *isp = usbp->epc[ep]->in_state;
|
||||
|
||||
isp->txsize = n;
|
||||
isp->txcnt = 0;
|
||||
|
||||
/* Transfer initialization.*/
|
||||
if (n == 0) {
|
||||
/* Special case, sending zero size packet.*/
|
||||
OTG->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(1) | DIEPTSIZ_XFRSIZ(0);
|
||||
}
|
||||
else {
|
||||
/* Normal case.*/
|
||||
pcnt = (n + usbp->epc[ep]->in_maxsize - 1) / usbp->epc[ep]->in_maxsize;
|
||||
OTG->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(pcnt) |
|
||||
DIEPTSIZ_XFRSIZ(usbp->epc[ep]->in_state->txsize);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Prepares for a receive transaction on an OUT endpoint.
|
||||
* @post The endpoint is ready for @p usbStartReceiveI().
|
||||
*
|
||||
* @param[in] usbp pointer to the @p USBDriver object
|
||||
* @param[in] ep endpoint number
|
||||
* @param[in] n maximum number of bytes to copy
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
static void otg_prepare_receive(USBDriver *usbp, usbep_t ep, size_t n) {
|
||||
uint32_t pcnt;
|
||||
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
|
||||
|
||||
osp->rxsize = n;
|
||||
osp->rxcnt = 0;
|
||||
|
||||
/* Transfer initialization.*/
|
||||
pcnt = (n + usbp->epc[ep]->out_maxsize - 1) / usbp->epc[ep]->out_maxsize;
|
||||
OTG->oe[ep].DOEPTSIZ = DOEPTSIZ_STUPCNT(3) | DOEPTSIZ_PKTCNT(pcnt) |
|
||||
DOEPTSIZ_XFRSIZ(usbp->epc[ep]->out_maxsize);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pushes a series of words into a FIFO.
|
||||
*
|
||||
* @param[in] fifop pointer to the FIFO register
|
||||
* @param[in] buf pointer to the words buffer, not necessarily word
|
||||
* aligned
|
||||
* @param[in] n number of words to push
|
||||
*
|
||||
* @return A pointer after the last word pushed.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static uint8_t *otg_do_push(volatile uint32_t *fifop, uint8_t *buf, size_t n) {
|
||||
|
||||
while (n > 0) {
|
||||
/* Note, this line relies on the Cortex-M3/M4 ability to perform
|
||||
unaligned word accesses and on the LSB-first memory organization.*/
|
||||
*fifop = *((uint32_t *)buf);
|
||||
buf += 4;
|
||||
n--;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes to a TX FIFO.
|
||||
|
@ -199,19 +277,8 @@ static uint32_t otg_ram_alloc(USBDriver *usbp, size_t size) {
|
|||
static void otg_fifo_write_from_buffer(usbep_t ep,
|
||||
const uint8_t *buf,
|
||||
size_t n) {
|
||||
volatile uint32_t *fifop;
|
||||
|
||||
fifop = OTG_FIFO(ep);
|
||||
n = (n + 3) / 4;
|
||||
while (n) {
|
||||
uint32_t dw = (uint32_t)buf[0] |
|
||||
((uint32_t)buf[1] << 8) |
|
||||
((uint32_t)buf[2] << 16) |
|
||||
((uint32_t)buf[3] << 24);
|
||||
*fifop = dw;
|
||||
n--;
|
||||
buf += 4;
|
||||
}
|
||||
otg_do_push(OTG_FIFO(ep), (uint8_t *)buf, (n + 3) / 4);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -226,43 +293,75 @@ static void otg_fifo_write_from_buffer(usbep_t ep,
|
|||
static void otg_fifo_write_from_queue(usbep_t ep,
|
||||
OutputQueue *oqp,
|
||||
size_t n) {
|
||||
size_t nw;
|
||||
uint8_t *bp;
|
||||
size_t ntogo;
|
||||
volatile uint32_t *fifop;
|
||||
|
||||
fifop = OTG_FIFO(ep);
|
||||
|
||||
/* Fetching data from the queue buffer directly.*/
|
||||
bp = oqp->q_rdptr;
|
||||
nw = (n + 3) / 4;
|
||||
do {
|
||||
uint32_t dw;
|
||||
dw = (uint32_t)*bp++;
|
||||
if (bp >= oqp->q_top)
|
||||
bp = oqp->q_buffer;
|
||||
dw |= (uint32_t)*bp++ << 8;
|
||||
if (bp >= oqp->q_top)
|
||||
bp = oqp->q_buffer;
|
||||
dw |= (uint32_t)*bp++ << 16;
|
||||
if (bp >= oqp->q_top)
|
||||
bp = oqp->q_buffer;
|
||||
dw |= (uint32_t)*bp++ << 24;
|
||||
if (bp >= oqp->q_top)
|
||||
bp = oqp->q_buffer;
|
||||
ntogo = n;
|
||||
while (ntogo > 0) {
|
||||
uint32_t dw, i;
|
||||
size_t streak, nw = ntogo / 4;
|
||||
uint32_t nw2end = (oqp->q_top - oqp->q_rdptr) / 4;
|
||||
|
||||
ntogo -= (streak = nw <= nw2end ? nw : nw2end) * 4;
|
||||
oqp->q_rdptr = otg_do_push(fifop, oqp->q_rdptr, streak);
|
||||
if (oqp->q_rdptr >= oqp->q_top) {
|
||||
oqp->q_rdptr = oqp->q_buffer;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If this condition is not satisfied then there is a word lying across
|
||||
queue circular buffer boundary.*/
|
||||
if (ntogo <= 0)
|
||||
break;
|
||||
|
||||
/* One byte at time.*/
|
||||
dw = 0;
|
||||
i = 0;
|
||||
while ((ntogo > 0) && (i < 4)) {
|
||||
dw |= (uint32_t)*oqp->q_rdptr++ << (i * 8);
|
||||
if (oqp->q_rdptr >= oqp->q_top)
|
||||
oqp->q_rdptr = oqp->q_buffer;
|
||||
ntogo--;
|
||||
i++;
|
||||
}
|
||||
*fifop = dw;
|
||||
} while (--nw > 0);
|
||||
}
|
||||
|
||||
/* Updating queue.*/
|
||||
chSysLockFromIsr();
|
||||
oqp->q_rdptr += n;
|
||||
if (oqp->q_rdptr >= oqp->q_top)
|
||||
oqp->q_rdptr -= chQSizeI(oqp);
|
||||
oqp->q_counter += n;
|
||||
while (notempty(&oqp->q_waiting))
|
||||
chSchReadyI(fifo_remove(&oqp->q_waiting))->p_u.rdymsg = Q_OK;
|
||||
chSysUnlockFromIsr();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pops a series of words from a FIFO.
|
||||
*
|
||||
* @param[in] fifop pointer to the FIFO register
|
||||
* @param[in] buf pointer to the words buffer, not necessarily word
|
||||
* aligned
|
||||
* @param[in] n number of words to push
|
||||
*
|
||||
* @return A pointer after the last word pushed.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static uint8_t *otg_do_pop(volatile uint32_t *fifop, uint8_t *buf, size_t n) {
|
||||
|
||||
while (n > 0) {
|
||||
uint32_t dw = *fifop;
|
||||
/* Note, this line relies on the Cortex-M3/M4 ability to perform
|
||||
unaligned word accesses and on the LSB-first memory organization.*/
|
||||
*((uint32_t *)buf) = dw;
|
||||
buf += 4;
|
||||
n--;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads a packet from the RXFIFO.
|
||||
*
|
||||
|
@ -281,10 +380,10 @@ static void otg_fifo_read_to_buffer(uint8_t *buf, size_t n, size_t max) {
|
|||
while (n) {
|
||||
uint32_t dw = *fifop;
|
||||
if (max) {
|
||||
*buf++ = (uint8_t)dw;
|
||||
*buf++ = (uint8_t)(dw >> 8);
|
||||
*buf++ = (uint8_t)(dw >> 16);
|
||||
*buf++ = (uint8_t)(dw >> 24);
|
||||
/* Note, this line relies on the Cortex-M3/M4 ability to perform
|
||||
unaligned word accesses and on the LSB-first memory organization.*/
|
||||
*((uint32_t *)buf) = dw;
|
||||
buf += 4;
|
||||
max--;
|
||||
}
|
||||
n--;
|
||||
|
@ -300,37 +399,40 @@ static void otg_fifo_read_to_buffer(uint8_t *buf, size_t n, size_t max) {
|
|||
* @notapi
|
||||
*/
|
||||
static void otg_fifo_read_to_queue(InputQueue *iqp, size_t n) {
|
||||
size_t nw, nb;
|
||||
size_t ntogo;
|
||||
volatile uint32_t *fifop;
|
||||
|
||||
fifop = OTG_FIFO(0);
|
||||
nb = n;
|
||||
nw = (n + 3) / 4;
|
||||
do {
|
||||
uint32_t dw = *fifop;
|
||||
*iqp->q_wrptr++ = (uint8_t)dw;
|
||||
if (iqp->q_wrptr >= iqp->q_top)
|
||||
|
||||
ntogo = n;
|
||||
while (ntogo > 0) {
|
||||
uint32_t dw, i;
|
||||
size_t streak, nw = ntogo / 4;
|
||||
uint32_t nw2end = (iqp->q_wrptr - iqp->q_wrptr) / 4;
|
||||
|
||||
ntogo -= (streak = nw <= nw2end ? nw : nw2end) * 4;
|
||||
iqp->q_wrptr = otg_do_pop(fifop, iqp->q_wrptr, streak);
|
||||
if (iqp->q_wrptr >= iqp->q_top) {
|
||||
iqp->q_wrptr = iqp->q_buffer;
|
||||
if (--nb > 0) {
|
||||
*iqp->q_wrptr++ = (uint8_t)(dw >> 8);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If this condition is not satisfied then there is a word lying across
|
||||
queue circular buffer boundary.*/
|
||||
if (ntogo <= 0)
|
||||
break;
|
||||
|
||||
/* One byte at time.*/
|
||||
dw = *fifop;
|
||||
i = 0;
|
||||
while ((ntogo > 0) && (i < 4)) {
|
||||
*iqp->q_wrptr++ = (uint8_t)dw >> (i * 8);
|
||||
if (iqp->q_wrptr >= iqp->q_top)
|
||||
iqp->q_wrptr = iqp->q_buffer;
|
||||
|
||||
if (--nb > 0) {
|
||||
*iqp->q_wrptr++ = (uint8_t)(dw >> 16);
|
||||
if (iqp->q_wrptr >= iqp->q_top)
|
||||
iqp->q_wrptr = iqp->q_buffer;
|
||||
|
||||
if (--nb > 0) {
|
||||
*iqp->q_wrptr++ = (uint8_t)(dw >> 24);
|
||||
if (iqp->q_wrptr >= iqp->q_top)
|
||||
iqp->q_wrptr = iqp->q_buffer;
|
||||
|
||||
--nb;
|
||||
}
|
||||
}
|
||||
ntogo--;
|
||||
i++;
|
||||
}
|
||||
} while (--nw > 0);
|
||||
}
|
||||
|
||||
/* Updating queue.*/
|
||||
chSysLockFromIsr();
|
||||
|
@ -846,18 +948,11 @@ void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) {
|
|||
*/
|
||||
void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep,
|
||||
uint8_t *buf, size_t n) {
|
||||
uint32_t pcnt;
|
||||
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
|
||||
|
||||
osp->rxqueued = FALSE;
|
||||
osp->rxsize = n;
|
||||
osp->rxcnt = 0;
|
||||
osp->mode.linear.rxbuf = buf;
|
||||
|
||||
/* Transfer initialization.*/
|
||||
pcnt = (n + usbp->epc[ep]->out_maxsize - 1) / usbp->epc[ep]->out_maxsize;
|
||||
OTG->oe[ep].DOEPTSIZ = DOEPTSIZ_STUPCNT(3) | DOEPTSIZ_PKTCNT(pcnt) |
|
||||
DOEPTSIZ_XFRSIZ(usbp->epc[ep]->out_maxsize);
|
||||
otg_prepare_receive(usbp, ep, n);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -872,30 +967,15 @@ void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep,
|
|||
*/
|
||||
void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep,
|
||||
const uint8_t *buf, size_t n) {
|
||||
uint32_t pcnt;
|
||||
USBInEndpointState *isp = usbp->epc[ep]->in_state;
|
||||
|
||||
isp->txqueued = FALSE;
|
||||
isp->txsize = n;
|
||||
isp->txcnt = 0;
|
||||
isp->mode.linear.txbuf = buf;
|
||||
|
||||
if (n == 0) {
|
||||
/* Special case, sending zero size packet.*/
|
||||
OTG->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(1) | DIEPTSIZ_XFRSIZ(0);
|
||||
}
|
||||
else {
|
||||
/* Transfer initialization.*/
|
||||
pcnt = (n + usbp->epc[ep]->in_maxsize - 1) / usbp->epc[ep]->in_maxsize;
|
||||
OTG->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(pcnt) |
|
||||
DIEPTSIZ_XFRSIZ(usbp->epc[ep]->in_state->txsize);
|
||||
}
|
||||
otg_prepare_transmit(usbp, ep, n);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Prepares for a receive transaction on an OUT endpoint.
|
||||
* @pre In order to use this function the endpoint must have been
|
||||
* initialized in transaction mode.
|
||||
* @post The endpoint is ready for @p usbStartReceiveI().
|
||||
* @note The receive transaction size is equal to the space in the queue
|
||||
* rounded to the lower multiple of a packet size. So make sure there
|
||||
|
@ -911,24 +991,15 @@ void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep,
|
|||
*/
|
||||
void usb_lld_prepare_queued_receive(USBDriver *usbp, usbep_t ep,
|
||||
InputQueue *iq, size_t n) {
|
||||
uint32_t pcnt;
|
||||
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
|
||||
|
||||
osp->rxqueued = TRUE;
|
||||
osp->rxsize = n;
|
||||
osp->rxcnt = 0;
|
||||
osp->mode.queue.rxqueue = iq;
|
||||
|
||||
/* Transfer initialization.*/
|
||||
pcnt = (n + usbp->epc[ep]->out_maxsize - 1) / usbp->epc[ep]->out_maxsize;
|
||||
OTG->oe[ep].DOEPTSIZ = DOEPTSIZ_STUPCNT(3) | DOEPTSIZ_PKTCNT(pcnt) |
|
||||
DOEPTSIZ_XFRSIZ(usbp->epc[ep]->out_maxsize);
|
||||
otg_prepare_receive(usbp, ep, n);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Prepares for a transmit transaction on an IN endpoint.
|
||||
* @pre In order to use this function the endpoint must have been
|
||||
* initialized in transaction mode.
|
||||
* @post The endpoint is ready for @p usbStartTransmitI().
|
||||
* @note The transmit transaction size is equal to the data contained
|
||||
* in the queue.
|
||||
|
@ -942,18 +1013,11 @@ void usb_lld_prepare_queued_receive(USBDriver *usbp, usbep_t ep,
|
|||
*/
|
||||
void usb_lld_prepare_queued_transmit(USBDriver *usbp, usbep_t ep,
|
||||
OutputQueue *oq, size_t n) {
|
||||
uint32_t pcnt;
|
||||
USBInEndpointState *isp = usbp->epc[ep]->in_state;
|
||||
|
||||
isp->txqueued = TRUE;
|
||||
isp->txsize = n;
|
||||
isp->txcnt = 0;
|
||||
isp->mode.queue.txqueue = oq;
|
||||
|
||||
/* Transfer initialization.*/
|
||||
pcnt = (n + usbp->epc[ep]->in_maxsize - 1) / usbp->epc[ep]->in_maxsize;
|
||||
OTG->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(pcnt) |
|
||||
DIEPTSIZ_XFRSIZ(usbp->epc[ep]->in_state->txsize);
|
||||
otg_prepare_transmit(usbp, ep, n);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -126,7 +126,7 @@ typedef struct {
|
|||
union {
|
||||
struct {
|
||||
/**
|
||||
* @brief Pointer to the transmission buffer.
|
||||
* @brief Pointer to the transmission linear buffer.
|
||||
*/
|
||||
const uint8_t *txbuf;
|
||||
} linear;
|
||||
|
@ -158,7 +158,7 @@ typedef struct {
|
|||
union {
|
||||
struct {
|
||||
/**
|
||||
* @brief Pointer to the receive buffer.
|
||||
* @brief Pointer to the receive linear buffer.
|
||||
*/
|
||||
uint8_t *rxbuf;
|
||||
} linear;
|
||||
|
@ -217,16 +217,12 @@ typedef struct {
|
|||
uint16_t out_maxsize;
|
||||
/**
|
||||
* @brief @p USBEndpointState associated to the IN endpoint.
|
||||
* @details This structure maintains the state of the IN endpoint when
|
||||
* the endpoint is not in packet mode. Endpoints configured in
|
||||
* packet mode must set this field to @p NULL.
|
||||
* @details This structure maintains the state of the IN endpoint.
|
||||
*/
|
||||
USBInEndpointState *in_state;
|
||||
/**
|
||||
* @brief @p USBEndpointState associated to the OUT endpoint.
|
||||
* @details This structure maintains the state of the OUT endpoint when
|
||||
* the endpoint is not in packet mode. Endpoints configured in
|
||||
* packet mode must set this field to @p NULL.
|
||||
* @details This structure maintains the state of the OUT endpoint.
|
||||
*/
|
||||
USBOutEndpointState *out_state;
|
||||
/* End of the mandatory fields.*/
|
||||
|
|
|
@ -120,6 +120,11 @@ static void inotify(GenericQueue *qp) {
|
|||
size_t n, maxsize;
|
||||
SerialUSBDriver *sdup = chQGetLink(qp);
|
||||
|
||||
/* If the USB driver is not in the appropriate state then transactions
|
||||
must not be started.*/
|
||||
if (usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE)
|
||||
return;
|
||||
|
||||
/* If there is in the queue enough space to hold at least one packet and
|
||||
a transaction is not yet started then a new transaction is started for
|
||||
the available space.*/
|
||||
|
@ -145,6 +150,11 @@ static void onotify(GenericQueue *qp) {
|
|||
size_t n;
|
||||
SerialUSBDriver *sdup = chQGetLink(qp);
|
||||
|
||||
/* If the USB driver is not in the appropriate state then transactions
|
||||
must not be started.*/
|
||||
if (usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE)
|
||||
return;
|
||||
|
||||
/* If there is not an ongoing transaction and the output queue contains
|
||||
data then a new transaction is started.*/
|
||||
if (!usbGetTransmitStatusI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP) &&
|
||||
|
@ -238,6 +248,22 @@ void sduStop(SerialUSBDriver *sdup) {
|
|||
usbStop(sdup->config->usbp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB device configured handler.
|
||||
*
|
||||
* @param[in] usbp pointer to the @p USBDriver object
|
||||
*
|
||||
* @iclass
|
||||
*/
|
||||
void sduConfigureHookI(USBDriver *usbp) {
|
||||
SerialUSBDriver *sdup = usbp->param;
|
||||
|
||||
sdup->flags = CHN_NO_ERROR;
|
||||
chIQResetI(&sdup->iqueue);
|
||||
chOQResetI(&sdup->oqueue);
|
||||
chnAddFlagsI(sdup, CHN_CONNECTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Default requests hook.
|
||||
* @details Applications wanting to use the Serial over USB driver can use
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
# Compiler options here.
|
||||
ifeq ($(USE_OPT),)
|
||||
USE_OPT = -O0 -ggdb -fomit-frame-pointer -falign-functions=16
|
||||
USE_OPT = -O2 -ggdb -fomit-frame-pointer -falign-functions=16
|
||||
endif
|
||||
|
||||
# C specific options here (added to USE_OPT).
|
||||
|
|
|
@ -296,13 +296,18 @@ static void usb_event(USBDriver *usbp, usbevent_t event) {
|
|||
case USB_EVENT_ADDRESS:
|
||||
return;
|
||||
case USB_EVENT_CONFIGURED:
|
||||
chSysLockFromIsr();
|
||||
|
||||
/* Enables the endpoints specified into the configuration.
|
||||
Note, this callback is invoked from an ISR so I-Class functions
|
||||
must be used.*/
|
||||
chSysLockFromIsr();
|
||||
usbInitEndpointI(usbp, USB_CDC_DATA_REQUEST_EP, &ep1config);
|
||||
usbInitEndpointI(usbp, USB_CDC_INTERRUPT_REQUEST_EP, &ep2config);
|
||||
usbInitEndpointI(usbp, USB_CDC_DATA_AVAILABLE_EP, &ep3config);
|
||||
|
||||
/* Resetting the state of the CDC subsystem.*/
|
||||
sduConfigureHookI(usbp);
|
||||
|
||||
chSysUnlockFromIsr();
|
||||
return;
|
||||
case USB_EVENT_SUSPEND:
|
||||
|
@ -437,10 +442,10 @@ int main(void) {
|
|||
/*
|
||||
* Activates the USB driver and then the USB bus pull-up on D+.
|
||||
*/
|
||||
usbDisconnectBus(serusbcfg.usbp);
|
||||
chThdSleepMilliseconds(1000);
|
||||
sduObjectInit(&SDU1);
|
||||
sduStart(&SDU1, &serusbcfg);
|
||||
usbDisconnectBus(serusbcfg.usbp);
|
||||
chThdSleepMilliseconds(100);
|
||||
usbConnectBus(serusbcfg.usbp);
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue