git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2719 35acf78f-673a-0410-8e92-d51de3d6d3f4

This commit is contained in:
gdisirio 2011-02-08 06:29:27 +00:00
parent 0847ae54f0
commit 9ab9d1b44b
4 changed files with 112 additions and 48 deletions

View File

@ -115,14 +115,10 @@ typedef struct {
InputQueue iqueue; \
/* Output queue.*/ \
OutputQueue oqueue; \
/* Input buffer 1.*/ \
uint8_t ib1[SERIAL_USB_BUFFERS_SIZE]; \
/* Input buffer 2.*/ \
uint8_t ib2[SERIAL_USB_BUFFERS_SIZE]; \
/* Output buffer 1.*/ \
uint8_t ob1[SERIAL_USB_BUFFERS_SIZE]; \
/* Output buffer 2.*/ \
uint8_t ob2[SERIAL_USB_BUFFERS_SIZE]; \
/* Input buffer.*/ \
uint8_t ib[SERIAL_USB_BUFFERS_SIZE]; \
/* Output buffer.*/ \
uint8_t ob[SERIAL_USB_BUFFERS_SIZE]; \
/* End of the mandatory fields.*/ \
/* Current configuration data.*/ \
const SerialUSBConfig *config;

View File

@ -58,11 +58,12 @@ static USBEndpointState ep0state;
* @brief EP0 initialization structure.
*/
static const USBEndpointConfig ep0config = {
EP_TYPE_CTRL,
_usb_ep0in,
_usb_ep0out,
0x40,
0x40,
EPR_EP_TYPE_CONTROL | EPR_STAT_TX_NAK | EPR_STAT_RX_VALID,
0,
0x40,
0x80
};
@ -178,50 +179,63 @@ CH_IRQ_HANDLER(USB_LP_IRQHandler) {
if (epr & EPR_CTR_TX) {
/* IN endpoint, transmission.*/
EPR_CLEAR_CTR_TX(ep);
n = USB_GET_DESCRIPTOR(ep)->TXCOUNT;
usbp->ep[ep]->txbuf += n;
usbp->ep[ep]->txcnt += n;
usbp->ep[ep]->txsize -= n;
if (usbp->ep[ep]->txsize > 0) {
/* Transfer not completed, there are more packets to send.*/
if (usbp->ep[ep]->txsize > epcp->in_maxsize)
n = epcp->in_maxsize;
else
n = usbp->ep[ep]->txsize;
write_packet(ep, usbp->ep[ep]->txbuf, n);
if (epcp->flags & USB_EP_FLAGS_IN_PACKET_MODE) {
/* Packet mode, just invokes the callback.*/
(usbp)->ep[ep]->transmitting = FALSE;
epcp->in_cb(usbp, ep);
}
else {
/* Transfer completed, invoking the callback, if defined.*/
(usbp)->ep[ep]->transmitting = FALSE;
if (epcp->in_cb)
/* Transaction mode.*/
n = USB_GET_DESCRIPTOR(ep)->TXCOUNT;
usbp->ep[ep]->txbuf += n;
usbp->ep[ep]->txcnt += n;
usbp->ep[ep]->txsize -= n;
if (usbp->ep[ep]->txsize > 0) {
/* Transfer not completed, there are more packets to send.*/
if (usbp->ep[ep]->txsize > epcp->in_maxsize)
n = epcp->in_maxsize;
else
n = usbp->ep[ep]->txsize;
write_packet(ep, usbp->ep[ep]->txbuf, n);
}
else {
/* Transfer completed, invokes the callback.*/
(usbp)->ep[ep]->transmitting = FALSE;
epcp->in_cb(usbp, ep);
}
}
}
if (epr & EPR_CTR_RX) {
EPR_CLEAR_CTR_RX(ep);
/* OUT endpoint, receive.*/
if ((epr & EPR_SETUP) && (ep == 0)) {
/* Special case, setup packet for EP0, enforcing a reset of the
EP0 state machine for robustness.*/
usbp->ep0state = USB_EP0_WAITING_SETUP;
read_packet(0, usbp->setup, 8);
if (epcp->flags & USB_EP_FLAGS_IN_PACKET_MODE) {
/* Packet mode, just invokes the callback.*/
(usbp)->ep[ep]->receiving = FALSE;
epcp->out_cb(usbp, ep);
}
else {
n = read_packet(ep, usbp->ep[ep]->rxbuf, usbp->ep[ep]->rxsize);
usbp->ep[ep]->rxbuf += n;
usbp->ep[ep]->rxcnt += n;
usbp->ep[ep]->rxsize -= n;
usbp->ep[ep]->rxpkts -= 1;
if (usbp->ep[ep]->rxpkts > 0) {
/* Transfer not completed, there are more packets to receive.*/
EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID);
if ((epr & EPR_SETUP) && (ep == 0)) {
/* Special case, setup packet for EP0, enforcing a reset of the
EP0 state machine for robustness.*/
usbp->ep0state = USB_EP0_WAITING_SETUP;
read_packet(0, usbp->setup, 8);
epcp->out_cb(usbp, ep);
}
else {
/* Transfer completed, invoking the callback, if defined.*/
(usbp)->ep[ep]->receiving = FALSE;
if (epcp->out_cb)
n = read_packet(ep, usbp->ep[ep]->rxbuf, usbp->ep[ep]->rxsize);
usbp->ep[ep]->rxbuf += n;
usbp->ep[ep]->rxcnt += n;
usbp->ep[ep]->rxsize -= n;
usbp->ep[ep]->rxpkts -= 1;
if (usbp->ep[ep]->rxpkts > 0) {
/* Transfer not completed, there are more packets to receive.*/
EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID);
}
else {
/* Transfer completed, invokes the callback.*/
(usbp)->ep[ep]->receiving = FALSE;
epcp->out_cb(usbp, ep);
}
}
}
}
@ -357,13 +371,43 @@ void usb_lld_set_address(USBDriver *usbp) {
* @notapi
*/
void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) {
uint16_t nblocks;
uint16_t nblocks, epr;
stm32_usb_descriptor_t *dp;
const USBEndpointConfig *epcp = usbp->ep[ep]->config;
/* Setting the endpoint type.*/
switch (epcp->ep_type) {
case EP_TYPE_ISOC:
epr = EPR_EP_TYPE_ISO;
break;
case EP_TYPE_BULK:
epr = EPR_EP_TYPE_BULK;
break;
case EP_TYPE_INTR:
epr = EPR_EP_TYPE_INTERRUPT;
break;
default:
epr = EPR_EP_TYPE_CONTROL;
}
/* IN endpoint settings, always in NAK mode initially.*/
if (epcp->in_cb)
epr |= EPR_STAT_TX_NAK;
/* OUT endpoint settings. If the endpoint is in packet mode then it must
start ready to accept data else it must start in NAK mode.*/
if (epcp->out_cb) {
if (epcp->flags & USB_EP_FLAGS_IN_PACKET_MODE) {
usbp->ep[ep]->receiving = TRUE;
epr |= EPR_STAT_RX_VALID;
}
else
epr |= EPR_STAT_RX_NAK;
}
/* EPxR register setup.*/
EPR_SET(ep, epcp->epr | ep);
EPR_TOGGLE(ep, epcp->epr);
EPR_SET(ep, epr | ep);
EPR_TOGGLE(ep, epr);
/* Endpoint size and address initialization.*/
if (epcp->out_maxsize > 62)

View File

@ -46,6 +46,16 @@
*/
#define USB_SET_ADDRESS_MODE USB_LATE_SET_ADDRESS
/**
* @brief Enables the packet mode for an IN endpoint.
*/
#define USB_EP_FLAGS_IN_PACKET_MODE 1
/**
* @brief Enables the packet mode for an OUT endpoint.
*/
#define USB_EP_FLAGS_OUT_PACKET_MODE 2
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
@ -98,28 +108,39 @@
* @note Platform specific restrictions may apply to endpoints.
*/
typedef struct {
/**
* @brief Type of the endpoint.
*/
usbeptype_t ep_type;
/**
* @brief IN endpoint notification callback.
* @details This field must be set to @p NULL if the IN endpoint is not
* used.
*/
usbepcallback_t in_cb;
/**
* @brief OUT endpoint notification callback.
* @details This field must be set to @p NULL if the OUT endpoint is not
* used.
*/
usbepcallback_t out_cb;
/**
* @brief IN endpoint maximum packet size.
* @details This field must be set to zero if the IN endpoint is not
* used.
*/
uint16_t in_maxsize;
/**
* @brief OUT endpoint maximum packet size.
* @details This field must be set to zero if the OUT endpoint is not
* used.
*/
uint16_t out_maxsize;
/* End of the mandatory fields.*/
/**
* @brief EPxR register initialization value.
* @note Do not specify the EA field, leave it to zero.
* @bief Endpoint mode flags.
*/
uint16_t epr;
uint16_t flags;
/**
* @brief Endpoint IN buffer address as offset in the PMA.
*/

View File

@ -251,11 +251,12 @@ USBEndpointState ep3state;
* @brief EP1 initialization structure (IN only).
*/
static const USBEndpointConfig ep1config = {
EP_TYPE_BULK,
sduDataTransmitted,
NULL,
0x0040,
0x0000,
EPR_EP_TYPE_BULK | EPR_STAT_TX_NAK | EPR_STAT_RX_DIS,
USB_EP_FLAGS_IN_PACKET_MODE,
0x00C0,
0x0000
};
@ -264,11 +265,12 @@ static const USBEndpointConfig ep1config = {
* @brief EP2 initialization structure (IN only).
*/
static const USBEndpointConfig ep2config = {
EP_TYPE_INTR,
sduInterruptTransmitted,
NULL,
0x0010,
0x0000,
EPR_EP_TYPE_INTERRUPT | EPR_STAT_TX_NAK | EPR_STAT_RX_DIS,
0,
0x0100,
0x0000
};
@ -277,11 +279,12 @@ static const USBEndpointConfig ep2config = {
* @brief EP3 initialization structure (OUT only).
*/
static const USBEndpointConfig ep3config = {
EP_TYPE_BULK,
NULL,
sduDataReceived,
0x0000,
0x0040,
EPR_EP_TYPE_BULK | EPR_STAT_TX_DIS | EPR_STAT_RX_VALID,
USB_EP_FLAGS_OUT_PACKET_MODE,
0x0000,
0x0110
};