Hi, I encountered problems using the USB-CDC-example out of the Atmel software package 1.5 with an AT91SAM9260. Sometimes, when sending data using USBD_Write, the USB driver hangs in the function/define SET_CSR waiting for the AT91C_UDP_TXPKTRDY flag. Other times, USBD_Write returns USBD_STATUS_LOCKED all times, while receiving data works fine.
char USBD_Write(unsigned char eptnum, const void *data, unsigned int size, TransferCallback callback, void *argument) { Endpoint *endpoint = &(endpoints[eptnum]); Transfer *transfer = &(endpoint->transfer); // Check that the endpoint is in Idle state if (endpoint->state != UDP_ENDPOINT_IDLE) { return USBD_STATUS_LOCKED; } trace_LOG(trace_INFO, "Write%d(%u) ", eptnum, size); // Setup the transfer descriptor transfer->data = (char *) data; transfer->remaining = size; transfer->buffered = 0; transfer->transferred = 0; transfer->callback = callback; transfer->argument = argument; // Send the first packet endpoint->state = UDP_ENDPOINT_SENDING; while((AT91C_BASE_UDP->UDP_CSR[eptnum]&AT91C_UDP_TXPKTRDY)==AT91C_UDP_TXPKTRDY); UDP_WritePayload(eptnum); SET_CSR(eptnum, AT91C_UDP_TXPKTRDY); // If double buffering is enabled and there is data remaining, // prepare another packet if ((BOARD_USB_ENDPOINTS_BANKS(eptnum) > 1) && (transfer->remaining > 0)) { UDP_WritePayload(eptnum); } // Enable interrupt on endpoint AT91C_BASE_UDP->UDP_IER = 1 << eptnum; return USBD_STATUS_SUCCESS; }
Does someone else have similar problems?
And another question concerning the USB-CDC-driver: Under WinXP usbser.sys is used as driver for the device and it can be used as a serial port. When connecting to the port (e.g. by HTerm) and then resetting the board, the connection can not be established again, until the device is plugged out and in again. Is this a problem of the USB-CDC-driver on the device or a generic problem of the windows driver?
Hi Stefan, > the USB driver hangs in the function/define SET_CSR waiting for the AT91C_UDP_TXPKTRDY flag. > we replaced the define ... by a function with a "timeout" ... Thus its not hanging any longer.
Your comment gives me chance to think of problem on the coding on the Atmel source code. I have doubt how this line is optimized by compiler,
while ( (AT91C_BASE_UDP->UDP_CSR[endpoint] & (flags)) != (flags));
In the Atmel source code, the macros are defined as follows - without any volatile.
AT91SAM9260.h #define AT91_CAST(a) (a) typedef struct _AT91S_UDP { AT91_REG UDP_NUM; // Frame Number Register AT91_REG UDP_GLBSTATE; // Global State Register AT91_REG UDP_FADDR; // Function Address Register AT91_REG Reserved0[1]; // AT91_REG UDP_IER; // Interrupt Enable Register AT91_REG UDP_IDR; // Interrupt Disable Register AT91_REG UDP_IMR; // Interrupt Mask Register AT91_REG UDP_ISR; // Interrupt Status Register AT91_REG UDP_ICR; // Interrupt Clear Register AT91_REG Reserved1[1]; // AT91_REG UDP_RSTEP; // Reset Endpoint Register AT91_REG Reserved2[1]; // AT91_REG UDP_CSR[6]; // Endpoint Control and Status Register AT91_REG Reserved3[2]; // AT91_REG UDP_FDR[6]; // Endpoint FIFO Data Register AT91_REG Reserved4[3]; // AT91_REG UDP_TXVC; // Transceiver Control Register } AT91S_UDP, *AT91PS_UDP; #define AT91C_BASE_UDP (AT91_CAST(AT91PS_UDP) 0xFFFA4000) // (UDP) Base Address
Tsuneo