git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4266 35acf78f-673a-0410-8e92-d51de3d6d3f4
parent
c762926b68
commit
d094e348c5
|
@ -416,11 +416,12 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp,
|
||||||
* @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] iq input queue to be filled with incoming data
|
* @param[in] iq input queue to be filled with incoming data
|
||||||
|
* @param[in] n maximum number of bytes to copy
|
||||||
*
|
*
|
||||||
* @special
|
* @special
|
||||||
*/
|
*/
|
||||||
#define usbPrepareQueuedReceive(usbp, ep, iq) \
|
#define usbPrepareQueuedReceive(usbp, ep, iq, n) \
|
||||||
usb_lld_prepare_queued_receive(usbp, ep, iq)
|
usb_lld_prepare_queued_receive(usbp, ep, iq, n)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Prepares for a transmit transaction on an IN endpoint.
|
* @brief Prepares for a transmit transaction on an IN endpoint.
|
||||||
|
@ -433,11 +434,12 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp,
|
||||||
* @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] oq output queue to be fetched for outgoing data
|
* @param[in] oq output queue to be fetched for outgoing data
|
||||||
|
* @param[in] n maximum number of bytes to copy
|
||||||
*
|
*
|
||||||
* @special
|
* @special
|
||||||
*/
|
*/
|
||||||
#define usbPrepareQueuedTransmit(usbp, ep, oq) \
|
#define usbPrepareQueuedTransmit(usbp, ep, oq, n) \
|
||||||
usb_lld_prepare_queued_transmit(usbp, ep, oq)
|
usb_lld_prepare_queued_transmit(usbp, ep, oq, n)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the exact size of a receive transaction.
|
* @brief Returns the exact size of a receive transaction.
|
||||||
|
|
|
@ -193,11 +193,12 @@ static uint32_t otg_ram_alloc(USBDriver *usbp, size_t size) {
|
||||||
* @param[in] ep endpoint number
|
* @param[in] ep endpoint number
|
||||||
* @param[in] buf buffer where to copy the endpoint data
|
* @param[in] buf buffer where to copy the endpoint data
|
||||||
* @param[in] n maximum number of bytes to copy
|
* @param[in] n maximum number of bytes to copy
|
||||||
* @return the number of bytes that were effectively written
|
|
||||||
*
|
*
|
||||||
* @notapi
|
* @notapi
|
||||||
*/
|
*/
|
||||||
static void otg_fifo_write(usbep_t ep, const uint8_t *buf, size_t n) {
|
static void otg_fifo_write_from_buffer(usbep_t ep,
|
||||||
|
const uint8_t *buf,
|
||||||
|
size_t n) {
|
||||||
volatile uint32_t *fifop;
|
volatile uint32_t *fifop;
|
||||||
|
|
||||||
fifop = OTG_FIFO(ep);
|
fifop = OTG_FIFO(ep);
|
||||||
|
@ -213,6 +214,55 @@ static void otg_fifo_write(usbep_t ep, const uint8_t *buf, size_t n) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Writes to a TX FIFO fetching data from a queue.
|
||||||
|
*
|
||||||
|
* @param[in] ep endpoint number
|
||||||
|
* @param[in] oqp pointer to an @p OutputQueue object
|
||||||
|
* @param[in] n maximum number of bytes to copy
|
||||||
|
*
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
static void otg_fifo_write_from_queue(usbep_t ep,
|
||||||
|
OutputQueue *oqp,
|
||||||
|
size_t n) {
|
||||||
|
size_t nw;
|
||||||
|
uint8_t *bp;
|
||||||
|
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;
|
||||||
|
*fifop = dw;
|
||||||
|
} while (--nw > 0);
|
||||||
|
|
||||||
|
/* Updating queue.*/
|
||||||
|
chSysLockFromIsr();
|
||||||
|
oqp->q_rdptr += n;
|
||||||
|
if (oqp->q_rdptr >= oqp->q_top)
|
||||||
|
oqp->q_rdptr = oqp->q_buffer;
|
||||||
|
oqp->q_counter += n;
|
||||||
|
while (notempty(&oqp->q_waiting))
|
||||||
|
chSchReadyI(fifo_remove(&oqp->q_waiting))->p_u.rdymsg = Q_OK;
|
||||||
|
chSysUnlockFromIsr();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Reads a packet from the RXFIFO.
|
* @brief Reads a packet from the RXFIFO.
|
||||||
*
|
*
|
||||||
|
@ -222,7 +272,7 @@ static void otg_fifo_write(usbep_t ep, const uint8_t *buf, size_t n) {
|
||||||
*
|
*
|
||||||
* @notapi
|
* @notapi
|
||||||
*/
|
*/
|
||||||
static void otg_fifo_read(uint8_t *buf, size_t n, size_t max) {
|
static void otg_fifo_read_to_buffer(uint8_t *buf, size_t n, size_t max) {
|
||||||
volatile uint32_t *fifop;
|
volatile uint32_t *fifop;
|
||||||
|
|
||||||
fifop = OTG_FIFO(0);
|
fifop = OTG_FIFO(0);
|
||||||
|
@ -241,6 +291,25 @@ static void otg_fifo_read(uint8_t *buf, size_t n, size_t max) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads a packet from the RXFIFO.
|
||||||
|
*
|
||||||
|
* @param[in] oqp pointer to an @p InputQueue object
|
||||||
|
* @param[in] n number of bytes to pull from the FIFO
|
||||||
|
*
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
static void otg_fifo_read_to_queue(InputQueue *iqp, size_t n) {
|
||||||
|
size_t nw;
|
||||||
|
volatile uint32_t *fifop;
|
||||||
|
|
||||||
|
fifop = OTG_FIFO(0);
|
||||||
|
nw = (n + 3) / 4;
|
||||||
|
do {
|
||||||
|
uint32_t dw = *fifop;
|
||||||
|
} while (--n > 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Incoming packets handler.
|
* @brief Incoming packets handler.
|
||||||
*
|
*
|
||||||
|
@ -258,15 +327,21 @@ static void otg_rxfifo_handler(USBDriver *usbp) {
|
||||||
case GRXSTSP_SETUP_DATA:
|
case GRXSTSP_SETUP_DATA:
|
||||||
cnt = (sts & GRXSTSP_BCNT_MASK) >> GRXSTSP_BCNT_OFF;
|
cnt = (sts & GRXSTSP_BCNT_MASK) >> GRXSTSP_BCNT_OFF;
|
||||||
ep = (sts & GRXSTSP_EPNUM_MASK) >> GRXSTSP_EPNUM_OFF;
|
ep = (sts & GRXSTSP_EPNUM_MASK) >> GRXSTSP_EPNUM_OFF;
|
||||||
otg_fifo_read(usbp->epc[ep]->setup_buf, cnt, 8);
|
otg_fifo_read_to_buffer(usbp->epc[ep]->setup_buf, cnt, 8);
|
||||||
break;
|
break;
|
||||||
case GRXSTSP_OUT_DATA:
|
case GRXSTSP_OUT_DATA:
|
||||||
cnt = (sts & GRXSTSP_BCNT_MASK) >> GRXSTSP_BCNT_OFF;
|
cnt = (sts & GRXSTSP_BCNT_MASK) >> GRXSTSP_BCNT_OFF;
|
||||||
ep = (sts & GRXSTSP_EPNUM_MASK) >> GRXSTSP_EPNUM_OFF;
|
ep = (sts & GRXSTSP_EPNUM_MASK) >> GRXSTSP_EPNUM_OFF;
|
||||||
otg_fifo_read(usbp->epc[ep]->out_state->rxbuf, cnt,
|
if (usbp->epc[ep]->out_state->rxqueued) {
|
||||||
|
/* Queue associated.*/
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
otg_fifo_read_to_buffer(usbp->epc[ep]->out_state->mode.linear.rxbuf,
|
||||||
|
cnt,
|
||||||
usbp->epc[ep]->out_state->rxsize -
|
usbp->epc[ep]->out_state->rxsize -
|
||||||
usbp->epc[ep]->out_state->rxcnt);
|
usbp->epc[ep]->out_state->rxcnt);
|
||||||
usbp->epc[ep]->out_state->rxbuf += cnt;
|
usbp->epc[ep]->out_state->mode.linear.rxbuf += cnt;
|
||||||
|
}
|
||||||
usbp->epc[ep]->out_state->rxcnt += cnt;
|
usbp->epc[ep]->out_state->rxcnt += cnt;
|
||||||
break;
|
break;
|
||||||
case GRXSTSP_OUT_GLOBAL_NAK:
|
case GRXSTSP_OUT_GLOBAL_NAK:
|
||||||
|
@ -287,12 +362,28 @@ static void otg_rxfifo_handler(USBDriver *usbp) {
|
||||||
static void otg_txfifo_handler(USBDriver *usbp, usbep_t ep) {
|
static void otg_txfifo_handler(USBDriver *usbp, usbep_t ep) {
|
||||||
uint32_t n;
|
uint32_t n;
|
||||||
|
|
||||||
|
/* Number of bytes remaining in current transaction.*/
|
||||||
n = usbp->epc[ep]->in_state->txsize - usbp->epc[ep]->in_state->txcnt;
|
n = usbp->epc[ep]->in_state->txsize - usbp->epc[ep]->in_state->txcnt;
|
||||||
if (n > usbp->epc[ep]->in_maxsize)
|
if (n > usbp->epc[ep]->in_maxsize)
|
||||||
n = usbp->epc[ep]->in_maxsize;
|
n = usbp->epc[ep]->in_maxsize;
|
||||||
otg_fifo_write(ep, usbp->epc[ep]->in_state->txbuf, n);
|
|
||||||
usbp->epc[ep]->in_state->txbuf += n;
|
if (usbp->epc[ep]->in_state->txqueued) {
|
||||||
|
/* Queue associated.*/
|
||||||
|
otg_fifo_write_from_queue(ep,
|
||||||
|
usbp->epc[ep]->in_state->mode.queue.txqueue,
|
||||||
|
n);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Linear buffer associated.*/
|
||||||
|
otg_fifo_write_from_buffer(ep,
|
||||||
|
usbp->epc[ep]->in_state->mode.linear.txbuf,
|
||||||
|
n);
|
||||||
|
usbp->epc[ep]->in_state->mode.linear.txbuf += n;
|
||||||
|
}
|
||||||
usbp->epc[ep]->in_state->txcnt += n;
|
usbp->epc[ep]->in_state->txcnt += n;
|
||||||
|
/* TODO: Potential issue, txcnt can be less than txsize after the planned
|
||||||
|
number of packets have been received, better disable the interrupt
|
||||||
|
at the end of the transaction in otg_epin_handler().*/
|
||||||
if (usbp->epc[ep]->in_state->txcnt >= usbp->epc[ep]->in_state->txsize) {
|
if (usbp->epc[ep]->in_state->txcnt >= usbp->epc[ep]->in_state->txsize) {
|
||||||
/* Transfer finished.*/
|
/* Transfer finished.*/
|
||||||
OTG->DIEPEMPMSK &= ~DIEPEMPMSK_INEPTXFEM(ep);
|
OTG->DIEPEMPMSK &= ~DIEPEMPMSK_INEPTXFEM(ep);
|
||||||
|
@ -313,14 +404,14 @@ static void otg_epin_handler(USBDriver *usbp, usbep_t ep) {
|
||||||
/* Resets all EP IRQ sources.*/
|
/* Resets all EP IRQ sources.*/
|
||||||
OTG->ie[ep].DIEPINT = 0xFFFFFFFF;
|
OTG->ie[ep].DIEPINT = 0xFFFFFFFF;
|
||||||
|
|
||||||
if (epint & DIEPINT_TXFE) {
|
|
||||||
/* TX FIFO empty or emptying.*/
|
|
||||||
otg_txfifo_handler(usbp, ep);
|
|
||||||
}
|
|
||||||
if (epint & DIEPINT_XFRC) {
|
if (epint & DIEPINT_XFRC) {
|
||||||
/* Transmit transfer complete.*/
|
/* Transmit transfer complete.*/
|
||||||
_usb_isr_invoke_in_cb(usbp, ep);
|
_usb_isr_invoke_in_cb(usbp, ep);
|
||||||
}
|
}
|
||||||
|
if (epint & DIEPINT_TXFE) {
|
||||||
|
/* TX FIFO empty or emptying.*/
|
||||||
|
otg_txfifo_handler(usbp, ep);
|
||||||
|
}
|
||||||
if (epint & DIEPINT_TOC) {
|
if (epint & DIEPINT_TOC) {
|
||||||
/* Timeouts not handled yet, not sure how to handle.*/
|
/* Timeouts not handled yet, not sure how to handle.*/
|
||||||
}
|
}
|
||||||
|
@ -730,9 +821,12 @@ void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep,
|
||||||
uint32_t pcnt;
|
uint32_t pcnt;
|
||||||
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
|
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
|
||||||
|
|
||||||
osp->rxbuf = buf;
|
osp->rxqueued = FALSE;
|
||||||
osp->rxsize = n;
|
osp->rxsize = n;
|
||||||
osp->rxcnt = 0;
|
osp->rxcnt = 0;
|
||||||
|
osp->mode.linear.rxbuf = buf;
|
||||||
|
|
||||||
|
/* Transfer initialization.*/
|
||||||
pcnt = (n + usbp->epc[ep]->out_maxsize - 1) / usbp->epc[ep]->out_maxsize;
|
pcnt = (n + usbp->epc[ep]->out_maxsize - 1) / usbp->epc[ep]->out_maxsize;
|
||||||
OTG->oe[ep].DOEPTSIZ = DOEPTSIZ_STUPCNT(3) | DOEPTSIZ_PKTCNT(pcnt) |
|
OTG->oe[ep].DOEPTSIZ = DOEPTSIZ_STUPCNT(3) | DOEPTSIZ_PKTCNT(pcnt) |
|
||||||
DOEPTSIZ_XFRSIZ(usbp->epc[ep]->out_maxsize);
|
DOEPTSIZ_XFRSIZ(usbp->epc[ep]->out_maxsize);
|
||||||
|
@ -753,9 +847,10 @@ void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep,
|
||||||
uint32_t pcnt;
|
uint32_t pcnt;
|
||||||
USBInEndpointState *isp = usbp->epc[ep]->in_state;
|
USBInEndpointState *isp = usbp->epc[ep]->in_state;
|
||||||
|
|
||||||
isp->txbuf = buf;
|
isp->txqueued = FALSE;
|
||||||
isp->txsize = n;
|
isp->txsize = n;
|
||||||
isp->txcnt = 0;
|
isp->txcnt = 0;
|
||||||
|
isp->mode.linear.txbuf = buf;
|
||||||
|
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
/* Special case, sending zero size packet.*/
|
/* Special case, sending zero size packet.*/
|
||||||
|
@ -782,12 +877,24 @@ void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep,
|
||||||
* @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] iq input queue to be filled with incoming data
|
* @param[in] iq input queue to be filled with incoming data
|
||||||
|
* @param[in] n maximum number of bytes to copy
|
||||||
*
|
*
|
||||||
* @special
|
* @special
|
||||||
*/
|
*/
|
||||||
void usb_lld_prepare_queued_receive(USBDriver *usbp, usbep_t ep,
|
void usb_lld_prepare_queued_receive(USBDriver *usbp, usbep_t ep,
|
||||||
InputQueue *iq) {
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -801,12 +908,24 @@ void usb_lld_prepare_queued_receive(USBDriver *usbp, usbep_t ep,
|
||||||
* @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] oq output queue to be fetched for outgoing data
|
* @param[in] oq output queue to be fetched for outgoing data
|
||||||
|
* @param[in] n maximum number of bytes to copy
|
||||||
*
|
*
|
||||||
* @special
|
* @special
|
||||||
*/
|
*/
|
||||||
void usb_lld_prepare_queued_transmit(USBDriver *usbp, usbep_t ep,
|
void usb_lld_prepare_queued_transmit(USBDriver *usbp, usbep_t ep,
|
||||||
OutputQueue *oq) {
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -108,13 +108,13 @@
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Type of an endpoint state structure.
|
* @brief Type of an IN endpoint state structure.
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/**
|
/**
|
||||||
* @brief Pointer to the transmission buffer.
|
* @brief Buffer mode, queue or linear.
|
||||||
*/
|
*/
|
||||||
const uint8_t *txbuf;
|
bool_t txqueued;
|
||||||
/**
|
/**
|
||||||
* @brief Requested transmit transfer size.
|
* @brief Requested transmit transfer size.
|
||||||
*/
|
*/
|
||||||
|
@ -123,16 +123,30 @@ typedef struct {
|
||||||
* @brief Transmitted bytes so far.
|
* @brief Transmitted bytes so far.
|
||||||
*/
|
*/
|
||||||
size_t txcnt;
|
size_t txcnt;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
/**
|
||||||
|
* @brief Pointer to the transmission buffer.
|
||||||
|
*/
|
||||||
|
const uint8_t *txbuf;
|
||||||
|
} linear;
|
||||||
|
struct {
|
||||||
|
/**
|
||||||
|
* @brief Pointer to the output queue.
|
||||||
|
*/
|
||||||
|
OutputQueue *txqueue;
|
||||||
|
} queue;
|
||||||
|
} mode;
|
||||||
} USBInEndpointState;
|
} USBInEndpointState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Type of an endpoint state structure.
|
* @brief Type of an OUT endpoint state structure.
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/**
|
/**
|
||||||
* @brief Pointer to the receive buffer.
|
* @brief Buffer mode, queue or linear.
|
||||||
*/
|
*/
|
||||||
uint8_t *rxbuf;
|
bool_t rxqueued;
|
||||||
/**
|
/**
|
||||||
* @brief Requested receive transfer size.
|
* @brief Requested receive transfer size.
|
||||||
*/
|
*/
|
||||||
|
@ -141,6 +155,20 @@ typedef struct {
|
||||||
* @brief Received bytes so far.
|
* @brief Received bytes so far.
|
||||||
*/
|
*/
|
||||||
size_t rxcnt;
|
size_t rxcnt;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
/**
|
||||||
|
* @brief Pointer to the receive buffer.
|
||||||
|
*/
|
||||||
|
uint8_t *rxbuf;
|
||||||
|
} linear;
|
||||||
|
struct {
|
||||||
|
/**
|
||||||
|
* @brief Pointer to the input queue.
|
||||||
|
*/
|
||||||
|
InputQueue *rxqueue;
|
||||||
|
} queue;
|
||||||
|
} mode;
|
||||||
} USBOutEndpointState;
|
} USBOutEndpointState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -378,9 +406,9 @@ extern "C" {
|
||||||
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);
|
||||||
void usb_lld_prepare_queued_receive(USBDriver *usbp, usbep_t ep,
|
void usb_lld_prepare_queued_receive(USBDriver *usbp, usbep_t ep,
|
||||||
InputQueue *iq);
|
InputQueue *iq, size_t n);
|
||||||
void usb_lld_prepare_queued_transmit(USBDriver *usbp, usbep_t ep,
|
void usb_lld_prepare_queued_transmit(USBDriver *usbp, usbep_t ep,
|
||||||
OutputQueue *oq);
|
OutputQueue *oq, size_t n);
|
||||||
void usb_lld_start_out(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_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);
|
||||||
|
|
|
@ -149,8 +149,8 @@ void sdObjectInit(SerialDriver *sdp, qnotify_t inotify, qnotify_t onotify) {
|
||||||
chEvtInit(&sdp->event);
|
chEvtInit(&sdp->event);
|
||||||
sdp->flags = CHN_NO_ERROR;
|
sdp->flags = CHN_NO_ERROR;
|
||||||
sdp->state = SD_STOP;
|
sdp->state = SD_STOP;
|
||||||
chIQInit(&sdp->iqueue, sdp->ib, SERIAL_BUFFERS_SIZE, inotify);
|
chIQInit(&sdp->iqueue, sdp->ib, SERIAL_BUFFERS_SIZE, inotify, sdp);
|
||||||
chOQInit(&sdp->oqueue, sdp->ob, SERIAL_BUFFERS_SIZE, onotify);
|
chOQInit(&sdp->oqueue, sdp->ob, SERIAL_BUFFERS_SIZE, onotify, sdp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -117,59 +117,47 @@ static const struct SerialUSBDriverVMT vmt = {
|
||||||
* @brief Notification of data removed from the input queue.
|
* @brief Notification of data removed from the input queue.
|
||||||
*/
|
*/
|
||||||
static void inotify(GenericQueue *qp) {
|
static void inotify(GenericQueue *qp) {
|
||||||
SerialUSBDriver *sdup = (SerialUSBDriver *)qp->q_wrptr;
|
size_t n, maxsize;
|
||||||
|
SerialUSBDriver *sdup = chQGetLink(qp);
|
||||||
|
|
||||||
#if 0
|
/* If there is in the queue enough space to hold at least one packet and
|
||||||
/* Writes to the input queue can only happen when the queue has been
|
a transaction is not yet started then a new transaction is started for
|
||||||
emptied, then a whole packet is loaded in the queue.*/
|
the available space.*/
|
||||||
|
maxsize = sdup->config->usbp->epc[USB_CDC_DATA_AVAILABLE_EP]->out_maxsize;
|
||||||
if (!usbGetReceiveStatusI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP) &&
|
if (!usbGetReceiveStatusI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP) &&
|
||||||
chIQIsEmptyI(&sdup->iqueue)) {
|
((n = chIQGetEmptyI(&sdup->iqueue)) >= maxsize)) {
|
||||||
chSysUnlock();
|
chSysUnlock();
|
||||||
|
|
||||||
/* Unlocked to make the potentially long read operation preemptable.*/
|
n = (n / maxsize) * maxsize;
|
||||||
size_t n = usbReadPacketBuffer(sdup->config->usbp,
|
usbPrepareQueuedReceive(sdup->config->usbp,
|
||||||
USB_CDC_DATA_AVAILABLE_EP,
|
USB_CDC_DATA_AVAILABLE_EP,
|
||||||
sdup->iqueue.q_buffer,
|
&sdup->iqueue, n);
|
||||||
SERIAL_USB_BUFFERS_SIZE);
|
|
||||||
|
|
||||||
chSysLock();
|
chSysLock();
|
||||||
usbStartReceiveI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP);
|
usbStartReceiveI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP);
|
||||||
chnAddFlagsI(sdup, CHN_INPUT_AVAILABLE);
|
|
||||||
sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer;
|
|
||||||
sdup->iqueue.q_counter = n;
|
|
||||||
while (notempty(&sdup->iqueue.q_waiting))
|
|
||||||
chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK;
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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;
|
|
||||||
size_t n;
|
size_t n;
|
||||||
|
SerialUSBDriver *sdup = chQGetLink(qp);
|
||||||
|
|
||||||
#if 0
|
/* If there is not an ongoing transaction and the output queue contains
|
||||||
/* If there is any data in the output queue then it is sent within a
|
data then a new transaction is started.*/
|
||||||
single packet and the queue is emptied.*/
|
if (!usbGetTransmitStatusI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP) &&
|
||||||
n = chOQGetFullI(&sdup->oqueue);
|
((n = chOQGetFullI(&sdup->oqueue)) > 0)) {
|
||||||
if (!usbGetTransmitStatusI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP)) {
|
|
||||||
chSysUnlock();
|
chSysUnlock();
|
||||||
|
|
||||||
/* Unlocked to make the potentially long write operation preemptable.*/
|
usbPrepareQueuedTransmit(sdup->config->usbp,
|
||||||
usbWritePacketBuffer(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP,
|
USB_CDC_DATA_REQUEST_EP,
|
||||||
sdup->oqueue.q_buffer, n);
|
&sdup->oqueue, n);
|
||||||
|
|
||||||
chSysLock();
|
chSysLock();
|
||||||
usbStartTransmitI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP);
|
usbStartTransmitI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP);
|
||||||
chnAddFlagsI(sdup, CHN_OUTPUT_EMPTY);
|
|
||||||
sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer;
|
|
||||||
sdup->oqueue.q_counter = chQSizeI(&sdup->oqueue);
|
|
||||||
while (notempty(&sdup->oqueue.q_waiting))
|
|
||||||
chSchReadyI(fifo_remove(&sdup->oqueue.q_waiting))->p_u.rdymsg = Q_OK;
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -201,12 +189,8 @@ void sduObjectInit(SerialUSBDriver *sdup) {
|
||||||
chEvtInit(&sdup->event);
|
chEvtInit(&sdup->event);
|
||||||
sdup->flags = CHN_NO_ERROR;
|
sdup->flags = CHN_NO_ERROR;
|
||||||
sdup->state = SDU_STOP;
|
sdup->state = SDU_STOP;
|
||||||
chIQInit(&sdup->iqueue, sdup->ib, SERIAL_USB_BUFFERS_SIZE, inotify);
|
chIQInit(&sdup->iqueue, sdup->ib, SERIAL_USB_BUFFERS_SIZE, inotify, sdup);
|
||||||
chOQInit(&sdup->oqueue, sdup->ob, SERIAL_USB_BUFFERS_SIZE, onotify);
|
chOQInit(&sdup->oqueue, sdup->ob, SERIAL_USB_BUFFERS_SIZE, onotify, sdup);
|
||||||
/* This is a dirty trick but those pointers are never used because queues
|
|
||||||
are accessed in block mode from the low level.*/
|
|
||||||
sdup->iqueue.q_wrptr = (uint8_t *)sdup;
|
|
||||||
sdup->oqueue.q_rdptr = (uint8_t *)sdup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -299,32 +283,28 @@ bool_t sduRequestsHook(USBDriver *usbp) {
|
||||||
* @param[in] ep endpoint number
|
* @param[in] ep endpoint number
|
||||||
*/
|
*/
|
||||||
void sduDataTransmitted(USBDriver *usbp, usbep_t ep) {
|
void sduDataTransmitted(USBDriver *usbp, usbep_t ep) {
|
||||||
SerialUSBDriver *sdup = usbp->param;
|
|
||||||
size_t n;
|
size_t n;
|
||||||
|
SerialUSBDriver *sdup = usbp->param;
|
||||||
|
|
||||||
#if 0
|
(void)ep;
|
||||||
|
|
||||||
|
chnAddFlagsI(sdup, CHN_OUTPUT_EMPTY);
|
||||||
chSysLockFromIsr();
|
chSysLockFromIsr();
|
||||||
/* If there is any data in the output queue then it is sent within a
|
|
||||||
single packet and the queue is emptied.*/
|
if ((n = chOQGetFullI(&sdup->oqueue)) > 0) {
|
||||||
n = chOQGetFullI(&sdup->oqueue);
|
|
||||||
if (n > 0) {
|
|
||||||
/* The endpoint cannot be busy, we are in the context of the callback,
|
/* The endpoint cannot be busy, we are in the context of the callback,
|
||||||
so it is safe to transmit without a check.*/
|
so it is safe to transmit without a check.*/
|
||||||
chSysUnlockFromIsr();
|
chSysUnlockFromIsr();
|
||||||
|
|
||||||
/* Unlocked to make the potentially long write operation preemptable.*/
|
usbPrepareQueuedTransmit(sdup->config->usbp,
|
||||||
usbWritePacketBuffer(usbp, ep, sdup->oqueue.q_buffer, n);
|
USB_CDC_DATA_REQUEST_EP,
|
||||||
|
&sdup->oqueue, n);
|
||||||
|
|
||||||
chSysLockFromIsr();
|
chSysLockFromIsr();
|
||||||
usbStartTransmitI(usbp, ep);
|
usbStartTransmitI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP);
|
||||||
chnAddFlagsI(sdup, CHN_OUTPUT_EMPTY);
|
|
||||||
sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer;
|
|
||||||
sdup->oqueue.q_counter = chQSizeI(&sdup->oqueue);
|
|
||||||
while (notempty(&sdup->oqueue.q_waiting))
|
|
||||||
chSchReadyI(fifo_remove(&sdup->oqueue.q_waiting))->p_u.rdymsg = Q_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
chSysUnlockFromIsr();
|
chSysUnlockFromIsr();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -336,33 +316,32 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) {
|
||||||
* @param[in] ep endpoint number
|
* @param[in] ep endpoint number
|
||||||
*/
|
*/
|
||||||
void sduDataReceived(USBDriver *usbp, usbep_t ep) {
|
void sduDataReceived(USBDriver *usbp, usbep_t ep) {
|
||||||
|
size_t n, maxsize;
|
||||||
SerialUSBDriver *sdup = usbp->param;
|
SerialUSBDriver *sdup = usbp->param;
|
||||||
|
|
||||||
#if 0
|
(void)ep;
|
||||||
|
|
||||||
|
chnAddFlagsI(sdup, CHN_INPUT_AVAILABLE);
|
||||||
chSysLockFromIsr();
|
chSysLockFromIsr();
|
||||||
/* Writes to the input queue can only happen when the queue has been
|
|
||||||
emptied, then a whole packet is loaded in the queue.*/
|
/* Writes to the input queue can only happen when there is enough space
|
||||||
if (chIQIsEmptyI(&sdup->iqueue)) {
|
to hold at least one packet.*/
|
||||||
|
maxsize = sdup->config->usbp->epc[USB_CDC_DATA_AVAILABLE_EP]->out_maxsize;
|
||||||
|
if ((n = chIQGetEmptyI(&sdup->iqueue)) >= maxsize) {
|
||||||
/* The endpoint cannot be busy, we are in the context of the callback,
|
/* The endpoint cannot be busy, we are in the context of the callback,
|
||||||
so a packet is in the buffer for sure.*/
|
so a packet is in the buffer for sure.*/
|
||||||
size_t n;
|
|
||||||
|
|
||||||
chSysUnlockFromIsr();
|
chSysUnlockFromIsr();
|
||||||
|
|
||||||
/* Unlocked to make the potentially long write operation preemptable.*/
|
n = (n / maxsize) * maxsize;
|
||||||
n = usbReadPacketBuffer(usbp, ep, sdup->iqueue.q_buffer,
|
usbPrepareQueuedReceive(sdup->config->usbp,
|
||||||
SERIAL_USB_BUFFERS_SIZE);
|
USB_CDC_DATA_AVAILABLE_EP,
|
||||||
|
&sdup->iqueue, n);
|
||||||
|
|
||||||
chSysLockFromIsr();
|
chSysLockFromIsr();
|
||||||
usbStartReceiveI(usbp, ep);
|
usbStartReceiveI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP);
|
||||||
chnAddFlagsI(sdup, CHN_INPUT_AVAILABLE);
|
|
||||||
sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer;
|
|
||||||
sdup->iqueue.q_counter = n;
|
|
||||||
while (notempty(&sdup->iqueue.q_waiting))
|
|
||||||
chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
chSysUnlockFromIsr();
|
chSysUnlockFromIsr();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -68,6 +68,7 @@ struct GenericQueue {
|
||||||
uint8_t *q_wrptr; /**< @brief Write pointer. */
|
uint8_t *q_wrptr; /**< @brief Write pointer. */
|
||||||
uint8_t *q_rdptr; /**< @brief Read pointer. */
|
uint8_t *q_rdptr; /**< @brief Read pointer. */
|
||||||
qnotify_t q_notify; /**< @brief Data notification callback. */
|
qnotify_t q_notify; /**< @brief Data notification callback. */
|
||||||
|
void *q_link; /**< @brief Application defined field. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -95,6 +96,17 @@ struct GenericQueue {
|
||||||
* @iclass
|
* @iclass
|
||||||
*/
|
*/
|
||||||
#define chQSpaceI(qp) ((qp)->q_counter)
|
#define chQSpaceI(qp) ((qp)->q_counter)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the queue application-defined link.
|
||||||
|
* @note This function can be called in any context.
|
||||||
|
*
|
||||||
|
* @param[in] qp pointer to a @p GenericQueue structure.
|
||||||
|
* @return The application-defined link.
|
||||||
|
*
|
||||||
|
* @special
|
||||||
|
*/
|
||||||
|
#define chQGetLink(qp) ((qp)->q_link)
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -185,15 +197,17 @@ typedef GenericQueue InputQueue;
|
||||||
* @param[in] buffer pointer to the queue buffer area
|
* @param[in] buffer pointer to the queue buffer area
|
||||||
* @param[in] size size of the queue buffer area
|
* @param[in] size size of the queue buffer area
|
||||||
* @param[in] inotify input notification callback pointer
|
* @param[in] inotify input notification callback pointer
|
||||||
|
* @param[in] link application defined pointer
|
||||||
*/
|
*/
|
||||||
#define _INPUTQUEUE_DATA(name, buffer, size, inotify) { \
|
#define _INPUTQUEUE_DATA(name, buffer, size, inotify, link) { \
|
||||||
_THREADSQUEUE_DATA(name), \
|
_THREADSQUEUE_DATA(name), \
|
||||||
0, \
|
0, \
|
||||||
(uint8_t *)(buffer), \
|
(uint8_t *)(buffer), \
|
||||||
(uint8_t *)(buffer) + (size), \
|
(uint8_t *)(buffer) + (size), \
|
||||||
(uint8_t *)(buffer), \
|
(uint8_t *)(buffer), \
|
||||||
(uint8_t *)(buffer), \
|
(uint8_t *)(buffer), \
|
||||||
inotify \
|
(inotify), \
|
||||||
|
(link) \
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -205,9 +219,10 @@ typedef GenericQueue InputQueue;
|
||||||
* @param[in] buffer pointer to the queue buffer area
|
* @param[in] buffer pointer to the queue buffer area
|
||||||
* @param[in] size size of the queue buffer area
|
* @param[in] size size of the queue buffer area
|
||||||
* @param[in] inotify input notification callback pointer
|
* @param[in] inotify input notification callback pointer
|
||||||
|
* @param[in] link application defined pointer
|
||||||
*/
|
*/
|
||||||
#define INPUTQUEUE_DECL(name, buffer, size, inotify) \
|
#define INPUTQUEUE_DECL(name, buffer, size, inotify, link) \
|
||||||
InputQueue name = _INPUTQUEUE_DATA(name, buffer, size, inotify)
|
InputQueue name = _INPUTQUEUE_DATA(name, buffer, size, inotify, link)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @extends GenericQueue
|
* @extends GenericQueue
|
||||||
|
@ -299,15 +314,17 @@ typedef GenericQueue OutputQueue;
|
||||||
* @param[in] buffer pointer to the queue buffer area
|
* @param[in] buffer pointer to the queue buffer area
|
||||||
* @param[in] size size of the queue buffer area
|
* @param[in] size size of the queue buffer area
|
||||||
* @param[in] onotify output notification callback pointer
|
* @param[in] onotify output notification callback pointer
|
||||||
|
* @param[in] link application defined pointer
|
||||||
*/
|
*/
|
||||||
#define _OUTPUTQUEUE_DATA(name, buffer, size, onotify) { \
|
#define _OUTPUTQUEUE_DATA(name, buffer, size, onotify, link) { \
|
||||||
_THREADSQUEUE_DATA(name), \
|
_THREADSQUEUE_DATA(name), \
|
||||||
(size), \
|
(size), \
|
||||||
(uint8_t *)(buffer), \
|
(uint8_t *)(buffer), \
|
||||||
(uint8_t *)(buffer) + (size), \
|
(uint8_t *)(buffer) + (size), \
|
||||||
(uint8_t *)(buffer), \
|
(uint8_t *)(buffer), \
|
||||||
(uint8_t *)(buffer), \
|
(uint8_t *)(buffer), \
|
||||||
onotify \
|
(onotify), \
|
||||||
|
(link) \
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -319,21 +336,24 @@ typedef GenericQueue OutputQueue;
|
||||||
* @param[in] buffer pointer to the queue buffer area
|
* @param[in] buffer pointer to the queue buffer area
|
||||||
* @param[in] size size of the queue buffer area
|
* @param[in] size size of the queue buffer area
|
||||||
* @param[in] onotify output notification callback pointer
|
* @param[in] onotify output notification callback pointer
|
||||||
|
* @param[in] link application defined pointer
|
||||||
*/
|
*/
|
||||||
#define OUTPUTQUEUE_DECL(name, buffer, size, onotify) \
|
#define OUTPUTQUEUE_DECL(name, buffer, size, onotify, link) \
|
||||||
OutputQueue name = _OUTPUTQUEUE_DATA(name, buffer, size, onotify)
|
OutputQueue name = _OUTPUTQUEUE_DATA(name, buffer, size, onotify, link)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
void chIQInit(InputQueue *iqp, uint8_t *bp, size_t size, qnotify_t infy);
|
void chIQInit(InputQueue *iqp, uint8_t *bp, size_t size, qnotify_t infy,
|
||||||
|
void *link);
|
||||||
void chIQResetI(InputQueue *iqp);
|
void chIQResetI(InputQueue *iqp);
|
||||||
msg_t chIQPutI(InputQueue *iqp, uint8_t b);
|
msg_t chIQPutI(InputQueue *iqp, uint8_t b);
|
||||||
msg_t chIQGetTimeout(InputQueue *iqp, systime_t time);
|
msg_t chIQGetTimeout(InputQueue *iqp, systime_t time);
|
||||||
size_t chIQReadTimeout(InputQueue *iqp, uint8_t *bp,
|
size_t chIQReadTimeout(InputQueue *iqp, uint8_t *bp,
|
||||||
size_t n, systime_t time);
|
size_t n, systime_t time);
|
||||||
|
|
||||||
void chOQInit(OutputQueue *oqp, uint8_t *bp, size_t size, qnotify_t onfy);
|
void chOQInit(OutputQueue *oqp, uint8_t *bp, size_t size, qnotify_t onfy,
|
||||||
|
void *link);
|
||||||
void chOQResetI(OutputQueue *oqp);
|
void chOQResetI(OutputQueue *oqp);
|
||||||
msg_t chOQPutTimeout(OutputQueue *oqp, uint8_t b, systime_t time);
|
msg_t chOQPutTimeout(OutputQueue *oqp, uint8_t b, systime_t time);
|
||||||
msg_t chOQGetI(OutputQueue *oqp);
|
msg_t chOQGetI(OutputQueue *oqp);
|
||||||
|
|
|
@ -83,16 +83,19 @@ static msg_t qwait(GenericQueue *qp, systime_t time) {
|
||||||
* @param[in] size size of the queue buffer
|
* @param[in] size size of the queue buffer
|
||||||
* @param[in] infy pointer to a callback function that is invoked when
|
* @param[in] infy pointer to a callback function that is invoked when
|
||||||
* data is read from the queue. The value can be @p NULL.
|
* data is read from the queue. The value can be @p NULL.
|
||||||
|
* @param[in] link application defined pointer
|
||||||
*
|
*
|
||||||
* @init
|
* @init
|
||||||
*/
|
*/
|
||||||
void chIQInit(InputQueue *iqp, uint8_t *bp, size_t size, qnotify_t infy) {
|
void chIQInit(InputQueue *iqp, uint8_t *bp, size_t size, qnotify_t infy,
|
||||||
|
void *link) {
|
||||||
|
|
||||||
queue_init(&iqp->q_waiting);
|
queue_init(&iqp->q_waiting);
|
||||||
iqp->q_counter = 0;
|
iqp->q_counter = 0;
|
||||||
iqp->q_buffer = iqp->q_rdptr = iqp->q_wrptr = bp;
|
iqp->q_buffer = iqp->q_rdptr = iqp->q_wrptr = bp;
|
||||||
iqp->q_top = bp + size;
|
iqp->q_top = bp + size;
|
||||||
iqp->q_notify = infy;
|
iqp->q_notify = infy;
|
||||||
|
iqp->q_link = link;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -260,16 +263,19 @@ size_t chIQReadTimeout(InputQueue *iqp, uint8_t *bp,
|
||||||
* @param[in] size size of the queue buffer
|
* @param[in] size size of the queue buffer
|
||||||
* @param[in] onfy pointer to a callback function that is invoked when
|
* @param[in] onfy pointer to a callback function that is invoked when
|
||||||
* data is written to the queue. The value can be @p NULL.
|
* data is written to the queue. The value can be @p NULL.
|
||||||
|
* @param[in] link application defined pointer
|
||||||
*
|
*
|
||||||
* @init
|
* @init
|
||||||
*/
|
*/
|
||||||
void chOQInit(OutputQueue *oqp, uint8_t *bp, size_t size, qnotify_t onfy) {
|
void chOQInit(OutputQueue *oqp, uint8_t *bp, size_t size, qnotify_t onfy,
|
||||||
|
void *link) {
|
||||||
|
|
||||||
queue_init(&oqp->q_waiting);
|
queue_init(&oqp->q_waiting);
|
||||||
oqp->q_counter = size;
|
oqp->q_counter = size;
|
||||||
oqp->q_buffer = oqp->q_rdptr = oqp->q_wrptr = bp;
|
oqp->q_buffer = oqp->q_rdptr = oqp->q_wrptr = bp;
|
||||||
oqp->q_top = bp + size;
|
oqp->q_top = bp + size;
|
||||||
oqp->q_notify = onfy;
|
oqp->q_notify = onfy;
|
||||||
|
oqp->q_link = link;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -144,6 +144,7 @@
|
||||||
3484947)(backported to 2.4.1).
|
3484947)(backported to 2.4.1).
|
||||||
- FIX: Fixed various minor documentation errors (bug 3484942)(backported
|
- FIX: Fixed various minor documentation errors (bug 3484942)(backported
|
||||||
to 2.4.1).
|
to 2.4.1).
|
||||||
|
- NEW: Added an application-defined field to I/O queues (a void pointer).
|
||||||
- NEW: Added board files for Maple Mini STM32F103, contributed by Wagner
|
- NEW: Added board files for Maple Mini STM32F103, contributed by Wagner
|
||||||
Sartori Junior.
|
Sartori Junior.
|
||||||
- NEW: Added SSP1 capability to the LPC13xx SPI driver.
|
- NEW: Added SSP1 capability to the LPC13xx SPI driver.
|
||||||
|
|
|
@ -460,7 +460,7 @@ static void bmk9_execute(void) {
|
||||||
static uint8_t ib[16];
|
static uint8_t ib[16];
|
||||||
static InputQueue iq;
|
static InputQueue iq;
|
||||||
|
|
||||||
chIQInit(&iq, ib, sizeof(ib), NULL);
|
chIQInit(&iq, ib, sizeof(ib), NULL, NULL);
|
||||||
n = 0;
|
n = 0;
|
||||||
test_wait_tick();
|
test_wait_tick();
|
||||||
test_start_timer(1000);
|
test_start_timer(1000);
|
||||||
|
|
|
@ -67,8 +67,8 @@ static void notify(GenericQueue *qp) {
|
||||||
* variables are explicitly initialized in each test case. It is done in order
|
* variables are explicitly initialized in each test case. It is done in order
|
||||||
* to test the macros.
|
* to test the macros.
|
||||||
*/
|
*/
|
||||||
static INPUTQUEUE_DECL(iq, test.wa.T0, TEST_QUEUES_SIZE, notify);
|
static INPUTQUEUE_DECL(iq, test.wa.T0, TEST_QUEUES_SIZE, notify, NULL);
|
||||||
static OUTPUTQUEUE_DECL(oq, test.wa.T1, TEST_QUEUES_SIZE, notify);
|
static OUTPUTQUEUE_DECL(oq, test.wa.T1, TEST_QUEUES_SIZE, notify, NULL);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @page test_queues_001 Input Queues functionality and APIs
|
* @page test_queues_001 Input Queues functionality and APIs
|
||||||
|
@ -81,7 +81,7 @@ static OUTPUTQUEUE_DECL(oq, test.wa.T1, TEST_QUEUES_SIZE, notify);
|
||||||
|
|
||||||
static void queues1_setup(void) {
|
static void queues1_setup(void) {
|
||||||
|
|
||||||
chIQInit(&iq, wa[0], TEST_QUEUES_SIZE, notify);
|
chIQInit(&iq, wa[0], TEST_QUEUES_SIZE, notify, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static msg_t thread1(void *p) {
|
static msg_t thread1(void *p) {
|
||||||
|
@ -168,7 +168,7 @@ ROMCONST struct testcase testqueues1 = {
|
||||||
|
|
||||||
static void queues2_setup(void) {
|
static void queues2_setup(void) {
|
||||||
|
|
||||||
chOQInit(&oq, wa[0], TEST_QUEUES_SIZE, notify);
|
chOQInit(&oq, wa[0], TEST_QUEUES_SIZE, notify, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static msg_t thread2(void *p) {
|
static msg_t thread2(void *p) {
|
||||||
|
|
Loading…
Reference in New Issue