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, I just run into the problem again. In the bootloader, the board hangs after transfering a specific amount of data. Its curious, that it only happens with some of our boards, but not all them. After some tests, if found, that the problem was caused by the use of a USB hub. I connected the boards directly to the PC and it runs fine. I think it is a timing problem, which - for whatever reason - does not apply to all boards.
Can you post your code, please. I would like to try, if this solves the problem.
For startup code and interrupt handling I'm using the framework described in this series of articles: " : "=r" (key_)); \ asm("MSR cpsr_c,#(0x1F | 0x80 | 0x40)"); \ }) #define ARM_INT_UNLOCK(key_) asm("MSR cpsr_c,%0" : : "r" (key_)) #endif Here is how you use them: ARM_INT_KEY_TYPE int_lock_key; /* lock interrupts */ ARM_INT_LOCK(int_lock_key); /* critical section goes here: */ /* ... */ /* put interrupt lock back into previous state */ ARM_INT_UNLOCK(int_lock_key); Locking interrupts stores the previous interrupt lock state and then turns off interrupts. This way if a callee already locked them, calling ARM_INT_UNLOCK will leave them locked. My code locks interrupts before setting the endpoint state to UDP_ENDPOINT_SENDING, and unlocks them after enabling the interrupt on the endpoint. This probably isn't the smallest critical section possible. If you're still having a problem you could also try locking interrupts in the USB interrupt handler, but that's a big piece of code..
Here is how you use them:
ARM_INT_KEY_TYPE int_lock_key; /* lock interrupts */ ARM_INT_LOCK(int_lock_key); /* critical section goes here: */ /* ... */ /* put interrupt lock back into previous state */ ARM_INT_UNLOCK(int_lock_key);
Locking interrupts stores the previous interrupt lock state and then turns off interrupts. This way if a callee already locked them, calling ARM_INT_UNLOCK will leave them locked.
My code locks interrupts before setting the endpoint state to UDP_ENDPOINT_SENDING, and unlocks them after enabling the interrupt on the endpoint. This probably isn't the smallest critical section possible.
If you're still having a problem you could also try locking interrupts in the USB interrupt handler, but that's a big piece of code..