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.*/
|
/** @brief No pending conditions.*/
|
||||||
#define CHN_NO_ERROR 0
|
#define CHN_NO_ERROR 0
|
||||||
/** @brief Connection happened.*/
|
/** @brief Connection happened.*/
|
||||||
#define ICHN_CONNECTED 1
|
#define CHN_CONNECTED 1
|
||||||
/** @brief Disconnection happened.*/
|
/** @brief Disconnection happened.*/
|
||||||
#define CHN_DISCONNECTED 2
|
#define CHN_DISCONNECTED 2
|
||||||
/** @brief Data available in the input queue.*/
|
/** @brief Data available in the input queue.*/
|
||||||
|
|
|
@ -160,6 +160,7 @@ extern "C" {
|
||||||
void sduObjectInit(SerialUSBDriver *sdp);
|
void sduObjectInit(SerialUSBDriver *sdp);
|
||||||
void sduStart(SerialUSBDriver *sdup, const SerialUSBConfig *config);
|
void sduStart(SerialUSBDriver *sdup, const SerialUSBConfig *config);
|
||||||
void sduStop(SerialUSBDriver *sdup);
|
void sduStop(SerialUSBDriver *sdup);
|
||||||
|
void sduConfigureHookI(USBDriver *usbp);
|
||||||
bool_t sduRequestsHook(USBDriver *usbp);
|
bool_t sduRequestsHook(USBDriver *usbp);
|
||||||
void sduDataTransmitted(USBDriver *usbp, usbep_t ep);
|
void sduDataTransmitted(USBDriver *usbp, usbep_t ep);
|
||||||
void sduDataReceived(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
|
* @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.
|
* @brief Connects the USB device.
|
||||||
*
|
*
|
||||||
|
* @param[in] usbp pointer to the @p USBDriver object
|
||||||
|
*
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
#define usbConnectBus(usbp) usb_lld_connect_bus(usbp)
|
#define usbConnectBus(usbp) usb_lld_connect_bus(usbp)
|
||||||
|
@ -331,6 +343,8 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp,
|
||||||
/**
|
/**
|
||||||
* @brief Disconnect the USB device.
|
* @brief Disconnect the USB device.
|
||||||
*
|
*
|
||||||
|
* @param[in] usbp pointer to the @p USBDriver object
|
||||||
|
*
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
#define usbDisconnectBus(usbp) usb_lld_disconnect_bus(usbp)
|
#define usbDisconnectBus(usbp) usb_lld_disconnect_bus(usbp)
|
||||||
|
|
|
@ -144,7 +144,7 @@ static void otg_rxfifo_flush(void) {
|
||||||
OTG->GRSTCTL = GRSTCTL_RXFFLSH;
|
OTG->GRSTCTL = GRSTCTL_RXFFLSH;
|
||||||
while ((OTG->GRSTCTL & GRSTCTL_RXFFLSH) != 0)
|
while ((OTG->GRSTCTL & GRSTCTL_RXFFLSH) != 0)
|
||||||
;
|
;
|
||||||
/* Wait for 3 PHY Clocks*/
|
/* Wait for 3 PHY Clocks.*/
|
||||||
halPolledDelay(12);
|
halPolledDelay(12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ static void otg_txfifo_flush(uint32_t fifo) {
|
||||||
OTG->GRSTCTL = GRSTCTL_TXFNUM(fifo) | GRSTCTL_TXFFLSH;
|
OTG->GRSTCTL = GRSTCTL_TXFNUM(fifo) | GRSTCTL_TXFFLSH;
|
||||||
while ((OTG->GRSTCTL & GRSTCTL_TXFFLSH) != 0)
|
while ((OTG->GRSTCTL & GRSTCTL_TXFFLSH) != 0)
|
||||||
;
|
;
|
||||||
/* Wait for 3 PHY Clocks*/
|
/* Wait for 3 PHY Clocks.*/
|
||||||
halPolledDelay(12);
|
halPolledDelay(12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,6 +186,84 @@ static uint32_t otg_ram_alloc(USBDriver *usbp, size_t size) {
|
||||||
"otg_fifo_alloc(), #1", "FIFO memory overflow");
|
"otg_fifo_alloc(), #1", "FIFO memory overflow");
|
||||||
return next;
|
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.
|
* @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,
|
static void otg_fifo_write_from_buffer(usbep_t ep,
|
||||||
const uint8_t *buf,
|
const uint8_t *buf,
|
||||||
size_t n) {
|
size_t n) {
|
||||||
volatile uint32_t *fifop;
|
|
||||||
|
|
||||||
fifop = OTG_FIFO(ep);
|
otg_do_push(OTG_FIFO(ep), (uint8_t *)buf, (n + 3) / 4);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -226,43 +293,75 @@ static void otg_fifo_write_from_buffer(usbep_t ep,
|
||||||
static void otg_fifo_write_from_queue(usbep_t ep,
|
static void otg_fifo_write_from_queue(usbep_t ep,
|
||||||
OutputQueue *oqp,
|
OutputQueue *oqp,
|
||||||
size_t n) {
|
size_t n) {
|
||||||
size_t nw;
|
size_t ntogo;
|
||||||
uint8_t *bp;
|
|
||||||
volatile uint32_t *fifop;
|
volatile uint32_t *fifop;
|
||||||
|
|
||||||
fifop = OTG_FIFO(ep);
|
fifop = OTG_FIFO(ep);
|
||||||
|
|
||||||
/* Fetching data from the queue buffer directly.*/
|
ntogo = n;
|
||||||
bp = oqp->q_rdptr;
|
while (ntogo > 0) {
|
||||||
nw = (n + 3) / 4;
|
uint32_t dw, i;
|
||||||
do {
|
size_t streak, nw = ntogo / 4;
|
||||||
uint32_t dw;
|
uint32_t nw2end = (oqp->q_top - oqp->q_rdptr) / 4;
|
||||||
dw = (uint32_t)*bp++;
|
|
||||||
if (bp >= oqp->q_top)
|
ntogo -= (streak = nw <= nw2end ? nw : nw2end) * 4;
|
||||||
bp = oqp->q_buffer;
|
oqp->q_rdptr = otg_do_push(fifop, oqp->q_rdptr, streak);
|
||||||
dw |= (uint32_t)*bp++ << 8;
|
if (oqp->q_rdptr >= oqp->q_top) {
|
||||||
if (bp >= oqp->q_top)
|
oqp->q_rdptr = oqp->q_buffer;
|
||||||
bp = oqp->q_buffer;
|
continue;
|
||||||
dw |= (uint32_t)*bp++ << 16;
|
}
|
||||||
if (bp >= oqp->q_top)
|
|
||||||
bp = oqp->q_buffer;
|
/* If this condition is not satisfied then there is a word lying across
|
||||||
dw |= (uint32_t)*bp++ << 24;
|
queue circular buffer boundary.*/
|
||||||
if (bp >= oqp->q_top)
|
if (ntogo <= 0)
|
||||||
bp = oqp->q_buffer;
|
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;
|
*fifop = dw;
|
||||||
} while (--nw > 0);
|
}
|
||||||
|
|
||||||
/* Updating queue.*/
|
/* Updating queue.*/
|
||||||
chSysLockFromIsr();
|
chSysLockFromIsr();
|
||||||
oqp->q_rdptr += n;
|
|
||||||
if (oqp->q_rdptr >= oqp->q_top)
|
|
||||||
oqp->q_rdptr -= chQSizeI(oqp);
|
|
||||||
oqp->q_counter += n;
|
oqp->q_counter += n;
|
||||||
while (notempty(&oqp->q_waiting))
|
while (notempty(&oqp->q_waiting))
|
||||||
chSchReadyI(fifo_remove(&oqp->q_waiting))->p_u.rdymsg = Q_OK;
|
chSchReadyI(fifo_remove(&oqp->q_waiting))->p_u.rdymsg = Q_OK;
|
||||||
chSysUnlockFromIsr();
|
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.
|
* @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) {
|
while (n) {
|
||||||
uint32_t dw = *fifop;
|
uint32_t dw = *fifop;
|
||||||
if (max) {
|
if (max) {
|
||||||
*buf++ = (uint8_t)dw;
|
/* Note, this line relies on the Cortex-M3/M4 ability to perform
|
||||||
*buf++ = (uint8_t)(dw >> 8);
|
unaligned word accesses and on the LSB-first memory organization.*/
|
||||||
*buf++ = (uint8_t)(dw >> 16);
|
*((uint32_t *)buf) = dw;
|
||||||
*buf++ = (uint8_t)(dw >> 24);
|
buf += 4;
|
||||||
max--;
|
max--;
|
||||||
}
|
}
|
||||||
n--;
|
n--;
|
||||||
|
@ -300,37 +399,40 @@ static void otg_fifo_read_to_buffer(uint8_t *buf, size_t n, size_t max) {
|
||||||
* @notapi
|
* @notapi
|
||||||
*/
|
*/
|
||||||
static void otg_fifo_read_to_queue(InputQueue *iqp, size_t n) {
|
static void otg_fifo_read_to_queue(InputQueue *iqp, size_t n) {
|
||||||
size_t nw, nb;
|
size_t ntogo;
|
||||||
volatile uint32_t *fifop;
|
volatile uint32_t *fifop;
|
||||||
|
|
||||||
fifop = OTG_FIFO(0);
|
fifop = OTG_FIFO(0);
|
||||||
nb = n;
|
|
||||||
nw = (n + 3) / 4;
|
ntogo = n;
|
||||||
do {
|
while (ntogo > 0) {
|
||||||
uint32_t dw = *fifop;
|
uint32_t dw, i;
|
||||||
*iqp->q_wrptr++ = (uint8_t)dw;
|
size_t streak, nw = ntogo / 4;
|
||||||
if (iqp->q_wrptr >= iqp->q_top)
|
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;
|
iqp->q_wrptr = iqp->q_buffer;
|
||||||
if (--nb > 0) {
|
continue;
|
||||||
*iqp->q_wrptr++ = (uint8_t)(dw >> 8);
|
}
|
||||||
|
|
||||||
|
/* 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)
|
if (iqp->q_wrptr >= iqp->q_top)
|
||||||
iqp->q_wrptr = iqp->q_buffer;
|
iqp->q_wrptr = iqp->q_buffer;
|
||||||
|
ntogo--;
|
||||||
if (--nb > 0) {
|
i++;
|
||||||
*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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} while (--nw > 0);
|
}
|
||||||
|
|
||||||
/* Updating queue.*/
|
/* Updating queue.*/
|
||||||
chSysLockFromIsr();
|
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,
|
void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep,
|
||||||
uint8_t *buf, size_t n) {
|
uint8_t *buf, size_t n) {
|
||||||
uint32_t pcnt;
|
|
||||||
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
|
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
|
||||||
|
|
||||||
osp->rxqueued = FALSE;
|
osp->rxqueued = FALSE;
|
||||||
osp->rxsize = n;
|
|
||||||
osp->rxcnt = 0;
|
|
||||||
osp->mode.linear.rxbuf = buf;
|
osp->mode.linear.rxbuf = buf;
|
||||||
|
otg_prepare_receive(usbp, ep, n);
|
||||||
/* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -872,30 +967,15 @@ void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep,
|
||||||
*/
|
*/
|
||||||
void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep,
|
void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep,
|
||||||
const uint8_t *buf, size_t n) {
|
const uint8_t *buf, size_t n) {
|
||||||
uint32_t pcnt;
|
|
||||||
USBInEndpointState *isp = usbp->epc[ep]->in_state;
|
USBInEndpointState *isp = usbp->epc[ep]->in_state;
|
||||||
|
|
||||||
isp->txqueued = FALSE;
|
isp->txqueued = FALSE;
|
||||||
isp->txsize = n;
|
|
||||||
isp->txcnt = 0;
|
|
||||||
isp->mode.linear.txbuf = buf;
|
isp->mode.linear.txbuf = buf;
|
||||||
|
otg_prepare_transmit(usbp, ep, n);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Prepares for a receive transaction on an OUT endpoint.
|
* @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().
|
* @post The endpoint is ready for @p usbStartReceiveI().
|
||||||
* @note The receive transaction size is equal to the space in the queue
|
* @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
|
* 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,
|
void usb_lld_prepare_queued_receive(USBDriver *usbp, usbep_t ep,
|
||||||
InputQueue *iq, size_t n) {
|
InputQueue *iq, size_t n) {
|
||||||
uint32_t pcnt;
|
|
||||||
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
|
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
|
||||||
|
|
||||||
osp->rxqueued = TRUE;
|
osp->rxqueued = TRUE;
|
||||||
osp->rxsize = n;
|
|
||||||
osp->rxcnt = 0;
|
|
||||||
osp->mode.queue.rxqueue = iq;
|
osp->mode.queue.rxqueue = iq;
|
||||||
|
otg_prepare_receive(usbp, ep, n);
|
||||||
/* 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 Prepares for a transmit transaction on an IN endpoint.
|
* @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().
|
* @post The endpoint is ready for @p usbStartTransmitI().
|
||||||
* @note The transmit transaction size is equal to the data contained
|
* @note The transmit transaction size is equal to the data contained
|
||||||
* in the queue.
|
* 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,
|
void usb_lld_prepare_queued_transmit(USBDriver *usbp, usbep_t ep,
|
||||||
OutputQueue *oq, size_t n) {
|
OutputQueue *oq, size_t n) {
|
||||||
uint32_t pcnt;
|
|
||||||
USBInEndpointState *isp = usbp->epc[ep]->in_state;
|
USBInEndpointState *isp = usbp->epc[ep]->in_state;
|
||||||
|
|
||||||
isp->txqueued = TRUE;
|
isp->txqueued = TRUE;
|
||||||
isp->txsize = n;
|
|
||||||
isp->txcnt = 0;
|
|
||||||
isp->mode.queue.txqueue = oq;
|
isp->mode.queue.txqueue = oq;
|
||||||
|
otg_prepare_transmit(usbp, ep, n);
|
||||||
/* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -126,7 +126,7 @@ typedef struct {
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
/**
|
/**
|
||||||
* @brief Pointer to the transmission buffer.
|
* @brief Pointer to the transmission linear buffer.
|
||||||
*/
|
*/
|
||||||
const uint8_t *txbuf;
|
const uint8_t *txbuf;
|
||||||
} linear;
|
} linear;
|
||||||
|
@ -158,7 +158,7 @@ typedef struct {
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
/**
|
/**
|
||||||
* @brief Pointer to the receive buffer.
|
* @brief Pointer to the receive linear buffer.
|
||||||
*/
|
*/
|
||||||
uint8_t *rxbuf;
|
uint8_t *rxbuf;
|
||||||
} linear;
|
} linear;
|
||||||
|
@ -217,16 +217,12 @@ typedef struct {
|
||||||
uint16_t out_maxsize;
|
uint16_t out_maxsize;
|
||||||
/**
|
/**
|
||||||
* @brief @p USBEndpointState associated to the IN endpoint.
|
* @brief @p USBEndpointState associated to the IN endpoint.
|
||||||
* @details This structure maintains the state of the IN endpoint when
|
* @details This structure maintains the state of the IN endpoint.
|
||||||
* the endpoint is not in packet mode. Endpoints configured in
|
|
||||||
* packet mode must set this field to @p NULL.
|
|
||||||
*/
|
*/
|
||||||
USBInEndpointState *in_state;
|
USBInEndpointState *in_state;
|
||||||
/**
|
/**
|
||||||
* @brief @p USBEndpointState associated to the OUT endpoint.
|
* @brief @p USBEndpointState associated to the OUT endpoint.
|
||||||
* @details This structure maintains the state of the OUT endpoint when
|
* @details This structure maintains the state of the OUT endpoint.
|
||||||
* the endpoint is not in packet mode. Endpoints configured in
|
|
||||||
* packet mode must set this field to @p NULL.
|
|
||||||
*/
|
*/
|
||||||
USBOutEndpointState *out_state;
|
USBOutEndpointState *out_state;
|
||||||
/* End of the mandatory fields.*/
|
/* End of the mandatory fields.*/
|
||||||
|
|
|
@ -120,6 +120,11 @@ static void inotify(GenericQueue *qp) {
|
||||||
size_t n, maxsize;
|
size_t n, maxsize;
|
||||||
SerialUSBDriver *sdup = chQGetLink(qp);
|
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
|
/* 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
|
a transaction is not yet started then a new transaction is started for
|
||||||
the available space.*/
|
the available space.*/
|
||||||
|
@ -145,6 +150,11 @@ static void onotify(GenericQueue *qp) {
|
||||||
size_t n;
|
size_t n;
|
||||||
SerialUSBDriver *sdup = chQGetLink(qp);
|
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
|
/* If there is not an ongoing transaction and the output queue contains
|
||||||
data then a new transaction is started.*/
|
data then a new transaction is started.*/
|
||||||
if (!usbGetTransmitStatusI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP) &&
|
if (!usbGetTransmitStatusI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP) &&
|
||||||
|
@ -238,6 +248,22 @@ void sduStop(SerialUSBDriver *sdup) {
|
||||||
usbStop(sdup->config->usbp);
|
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.
|
* @brief Default requests hook.
|
||||||
* @details Applications wanting to use the Serial over USB driver can use
|
* @details Applications wanting to use the Serial over USB driver can use
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
# Compiler options here.
|
# Compiler options here.
|
||||||
ifeq ($(USE_OPT),)
|
ifeq ($(USE_OPT),)
|
||||||
USE_OPT = -O0 -ggdb -fomit-frame-pointer -falign-functions=16
|
USE_OPT = -O2 -ggdb -fomit-frame-pointer -falign-functions=16
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# C specific options here (added to USE_OPT).
|
# 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:
|
case USB_EVENT_ADDRESS:
|
||||||
return;
|
return;
|
||||||
case USB_EVENT_CONFIGURED:
|
case USB_EVENT_CONFIGURED:
|
||||||
|
chSysLockFromIsr();
|
||||||
|
|
||||||
/* Enables the endpoints specified into the configuration.
|
/* Enables the endpoints specified into the configuration.
|
||||||
Note, this callback is invoked from an ISR so I-Class functions
|
Note, this callback is invoked from an ISR so I-Class functions
|
||||||
must be used.*/
|
must be used.*/
|
||||||
chSysLockFromIsr();
|
|
||||||
usbInitEndpointI(usbp, USB_CDC_DATA_REQUEST_EP, &ep1config);
|
usbInitEndpointI(usbp, USB_CDC_DATA_REQUEST_EP, &ep1config);
|
||||||
usbInitEndpointI(usbp, USB_CDC_INTERRUPT_REQUEST_EP, &ep2config);
|
usbInitEndpointI(usbp, USB_CDC_INTERRUPT_REQUEST_EP, &ep2config);
|
||||||
usbInitEndpointI(usbp, USB_CDC_DATA_AVAILABLE_EP, &ep3config);
|
usbInitEndpointI(usbp, USB_CDC_DATA_AVAILABLE_EP, &ep3config);
|
||||||
|
|
||||||
|
/* Resetting the state of the CDC subsystem.*/
|
||||||
|
sduConfigureHookI(usbp);
|
||||||
|
|
||||||
chSysUnlockFromIsr();
|
chSysUnlockFromIsr();
|
||||||
return;
|
return;
|
||||||
case USB_EVENT_SUSPEND:
|
case USB_EVENT_SUSPEND:
|
||||||
|
@ -437,10 +442,10 @@ int main(void) {
|
||||||
/*
|
/*
|
||||||
* Activates the USB driver and then the USB bus pull-up on D+.
|
* Activates the USB driver and then the USB bus pull-up on D+.
|
||||||
*/
|
*/
|
||||||
|
usbDisconnectBus(serusbcfg.usbp);
|
||||||
|
chThdSleepMilliseconds(1000);
|
||||||
sduObjectInit(&SDU1);
|
sduObjectInit(&SDU1);
|
||||||
sduStart(&SDU1, &serusbcfg);
|
sduStart(&SDU1, &serusbcfg);
|
||||||
usbDisconnectBus(serusbcfg.usbp);
|
|
||||||
chThdSleepMilliseconds(100);
|
|
||||||
usbConnectBus(serusbcfg.usbp);
|
usbConnectBus(serusbcfg.usbp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue