Improvements to the USB driver, first phase.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3449 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
78325ebdf2
commit
309b1e4114
|
@ -129,23 +129,7 @@ static void cmd_mem(BaseChannel *chp, int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cmd_threads(BaseChannel *chp, int argc, char *argv[]) {
|
static void cmd_threads(BaseChannel *chp, int argc, char *argv[]) {
|
||||||
static const char *states[] = {
|
static const char *states[] = {THD_STATE_NAMES};
|
||||||
"READY",
|
|
||||||
"CURRENT",
|
|
||||||
"SUSPENDED",
|
|
||||||
"WTSEM",
|
|
||||||
"WTMTX",
|
|
||||||
"WTCOND",
|
|
||||||
"SLEEPING",
|
|
||||||
"WTEXIT",
|
|
||||||
"WTOREVT",
|
|
||||||
"WTANDEVT",
|
|
||||||
"SNDMSGQ",
|
|
||||||
"SNDMSG",
|
|
||||||
"WTMSG",
|
|
||||||
"WTQUEUE",
|
|
||||||
"FINAL"
|
|
||||||
};
|
|
||||||
Thread *tp;
|
Thread *tp;
|
||||||
|
|
||||||
(void)argv;
|
(void)argv;
|
||||||
|
|
|
@ -129,23 +129,7 @@ static void cmd_mem(BaseChannel *chp, int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cmd_threads(BaseChannel *chp, int argc, char *argv[]) {
|
static void cmd_threads(BaseChannel *chp, int argc, char *argv[]) {
|
||||||
static const char *states[] = {
|
static const char *states[] = {THD_STATE_NAMES};
|
||||||
"READY",
|
|
||||||
"CURRENT",
|
|
||||||
"SUSPENDED",
|
|
||||||
"WTSEM",
|
|
||||||
"WTMTX",
|
|
||||||
"WTCOND",
|
|
||||||
"SLEEPING",
|
|
||||||
"WTEXIT",
|
|
||||||
"WTOREVT",
|
|
||||||
"WTANDEVT",
|
|
||||||
"SNDMSGQ",
|
|
||||||
"SNDMSG",
|
|
||||||
"WTMSG",
|
|
||||||
"WTQUEUE",
|
|
||||||
"FINAL"
|
|
||||||
};
|
|
||||||
Thread *tp;
|
Thread *tp;
|
||||||
|
|
||||||
(void)argv;
|
(void)argv;
|
||||||
|
|
|
@ -117,23 +117,7 @@ static void cmd_mem(BaseChannel *chp, int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cmd_threads(BaseChannel *chp, int argc, char *argv[]) {
|
static void cmd_threads(BaseChannel *chp, int argc, char *argv[]) {
|
||||||
static const char *states[] = {
|
static const char *states[] = {THD_STATE_NAMES};
|
||||||
"READY",
|
|
||||||
"CURRENT",
|
|
||||||
"SUSPENDED",
|
|
||||||
"WTSEM",
|
|
||||||
"WTMTX",
|
|
||||||
"WTCOND",
|
|
||||||
"SLEEPING",
|
|
||||||
"WTEXIT",
|
|
||||||
"WTOREVT",
|
|
||||||
"WTANDEVT",
|
|
||||||
"SNDMSGQ",
|
|
||||||
"SNDMSG",
|
|
||||||
"WTMSG",
|
|
||||||
"WTQUEUE",
|
|
||||||
"FINAL"
|
|
||||||
};
|
|
||||||
Thread *tp;
|
Thread *tp;
|
||||||
|
|
||||||
(void)argv;
|
(void)argv;
|
||||||
|
|
|
@ -194,23 +194,7 @@ static void cmd_mem(BaseChannel *chp, int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cmd_threads(BaseChannel *chp, int argc, char *argv[]) {
|
static void cmd_threads(BaseChannel *chp, int argc, char *argv[]) {
|
||||||
static const char *states[] = {
|
static const char *states[] = {THD_STATE_NAMES};
|
||||||
"READY",
|
|
||||||
"CURRENT",
|
|
||||||
"SUSPENDED",
|
|
||||||
"WTSEM",
|
|
||||||
"WTMTX",
|
|
||||||
"WTCOND",
|
|
||||||
"SLEEPING",
|
|
||||||
"WTEXIT",
|
|
||||||
"WTOREVT",
|
|
||||||
"WTANDEVT",
|
|
||||||
"SNDMSGQ",
|
|
||||||
"SNDMSG",
|
|
||||||
"WTMSG",
|
|
||||||
"WTQUEUE",
|
|
||||||
"FINAL"
|
|
||||||
};
|
|
||||||
Thread *tp;
|
Thread *tp;
|
||||||
|
|
||||||
(void)argv;
|
(void)argv;
|
||||||
|
|
|
@ -44,23 +44,7 @@ static void cmd_mem(BaseChannel *chp, int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cmd_threads(BaseChannel *chp, int argc, char *argv[]) {
|
static void cmd_threads(BaseChannel *chp, int argc, char *argv[]) {
|
||||||
static const char *states[] = {
|
static const char *states[] = {THD_STATE_NAMES};
|
||||||
"READY",
|
|
||||||
"CURRENT",
|
|
||||||
"SUSPENDED",
|
|
||||||
"WTSEM",
|
|
||||||
"WTMTX",
|
|
||||||
"WTCOND",
|
|
||||||
"SLEEPING",
|
|
||||||
"WTEXIT",
|
|
||||||
"WTOREVT",
|
|
||||||
"WTANDEVT",
|
|
||||||
"SNDMSGQ",
|
|
||||||
"SNDMSG",
|
|
||||||
"WTMSG",
|
|
||||||
"WTQUEUE",
|
|
||||||
"FINAL"
|
|
||||||
};
|
|
||||||
Thread *tp;
|
Thread *tp;
|
||||||
|
|
||||||
(void)argv;
|
(void)argv;
|
||||||
|
|
|
@ -51,23 +51,7 @@ static void cmd_mem(BaseChannel *chp, int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cmd_threads(BaseChannel *chp, int argc, char *argv[]) {
|
static void cmd_threads(BaseChannel *chp, int argc, char *argv[]) {
|
||||||
static const char *states[] = {
|
static const char *states[] = {THD_STATE_NAMES};
|
||||||
"READY",
|
|
||||||
"CURRENT",
|
|
||||||
"SUSPENDED",
|
|
||||||
"WTSEM",
|
|
||||||
"WTMTX",
|
|
||||||
"WTCOND",
|
|
||||||
"SLEEPING",
|
|
||||||
"WTEXIT",
|
|
||||||
"WTOREVT",
|
|
||||||
"WTANDEVT",
|
|
||||||
"SNDMSGQ",
|
|
||||||
"SNDMSG",
|
|
||||||
"WTMSG",
|
|
||||||
"WTQUEUE",
|
|
||||||
"FINAL"
|
|
||||||
};
|
|
||||||
Thread *tp;
|
Thread *tp;
|
||||||
|
|
||||||
(void)argv;
|
(void)argv;
|
||||||
|
|
|
@ -49,23 +49,7 @@ static void cmd_mem(BaseChannel *chp, int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cmd_threads(BaseChannel *chp, int argc, char *argv[]) {
|
static void cmd_threads(BaseChannel *chp, int argc, char *argv[]) {
|
||||||
static const char *states[] = {
|
static const char *states[] = {THD_STATE_NAMES};
|
||||||
"READY",
|
|
||||||
"CURRENT",
|
|
||||||
"SUSPENDED",
|
|
||||||
"WTSEM",
|
|
||||||
"WTMTX",
|
|
||||||
"WTCOND",
|
|
||||||
"SLEEPING",
|
|
||||||
"WTEXIT",
|
|
||||||
"WTOREVT",
|
|
||||||
"WTANDEVT",
|
|
||||||
"SNDMSGQ",
|
|
||||||
"SNDMSG",
|
|
||||||
"WTMSG",
|
|
||||||
"WTQUEUE",
|
|
||||||
"FINAL"
|
|
||||||
};
|
|
||||||
Thread *tp;
|
Thread *tp;
|
||||||
|
|
||||||
(void)argv;
|
(void)argv;
|
||||||
|
|
|
@ -172,11 +172,6 @@
|
||||||
USB_DESC_BYTE(bInterval)
|
USB_DESC_BYTE(bInterval)
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returned by some functions to report a busy endpoint.
|
|
||||||
*/
|
|
||||||
#define USB_ENDPOINT_BUSY ((size_t)0xFFFFFFFF)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name Endpoint types and settings
|
* @name Endpoint types and settings
|
||||||
* @{
|
* @{
|
||||||
|
@ -362,6 +357,75 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp,
|
||||||
*/
|
*/
|
||||||
#define usbGetReceiveStatusI(usbp, ep) ((usbp)->receiving & (1 << (ep)))
|
#define usbGetReceiveStatusI(usbp, ep) ((usbp)->receiving & (1 << (ep)))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads from a dedicated packet buffer.
|
||||||
|
* @pre In order to use this function he endpoint must have been
|
||||||
|
* initialized in packet mode.
|
||||||
|
* @note This function can be invoked both in thread and IRQ context.
|
||||||
|
*
|
||||||
|
* @param[in] usbp pointer to the @p USBDriver object
|
||||||
|
* @param[in] ep endpoint number
|
||||||
|
* @param[out] buf buffer where to copy the packet data
|
||||||
|
* @param[in] n maximum number of bytes to copy. This value must
|
||||||
|
* not exceed the maximum packet size for this endpoint.
|
||||||
|
* @return The received packet size regardless the specified
|
||||||
|
* @p n parameter.
|
||||||
|
* @retval 0 Zero size packet received.
|
||||||
|
*
|
||||||
|
* @special
|
||||||
|
*/
|
||||||
|
#define usbReadPacketBuffer(usbp, ep, buf, n) \
|
||||||
|
usb_lld_read_packet_buffer(usbp, ep, buf, n)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Writes to a dedicated packet buffer.
|
||||||
|
* @pre In order to use this function he endpoint must have been
|
||||||
|
* initialized in packet mode.
|
||||||
|
* @note This function can be invoked both in thread and IRQ context.
|
||||||
|
*
|
||||||
|
* @param[in] usbp pointer to the @p USBDriver object
|
||||||
|
* @param[in] ep endpoint number
|
||||||
|
* @param[in] buf buffer where to fetch the packet data
|
||||||
|
* @param[in] n maximum number of bytes to copy. This value must
|
||||||
|
* not exceed the maximum packet size for this endpoint.
|
||||||
|
*
|
||||||
|
* @special
|
||||||
|
*/
|
||||||
|
#define usbWritePacketBuffer(usbp, ep, buf, n) \
|
||||||
|
usb_lld_write_packet_buffer(usbp, ep, buf, n)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Prepares for a receive transaction on an OUT endpoint.
|
||||||
|
* @pre In order to use this function he endpoint must have been
|
||||||
|
* initialized in transaction mode.
|
||||||
|
* @post The endpoint is ready for @p usbStartReceiveI().
|
||||||
|
*
|
||||||
|
* @param[in] usbp pointer to the @p USBDriver object
|
||||||
|
* @param[in] ep endpoint number
|
||||||
|
* @param[out] buf buffer where to copy the received data
|
||||||
|
* @param[in] n maximum number of bytes to copy
|
||||||
|
*
|
||||||
|
* @special
|
||||||
|
*/
|
||||||
|
#define usbPrepareReceive(usbp, ep, buf, n) \
|
||||||
|
usb_lld_prepare_receive(usbp, ep, buf, n)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Prepares for a transmit transaction on an IN endpoint.
|
||||||
|
* @pre In order to use this function he endpoint must have been
|
||||||
|
* initialized in transaction mode.
|
||||||
|
* @post The endpoint is ready for @p usbStartTransmitI().
|
||||||
|
*
|
||||||
|
* @param[in] usbp pointer to the @p USBDriver object
|
||||||
|
* @param[in] ep endpoint number
|
||||||
|
* @param[in] buf buffer where to fetch the data to be transmitted
|
||||||
|
* @param[in] n maximum number of bytes to copy
|
||||||
|
*
|
||||||
|
* @special
|
||||||
|
*/
|
||||||
|
#define usbPrepareTransmit(usbp, ep, buf, n) \
|
||||||
|
usb_lld_prepare_transmit(usbp, ep, buf, n)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the exact size of a receive transaction.
|
* @brief Returns the exact size of a receive transaction.
|
||||||
* @details The received size can be different from the size specified in
|
* @details The received size can be different from the size specified in
|
||||||
|
@ -417,7 +481,7 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp,
|
||||||
* callback in order to read the received setup packet.
|
* callback in order to read the received setup packet.
|
||||||
* @pre In order to use this function the endpoint must have been
|
* @pre In order to use this function the endpoint must have been
|
||||||
* initialized as a control endpoint.
|
* initialized as a control endpoint.
|
||||||
* @post The endpoint is ready to accept another packet.
|
* @note This function can be invoked both in thread and IRQ context.
|
||||||
*
|
*
|
||||||
* @param[in] usbp pointer to the @p USBDriver object
|
* @param[in] usbp pointer to the @p USBDriver object
|
||||||
* @param[in] ep endpoint number
|
* @param[in] ep endpoint number
|
||||||
|
@ -511,14 +575,8 @@ extern "C" {
|
||||||
const USBEndpointConfig *epcp);
|
const USBEndpointConfig *epcp);
|
||||||
void usbDisableEndpointsI(USBDriver *usbp);
|
void usbDisableEndpointsI(USBDriver *usbp);
|
||||||
void usbReadSetupI(USBDriver *usbp, usbep_t ep, uint8_t *buf);
|
void usbReadSetupI(USBDriver *usbp, usbep_t ep, uint8_t *buf);
|
||||||
size_t usbReadPacketI(USBDriver *usbp, usbep_t ep,
|
bool_t usbStartReceiveI(USBDriver *usbp, usbep_t ep);
|
||||||
uint8_t *buf, size_t n);
|
bool_t usbStartTransmitI(USBDriver *usbp, usbep_t ep);
|
||||||
size_t usbWritePacketI(USBDriver *usbp, usbep_t ep,
|
|
||||||
const uint8_t *buf, size_t n);
|
|
||||||
bool_t usbStartReceiveI(USBDriver *usbp, usbep_t ep,
|
|
||||||
uint8_t *buf, size_t n);
|
|
||||||
bool_t usbStartTransmitI(USBDriver *usbp, usbep_t ep,
|
|
||||||
const uint8_t *buf, size_t n);
|
|
||||||
bool_t usbStallReceiveI(USBDriver *usbp, usbep_t ep);
|
bool_t usbStallReceiveI(USBDriver *usbp, usbep_t ep);
|
||||||
bool_t usbStallTransmitI(USBDriver *usbp, usbep_t ep);
|
bool_t usbStallTransmitI(USBDriver *usbp, usbep_t ep);
|
||||||
void _usb_reset(USBDriver *usbp);
|
void _usb_reset(USBDriver *usbp);
|
||||||
|
|
|
@ -109,58 +109,6 @@ static uint32_t pm_alloc(USBDriver *usbp, size_t size) {
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Copies a packet from memory into a packet buffer.
|
|
||||||
*
|
|
||||||
* @param[in] ep endpoint number
|
|
||||||
* @param[in] buf buffer where to fetch the endpoint data
|
|
||||||
* @param[in] n maximum number of bytes to copy
|
|
||||||
*/
|
|
||||||
static void write_packet(usbep_t ep, const uint8_t *buf, size_t n){
|
|
||||||
uint32_t *pmap;
|
|
||||||
stm32_usb_descriptor_t *udp;
|
|
||||||
size_t count;
|
|
||||||
|
|
||||||
udp = USB_GET_DESCRIPTOR(ep);
|
|
||||||
pmap = USB_ADDR2PTR(udp->TXADDR);
|
|
||||||
udp->TXCOUNT = n;
|
|
||||||
count = (n + 1) / 2;
|
|
||||||
while (count) {
|
|
||||||
*pmap++ = *(uint16_t *)buf;
|
|
||||||
buf += 2;
|
|
||||||
count--;
|
|
||||||
}
|
|
||||||
EPR_SET_STAT_TX(ep, EPR_STAT_TX_VALID);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Copies a packet from a packet buffer into memory.
|
|
||||||
*
|
|
||||||
* @param[in] ep endpoint number
|
|
||||||
* @param[in] buf buffer where to copy the endpoint data
|
|
||||||
* @param[in] n maximum number of bytes to copy
|
|
||||||
* @return The packet size.
|
|
||||||
* @retval 0 Special case, zero sized packet.
|
|
||||||
*/
|
|
||||||
static size_t read_packet(usbep_t ep, uint8_t *buf, size_t n){
|
|
||||||
uint32_t *pmap;
|
|
||||||
stm32_usb_descriptor_t *udp;
|
|
||||||
size_t count;
|
|
||||||
|
|
||||||
udp = USB_GET_DESCRIPTOR(ep);
|
|
||||||
pmap = USB_ADDR2PTR(udp->RXADDR);
|
|
||||||
count = udp->RXCOUNT & RXCOUNT_COUNT_MASK;
|
|
||||||
if (n > count)
|
|
||||||
n = count;
|
|
||||||
count = (n + 1) / 2;
|
|
||||||
while (count) {
|
|
||||||
*(uint16_t *)buf = (uint16_t)*pmap++;
|
|
||||||
buf += 2;
|
|
||||||
count--;
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* Driver interrupt handlers. */
|
/* Driver interrupt handlers. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -257,7 +205,8 @@ CH_IRQ_HANDLER(Vector90) {
|
||||||
n = epcp->in_maxsize;
|
n = epcp->in_maxsize;
|
||||||
else
|
else
|
||||||
n = epcp->in_state->txsize;
|
n = epcp->in_state->txsize;
|
||||||
write_packet(ep, epcp->in_state->txbuf, n);
|
usb_lld_write_packet_buffer(usbp, ep, epcp->in_state->txbuf, n);
|
||||||
|
usb_lld_start_in(usbp, ep);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* Transfer completed, invokes the callback.*/
|
/* Transfer completed, invokes the callback.*/
|
||||||
|
@ -279,7 +228,10 @@ CH_IRQ_HANDLER(Vector90) {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* Transaction mode.*/
|
/* Transaction mode.*/
|
||||||
n = read_packet(ep, epcp->out_state->rxbuf, epcp->out_state->rxsize);
|
n = usb_lld_read_packet_buffer(usbp, ep,
|
||||||
|
epcp->out_state->rxbuf,
|
||||||
|
epcp->out_state->rxsize);
|
||||||
|
usb_lld_start_out(usbp, ep);
|
||||||
epcp->out_state->rxbuf += n;
|
epcp->out_state->rxbuf += n;
|
||||||
epcp->out_state->rxcnt += n;
|
epcp->out_state->rxcnt += n;
|
||||||
epcp->out_state->rxsize -= n;
|
epcp->out_state->rxsize -= n;
|
||||||
|
@ -569,14 +521,13 @@ void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) {
|
||||||
*(uint16_t *)buf = (uint16_t)*pmap++;
|
*(uint16_t *)buf = (uint16_t)*pmap++;
|
||||||
buf += 2;
|
buf += 2;
|
||||||
}
|
}
|
||||||
EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Reads a packet from the dedicated packet buffer.
|
* @brief Reads from a dedicated packet buffer.
|
||||||
* @pre In order to use this function he endpoint must have been
|
* @pre In order to use this function he endpoint must have been
|
||||||
* initialized in packet mode.
|
* initialized in packet mode.
|
||||||
* @post The endpoint is ready to accept another packet.
|
* @note This function can be invoked both in thread and IRQ context.
|
||||||
*
|
*
|
||||||
* @param[in] usbp pointer to the @p USBDriver object
|
* @param[in] usbp pointer to the @p USBDriver object
|
||||||
* @param[in] ep endpoint number
|
* @param[in] ep endpoint number
|
||||||
|
@ -589,7 +540,7 @@ void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) {
|
||||||
*
|
*
|
||||||
* @notapi
|
* @notapi
|
||||||
*/
|
*/
|
||||||
size_t usb_lld_read_packet(USBDriver *usbp, usbep_t ep,
|
size_t usb_lld_read_packet_buffer(USBDriver *usbp, usbep_t ep,
|
||||||
uint8_t *buf, size_t n) {
|
uint8_t *buf, size_t n) {
|
||||||
uint32_t *pmap;
|
uint32_t *pmap;
|
||||||
stm32_usb_descriptor_t *udp;
|
stm32_usb_descriptor_t *udp;
|
||||||
|
@ -607,15 +558,14 @@ size_t usb_lld_read_packet(USBDriver *usbp, usbep_t ep,
|
||||||
buf += 2;
|
buf += 2;
|
||||||
n--;
|
n--;
|
||||||
}
|
}
|
||||||
EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID);
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Writes a packet to the dedicated packet buffer.
|
* @brief Writes to a dedicated packet buffer.
|
||||||
* @pre In order to use this function he endpoint must have been
|
* @pre In order to use this function he endpoint must have been
|
||||||
* initialized in packet mode.
|
* initialized in packet mode.
|
||||||
* @post The endpoint is ready to transmit the packet.
|
* @note This function can be invoked both in thread and IRQ context.
|
||||||
*
|
*
|
||||||
* @param[in] usbp pointer to the @p USBDriver object
|
* @param[in] usbp pointer to the @p USBDriver object
|
||||||
* @param[in] ep endpoint number
|
* @param[in] ep endpoint number
|
||||||
|
@ -625,7 +575,7 @@ size_t usb_lld_read_packet(USBDriver *usbp, usbep_t ep,
|
||||||
*
|
*
|
||||||
* @notapi
|
* @notapi
|
||||||
*/
|
*/
|
||||||
void usb_lld_write_packet(USBDriver *usbp, usbep_t ep,
|
void usb_lld_write_packet_buffer(USBDriver *usbp, usbep_t ep,
|
||||||
const uint8_t *buf, size_t n) {
|
const uint8_t *buf, size_t n) {
|
||||||
uint32_t *pmap;
|
uint32_t *pmap;
|
||||||
stm32_usb_descriptor_t *udp;
|
stm32_usb_descriptor_t *udp;
|
||||||
|
@ -640,20 +590,19 @@ void usb_lld_write_packet(USBDriver *usbp, usbep_t ep,
|
||||||
buf += 2;
|
buf += 2;
|
||||||
n--;
|
n--;
|
||||||
}
|
}
|
||||||
EPR_SET_STAT_TX(ep, EPR_STAT_TX_VALID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Starts a receive operation on an OUT endpoint.
|
* @brief Prepares for a receive operation.
|
||||||
*
|
*
|
||||||
* @param[in] usbp pointer to the @p USBDriver object
|
* @param[in] usbp pointer to the @p USBDriver object
|
||||||
* @param[in] ep endpoint number
|
* @param[in] ep endpoint number
|
||||||
* @param[out] buf buffer where to copy the endpoint data
|
* @param[out] buf buffer where to copy the received data
|
||||||
* @param[in] n maximum number of bytes to copy in the buffer
|
* @param[in] n maximum number of bytes to copy
|
||||||
*
|
*
|
||||||
* @notapi
|
* @notapi
|
||||||
*/
|
*/
|
||||||
void usb_lld_start_out(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) {
|
||||||
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
|
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
|
||||||
|
|
||||||
|
@ -665,6 +614,42 @@ void usb_lld_start_out(USBDriver *usbp, usbep_t ep,
|
||||||
else
|
else
|
||||||
osp->rxpkts = (uint16_t)((n + usbp->epc[ep]->out_maxsize - 1) /
|
osp->rxpkts = (uint16_t)((n + usbp->epc[ep]->out_maxsize - 1) /
|
||||||
usbp->epc[ep]->out_maxsize);
|
usbp->epc[ep]->out_maxsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Prepares for a transmit operation.
|
||||||
|
*
|
||||||
|
* @param[in] usbp pointer to the @p USBDriver object
|
||||||
|
* @param[in] ep endpoint number
|
||||||
|
* @param[in] buf buffer where to fetch the data to be transmitted
|
||||||
|
* @param[in] n maximum number of bytes to copy
|
||||||
|
*
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep,
|
||||||
|
const uint8_t *buf, size_t n) {
|
||||||
|
USBInEndpointState *isp = usbp->epc[ep]->in_state;
|
||||||
|
|
||||||
|
isp->txbuf = buf;
|
||||||
|
isp->txsize = n;
|
||||||
|
isp->txcnt = 0;
|
||||||
|
if (n > (size_t)usbp->epc[ep]->in_maxsize)
|
||||||
|
n = (size_t)usbp->epc[ep]->in_maxsize;
|
||||||
|
usb_lld_write_packet_buffer(usbp, ep, buf, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Starts a receive operation on an OUT endpoint.
|
||||||
|
*
|
||||||
|
* @param[in] usbp pointer to the @p USBDriver object
|
||||||
|
* @param[in] ep endpoint number
|
||||||
|
*
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
void usb_lld_start_out(USBDriver *usbp, usbep_t ep) {
|
||||||
|
|
||||||
|
(void)usbp;
|
||||||
|
|
||||||
EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID);
|
EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -678,16 +663,11 @@ void usb_lld_start_out(USBDriver *usbp, usbep_t ep,
|
||||||
*
|
*
|
||||||
* @notapi
|
* @notapi
|
||||||
*/
|
*/
|
||||||
void usb_lld_start_in(USBDriver *usbp, usbep_t ep,
|
void usb_lld_start_in(USBDriver *usbp, usbep_t ep) {
|
||||||
const uint8_t *buf, size_t n) {
|
|
||||||
USBInEndpointState *isp = usbp->epc[ep]->in_state;
|
|
||||||
|
|
||||||
isp->txbuf = buf;
|
(void)usbp;
|
||||||
isp->txsize = n;
|
|
||||||
isp->txcnt = 0;
|
EPR_SET_STAT_TX(ep, EPR_STAT_TX_VALID);
|
||||||
if (n > (size_t)usbp->epc[ep]->in_maxsize)
|
|
||||||
n = (size_t)usbp->epc[ep]->in_maxsize;
|
|
||||||
write_packet(ep, buf, n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -701,6 +681,7 @@ void usb_lld_start_in(USBDriver *usbp, usbep_t ep,
|
||||||
void usb_lld_stall_out(USBDriver *usbp, usbep_t ep) {
|
void usb_lld_stall_out(USBDriver *usbp, usbep_t ep) {
|
||||||
|
|
||||||
(void)usbp;
|
(void)usbp;
|
||||||
|
|
||||||
EPR_SET_STAT_RX(ep, EPR_STAT_RX_STALL);
|
EPR_SET_STAT_RX(ep, EPR_STAT_RX_STALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -375,16 +375,18 @@ extern "C" {
|
||||||
usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep);
|
usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep);
|
||||||
usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep);
|
usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep);
|
||||||
void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf);
|
void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf);
|
||||||
size_t usb_lld_read_packet(USBDriver *usbp, usbep_t ep,
|
size_t usb_lld_read_packet_buffer(USBDriver *usbp, usbep_t ep,
|
||||||
uint8_t *buf, size_t n);
|
uint8_t *buf, size_t n);
|
||||||
void usb_lld_write_packet(USBDriver *usbp, usbep_t ep,
|
void usb_lld_write_packet_buffer(USBDriver *usbp, usbep_t ep,
|
||||||
const uint8_t *buf, size_t n);
|
const uint8_t *buf, size_t n);
|
||||||
void usb_lld_start_out(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);
|
||||||
void usb_lld_start_in(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);
|
||||||
void usb_lld_stall_in(USBDriver *usbp, usbep_t ep);
|
void usb_lld_start_out(USBDriver *usbp, usbep_t ep);
|
||||||
|
void usb_lld_start_in(USBDriver *usbp, usbep_t ep);
|
||||||
void usb_lld_stall_out(USBDriver *usbp, usbep_t ep);
|
void usb_lld_stall_out(USBDriver *usbp, usbep_t ep);
|
||||||
|
void usb_lld_stall_in(USBDriver *usbp, usbep_t ep);
|
||||||
void usb_lld_clear_out(USBDriver *usbp, usbep_t ep);
|
void usb_lld_clear_out(USBDriver *usbp, usbep_t ep);
|
||||||
void usb_lld_clear_in(USBDriver *usbp, usbep_t ep);
|
void usb_lld_clear_in(USBDriver *usbp, usbep_t ep);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -118,15 +118,21 @@ static const struct SerialUSBDriverVMT vmt = {
|
||||||
*/
|
*/
|
||||||
static void inotify(GenericQueue *qp) {
|
static void inotify(GenericQueue *qp) {
|
||||||
SerialUSBDriver *sdup = (SerialUSBDriver *)qp->q_wrptr;
|
SerialUSBDriver *sdup = (SerialUSBDriver *)qp->q_wrptr;
|
||||||
size_t n;
|
|
||||||
|
|
||||||
/* Writes to the input queue can only happen when the queue has been
|
/* Writes to the input queue can only happen when the queue has been
|
||||||
emptied, then a whole packet is loaded in the queue.*/
|
emptied, then a whole packet is loaded in the queue.*/
|
||||||
if (chIQIsEmptyI(&sdup->iqueue)) {
|
if (!usbGetReceiveStatusI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP) &&
|
||||||
|
chIQIsEmptyI(&sdup->iqueue)) {
|
||||||
|
chSysUnlock();
|
||||||
|
|
||||||
n = usbReadPacketI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP,
|
/* Unlocked to make the potentially long read operation preemptable.*/
|
||||||
sdup->iqueue.q_buffer, SERIAL_USB_BUFFERS_SIZE);
|
size_t n = usbReadPacketBuffer(sdup->config->usbp,
|
||||||
if (n != USB_ENDPOINT_BUSY) {
|
USB_CDC_DATA_AVAILABLE_EP,
|
||||||
|
sdup->iqueue.q_buffer,
|
||||||
|
SERIAL_USB_BUFFERS_SIZE);
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
usbStartReceiveI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP);
|
||||||
chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE);
|
chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE);
|
||||||
sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer;
|
sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer;
|
||||||
sdup->iqueue.q_counter = n;
|
sdup->iqueue.q_counter = n;
|
||||||
|
@ -134,21 +140,26 @@ static void inotify(GenericQueue *qp) {
|
||||||
chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK;
|
chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Notification of data inserted into the output queue.
|
* @brief Notification of data inserted into the output queue.
|
||||||
*/
|
*/
|
||||||
static void onotify(GenericQueue *qp) {
|
static void onotify(GenericQueue *qp) {
|
||||||
SerialUSBDriver *sdup = (SerialUSBDriver *)qp->q_rdptr;
|
SerialUSBDriver *sdup = (SerialUSBDriver *)qp->q_rdptr;
|
||||||
size_t w, n;
|
size_t n;
|
||||||
|
|
||||||
/* If there is any data in the output queue then it is sent within a
|
/* If there is any data in the output queue then it is sent within a
|
||||||
single packet and the queue is emptied.*/
|
single packet and the queue is emptied.*/
|
||||||
n = chOQGetFullI(&sdup->oqueue);
|
n = chOQGetFullI(&sdup->oqueue);
|
||||||
w = usbWritePacketI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP,
|
if (!usbGetTransmitStatusI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP)) {
|
||||||
|
chSysUnlock();
|
||||||
|
|
||||||
|
/* Unlocked to make the potentially long write operation preemptable.*/
|
||||||
|
usbWritePacketBuffer(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP,
|
||||||
sdup->oqueue.q_buffer, n);
|
sdup->oqueue.q_buffer, n);
|
||||||
if (w != USB_ENDPOINT_BUSY) {
|
|
||||||
|
chSysLock();
|
||||||
|
usbStartTransmitI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP);
|
||||||
chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY);
|
chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY);
|
||||||
sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer;
|
sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer;
|
||||||
sdup->oqueue.q_counter = chQSizeI(&sdup->oqueue);
|
sdup->oqueue.q_counter = chQSizeI(&sdup->oqueue);
|
||||||
|
@ -285,22 +296,28 @@ bool_t sduRequestsHook(USBDriver *usbp) {
|
||||||
*/
|
*/
|
||||||
void sduDataTransmitted(USBDriver *usbp, usbep_t ep) {
|
void sduDataTransmitted(USBDriver *usbp, usbep_t ep) {
|
||||||
SerialUSBDriver *sdup = usbp->param;
|
SerialUSBDriver *sdup = usbp->param;
|
||||||
size_t n, w;
|
size_t n;
|
||||||
|
|
||||||
chSysLockFromIsr();
|
chSysLockFromIsr();
|
||||||
/* If there is any data in the output queue then it is sent within a
|
/* If there is any data in the output queue then it is sent within a
|
||||||
single packet and the queue is emptied.*/
|
single packet and the queue is emptied.*/
|
||||||
n = chOQGetFullI(&sdup->oqueue);
|
n = chOQGetFullI(&sdup->oqueue);
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
w = usbWritePacketI(usbp, ep, sdup->oqueue.q_buffer, n);
|
/* The endpoint cannot be busy, we are in the context of the callback,
|
||||||
if (w != USB_ENDPOINT_BUSY) {
|
so it is safe to transmit without a check.*/
|
||||||
|
chSysUnlockFromIsr();
|
||||||
|
|
||||||
|
/* Unlocked to make the potentially long write operation preemptable.*/
|
||||||
|
usbWritePacketBuffer(usbp, ep, sdup->oqueue.q_buffer, n);
|
||||||
|
|
||||||
|
chSysLockFromIsr();
|
||||||
|
usbStartTransmitI(usbp, ep);
|
||||||
chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY);
|
chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY);
|
||||||
sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer;
|
sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer;
|
||||||
sdup->oqueue.q_counter = chQSizeI(&sdup->oqueue);
|
sdup->oqueue.q_counter = chQSizeI(&sdup->oqueue);
|
||||||
while (notempty(&sdup->oqueue.q_waiting))
|
while (notempty(&sdup->oqueue.q_waiting))
|
||||||
chSchReadyI(fifo_remove(&sdup->oqueue.q_waiting))->p_u.rdymsg = Q_OK;
|
chSchReadyI(fifo_remove(&sdup->oqueue.q_waiting))->p_u.rdymsg = Q_OK;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
chSysUnlockFromIsr();
|
chSysUnlockFromIsr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,18 +336,24 @@ void sduDataReceived(USBDriver *usbp, usbep_t ep) {
|
||||||
/* Writes to the input queue can only happen when the queue has been
|
/* Writes to the input queue can only happen when the queue has been
|
||||||
emptied, then a whole packet is loaded in the queue.*/
|
emptied, then a whole packet is loaded in the queue.*/
|
||||||
if (chIQIsEmptyI(&sdup->iqueue)) {
|
if (chIQIsEmptyI(&sdup->iqueue)) {
|
||||||
|
/* The endpoint cannot be busy, we are in the context of the callback,
|
||||||
|
so a packet is in the buffer for sure.*/
|
||||||
size_t n;
|
size_t n;
|
||||||
|
|
||||||
n = usbReadPacketI(usbp, ep, sdup->iqueue.q_buffer,
|
chSysUnlockFromIsr();
|
||||||
|
|
||||||
|
/* Unlocked to make the potentially long write operation preemptable.*/
|
||||||
|
n = usbReadPacketBuffer(usbp, ep, sdup->iqueue.q_buffer,
|
||||||
SERIAL_USB_BUFFERS_SIZE);
|
SERIAL_USB_BUFFERS_SIZE);
|
||||||
if (n != USB_ENDPOINT_BUSY) {
|
|
||||||
|
chSysLockFromIsr();
|
||||||
|
usbStartReceiveI(usbp, ep);
|
||||||
chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE);
|
chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE);
|
||||||
sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer;
|
sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer;
|
||||||
sdup->iqueue.q_counter = n;
|
sdup->iqueue.q_counter = n;
|
||||||
while (notempty(&sdup->iqueue.q_waiting))
|
while (notempty(&sdup->iqueue.q_waiting))
|
||||||
chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK;
|
chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
chSysUnlockFromIsr();
|
chSysUnlockFromIsr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
107
os/hal/src/usb.c
107
os/hal/src/usb.c
|
@ -309,7 +309,7 @@ void usbInitEndpointI(USBDriver *usbp, usbep_t ep,
|
||||||
chDbgCheck((usbp != NULL) && (epcp != NULL), "usbInitEndpointI");
|
chDbgCheck((usbp != NULL) && (epcp != NULL), "usbInitEndpointI");
|
||||||
chDbgAssert(usbp->state == USB_ACTIVE,
|
chDbgAssert(usbp->state == USB_ACTIVE,
|
||||||
"usbEnableEndpointI(), #1", "invalid state");
|
"usbEnableEndpointI(), #1", "invalid state");
|
||||||
chDbgAssert(usbp->epc[ep] != NULL,
|
chDbgAssert(usbp->epc[ep] == NULL,
|
||||||
"usbEnableEndpointI(), #2", "already initialized");
|
"usbEnableEndpointI(), #2", "already initialized");
|
||||||
|
|
||||||
/* Logically enabling the endpoint in the USBDriver structure.*/
|
/* Logically enabling the endpoint in the USBDriver structure.*/
|
||||||
|
@ -351,127 +351,55 @@ void usbDisableEndpointsI(USBDriver *usbp) {
|
||||||
usb_lld_disable_endpoints(usbp);
|
usb_lld_disable_endpoints(usbp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Reads a packet from the dedicated packet buffer.
|
|
||||||
* @pre In order to use this function he endpoint must have been
|
|
||||||
* initialized in packet mode.
|
|
||||||
* @post The endpoint is ready to accept another packet.
|
|
||||||
*
|
|
||||||
* @param[in] usbp pointer to the @p USBDriver object
|
|
||||||
* @param[in] ep endpoint number
|
|
||||||
* @param[out] buf buffer where to copy the packet data
|
|
||||||
* @param[in] n maximum number of bytes to copy. This value must
|
|
||||||
* not exceed the maximum packet size for this endpoint.
|
|
||||||
* @return The received packet size regardless the specified
|
|
||||||
* @p n parameter.
|
|
||||||
* @retval USB_ENDPOINT_BUSY Endpoint busy receiving.
|
|
||||||
* @retval 0 Zero size packet received.
|
|
||||||
*
|
|
||||||
* @iclass
|
|
||||||
*/
|
|
||||||
size_t usbReadPacketI(USBDriver *usbp, usbep_t ep,
|
|
||||||
uint8_t *buf, size_t n) {
|
|
||||||
|
|
||||||
chDbgCheckClassI();
|
|
||||||
chDbgCheck((usbp != NULL) && (buf != NULL), "usbReadPacketI");
|
|
||||||
|
|
||||||
if (usbGetReceiveStatusI(usbp, ep))
|
|
||||||
return USB_ENDPOINT_BUSY;
|
|
||||||
|
|
||||||
usbp->receiving |= (1 << ep);
|
|
||||||
return usb_lld_read_packet(usbp, ep, buf, n);;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Writes a packet to the dedicated packet buffer.
|
|
||||||
* @pre In order to use this function he endpoint must have been
|
|
||||||
* initialized in packet mode.
|
|
||||||
* @post The endpoint is ready to transmit the packet.
|
|
||||||
*
|
|
||||||
* @param[in] usbp pointer to the @p USBDriver object
|
|
||||||
* @param[in] ep endpoint number
|
|
||||||
* @param[in] buf buffer where to fetch the packet data
|
|
||||||
* @param[in] n maximum number of bytes to copy. This value must
|
|
||||||
* not exceed the maximum packet size for this endpoint.
|
|
||||||
* @return The operation status.
|
|
||||||
* @retval USB_ENDPOINT_BUSY Endpoint busy transmitting.
|
|
||||||
* @retval 0 Operation complete.
|
|
||||||
*
|
|
||||||
* @iclass
|
|
||||||
*/
|
|
||||||
size_t usbWritePacketI(USBDriver *usbp, usbep_t ep,
|
|
||||||
const uint8_t *buf, size_t n) {
|
|
||||||
|
|
||||||
chDbgCheckClassI();
|
|
||||||
chDbgCheck((usbp != NULL) && (buf != NULL), "usbWritePacketI");
|
|
||||||
|
|
||||||
if (usbGetTransmitStatusI(usbp, ep))
|
|
||||||
return USB_ENDPOINT_BUSY;
|
|
||||||
|
|
||||||
usbp->transmitting |= (1 << ep);
|
|
||||||
usb_lld_write_packet(usbp, ep, buf, n);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Starts a receive transaction on an OUT endpoint.
|
* @brief Starts a receive transaction on an OUT endpoint.
|
||||||
* @pre In order to use this function he endpoint must have been
|
|
||||||
* initialized in transaction mode.
|
|
||||||
* @post The endpoint callback is invoked when the transfer has been
|
* @post The endpoint callback is invoked when the transfer has been
|
||||||
* completed.
|
* completed.
|
||||||
*
|
*
|
||||||
* @param[in] usbp pointer to the @p USBDriver object
|
* @param[in] usbp pointer to the @p USBDriver object
|
||||||
* @param[in] ep endpoint number
|
* @param[in] ep endpoint number
|
||||||
* @param[out] buf buffer where to copy the received data
|
|
||||||
* @param[in] n maximum number of bytes to copy
|
|
||||||
* @return The operation status.
|
* @return The operation status.
|
||||||
* @retval FALSE Operation started successfully.
|
* @retval FALSE Operation started successfully.
|
||||||
* @retval TRUE Endpoint busy, operation not started.
|
* @retval TRUE Endpoint busy, operation not started.
|
||||||
*
|
*
|
||||||
* @iclass
|
* @iclass
|
||||||
*/
|
*/
|
||||||
bool_t usbStartReceiveI(USBDriver *usbp, usbep_t ep,
|
bool_t usbStartReceiveI(USBDriver *usbp, usbep_t ep) {
|
||||||
uint8_t *buf, size_t n) {
|
|
||||||
|
|
||||||
chDbgCheckClassI();
|
chDbgCheckClassI();
|
||||||
chDbgCheck((usbp != NULL) && (buf != NULL), "usbStartReceiveI");
|
chDbgCheck(usbp != NULL, "usbStartReceiveI");
|
||||||
|
|
||||||
if (usbGetReceiveStatusI(usbp, ep))
|
if (usbGetReceiveStatusI(usbp, ep))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
usbp->receiving |= (1 << ep);
|
usbp->receiving |= (1 << ep);
|
||||||
usb_lld_start_out(usbp, ep, buf, n);
|
usb_lld_start_out(usbp, ep);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Starts a transmit transaction on an IN endpoint.
|
* @brief Starts a transmit transaction on an IN endpoint.
|
||||||
* @pre In order to use this function he endpoint must have been
|
|
||||||
* initialized in transaction mode.
|
|
||||||
* @post The endpoint callback is invoked when the transfer has been
|
* @post The endpoint callback is invoked when the transfer has been
|
||||||
* completed.
|
* completed.
|
||||||
*
|
*
|
||||||
* @param[in] usbp pointer to the @p USBDriver object
|
* @param[in] usbp pointer to the @p USBDriver object
|
||||||
* @param[in] ep endpoint number
|
* @param[in] ep endpoint number
|
||||||
* @param[in] buf buffer where to fetch the data to be transmitted
|
|
||||||
* @param[in] n maximum number of bytes to copy
|
|
||||||
* @return The operation status.
|
* @return The operation status.
|
||||||
* @retval FALSE Operation started successfully.
|
* @retval FALSE Operation started successfully.
|
||||||
* @retval TRUE Endpoint busy, operation not started.
|
* @retval TRUE Endpoint busy, operation not started.
|
||||||
*
|
*
|
||||||
* @iclass
|
* @iclass
|
||||||
*/
|
*/
|
||||||
bool_t usbStartTransmitI(USBDriver *usbp, usbep_t ep,
|
bool_t usbStartTransmitI(USBDriver *usbp, usbep_t ep) {
|
||||||
const uint8_t *buf, size_t n) {
|
|
||||||
|
|
||||||
chDbgCheckClassI();
|
chDbgCheckClassI();
|
||||||
chDbgCheck((usbp != NULL) && (buf != NULL), "usbStartTransmitI");
|
chDbgCheck(usbp != NULL, "usbStartTransmitI");
|
||||||
|
|
||||||
if (usbGetTransmitStatusI(usbp, ep))
|
if (usbGetTransmitStatusI(usbp, ep))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
usbp->transmitting |= (1 << ep);
|
usbp->transmitting |= (1 << ep);
|
||||||
usb_lld_start_in(usbp, ep, buf, n);
|
usb_lld_start_in(usbp, ep);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -597,13 +525,15 @@ void _usb_ep0setup(USBDriver *usbp, usbep_t ep) {
|
||||||
if (usbp->ep0n > 0) {
|
if (usbp->ep0n > 0) {
|
||||||
/* Starts the transmit phase.*/
|
/* Starts the transmit phase.*/
|
||||||
usbp->ep0state = USB_EP0_TX;
|
usbp->ep0state = USB_EP0_TX;
|
||||||
usb_lld_start_in(usbp, 0, usbp->ep0next, usbp->ep0n);
|
usb_lld_prepare_transmit(usbp, 0, usbp->ep0next, usbp->ep0n);
|
||||||
|
usb_lld_start_in(usbp, 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* No transmission phase, directly receiving the zero sized status
|
/* No transmission phase, directly receiving the zero sized status
|
||||||
packet.*/
|
packet.*/
|
||||||
usbp->ep0state = USB_EP0_WAITING_STS;
|
usbp->ep0state = USB_EP0_WAITING_STS;
|
||||||
usb_lld_start_out(usbp, 0, NULL, 0);
|
usb_lld_prepare_receive(usbp, 0, NULL, 0);
|
||||||
|
usb_lld_start_out(usbp, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -611,13 +541,15 @@ void _usb_ep0setup(USBDriver *usbp, usbep_t ep) {
|
||||||
if (usbp->ep0n > 0) {
|
if (usbp->ep0n > 0) {
|
||||||
/* Starts the receive phase.*/
|
/* Starts the receive phase.*/
|
||||||
usbp->ep0state = USB_EP0_RX;
|
usbp->ep0state = USB_EP0_RX;
|
||||||
usb_lld_start_out(usbp, 0, usbp->ep0next, usbp->ep0n);
|
usb_lld_prepare_receive(usbp, 0, usbp->ep0next, usbp->ep0n);
|
||||||
|
usb_lld_start_out(usbp, 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* No receive phase, directly sending the zero sized status
|
/* No receive phase, directly sending the zero sized status
|
||||||
packet.*/
|
packet.*/
|
||||||
usbp->ep0state = USB_EP0_SENDING_STS;
|
usbp->ep0state = USB_EP0_SENDING_STS;
|
||||||
usb_lld_start_in(usbp, 0, NULL, 0);
|
usb_lld_prepare_transmit(usbp, 0, NULL, 0);
|
||||||
|
usb_lld_start_in(usbp, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -644,13 +576,15 @@ void _usb_ep0in(USBDriver *usbp, usbep_t ep) {
|
||||||
transmitted.*/
|
transmitted.*/
|
||||||
if ((usbp->ep0n < max) &&
|
if ((usbp->ep0n < max) &&
|
||||||
((usbp->ep0n % usbp->epc[0]->in_maxsize) == 0)) {
|
((usbp->ep0n % usbp->epc[0]->in_maxsize) == 0)) {
|
||||||
usb_lld_start_in(usbp, 0, NULL, 0);
|
usb_lld_prepare_transmit(usbp, 0, NULL, 0);
|
||||||
|
usb_lld_start_in(usbp, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Transmit phase over, receiving the zero sized status packet.*/
|
/* Transmit phase over, receiving the zero sized status packet.*/
|
||||||
usbp->ep0state = USB_EP0_WAITING_STS;
|
usbp->ep0state = USB_EP0_WAITING_STS;
|
||||||
usb_lld_start_out(usbp, 0, NULL, 0);
|
usb_lld_prepare_receive(usbp, 0, NULL, 0);
|
||||||
|
usb_lld_start_out(usbp, 0);
|
||||||
return;
|
return;
|
||||||
case USB_EP0_SENDING_STS:
|
case USB_EP0_SENDING_STS:
|
||||||
/* Status packet sent, invoking the callback if defined.*/
|
/* Status packet sent, invoking the callback if defined.*/
|
||||||
|
@ -687,7 +621,8 @@ void _usb_ep0out(USBDriver *usbp, usbep_t ep) {
|
||||||
case USB_EP0_RX:
|
case USB_EP0_RX:
|
||||||
/* Receive phase over, sending the zero sized status packet.*/
|
/* Receive phase over, sending the zero sized status packet.*/
|
||||||
usbp->ep0state = USB_EP0_SENDING_STS;
|
usbp->ep0state = USB_EP0_SENDING_STS;
|
||||||
usb_lld_start_in(usbp, 0, NULL, 0);
|
usb_lld_prepare_transmit(usbp, 0, NULL, 0);
|
||||||
|
usb_lld_start_in(usbp, 0);
|
||||||
return;
|
return;
|
||||||
case USB_EP0_WAITING_STS:
|
case USB_EP0_WAITING_STS:
|
||||||
/* Status packet received, it must be zero sized, invoking the callback
|
/* Status packet received, it must be zero sized, invoking the callback
|
||||||
|
|
|
@ -51,6 +51,16 @@
|
||||||
#define THD_STATE_WTMSG 12 /**< @brief Waiting for a message. */
|
#define THD_STATE_WTMSG 12 /**< @brief Waiting for a message. */
|
||||||
#define THD_STATE_WTQUEUE 13 /**< @brief Waiting on an I/O queue. */
|
#define THD_STATE_WTQUEUE 13 /**< @brief Waiting on an I/O queue. */
|
||||||
#define THD_STATE_FINAL 14 /**< @brief Thread terminated. */
|
#define THD_STATE_FINAL 14 /**< @brief Thread terminated. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Thread states as array of strings.
|
||||||
|
* @details Each element in an array initialized with this macro can be
|
||||||
|
* indexed using the numeric thread state values.
|
||||||
|
*/
|
||||||
|
#define THD_STATE_NAMES \
|
||||||
|
"READY", "CURRENT", "SUSPENDED", "WTSEM", "WTMTX", "WTCOND", "SLEEPING", \
|
||||||
|
"WTEXIT", "WTOREVT", "WTANDEVT", "SNDMSGQ", "SNDMSG", "WTMSG", "WTQUEUE", \
|
||||||
|
"FINAL"
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -152,9 +152,8 @@ msg_t chIQPutI(InputQueue *iqp, uint8_t b) {
|
||||||
* @details This function reads a byte value from an input queue. If the queue
|
* @details This function reads a byte value from an input queue. If the queue
|
||||||
* is empty then the calling thread is suspended until a byte arrives
|
* is empty then the calling thread is suspended until a byte arrives
|
||||||
* in the queue or a timeout occurs.
|
* in the queue or a timeout occurs.
|
||||||
* @note The callback is invoked if the queue is empty before entering the
|
* @note The callback is invoked before reading the character from the
|
||||||
* @p THD_STATE_WTQUEUE state in order to solicit the low level to
|
* buffer or before entering the state @p THD_STATE_WTQUEUE.
|
||||||
* start queue filling.
|
|
||||||
*
|
*
|
||||||
* @param[in] iqp pointer to an @p InputQueue structure
|
* @param[in] iqp pointer to an @p InputQueue structure
|
||||||
* @param[in] time the number of ticks before the operation timeouts,
|
* @param[in] time the number of ticks before the operation timeouts,
|
||||||
|
@ -172,12 +171,11 @@ msg_t chIQGetTimeout(InputQueue *iqp, systime_t time) {
|
||||||
uint8_t b;
|
uint8_t b;
|
||||||
|
|
||||||
chSysLock();
|
chSysLock();
|
||||||
while (chIQIsEmptyI(iqp)) {
|
|
||||||
msg_t msg;
|
|
||||||
|
|
||||||
if (iqp->q_notify)
|
if (iqp->q_notify)
|
||||||
iqp->q_notify(iqp);
|
iqp->q_notify(iqp);
|
||||||
|
|
||||||
|
while (chIQIsEmptyI(iqp)) {
|
||||||
|
msg_t msg;
|
||||||
if ((msg = qwait((GenericQueue *)iqp, time)) < Q_OK) {
|
if ((msg = qwait((GenericQueue *)iqp, time)) < Q_OK) {
|
||||||
chSysUnlock();
|
chSysUnlock();
|
||||||
return msg;
|
return msg;
|
||||||
|
@ -201,9 +199,8 @@ msg_t chIQGetTimeout(InputQueue *iqp, systime_t time) {
|
||||||
* been reset.
|
* been reset.
|
||||||
* @note The function is not atomic, if you need atomicity it is suggested
|
* @note The function is not atomic, if you need atomicity it is suggested
|
||||||
* to use a semaphore or a mutex for mutual exclusion.
|
* to use a semaphore or a mutex for mutual exclusion.
|
||||||
* @note The callback is invoked if the queue is empty before entering the
|
* @note The callback is invoked before reading each character from the
|
||||||
* @p THD_STATE_WTQUEUE state in order to solicit the low level to
|
* buffer or before entering the state @p THD_STATE_WTQUEUE.
|
||||||
* start queue filling.
|
|
||||||
*
|
*
|
||||||
* @param[in] iqp pointer to an @p InputQueue structure
|
* @param[in] iqp pointer to an @p InputQueue structure
|
||||||
* @param[out] bp pointer to the data buffer
|
* @param[out] bp pointer to the data buffer
|
||||||
|
@ -227,10 +224,10 @@ size_t chIQReadTimeout(InputQueue *iqp, uint8_t *bp,
|
||||||
|
|
||||||
chSysLock();
|
chSysLock();
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
while (chIQIsEmptyI(iqp)) {
|
|
||||||
if (nfy)
|
if (nfy)
|
||||||
nfy(iqp);
|
nfy(iqp);
|
||||||
|
|
||||||
|
while (chIQIsEmptyI(iqp)) {
|
||||||
if (qwait((GenericQueue *)iqp, time) != Q_OK) {
|
if (qwait((GenericQueue *)iqp, time) != Q_OK) {
|
||||||
chSysUnlock();
|
chSysUnlock();
|
||||||
return r;
|
return r;
|
||||||
|
|
|
@ -76,6 +76,11 @@
|
||||||
*** 2.3.4 ***
|
*** 2.3.4 ***
|
||||||
- FIX: Fixed broken TIM8 support in STM32 PWM driver (bug 3418620).
|
- FIX: Fixed broken TIM8 support in STM32 PWM driver (bug 3418620).
|
||||||
- FIX: Fixed halconf.h file corrupted in some STM32 demos (bug 3418626).
|
- FIX: Fixed halconf.h file corrupted in some STM32 demos (bug 3418626).
|
||||||
|
- NEW: Updated USB driver model and STM32 implementation. Updated the
|
||||||
|
SERIAL_USB driver to match the new API. Fixed several problems in
|
||||||
|
both drivers.
|
||||||
|
- NEW: Added a macro THD_STATE_NAMES to chthreads.h. This macro is an
|
||||||
|
initializer for string arrays containing thread state names.
|
||||||
- NEW: Added memory copy functionality to the STM32 DMA driver.
|
- NEW: Added memory copy functionality to the STM32 DMA driver.
|
||||||
- NEW: Implemented new makefile system for ARM GCC ports, now objects,
|
- NEW: Implemented new makefile system for ARM GCC ports, now objects,
|
||||||
listings and output files are generated into a "build" directory and not
|
listings and output files are generated into a "build" directory and not
|
||||||
|
@ -84,6 +89,9 @@
|
||||||
rebuild if touched.
|
rebuild if touched.
|
||||||
- NEW: Updated AVR demos to use the new PAL driver.
|
- NEW: Updated AVR demos to use the new PAL driver.
|
||||||
- NEW: Added Keil build files to the STM32L-Discovery demo.
|
- NEW: Added Keil build files to the STM32L-Discovery demo.
|
||||||
|
- CHANGE: Now the callback associated to input queues is invoked before
|
||||||
|
reading each character. Previously it was invoked only before going
|
||||||
|
to sleep into the THD_STATE_WTQUEUE state.
|
||||||
- CHANGE: Moved the STM32 DMA helper drivers files under the sub-family
|
- CHANGE: Moved the STM32 DMA helper drivers files under the sub-family
|
||||||
specific directories because documentation issues.
|
specific directories because documentation issues.
|
||||||
|
|
||||||
|
|
|
@ -332,22 +332,7 @@ static void cmd_mem(BaseChannel *chp, int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cmd_threads(BaseChannel *chp, int argc, char *argv[]) {
|
static void cmd_threads(BaseChannel *chp, int argc, char *argv[]) {
|
||||||
static const char *states[] = {
|
static const char *states[] = {THD_STATE_NAMES};
|
||||||
"READY",
|
|
||||||
"CURRENT",
|
|
||||||
"SUSPENDED",
|
|
||||||
"WTSEM",
|
|
||||||
"WTMTX",
|
|
||||||
"WTCOND",
|
|
||||||
"SLEEPING",
|
|
||||||
"WTEXIT",
|
|
||||||
"WTOREVT",
|
|
||||||
"WTANDEVT",
|
|
||||||
"SNDMSGQ",
|
|
||||||
"SNDMSG",
|
|
||||||
"WTMSG",
|
|
||||||
"FINAL"
|
|
||||||
};
|
|
||||||
Thread *tp;
|
Thread *tp;
|
||||||
|
|
||||||
(void)argv;
|
(void)argv;
|
||||||
|
|
Loading…
Reference in New Issue