| Author |
Message |
|
|
Posted: Nov 25, 2011 - 10:08 AM |
|

Joined: Mar 17, 2005
Posts: 1307
Location: Stockholm, Sweden
|
|
| It seems Atmels programmers think that the "Usb_reset_endpoint_fifo_access(TX_EP);" should only be called if there has first been a bootup or a "Usb_ack_in_ready_send(TX_EP);" sent, so I added a flag like they do like this:
Code:
if (b_tx_new) {
Usb_reset_endpoint_fifo_access(TX_EP);
b_tx_new = FALSE;
}
Where "b_tx_new" is set to true when "Usb_ack_in_ready_send(TX_EP);" is sent. And this is done in the top of the transfer routine, right after the Is_device_enumerated check and after incomming data check.
I have tried re-programming my routine like all the different suggestions, but nothing works. Atmel has this routine also:
Code:
if (sof_cnt >= NB_MS_BEFORE_FLUSH) { //Flush buffer in Timeout
sof_cnt = 0;
if( 0 == Usb_nb_busy_bank(TX_EP) ) {
Usb_ack_in_ready_send(TX_EP);
b_tx_new = TRUE;
}
}
And it is needed, as I understand it, to get shorter messages to go through. I have two different kinds of transfers. One is for messaging (setups and initiations), they are 4-20 bytes, and then there is the bulk transfer from the uC to the PC that needs to top at arount 20 Mbit/s and several megs. |
|
|
| |
|
|
|
|
|
Posted: Nov 25, 2011 - 10:23 AM |
|

Joined: Aug 25, 2011
Posts: 392
Location: Europe
|
|
|
AgwanII wrote:
I have two different kinds of transfers. One is for messaging (setups and initiations) and then there is the bulk transfer from the uC to the PC that needs to top at arount 20 Mbit/s.
With such speeds, are you sure you don’t want to use the USBB’s DMA controller with bank-autoswitch? You just tell it how many bytes you want to transfer and that you want the last partial block to be sent automatically. That way you don’t have to take care of unsent bytes, stalled reads on the PC, resetting the FIFO, ACK’ing and sending the endpoint or whatever.
I wrote myself a macro for that:
Code:
#define Enable_usb_dma_tx_send(start_address, length) { \
AVR32_USBB.uddma1_addr = (uint32_t)(start_address); \
AVR32_USBB.uddma1_control = ((length) << 16) | \
AVR32_USBB_UXDMAX_CONTROL_DMAEND_EN_MASK | \
AVR32_USBB_UXDMAX_CONTROL_CH_EN_MASK; \
}
Copies length bytes starting from start_address into endpoint 1 (due to uddma1) and finishes the USB transfer even if length is not a multiple of 512 (or 64). Then you can just poll the DMA channel busy flag until the transfer’s done and you’re finished.
I’m actually using the transfer finished interrupt, but I removed that from the macro above. |
|
|
| |
|
|
|
|
|
Posted: Nov 25, 2011 - 11:00 AM |
|

Joined: Mar 17, 2005
Posts: 1307
Location: Stockholm, Sweden
|
|
Ill try to figure out how to try that right away.
What speeds are you getting with that method? |
|
|
| |
|
|
|
|
|
Posted: Nov 25, 2011 - 11:14 AM |
|

Joined: Aug 25, 2011
Posts: 392
Location: Europe
|
|
Can’t remember the early benchmarks. Something above 300 Mbit/s, I think.
I’m currently using the MCU on an adaptor to serial buses, so the throughput is limited by those buses and I’m getting slower speeds on the USB connection. I need the DMA controller for the lower CPU usage. |
|
|
| |
|
|
|
|
|
Posted: Nov 25, 2011 - 11:22 AM |
|

Joined: Mar 17, 2005
Posts: 1307
Location: Stockholm, Sweden
|
|
| Are you getting 300 Mbit/s using DMA and VPC?! Isn´t more than one end-point needed for above 30 Mbit/s something? |
|
|
| |
|
|
|
|
|
Posted: Nov 25, 2011 - 11:36 AM |
|

Joined: Aug 25, 2011
Posts: 392
Location: Europe
|
|
Sorry, I’m not entirely sure anymore because I did that benchmark about 1.5 years ago, but it was really fast with the DMA controller. Keep in mind that it’s theoretically possible to transfer 1 Gbit/s over the MCU’s HSB (66 MHz, unlimited burst mode, reads have one cycle delay, 32 bits per read).
The benchmark was a simple uni-directional transfer, just shovelling data from the MCU to the PC as fast as possible. The PC discarded the data after measuring the speed. The speeds in a proper application will be lower, of course.
With VPC you mean the virtual serial port mode? Yes, I was using that with Linux on the PC. |
|
|
| |
|
|
|
|
|
Posted: Nov 25, 2011 - 12:02 PM |
|

Joined: Mar 17, 2005
Posts: 1307
Location: Stockholm, Sweden
|
|
That sounds very good. Id be very happy if I get 1/5 of that. Im working on it right now trying to get transfer to work.
To get the DMA working on SPI, I first (after config) need to load one byte into the SPI to get it started. Is it the same here?
I feel that this should be the only thing I need to start the DMA transfer.
Code:
AVR32_USBB_UDDMAX_addr(1) = AVR32_EBI_CS0_ADDRESS;
AVR32_USBB_UDDMAX_control(1) = ((nonWrittenBytes) << 16) | AVR32_USBB_UXDMAX_CONTROL_DMAEND_EN_MASK | AVR32_USBB_UXDMAX_CONTROL_CH_EN_MASK;
while ((AVR32_USBB_UDDMAX_status(1)&AVR32_USBB_UXDMAX_CONTROL_CH_EN_MASK) == 1) {
// Just wait for now, optimize later
}
However, the uC just hangs, in the while obviously.
I am missing some kind of link to TX_EP...
Edit: To answer the last, I guess there is one DMA/endpoint, so DMA1 is for EP1... |
|
|
| |
|
|
|
|
|
Posted: Nov 25, 2011 - 02:08 PM |
|

Joined: Mar 17, 2005
Posts: 1307
Location: Stockholm, Sweden
|
|
| Do I not also have to set the automatic bank switching for the endpoint in the UECFGn-register to handle multiple packets? Or is this done by default? |
|
|
| |
|
|
|
|
|
Posted: Nov 25, 2011 - 02:09 PM |
|

Joined: Aug 25, 2011
Posts: 392
Location: Europe
|
|
You should have the endpoint configured for double-bank (already set if you’re using the CDC example code) and then you must enable bank auto-switching: Usb_enable_endpoint_bank_autoswitch(TX_EP);
Otherwise the DMA controller will stall after one bank is filled.
Chapter 26.7.4 of the datasheet has explanations and examples on how to use the DMA controller. |
|
|
| |
|
|
|
|
|
Posted: Nov 25, 2011 - 02:29 PM |
|

Joined: Mar 17, 2005
Posts: 1307
Location: Stockholm, Sweden
|
|
| I wrote that row in the "void device_cdc_task_init(void)"-function so that it is done at the beginning.
Code:
Usb_enable_endpoint_bank_autoswitch(TX_EP);
Usb_configure_endpoint_bank(TX_EP, 2);
I do need to configure the H_matrix for this transfer too? The transfer is stalling, and before I get any bytes to the PC at all.
Then I tried this:
Code:
Enable_usb_dma_tx_send(AVR32_EBI_CS0_ADDRESS, nonWrittenBytes);
while ((AVR32_USBB_UDDMAX_status(TX_EP)&AVR32_USBB_UXDMAX_CONTROL_CH_EN_MASK) == 1) {
LED_On(LED0);
}
LED_Off(LED0);
And this:
Code:
AVR32_USBB_UDDMAX_addr(TX_EP) = AVR32_EBI_CS0_ADDRESS;
AVR32_USBB_UDDMAX_control(TX_EP) = ((nonWrittenBytes) << 16) | AVR32_USBB_UXDMAX_CONTROL_DMAEND_EN_MASK | AVR32_USBB_UXDMAX_CONTROL_CH_EN_MASK;
(void)AVR32_USBB_UDDMAX_control(TX_EP);
while ((AVR32_USBB_UDDMAX_status(TX_EP)&AVR32_USBB_UXDMAX_CONTROL_CH_EN_MASK) == 1) {
LED_On(LED0);
}
LED_Off(LED0);
But both stalls on the LED. |
|
|
| |
|
|
|
|
|
Posted: Nov 25, 2011 - 02:43 PM |
|

Joined: Aug 25, 2011
Posts: 392
Location: Europe
|
|
You don’t need to configure the H_matrix if the defaults are fast enough for you. No H_matrix-configuration should be able to completely stall your UDDMA transfer.
Right now I have no good idea why it stalls for you. Have you tried transferring some data from SRAM instead of the external RAM? |
|
|
| |
|
|
|
|
|
Posted: Nov 25, 2011 - 02:55 PM |
|

Joined: Mar 17, 2005
Posts: 1307
Location: Stockholm, Sweden
|
|
| And your little script have no connection to which EP, it just assumes EP_TX is 1, right? So that should be correct. |
|
|
| |
|
|
|
|
|
Posted: Nov 25, 2011 - 02:57 PM |
|

Joined: Aug 25, 2011
Posts: 392
Location: Europe
|
|
| Yes, it assumes the TX endpoint to be 1. It’s a timing-critical application, so some parts of the code aren’t very pretty. |
|
|
| |
|
|
|
|
|
Posted: Nov 25, 2011 - 03:38 PM |
|

Joined: Mar 17, 2005
Posts: 1307
Location: Stockholm, Sweden
|
|
Not complaining, just trying to understand.  |
|
|
| |
|
|
|
|
|
Posted: Nov 25, 2011 - 04:23 PM |
|

Joined: Mar 17, 2005
Posts: 1307
Location: Stockholm, Sweden
|
|
Do I have to worry about the ofset between the "HSB Address" and "Control"? That is only when I use a linked list of new "Descriptor Address", right? Those lists need to be aligned correct.
When I get the lock-up directly when trying to send, I have the following parameters in the status register:
CHEN = 1
CHACTIVE = 0
EOTSTA = 0
EOCHBUFFSTA = 1
DESCLDSTA = 0
If that sais anything. The channel is not active... |
|
|
| |
|
|
|
|
|
Posted: Nov 25, 2011 - 04:31 PM |
|

Joined: Aug 25, 2011
Posts: 392
Location: Europe
|
|
The elements of the linked lists must adhere to special alignment. The source or destination address of the DMA transfer can be anything.
Note: I noticed that the DMA controller can do transfers to any byte address (as the datasheet states), but if the address is not aligned to 4 bytes, the preceding and following bytes up to the next 4 byte aligned address will be overwritten (not mentioned in the datasheet).
Imagine an array aligned to 4 bytes: If you tell the DMA controller to write 4 bytes to position 4 (zero based array), it will write to bytes 4, 5, 6 and 7. If you tell it to write 4 bytes to position 6, it will write 6, 7, 8 and 9 while clobbering 4, 5, 10 and 11. If you tell it to write one byte to position 2, it will clobber 0, 1 and 3.
This only applies to write access into your memory locations. Reading from memory into the USBB of course doesn’t clobber anything.
CHACTIVE is 0 because EOCHBUFFSTA is 1, telling you that the channel’s byte count reached 0 because it’s done transferring.
Actually I just remembered that you have to poll until EOCHBUFFSTA is 1. When that happens, CHEN will still be 1 because the endpoint bank is still marked as busy. Then you have to poll CHEN until it is 0, meaning that the bank was freed and you can proceed.
Sorry for mixing that up. I’m using the DMA controller with interrupts, so it’s a bit different. |
|
|
| |
|
|
|
|
|
Posted: Nov 25, 2011 - 04:44 PM |
|

Joined: Mar 17, 2005
Posts: 1307
Location: Stockholm, Sweden
|
|
| Not a single byte showing up at my terminal program. But I can send commands to the device. |
|
|
| |
|
|
|
|
|
Posted: Nov 25, 2011 - 04:46 PM |
|

Joined: Aug 25, 2011
Posts: 392
Location: Europe
|
|
| Are you starting the DMA transfer before or after opening the serial port on the PC? Actually, are you sending anything at all from the MCU to the PC before opening the serial port? |
|
|
| |
|
|
|
|
|
Posted: Nov 25, 2011 - 04:48 PM |
|

Joined: Mar 17, 2005
Posts: 1307
Location: Stockholm, Sweden
|
|
I have tried both with and without serial port opened in the terminal program. Im not sending any other data than when I press the button. So both tried on question number two also.
And I dont need any fifo access reset or ack-in-ready? |
|
|
| |
|
|
|
|
|
Posted: Nov 25, 2011 - 04:50 PM |
|

Joined: Aug 25, 2011
Posts: 392
Location: Europe
|
|
Running out of ideas again...
Did you try reading data from the internal SRAM instead of the external RAM? Did you try different transfer lengths? |
|
|
| |
|
|
|
|
|