udp fifo stuff

This commit is contained in:
Olaf Rempel 2008-02-06 22:18:33 +01:00
parent 23be9b58b9
commit 6422cf0bd8
4 changed files with 217 additions and 151 deletions

View File

@ -23,6 +23,9 @@ uint32_t fifo_remove(struct fifo *fifo, uint32_t len);
uint32_t fifo_rxpdc(struct fifo *fifo, AT91S_PDC *pdc, uint16_t maxsize); uint32_t fifo_rxpdc(struct fifo *fifo, AT91S_PDC *pdc, uint16_t maxsize);
uint32_t fifo_txpdc(struct fifo *fifo, AT91S_PDC *pdc, uint16_t maxsize); uint32_t fifo_txpdc(struct fifo *fifo, AT91S_PDC *pdc, uint16_t maxsize);
uint32_t fifo_txudp(struct fifo *fifo, uint32_t ep, uint32_t maxsize);
uint32_t fifo_rxudp(struct fifo *fifo, uint32_t ep, uint32_t maxsize);
uint32_t fifo_putbyte(struct fifo *fifo, char c); uint32_t fifo_putbyte(struct fifo *fifo, char c);
uint32_t fifo_getbyte(struct fifo *fifo, char *p); uint32_t fifo_getbyte(struct fifo *fifo, char *p);

7
main.c
View File

@ -38,7 +38,7 @@ static uint32_t pitc_test(struct pitc_timer *timer)
*AT91C_PIOA_SODR = i; *AT91C_PIOA_SODR = i;
i = i ^ LED_GREEN; i = i ^ LED_GREEN;
*AT91C_PIOA_CODR = i; *AT91C_PIOA_CODR = i;
/*
struct rc_values rc; struct rc_values rc;
uint32_t count = rcontrol_getvalues(&rc); uint32_t count = rcontrol_getvalues(&rc);
@ -48,11 +48,12 @@ static uint32_t pitc_test(struct pitc_timer *timer)
printf("%+5d ", rc.chan[j]); printf("%+5d ", rc.chan[j]);
printf("\r"); printf("\r");
*/
return PITC_RESTART_TIMER; return PITC_RESTART_TIMER;
} }
static struct pitc_timer pitc_test_timer = { static struct pitc_timer pitc_test_timer = {
.interval = 1, .interval = 10,
.func = &pitc_test, .func = &pitc_test,
}; };
@ -83,7 +84,7 @@ int main(void)
at91_twi_init(); at91_twi_init();
/* usb */ /* usb */
// at91_udp_init(); at91_udp_init();
printf("static alloc: %5ld bytes\n\r", static_alloc_used()); printf("static alloc: %5ld bytes\n\r", static_alloc_used());

View File

@ -17,14 +17,13 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#include <stdio.h> #include <stdio.h>
#include "AT91SAM7S256.h" #include "AT91SAM7S256.h"
#include "at91_pio.h" #include "at91_pio.h"
#include "board.h" #include "board.h"
#include "fifo.h"
#include "usb_ch9.h" #include "usb_ch9.h"
#include "usb_cdc.h" #include "usb_cdc.h"
#include "usb_dfu.h"
#define csr_clear_flags(csr, flags) \ #define csr_clear_flags(csr, flags) \
while ((csr) & (flags)) \ while ((csr) & (flags)) \
@ -34,25 +33,37 @@
while (((csr) & (flags)) != (flags)) \ while (((csr) & (flags)) != (flags)) \
(csr) |= (flags); (csr) |= (flags);
// TODO: name? struct ep_transfer {
struct udp_transfer {
uint16_t address;
uint16_t maxpkt;
// TODO: last bank used / ping pong
// TODO: direction (IN/OUT)
uint16_t length; uint16_t length;
uint16_t curpos; uint16_t curpos;
char *data; char *data;
void (*complete_cb)(void); void (*complete_cb)(void);
// TODO: privdata?
}; };
struct ep_ctx {
uint16_t maxpktsize;
uint16_t flags;
union {
struct ep_transfer *transfer;
struct fifo *fifo;
};
};
#define CTX_TRANSFER 0x01 /* ctx use ep_transfer struct */
#define CTX_FIFO 0x02 /* ctx use fifo */
#define CTX_IN 0x04 /* write to the host */
#define CTX_OUT 0x08 /* read from the host */
#define CTX_RXBANK0 0x10
#define CTX_RXBANK1 0x20
static struct ep_transfer ep0_transfer;
static struct ep_ctx ep_ctx[4];
static uint16_t current_address; static uint16_t current_address;
static uint16_t current_config; static uint16_t current_config;
static uint16_t current_interface; static uint16_t current_interface;
static struct udp_transfer ep_transfer[4];
static const struct usb_device_descriptor dev_descriptor = { static const struct usb_device_descriptor dev_descriptor = {
.bLength = sizeof(struct usb_device_descriptor), .bLength = sizeof(struct usb_device_descriptor),
@ -76,8 +87,6 @@ struct my_config {
struct usb_interface_descriptor data_iface; struct usb_interface_descriptor data_iface;
struct usb_endpoint_descriptor dataout_ep; struct usb_endpoint_descriptor dataout_ep;
struct usb_endpoint_descriptor datain_ep; struct usb_endpoint_descriptor datain_ep;
struct usb_interface_descriptor dfu_iface;
struct usb_dfu_descriptor dfu;
} __attribute__ ((packed)); } __attribute__ ((packed));
static const struct my_config cfg_descriptor = { static const struct my_config cfg_descriptor = {
@ -85,7 +94,7 @@ static const struct my_config cfg_descriptor = {
.bLength = sizeof(struct usb_config_descriptor), .bLength = sizeof(struct usb_config_descriptor),
.bDescriptorType = USB_DT_CONFIG, .bDescriptorType = USB_DT_CONFIG,
.wTotalLength = sizeof(struct my_config), .wTotalLength = sizeof(struct my_config),
.bNumInterfaces = 3, .bNumInterfaces = 2,
.bConfigurationValue = 1, .bConfigurationValue = 1,
.bmAttributes = USB_CONFIG_ATT_SELFPOWER | USB_CONFIG_ATT_WAKEUP, .bmAttributes = USB_CONFIG_ATT_SELFPOWER | USB_CONFIG_ATT_WAKEUP,
.bMaxPower = 50, .bMaxPower = 50,
@ -154,88 +163,79 @@ static const struct my_config cfg_descriptor = {
.bmAttributes = USB_ENDPOINT_XFER_BULK, .bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = 64, .wMaxPacketSize = 64,
}, },
.dfu_iface = {
.bLength = sizeof(struct usb_interface_descriptor),
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 2,
.bNumEndpoints = 0,
.bInterfaceClass = USB_CLASS_APP_SPEC,
.bInterfaceSubClass = 0x01, /* DFU */
},
.dfu = {
.bLength = sizeof(struct usb_dfu_descriptor),
.bDescriptorType = USB_TYPE_DFU,
.bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_CAN_UPLOAD,
.wDetachTimeOut = 0xff00,
.wTransferSize = AT91C_IFLASH_PAGE_SIZE,
.bcdDFUVersion = 0x0100,
},
}; };
static struct dfu_status dfu_status = { static void ep_transfer_send(uint32_t ep, char *data, uint32_t length,
.bStatus = DFU_STATUS_OK, void (*complete_cb)(void))
.bwPollTimeout = {0x00, 0x04, 0x00},
.bState = DFU_STATE_appIDLE,
};
static void udp_configure_ep(const struct usb_endpoint_descriptor *desc)
{ {
/* get endpoint type (ctrl, iso, bulb, int) */ struct ep_ctx *ctx = &ep_ctx[ep];
uint32_t eptype = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; // printf("ep_transfer_send(%ld) size=%ld flags=0x%x\n\r", ep, length, ctx->flags);
if (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) if (!(ctx->flags & CTX_TRANSFER) || (ctx->flags & (CTX_IN | CTX_OUT)))
eptype |= 0x04;
/* get endpoint address, set Max Packet Size */
uint32_t address = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
ep_transfer[address].maxpkt = desc->wMaxPacketSize;
/* configure UDP endpoint and enable interrupt */
AT91C_UDP_CSR[address] = AT91C_UDP_EPEDS | (eptype << 8);
*AT91C_UDP_IER = (1 << address);
}
static void udp_fill_fifo(struct udp_transfer *trans)
{
uint16_t ep = trans->address;
if (AT91C_UDP_CSR[ep] & AT91C_UDP_TXPKTRDY) {
printf("TX!RDY\n\r");
return; return;
}
/* fill fifo */ /* from buffer to usb */
uint16_t max = trans->maxpkt; ctx->flags |= CTX_IN;
while (trans->curpos < trans->length && max--)
AT91C_UDP_FDR[ep] = trans->data[trans->curpos++];
/* trigger transmission */ struct ep_transfer *transfer = ctx->transfer;
transfer->length = length;
transfer->curpos = 0;
transfer->data = data;
transfer->complete_cb = complete_cb;
uint32_t maxsize = ctx->maxpktsize;
/* get data from transfer */
while (transfer->curpos < transfer->length && maxsize--)
AT91C_UDP_FDR[ep] = transfer->data[transfer->curpos++];
/* trigger tx */
AT91C_UDP_CSR[ep] |= AT91C_UDP_TXPKTRDY; AT91C_UDP_CSR[ep] |= AT91C_UDP_TXPKTRDY;
} }
static void udp_send_data(struct udp_transfer *trans, const char *data, static void ep_transfer_receive(uint32_t ep, char *data, uint32_t length,
uint32_t length, void (*complete_cb)(void)) void (*complete_cb)(void))
{ {
if (trans->length != trans->curpos) { struct ep_ctx *ctx = &ep_ctx[ep];
printf("TXOVF\n\r"); // printf("ep_transfer_receive(%ld) size=%ld flags=0x%x\n\r", ep, length, ctx->flags);
if (!(ctx->flags & CTX_TRANSFER) || (ctx->flags & (CTX_IN | CTX_OUT)))
return; return;
}
/* setup data transmission */ /* from usb to buffer */
trans->length = length; ctx->flags |= CTX_OUT;
trans->curpos = 0;
trans->data = (char *)data;
trans->complete_cb = complete_cb;
udp_fill_fifo(trans); struct ep_transfer *transfer = ctx->transfer;
transfer->length = length;
transfer->curpos = 0;
transfer->data = data;
transfer->complete_cb = complete_cb;
} }
/* stalls the endpoint */ /* stalls the endpoint */
static void udp_send_stall(uint32_t ep) static void ep_send_stall(uint32_t ep)
{ {
printf("stall\n\r"); printf("stall\n\r");
AT91C_UDP_CSR[ep] |= AT91C_UDP_FORCESTALL; AT91C_UDP_CSR[ep] |= AT91C_UDP_FORCESTALL;
} }
static void udp_configure_ep(const struct usb_endpoint_descriptor *desc)
{
/* get endpoint address, set Max Packet Size */
uint32_t ep = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
ep_ctx[ep].maxpktsize = desc->wMaxPacketSize;
/* get endpoint type (ctrl, iso, bulb, int) */
uint32_t eptype = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
if (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
eptype |= 0x04;
} else {
ep_ctx[ep].flags |= CTX_RXBANK0;
}
/* configure UDP endpoint and enable interrupt */
AT91C_UDP_CSR[ep] = AT91C_UDP_EPEDS | (eptype << 8);
*AT91C_UDP_IER = (1 << ep);
}
/* /*
* set local address * set local address
* (USB_REQ_SET_ADDRESS callback) * (USB_REQ_SET_ADDRESS callback)
@ -265,7 +265,7 @@ static void udp_txcb_setinterface(void)
printf("claim interface %d\n\r", current_interface); printf("claim interface %d\n\r", current_interface);
} }
static void udp_handle_ctrlrequest(struct usb_ctrlrequest *req) static void ep_handle_ctrlrequest(struct usb_ctrlrequest *req)
{ {
printf("typ:0x%02x req:0x%02x val:0x%04x idx:0x%04x len:0x%04x\n\r", printf("typ:0x%02x req:0x%02x val:0x%04x idx:0x%04x len:0x%04x\n\r",
req->bRequestType, req->bRequest, req->wValue, req->wIndex, req->wLength); req->bRequestType, req->bRequest, req->wValue, req->wIndex, req->wLength);
@ -275,89 +275,81 @@ static void udp_handle_ctrlrequest(struct usb_ctrlrequest *req)
switch (req->bRequest) { switch (req->bRequest) {
case USB_REQ_SET_ADDRESS: /* 0x05 */ case USB_REQ_SET_ADDRESS: /* 0x05 */
current_address = req->wValue; current_address = req->wValue;
udp_send_data(&ep_transfer[0], NULL, 0, udp_txcb_setaddress); ep_transfer_send(0, NULL, 0, udp_txcb_setaddress);
break; break;
case USB_REQ_GET_DESCRIPTOR: /* 0x06 */ case USB_REQ_GET_DESCRIPTOR: /* 0x06 */
switch (req->wValue >> 8) { switch (req->wValue >> 8) {
case USB_DT_DEVICE: /* 0x01 */ case USB_DT_DEVICE: /* 0x01 */
udp_send_data(&ep_transfer[0], (const char *)&dev_descriptor, ep_transfer_send(0, (char *)&dev_descriptor,
MIN(sizeof(dev_descriptor), req->wLength), NULL); MIN(sizeof(dev_descriptor), req->wLength),
NULL);
break; break;
case USB_DT_CONFIG: /* 0x02 */ case USB_DT_CONFIG: /* 0x02 */
udp_send_data(&ep_transfer[0], (const char *)&cfg_descriptor, ep_transfer_send(0, (char *)&cfg_descriptor,
MIN(sizeof(cfg_descriptor), req->wLength), NULL); MIN(sizeof(cfg_descriptor), req->wLength),
NULL);
break; break;
default: default:
udp_send_stall(0); ep_send_stall(0);
break; break;
} }
break; break;
case USB_REQ_SET_CONFIGURATION: /* 0x09 */ case USB_REQ_SET_CONFIGURATION: /* 0x09 */
current_config = req->wValue; current_config = req->wValue;
udp_send_data(&ep_transfer[0], NULL, 0, udp_txcb_setconfig); ep_transfer_send(0, NULL, 0, udp_txcb_setconfig);
break; break;
default: default:
udp_send_stall(0); ep_send_stall(0);
break; break;
} }
break; break;
case (USB_TYPE_STANDARD | USB_RECIP_INTERFACE): /* 0x01/0x81 */ case (USB_TYPE_STANDARD | USB_RECIP_INTERFACE): /* 0x01/0x81 */
// TODO: follow current_interface // TODO: follow current_interface
switch (req->bRequest) { switch (req->bRequest) {
case USB_REQ_SET_INTERFACE: /* 0x0b */ case USB_REQ_SET_INTERFACE: /* 0x0b */
current_interface = req->wValue; current_interface = req->wValue;
udp_send_data(&ep_transfer[0], NULL, 0, udp_txcb_setinterface); ep_transfer_send(0, NULL, 0, udp_txcb_setinterface);
break; break;
default: default:
udp_send_stall(0); ep_send_stall(0);
break; break;
} }
break; break;
case (USB_TYPE_CLASS | USB_RECIP_INTERFACE): /* 0x21/0xA1 */ case (USB_TYPE_CLASS | USB_RECIP_INTERFACE): /* 0x21/0xA1 */
// TODO: follow current_interface // TODO: follow current_interface
switch (req->bRequest) { switch (req->bRequest) {
case USB_REQ_DFU_DETACH: /* 0x00 */ case USB_CDC_REQ_SET_LINE_CODING: /* 0x20 */
udp_send_data(&ep_transfer[0], NULL, 0, NULL); /* read 7 bytes */
break;
case USB_REQ_DFU_GETSTATUS: /* 0x03 */
udp_send_data(&ep_transfer[0], (const char *)&dfu_status,
MIN(sizeof(struct dfu_status), req->wLength), NULL);
break; break;
case USB_CDC_REQ_SET_LINE_CODING: /* 0x20 */ case USB_CDC_REQ_SET_CONTROL_LINE_STATE: /* 0x22 */
// TODO: read 7 data bytes ep_transfer_send(0, NULL, 0, NULL);
break;
case USB_CDC_REQ_SET_CONTROL_LINE_STATE: /* 0x22 */
udp_send_data(&ep_transfer[0], NULL, 0, NULL);
break; break;
default: default:
udp_send_stall(0); ep_send_stall(0);
break; break;
} }
break; break;
default: default:
udp_send_stall(0); ep_send_stall(0);
break; break;
} }
} }
static void udp_handle_ep(uint32_t ep) static void udp_handle_ep(uint32_t ep)
{ {
AT91_REG *csr = &AT91C_UDP_CSR[ep];
/* endpoint enabled? */ /* endpoint enabled? */
AT91_REG *csr = &AT91C_UDP_CSR[ep];
if (!(*csr & AT91C_UDP_EPEDS)) if (!(*csr & AT91C_UDP_EPEDS))
return; return;
@ -372,23 +364,42 @@ static void udp_handle_ep(uint32_t ep)
if (req.bRequestType & USB_DIR_IN) if (req.bRequestType & USB_DIR_IN)
*csr |= AT91C_UDP_DIR; *csr |= AT91C_UDP_DIR;
/* clear interrupt (THIS MUST USE csr_clear_flags()!) */ /* clear interrupt - *MUST* use csr_clear_flags() here */
csr_clear_flags(*csr, AT91C_UDP_RXSETUP); csr_clear_flags(*csr, AT91C_UDP_RXSETUP);
udp_handle_ctrlrequest(&req); ep_handle_ctrlrequest(&req);
} }
/* transmit complete? */ /* transmit complete? */
if (*csr & AT91C_UDP_TXCOMP) { if (*csr & AT91C_UDP_TXCOMP) {
struct udp_transfer *trans = &ep_transfer[ep]; struct ep_ctx *ctx = &ep_ctx[ep];
/* refill fifo, if transfer is incomplete */ if (ctx->flags & CTX_FIFO) {
if (trans->length != trans->curpos) /* get data from fifo */
udp_fill_fifo(trans); if (fifo_txudp(ctx->fifo, ep, ctx->maxpktsize))
AT91C_UDP_CSR[ep] |= AT91C_UDP_TXPKTRDY;
/* execute callback when transfer is complete */ } else if ((ctx->flags & (CTX_TRANSFER | CTX_IN)) == (CTX_TRANSFER | CTX_IN)) {
else if (trans->complete_cb) /* transfer not complete */
trans->complete_cb(); struct ep_transfer *transfer = ctx->transfer;
if (transfer->length != transfer->curpos) {
uint32_t maxsize = ctx->maxpktsize;
/* get data from transfer */
while (transfer->curpos < transfer->length && maxsize--)
AT91C_UDP_FDR[ep] = transfer->data[transfer->curpos++];
/* trigger tx */
AT91C_UDP_CSR[ep] |= AT91C_UDP_TXPKTRDY;
/* transfer complete, execute callback */
} else {
ctx->flags &= ~CTX_IN;
if (transfer->complete_cb)
transfer->complete_cb();
}
}
/* clear interrupt */ /* clear interrupt */
*csr &= ~(AT91C_UDP_TXCOMP); *csr &= ~(AT91C_UDP_TXCOMP);
@ -400,33 +411,59 @@ static void udp_handle_ep(uint32_t ep)
/* data ready to read? */ /* data ready to read? */
if (*csr & (AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1)) { if (*csr & (AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1)) {
struct ep_ctx *ctx = &ep_ctx[ep];
uint16_t len = (*csr & AT91C_UDP_RXBYTECNT) >> 16; uint16_t len = (*csr & AT91C_UDP_RXBYTECNT) >> 16;
if (len) {
printf("rx: ");
while (len--)
printf("0x%02x ", AT91C_UDP_FDR[ep]);
printf("\n\r"); // TODO: only ep0 status OUT?
if (!len && (ctx->flags & CTX_TRANSFER)) {
} else { ctx->flags &= ~(CTX_OUT | CTX_IN);
/* clear a pending transfer! */ ctx->transfer->length = 0;
ep_transfer[ep].length = 0; ctx->transfer->curpos = 0;
ep_transfer[ep].curpos = 0;
} }
/* TODO: ping pong FIFOs */ if (ctx->flags & CTX_FIFO) {
if (*csr & AT91C_UDP_RX_DATA_BK0) fifo_rxudp(ctx->fifo, ep, len);
csr_clear_flags(*csr, AT91C_UDP_RX_DATA_BK0);
if (*csr & AT91C_UDP_RX_DATA_BK1) } else if ((ctx->flags & (CTX_TRANSFER | CTX_OUT)) == (CTX_TRANSFER | CTX_OUT)) {
csr_clear_flags(*csr, AT91C_UDP_RX_DATA_BK1);
/* transfer not complete */
struct ep_transfer *transfer = ctx->transfer;
if (transfer->length != transfer->curpos) {
/* get data from transfer */
while (transfer->curpos < transfer->length && len--)
transfer->data[transfer->curpos++] = AT91C_UDP_FDR[ep];
}
/* test again */
if (transfer->length == transfer->curpos) {
ctx->flags &= ~CTX_OUT;
if (transfer->complete_cb)
transfer->complete_cb();
}
}
if (ctx->flags & CTX_RXBANK0) {
if (*csr & AT91C_UDP_RX_DATA_BK0)
csr_clear_flags(*csr, AT91C_UDP_RX_DATA_BK0);
/* all but ep0 have ping pong buffers */
if (ep > 0)
ctx->flags = (ctx->flags & ~CTX_RXBANK0) | CTX_RXBANK1;
} else if (ctx->flags & CTX_RXBANK1) {
if (*csr & AT91C_UDP_RX_DATA_BK1)
csr_clear_flags(*csr, AT91C_UDP_RX_DATA_BK1);
ctx->flags = (ctx->flags & ~CTX_RXBANK1) | CTX_RXBANK0;
}
} }
} }
static void udp_isr(void) static void udp_isr(void)
{ {
uint32_t isr = *AT91C_UDP_ISR; uint32_t isr = *AT91C_UDP_ISR;
if (isr & AT91C_UDP_ENDBUSRES) { if (isr & AT91C_UDP_ENDBUSRES) {
AT91S_UDP *udp = AT91C_BASE_UDP; AT91S_UDP *udp = AT91C_BASE_UDP;
@ -435,15 +472,13 @@ static void udp_isr(void)
AT91C_UDP_EP2 | AT91C_UDP_EP3) ; AT91C_UDP_EP2 | AT91C_UDP_EP3) ;
udp->UDP_RSTEP = 0; udp->UDP_RSTEP = 0;
/* clear all transfers, set default values */ /* init ep0 */
uint32_t i; struct ep_ctx *ctx = &ep_ctx[0];
for (i = 0; i < 4; i++) { ctx->maxpktsize = 8;
ep_transfer[i].address = i; ctx->flags = CTX_TRANSFER | CTX_RXBANK0;
ep_transfer[i].maxpkt = 64; ctx->transfer = &ep0_transfer;
ep_transfer[i].length = 0; ctx->transfer->length = 0;
ep_transfer[i].curpos = 0; ctx->transfer->curpos = 0;
}
ep_transfer[0].maxpkt = 8;
/* Configure endpoint0 as Control EP */ /* Configure endpoint0 as Control EP */
udp->UDP_CSR[0] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL); udp->UDP_CSR[0] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL);
@ -458,7 +493,7 @@ static void udp_isr(void)
/* Handle Endpoint Interrupts */ /* Handle Endpoint Interrupts */
uint32_t i; uint32_t i;
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
if (isr & (1<<i)) if (isr & *AT91C_UDP_IMR & (1<<i))
udp_handle_ep(i); udp_handle_ep(i);
} }

View File

@ -174,6 +174,33 @@ uint32_t fifo_txpdc(struct fifo *fifo, AT91S_PDC *pdc, uint16_t maxsize)
return fifo->pdc_tx; return fifo->pdc_tx;
} }
uint32_t fifo_rxudp(struct fifo *fifo, uint32_t ep, uint32_t maxsize)
{
uint32_t left = fifo->size - fifo_used(fifo);
if (left > maxsize)
left = maxsize;
uint32_t count = left;
while (count--)
fifo->buf[fifo->in++ & FIFO_MASK(fifo)] = AT91C_UDP_FDR[ep];
return left;
}
uint32_t fifo_txudp(struct fifo *fifo, uint32_t ep, uint32_t maxsize)
{
uint32_t size = fifo_used(fifo);
if (size > maxsize)
size = maxsize;
uint32_t count = size;
while (count--)
AT91C_UDP_FDR[ep] = fifo->buf[fifo->out++ & FIFO_MASK(fifo)];
return size;
}
/* /*
* put one byte into the fifo * put one byte into the fifo
* returns 0 if fifo was full * returns 0 if fifo was full