Forum Menu




 


Log in Problems?
New User? Sign Up!
AVR Freaks Forum Index

Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Author Message
AgwanII
PostPosted: Nov 22, 2011 - 07:01 AM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

Hi,

I have a custom board with a UC3A3128 on and a firmware based on the USB Device CDC Example.

Code:
usb_write_ep_txpacket(TX_EP, (char*) array, numberOfBytesInAUSBFrame, NULL);
I use this command to load a message into the USB interface. When the variable numberOfBytesInAUSBFrame = 512, the message gets sent automatically and it all works fine. But when numberOfBytesInAUSBFrame < 512, it sometimes screws up. I think it is because the buffer is not sent in time, so it is still there when I want to send the next message and then it starts to pad the messages.

So what I want to do is to perform a command after the loading of the message into USB interface, that sais that the buffer is ready to send. How do I do this? I tried "Usb_send_in(TX_EP);" and "Usb_raise_sof();". But what is the correct way?
 
 View user's profile Send private message  
Reply with quote Back to top
sambrown
PostPosted: Nov 22, 2011 - 09:22 AM
Hangaround


Joined: May 24, 2011
Posts: 253
Location: Berlin

Hi Agwanil,

I'm not so familiar with USB device, only USB host.

But maybe it's worth to have a look at the V2 USB device stack in:
<asf>/common/services/usb/class/cdc/device

There seems to exist a callback functionality for your issue:

udi_cdc.c -> udi_cdc_data_sent() "Callback called after data transfer on USB line"

You may not be happy to hear something like "use another software stack". I don't know how Atmel deals with outdated software, but the V1 stack might not be supported in future anyway.

-sb
 
 View user's profile Send private message  
Reply with quote Back to top
catweax
PostPosted: Nov 22, 2011 - 09:33 AM
Hangaround


Joined: Aug 25, 2011
Posts: 391
Location: Europe

I think you need to "ack" (acknowledge) the IN endpoint when not sending a full 512 packet. The ASF has the macro Usb_ack_in_ready(ep) macro for that. Usually you’ll end up using it together with the send macro, so there’s a combined macro called Usb_ack_in_ready_send(ep) that you can use instead of just Usb_send_in(ep). Maybe that solves your problem. Have a look at one of the USB example projects. It should be used in there.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 22, 2011 - 10:23 AM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

Thanks for your assistance. I tried the "Usb_ack_in_ready_send(ep)" but it does not help. If I have too short time between data transfers (still at least 2ms) everything hangs. Both on computer side and on uC side. I would expect beening able to send microframes 8(?) times/µs.

There is going to be quite a lot of work getting V2 of the USB stack. There seems to be a lot of changes. Ill look a little into it, but I have written quite a lot of code into the old example.
 
 View user's profile Send private message  
Reply with quote Back to top
catweax
PostPosted: Nov 22, 2011 - 10:30 AM
Hangaround


Joined: Aug 25, 2011
Posts: 391
Location: Europe

Sorry, I slightly misunderstood your initial question. You were asking how to tell whether the endpoint is ready: Use the Is_usb_in_ready(ep) macro for that, possibly by just polling it. It probably only works properly if you use the Usb_ack_in_ready_send(ep) macro afterwards. Usb_raise_sof() has nothing to do with it, so better don’t touch it.
 
 View user's profile Send private message  
Reply with quote Back to top
daffniles
PostPosted: Nov 22, 2011 - 08:45 PM
Hangaround


Joined: Mar 28, 2010
Posts: 127
Location: Palmerston North, New Zealand

Hi Agwanll,

Had the same problem, I use the following code

Code:
uiIndex = 0;
unwrittenBytes = 0;
Usb_reset_endpoint_fifo_access(TX_EP);
do {
   unwrittenBytes = usb_write_ep_txpacket(TX_EP, &(ucUSBTxBuffer[uiIndex]), (usUSBTxDataCount - uiIndex), NULL);
   uiIndex = uiIndex + (usUSBTxDataCount - (unwrittenBytes + uiIndex));
   Usb_ack_in_ready_send(TX_EP);
   uiTimeout = 100000;
   while(!Is_usb_in_ready(TX_EP)) {
      uiTimeout--;
      if(uiTimeout == 0) {
         break;
      }
   }
} while (unwrittenBytes != 0);


Points to note, until the Is_usb_in_ready(TX_EP) returns true (Hardware indicating that the last transaction completed) I busy wait with a timeout. This is very similar to the send code in the framework (for the host CDC task).

Also the transactions only send 64 bytes at a time, hence when sending a buffer that is larger, I needed to manage the amount of data already sent from the buffer and the location to send.

Its not pretty but it works.

Regards.

(EDIT:) This is for the older framework 1.7...
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
AgwanII
PostPosted: Nov 23, 2011 - 08:08 AM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

Thanks daffniles, just handling un-sent data fixed my byte dropping problem. Just why did I not try that earlier?? I thought I never got un-transfered bytes, but apperantly the computer does not read fast enough to keep up. (strange?)

So no dropped data now, but still computer software hang when data is sent too fast. Connecting and disconnecting the PC program (Realterm) to the port jiggles the bytes loose, and after a few times, everything runs again. And I know that when the computer does not read the bytes, the device stops and waits for the PC to read, so that works.

Also running remote desktop onto the computer who has the connection to the device makes it fail a lot more. Closing all programs possible, makes if fail less often. Stupid computer not beeing able to handle one single USB endpoint at close to speed limit. 18-22 Mbit/s is my transfer rate.
 
 View user's profile Send private message  
Reply with quote Back to top
catweax
PostPosted: Nov 23, 2011 - 09:18 AM
Hangaround


Joined: Aug 25, 2011
Posts: 391
Location: Europe

The problem you described is something I observed with Realterm as well, so I don’t think it’s your computer. Keep in mind that Realterm was probably designed for real serial connections, chugging along at 115200 bytes/s at best. Usually it displays all data on screen and that’s not really fast. If you throw 18-22 Mbit/s at it, the screen redrawing just takes to long and Realterm starts choking. If you want to store the data on your PC, use that option that just captures incoming data and writes it into a file. Then everything should work fine without hanging or stalling. Otherwise just write a simple Program yourself to shovel the data from the virtual serial port to somewhere else (or install Cygwin and just use dd Razz).
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 24, 2011 - 07:46 AM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

Is there a known bug in the driver for atmels CDC VPC? Talking about the 1.7 framework version.

I send a request to my uC to give me about 9 megs of data. After a few megs, the transfer stops. But I can get it to send another 16384 bytes if I send a byte to the uC again. I get the exakt amount for every transfer I do until the full 9 megs has been transfered. Then the uC starts to respond as ursually to bytes sent to it.

It feels like someone sitting in the middle of my uC and my PC program stops the transfer and fills its buffer until it is poked upon with a message from the other side.
 
 View user's profile Send private message  
Reply with quote Back to top
catweax
PostPosted: Nov 24, 2011 - 09:22 AM
Hangaround


Joined: Aug 25, 2011
Posts: 391
Location: Europe

I’m using the ASF 1.7 and I experienced similar problems during initial development, but it was always an error on my part, not calling the right functions at the right time or not setting the correct flags. It works perfectly now and I can send arbitrary amounts of data from and to the MCU without ever losing data. I’m using the UDDMA instead of accessing the USBB SRAM directly, though.

You description is rather vague, so my only guess would be that you’re not ACK’ing the data at some point, either because the order of function calls is incorrect or because you’re missing an event somewhere. Maybe you swapped the endpoint numbers for RX and TX somewhere, ACK’ing the wrong endpoint and it works once you send something in the opposite direction.

If you’re still using Realterm to display your data on screen, I’d blame that, though.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 24, 2011 - 09:50 AM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

My send routine does not do much.
Code:
// USB free and should I send and am I in send state?
if (uart_usb_tx_ready() && isToSendData() && (state == STATE_SEND)) {   
   // Are there unsent bytes since last try? Send it.
   if (nonWrittenBytes > 0) {
      nonWrittenBytes = usb_write_ep_txpacket(TX_EP, (char*) array, nonWrittenBytes, NULL);
   }
   // Else send new bytes if not enough bytes already sent
   else if (counter++ < numberOfBytesInAPacket) {
      nonWrittenBytes = usb_write_ep_txpacket(TX_EP, (char*) array, numberOfBytesInAUSBFrame, NULL);
   }
   // if enough bytes has been sent for this packet, reset counter and change state
   else {
      counter = 0;
      state = STATE_SAMPLE;
      // if enougt packets has been sent, reset counter and state
      if (counter2 >= numberOfDatasPackets) {
         counter2 = 0;
         endReadFrame();
      }
   }
}
I do set both number of bytes to send every USB frame, USB-frames/packet and number of packets to send. Between each packet I have a sample time.
Sampling state switches some GPIO:s and has a
Code:
cpu_delay_us( sampleTime , 12000000 );
in it. If I remove the delay, all bytes are sent trough. But then my sampling time is not settable. I don´t understand how this delay does anything but makes the USB transfers happen less often.
 
 View user's profile Send private message  
Reply with quote Back to top
catweax
PostPosted: Nov 24, 2011 - 10:08 AM
Hangaround


Joined: Aug 25, 2011
Posts: 391
Location: Europe

Where do you tell the USBB to actually send the data? I don’t see a Usb_ack_in_ready_send(ep) or Usb_send_in(ep) anywhere. Also do you call Usb_reset_endpoint_fifo_access(ep) before the first write into an empty endpoint?

Sending a packet should happen like this:
    - Call Usb_reset_endpoint_fifo_access(ep)
    - Call usb_write_ep_txpacket(...) as many times as necessary until the endpoint is full
    - Call Usb_ack_in_ready_send(ep)
    - Repeat cycle for next block
Maybe have a look at the notes in the description of the usb_write_ep_txpacket(...) function.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 24, 2011 - 10:27 AM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

I have this routine to send the data:
Code:
if (!Is_usb_write_enabled(TX_EP)) { // If Endpoint full -> flush
   Usb_ack_in_ready_send(TX_EP);
}
In the end of the sampling routine I call "Usb_reset_endpoint_fifo_access(TX_EP);" and then go over to the loading of data into buffer I showed above. As you can see in the prior code I posted, the sample routine is called between each packet. The packet can be multiple 512 bytes thou, is that ok?
 
 View user's profile Send private message  
Reply with quote Back to top
catweax
PostPosted: Nov 24, 2011 - 10:37 AM
Hangaround


Joined: Aug 25, 2011
Posts: 391
Location: Europe

I think you need to call Usb_reset_endpoint_fifo_access(TX_EP); after every Usb_ack_in_ready_send(TX_EP);

I didn’t catch whether you’re doing that every time or just once per 16k block.

The size of your data block isn’t restricted to multiples of 512 bytes. It can be anything, as long as you properly call Usb_ack_in_ready_send(TX_EP); at the end.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 24, 2011 - 11:27 AM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

I'm doing it once every 1 to 200 batches of 1-512 bytes each. Number of batches and number of bytes in a batch is settable.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 24, 2011 - 12:29 PM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

Another thing that makes the transfer not hang is if I remove the "Usb_ack_in_ready_send(TX_EP);", and use this to flush the data out, but have 10 ms timer for it:
Code:
if (sof_cnt >= NB_MS_BEFORE_FLUSH) { //Flush buffer in Timeout
      sof_cnt = 0;
      uart_usb_flush();
   }
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 24, 2011 - 01:37 PM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

I don't really get how this should be done correct.

Lets say I want to sample 10 times for 5 ms and each sample to be 300 bytes.

I am guessing like this:
Code:
Start sampling
Stop sampling
Usb_reset_endpoint_fifo_access(TX_EP);
usb_write_ep_txpacket(TX_EP, (char*) array, 300, NULL);
Usb_ack_in_ready_send(TX_EP);
Can I do it like that?

And how much data can I transfer between each reset of endpoint and ack-in-ready-send?

Lets say I want to sample 10 times for 5 ms and each sample to be 100k bytes instead. Do I do reset of endpoint and ack-in-ready-send for every 512 butes or for every 16k bytes? Or do I use a command to get if the buffer is full and then do it?
 
 View user's profile Send private message  
Reply with quote Back to top
catweax
PostPosted: Nov 24, 2011 - 02:11 PM
Hangaround


Joined: Aug 25, 2011
Posts: 391
Location: Europe

Between endpoint FIFO reset and ack-in-ready-send you can put data into the endpoint until it is full. How much the endpoint takes depends on how you configured it and whether you use FullSpeed or HiSpeed USB. It’s best to just use Is_usb_write_enabled.

Maybe try it like this:
Code:
start_sampling();
stop_sampling();

Usb_reset_endpoint_fifo_access(TX_EP);
while (Is_usb_write_enabled(TX_EP)) {
  unwritten = usb_write_ep_txpacket(TX_EP, things, amount, NULL);
  // handle unwritten data here
}
Usb_ack_in_ready_send(TX_EP);
If I understood the ASF correctly, it should work like that.

So you actually don’t call the endpoint FIFO reset and ack-in-ready-send for every 512 bytes, every 16k or another fixed size. You call them once for every block of data that fits into the endpoint, as determined by Is_usb_write_enabled(TX_EP).
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 24, 2011 - 03:42 PM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

So is there a reason to not call reset-endpoint-fifo-access every time just after the usb-ack-in-ready? It feels like it should be some time in between there or another kind of contition.

Is it so that I cannot call the reset-command until I get usb-write-enabled?
 
 View user's profile Send private message  
Reply with quote Back to top
catweax
PostPosted: Nov 24, 2011 - 04:34 PM
Hangaround


Joined: Aug 25, 2011
Posts: 391
Location: Europe

Calling the reset-command before writing is better style because you might not know in which state the endpoint FIFO was left after the last access. Also the endpoint is busy until Is_usb_write_enabled() returns true, so the program behaves more similar to the hardware if you call reset only after the endpoint is writeable again.

You could probably mix it around however you want, but that will make your program harder to understand and harder to debug.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 25, 2011 - 10:08 AM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
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.
 
 View user's profile Send private message  
Reply with quote Back to top
catweax
PostPosted: Nov 25, 2011 - 10:23 AM
Hangaround


Joined: Aug 25, 2011
Posts: 391
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.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 25, 2011 - 11:00 AM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

Ill try to figure out how to try that right away.

What speeds are you getting with that method?
 
 View user's profile Send private message  
Reply with quote Back to top
catweax
PostPosted: Nov 25, 2011 - 11:14 AM
Hangaround


Joined: Aug 25, 2011
Posts: 391
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.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 25, 2011 - 11:22 AM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
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?
 
 View user's profile Send private message  
Reply with quote Back to top
catweax
PostPosted: Nov 25, 2011 - 11:36 AM
Hangaround


Joined: Aug 25, 2011
Posts: 391
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.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 25, 2011 - 12:02 PM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
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...
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 25, 2011 - 02:08 PM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
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?
 
 View user's profile Send private message  
Reply with quote Back to top
catweax
PostPosted: Nov 25, 2011 - 02:09 PM
Hangaround


Joined: Aug 25, 2011
Posts: 391
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.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 25, 2011 - 02:29 PM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
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.
 
 View user's profile Send private message  
Reply with quote Back to top
catweax
PostPosted: Nov 25, 2011 - 02:43 PM
Hangaround


Joined: Aug 25, 2011
Posts: 391
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?
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 25, 2011 - 02:55 PM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
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.
 
 View user's profile Send private message  
Reply with quote Back to top
catweax
PostPosted: Nov 25, 2011 - 02:57 PM
Hangaround


Joined: Aug 25, 2011
Posts: 391
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.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 25, 2011 - 03:38 PM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

Not complaining, just trying to understand. Smile
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 25, 2011 - 04:23 PM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
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...
 
 View user's profile Send private message  
Reply with quote Back to top
catweax
PostPosted: Nov 25, 2011 - 04:31 PM
Hangaround


Joined: Aug 25, 2011
Posts: 391
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.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 25, 2011 - 04:44 PM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

Not a single byte showing up at my terminal program. But I can send commands to the device.
 
 View user's profile Send private message  
Reply with quote Back to top
catweax
PostPosted: Nov 25, 2011 - 04:46 PM
Hangaround


Joined: Aug 25, 2011
Posts: 391
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?
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 25, 2011 - 04:48 PM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
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?
 
 View user's profile Send private message  
Reply with quote Back to top
catweax
PostPosted: Nov 25, 2011 - 04:50 PM
Hangaround


Joined: Aug 25, 2011
Posts: 391
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?
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 25, 2011 - 04:52 PM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

I'm doing internal SRAM now, just a buffer "char Buffer[5120];" If I send it like this just before the DMA call:
Code:
Usb_reset_endpoint_fifo_access(TX_EP);
usb_write_ep_txpacket(TX_EP, Buffer, nonWrittenBytes, NULL);
Usb_ack_in_ready_send(TX_EP);
I get zeros. Tried 10 bytes, 512, 1000.
 
 View user's profile Send private message  
Reply with quote Back to top
catweax
PostPosted: Nov 25, 2011 - 04:58 PM
Hangaround


Joined: Aug 25, 2011
Posts: 391
Location: Europe

The FIFO access is only for when you directly write into the USBB’s SRAM. The UDDMA doesn’t care about that. You don’t have to "ACK" or "send" anything either when you have automatic bank switching enabled and set AVR32_USBB_UXDMAX_CONTROL_DMAEND_EN_MASK when starting a transfer.

You get zeros? So you do get something on the PC, but it’s just all zeros instead of the array’s contents? (Assuming that the array is filled with something besides zeros)
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 25, 2011 - 05:03 PM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

I get zeros and the array is probably that, but it is when just above the DMA transfer launching the code I posted above, so its the non DMA that does that transfer. Sad

It feels like the USB DMA is not that complex. And I feel that I understand how it works. But still nothing.
 
 View user's profile Send private message  
Reply with quote Back to top
catweax
PostPosted: Nov 25, 2011 - 05:10 PM
Hangaround


Joined: Aug 25, 2011
Posts: 391
Location: Europe

I’m not sure whether mixing DMA and non-DMA accesses is a good idea, but it should work.

By now I have no idea anymore why it doesn’t work for you. I gave the same DMA controller code to a colleague for a USB data logger and it worked for him.

Something you could try: Place the Usb_enable_endpoint_bank_autoswitch(TX_EP); into the Usb_set_configuration_action(), because that’s where I have it.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 25, 2011 - 09:34 PM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

That might do it. Perhaps the endpoint cannot be changed after it has been started. Ill try on ASAP.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 28, 2011 - 06:55 AM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

And its working! I'm not fully sure that it was this that was the problem, but I think it was that I did not have audo-bank-switching on first. Then when I added it, I called Usb_configure_endpoint_bank and instead of sending the DOUBLE_BANK define, I sent 2. Stupid of me, 0 is single bank, 1 is doubble and 2 is tripple bank. And tripple bank is not supported as I understood it from datasheet.

But there is no need to configure the double bank, from what I can see from all the settings in the example code, it is always set to DOUBLE_BANK.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 28, 2011 - 07:32 AM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

This works very well. I'm hitting the top of max bytes that can be sent in one DMA transfer, 65k, but that should be easy to handle.

You have been very helpful, thank you so much!! One week of work and now it looks correct and I feel that I know whats happening. I am very greatful.
 
 View user's profile Send private message  
Reply with quote Back to top
catweax
PostPosted: Nov 28, 2011 - 09:23 AM
Hangaround


Joined: Aug 25, 2011
Posts: 391
Location: Europe

You’re welcome. Glad to be able to share my knowledge.

If 64k isn’t enough for you, try the linked list mode. With that you should be able to send arbitrary amounts of data. I don’t need it and haven’t used it, so I can’t help you there, though.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 28, 2011 - 12:30 PM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

Have you ever had any problems sending 2^15-512 bytes? Sending 32257 or 32255 gets the correct number of bytes to the PC. Sending 32256 bytes gives 32768 bytes. (32256 = 32768 - 512) I find it quite strange. It does not really fit signed/unsigned-problem either.

Edit: Same goes for 2^15-1024, it sends 2^15 bytes.
 
 View user's profile Send private message  
Reply with quote Back to top
catweax
PostPosted: Nov 28, 2011 - 01:49 PM
Hangaround


Joined: Aug 25, 2011
Posts: 391
Location: Europe

No, can’t help you there. My packets are <=160 bytes.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 28, 2011 - 02:14 PM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

Then you are safe from 512 bytes too. That sends 0 bytes. And I guess 1024 and 2048 also sends 0 bytes.

When the number of bytes sent from the uC reaches 4096, they are transferred trough to the PC. So thats four sends of 1024 bytes.

And when checking with 512 bytes, it needs 8 sends to actually transfere the data to the PC.

Does this have anything to do with "bug 3501"? I cant seem to find the definition about it, just see that in the V2 of ASF there is a mention about it and a call to read the control of the DMA as a workaround. Does not work-around for me thou.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 29, 2011 - 07:05 AM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

Do you still do "Usb_reset_endpoint_fifo_access(TX_EP);" before sending by DMA and end with "Usb_ack_in_ready_send(TX_EP);" after DMA finish?
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 29, 2011 - 08:03 AM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

So doing it like this makes it work for me including the 512/1024 and so on byte send.
Code:
Usb_reset_endpoint_fifo_access(TX_EP);
usb_dma_send(array, 0); // 0 length means max length, 65k.
while ((AVR32_USBB_UDDMAX_status(TX_EP) & AVR32_USBB_UXDMAX_STATUS_CH_EN_MASK) == 1) {
}
Usb_ack_in_ready_send(TX_EP);
Where the usb_dma_send is the macro for sending over DMA.
 
 View user's profile Send private message  
Reply with quote Back to top
catweax
PostPosted: Nov 29, 2011 - 09:30 AM
Hangaround


Joined: Aug 25, 2011
Posts: 391
Location: Europe

Usb_reset_endpoint_fifo_access(TX_EP) can’t really be related to your problem because it only acts on a pointer/union located in in RAM for software access to the USBB’s SRAM (called pep_fifo). It should have no influence on the hardware.

I’m not using Usb_reset_endpoint_fifo_access(TX_EP) or Usb_ack_in_ready_send(TX_EP). All I do is
    - set USB DMA source/destination address,
    - write transfer length, EOBUFF_IRQ_EN flag, DMAEND_EN flag and CH_EN flag to the control register,
    - check AVR32_USBB.UDDMAx_STATUS.ch_en flag inside the EOBUFF_IRQ handler.
I can’t find it right now, but somewhere in one of the datasheets it said that you have to read the CH_EN flag from the status register after all bytes have been transferred to properly finish the transfer. When I left that out, I got funny behaviour.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 29, 2011 - 11:34 AM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

Nah, that does not work for me. I have to do "Usb_reset_endpoint_fifo_access(TX_EP);" before each transfer and end them with "Usb_ack_in_ready_send(TX_EP);". Doing just "Usb_ack_in_ready_send(TX_EP);" is not enough. I have not tried the linked list, so I dont know if that would eliminate one set of calls to these functions.

How do you read the ch flag? " (void)AVR32_USBB_UDDMAX_status(TX_EP);"?
 
 View user's profile Send private message  
Reply with quote Back to top
catweax
PostPosted: Nov 29, 2011 - 11:51 AM
Hangaround


Joined: Aug 25, 2011
Posts: 391
Location: Europe

I’m not too fond of the ASF, so I’m doing most peripheral accesses myself, such as this:
Code:
while (AVR32_USBB.UDDMAx_STATUS.ch_en);
With x = 1 for TX_EP, etc.
Waits until the CH_EN bit is 0. Inside the EOBUFF_IRQ handler this seems to be the case on the first access, but leaving it out leads to funny behaviour.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Nov 30, 2011 - 03:03 PM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

Just wanted to comment that the transfer is still not working properly. For instance 12x512 bytes beeing sent fails to deliver all bytes 1-2/100 times.

I have added transfer descriptors, and they work, but not using the "load next descriptor now" feature which I would have like to use. I set up a list of 4 descriptor already linked to eachother and to send I just start at any one of them. The last sends as many bytes as it is programmed to before each transfer, all of the others send maximum amount, 64k.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Dec 01, 2011 - 09:59 AM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

I have my endpoints configured as 512 bytes, is that wrong? When I set them to 64 byte, the 12x512 byte transfers are all ok. But changing to 64 byte I loose about 10% speed. Speed that I'd like to have.
 
 View user's profile Send private message  
Reply with quote Back to top
catweax
PostPosted: Dec 01, 2011 - 10:36 AM
Hangaround


Joined: Aug 25, 2011
Posts: 391
Location: Europe

For that I’m using the code that came with the CDC example and it looks like it’s using 512 byte banks. Here’s the code from usb_specific_request.c:
Code:
#if (USB_HIGH_SPEED_SUPPORT==ENABLED)
   if( !Is_usb_full_speed_mode() )
   {
      (void)Usb_configure_endpoint(INT_EP,
                             EP_ATTRIBUTES_3,
                             DIRECTION_IN,
                             EP_SIZE_3,
                             SINGLE_BANK);
   
      (void)Usb_configure_endpoint(TX_EP,
                             EP_ATTRIBUTES_1,
                             DIRECTION_IN,
                             EP_SIZE_1_HS,
                             DOUBLE_BANK);
   
      (void)Usb_configure_endpoint(RX_EP,
                             EP_ATTRIBUTES_2,
                             DIRECTION_OUT,
                             EP_SIZE_2_HS,
                             DOUBLE_BANK);
      return;
   }
#endif
From usb_descriptors.h:
Code:
#define EP_IN_LENGTH_1_HS   512
#define EP_SIZE_1_HS        EP_IN_LENGTH_1_HS
While looking around I notice that I’m using some files from the ASF 1.6 and some from 1.7 (it’s a slightly older project). I also remembered that I changed a bunch of stuff out of curiosity, so I made a quick diff for you (< original ASF, > my modifications):
usb_descriptors.h:
Code:
< #define CONF_ATTRIBUTES    USB_CONFIG_SELFPOWERED
103,104c103,104
< #define MAX_POWER          50    // 100 mA
---
> #define CONF_ATTRIBUTES    USB_CONFIG_BUSPOWERED
> #define MAX_POWER          240    // 480 mA
130c130
< #define EP_INTERVAL_3       0xFF
---
> #define EP_INTERVAL_3       0x10
I changed a lot in usb_specific_request.c, but I think that’s not relevant to your problem.

Now that I look at it, I actually changed quite a bit because I modified the ASF code to be fully interrupt-driven. I kicked out all that usb_task(), device_cdc_task() and "usb event" crap because I wanted my MCU to sleep when it’s not doing anything, not polling the USBB like a madman.

The main loop from the ASF looked like this:
Code:
  // No OS here. Need to call each task in round-robin mode.
  while (TRUE)
  {
    usb_task();
  #if USB_DEVICE_FEATURE == ENABLED
    device_cdc_task();
  #endif
  #if USB_HOST_FEATURE == ENABLED
    host_cdc_task();
  #endif
  }
Mine looks like this:
Code:
while (true) {
    // go sleep
    SLEEP(AVR32_PM_SMODE_IDLE);
}
The relevant difference between my code and your code could be anywhere, if there even is a difference relevant to the problem you’re experiencing. Sad

You could give the modification in usb_descriptors.h a try, though:
Code:
#define EP_INTERVAL_3       0x10
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Dec 01, 2011 - 11:39 AM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

I did try with 0x0A, but that did not do much differance.

I kind if believe that you have the same error I do, but you dont ever send the exact number of data that causes the problem. Or your PC program talkes to your uC more. Because the data "comes loose" when data is sent to the uC, then I can always get all data.

I will try using 0x10 on the EP_INTERVAL_3.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Dec 01, 2011 - 11:45 AM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

Nope, 0x10 did not change much. Making it 0x00 did make it a lot worse thou. Guess the interrupt endpoint takes all the packages.

Thanks for taking your time with this!

If you want to use your interface in any other way, do a test transferring 5120 bytes in a DMA transfer. Let it finish and loop that 100 or 1000 times. Mine fails 1-2/100 or so.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Dec 01, 2011 - 02:43 PM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

I got the answer from atmel now about this problem. They say I should upgrade to the newer USB stack and told me to read the migration PDF about it. The PDF sais that too much has changed, start over som one of the examples. Doh!
 
 View user's profile Send private message  
Reply with quote Back to top
catweax
PostPosted: Dec 01, 2011 - 02:58 PM
Hangaround


Joined: Aug 25, 2011
Posts: 391
Location: Europe

Have you been using the ASF 2.x all along or have you been trying with 1.7? With 1.7 it should’ve worked the same as it did for me. I guess “upgrade to the newest version” is the default answer if they have no idea and don’t want to spend too much time on it...

If you’re starting a new project, using the newest ASF is probably a good choice either way.

I’m not going to upgrade due to the interrupt-related changes I implemented and with the new AVR Studio 5 they chucked the Linux support. Confused

Good luck with the new ASF.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Dec 16, 2011 - 08:13 AM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

I have been using ASF 1.7 all the time, and the program is developed for 1 year now, so it is quite a lot of code. Porting all to 2.x is a lot of work. And will that fix the problem??

I did a quick test with 2.x to see if they increased the transfer speed. But it is as low in the 2.x example as it was in the 1.7 example when I started. And that is very very slow.

Back to why Im posting right now. Is anyone else experiencing that he transfer fail rate is depending on computer and operating system a lot? I am developing on a XP 64, but have a Win7 to test on too. And in the lab we have Vistas too. At my desk, I get all transfers to work without fail at all on both XP64 and Win7, but in the lab we have one computer which never fails, and a bunch that fails from rarely to very often. And there Win7 never works.

Anyone have any experiance from this? Any thought?
 
 View user's profile Send private message  
Reply with quote Back to top
catweax
PostPosted: Dec 16, 2011 - 10:05 AM
Hangaround


Joined: Aug 25, 2011
Posts: 391
Location: Europe

Are you still referring to the problem with transfer sizes that are multiples of 64 bytes?

If not, here are my OS experiences:
I’m developing on Linux 64 bit and porting some programs to Cygwin 32 bit as well.

Linux 64 bit: flawless
Windows 7 64 bit (with Cygwin 32 bit): no transfer problems
Windows XP 32 bit (with Cygwin 32 bit): only one unknown transfer freeze (I blame Matlab for that)

I’m only transferring packets smaller than 64 bytes, though, usually 8 or 25 bytes long. I have the UDDMA copy them into the USBB without the transfer end flag set if I have more than one to send, so it might end up sending 64 bytes in one USB packet. Then again I’m only using 512 byte HiSpeed endpoints.

Not sure if any of this helps.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Dec 16, 2011 - 11:44 AM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

I don't see any problems either when sending smaller packages. Its when I send larger packages many many times some of them fail.

I have packages that are 98 816 bytes and I send them at 30 Hz. The bytes are connected using transfer descriptors and UDDMA. On some computers the transfers never fail, on other it fails 1/5(?) of the tranfers.

Are there any configures for the PC side? Something I can do to give this transfer priority or remove/add buffers?
 
 View user's profile Send private message  
Reply with quote Back to top
catweax
PostPosted: Dec 16, 2011 - 12:40 PM
Hangaround


Joined: Aug 25, 2011
Posts: 391
Location: Europe

AFAIK it’s not possible to change the receive buffer of the virtual serial port, but if you’re on Windows you could try changing your program’s process priority via the task manager.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Dec 16, 2011 - 01:15 PM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

I have tried that, and it seems it can make things a bit better, but never go from not working perfectly to working perfectly. So on a computer which get receive errors, I still get them.
 
 View user's profile Send private message  
Reply with quote Back to top
catweax
PostPosted: Dec 16, 2011 - 01:21 PM
Hangaround


Joined: Aug 25, 2011
Posts: 391
Location: Europe

Have you checked what happens if your program doesn’t pick up incoming data quickly enough?

For me once the PC’s receive buffer is full the USB connection won’t transfer any more incoming data, causing the UDDMA to wait. Then my AVR32 program starts queuing data internally. Once I pick up some data on the PC, all transfers resume.

Maybe some part of this chain doesn’t work for you and the PC’s little 4k receive buffer overflows, causing data loss? Or maybe you’re not noticing a stalled transfer quickly enough and your AVR32 application starts losing data and things go bad?
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Dec 16, 2011 - 02:35 PM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

I have done tests regarding that. I have a LED that turns on when data is waiting for transmission. And a button on the unit that when I press, send one batch of data. And the LED can be on for a long while if I dont read, but as soon as I start reading, the data starts transmitting again without loosing data. So that seems to be working.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Feb 29, 2012 - 05:30 PM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

Has been spending another day on this issue. I ended up with setting the transfer descriptors the way that feels correct rather than what I understand from the datasheet. Only the last transfer descriptor is set up to end/close/finish the transmission. The others is just set to enable the transfer and load next descriptor in the end of its buffer. This far that change has given no more errors.

Another thing I took a look at was how I set up the SMC that the UDDMA reads from. It seems I have not done that correctly before. I have a feeling it used the default memory settings rather than what I set. Finaly I got the transmission rate to become much slower when I multiplied all delay states in the memory configuration by 10. Now that the settins are corrected and I devided all the delay settings by 10 instead, I get an incredible speed for the data transfer. I have not yet set the all delays to 0 (which might not always be the fastest setting) and already got transfer speeds of 62 MBit! I read in the datasheet that around 52 MBit would be about the fastest continous you could get. So that is a bit worrying. But it might be that the tests done for the datasheet uses the SDRAM that is used on any of the EVK:s and the one I have is infinitely fast in comparison to that.

At first I did not get any data, but had that 78 MBit speed (computer just read zeros). But after configuring the SMC correctly/better, I did get data. I have not checked yet that it is absolutely and always correct data. But it did look like the data I would normaly get and the amount of bytes is correct.

I thought that 32 MBit/s was maximum speed. But it seems that each micro frame can carry not 512 bytes, but 4096 bytes. So then 262 Mbit/s should be max. Not that the UC3A3 can have that throughput.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Mar 01, 2012 - 07:00 AM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

I have been experimenting a little further now. Sending 9 836 600 bytes takes atleast 0.902 seconds. So thats about 87 Mbits/s. And it scales up quite well too. 98 366 000 bytes takes 9.644 seconds to transfer.
 
 View user's profile Send private message  
Reply with quote Back to top
daffniles
PostPosted: Mar 07, 2012 - 12:44 AM
Hangaround


Joined: Mar 28, 2010
Posts: 127
Location: Palmerston North, New Zealand

Hi Agwanll,

Can I ask if you would post a summary of how you ended up configuring the USB, as I on occasion still seem to get dropped points, and this is a long post.

A complete summary would be outstanding....

Regards.
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
AgwanII
PostPosted: Mar 07, 2012 - 10:33 AM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

I have not for my self either made this summary. But this might help you at least a little. All these changes are done in the "device_cdc_task.c"-file. There are much more changes to that file, but most of that should be connected to my specific application code. This is not a guide on all you have to do to get it working. I have been programming this for a year.

I started with the USART CDC example ASF 1.7.

The USB settings:
Code:
void device_cdc_task_init(void) {
  sof_cnt   = 0;
  Usb_enable_sof_interrupt();
}

void usb_set_configuration_action(void) {
   Usb_enable_endpoint_bank_autoswitch(TX_EP);
}

void usb_sof_action(void) {
  sof_cnt++;
}
In the main device_cdc_task loop I have this to push out data that might get stuck:
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);
      }         
   }
Transfer descriptor creation:
Code:
typedef struct {
   unsigned long int nextDescriptorAddress __attribute__ ((aligned (32)));
   unsigned long int HSBAddress __attribute__ ((packed));
   unsigned long int control __attribute__ ((packed));
}TransferDescriptor;
And setup:
Code:
   replyTransferDescriptor.nextDescriptorAddress = (unsigned long int)NULL;
   replyTransferDescriptor.HSBAddress = 0;
   replyTransferDescriptor.control = 0;
I then have this for sending smaller messages where one transfer descriptor is enough. (65k bytes)
Code:
void sendMessage(void *txbuf, int messageLenght) {
   replyTransferDescriptor.HSBAddress = (unsigned long int)txbuf;   
   replyTransferDescriptor.control = ((messageLenght) << 16) | AVR32_USBB_UXDMAX_CONTROL_DMAEND_EN_MASK | AVR32_USBB_UXDMAX_CONTROL_BUFF_CLOSE_IN_EN_MASK |  AVR32_USBB_UXDMAX_CONTROL_CH_EN_MASK;   
   AVR32_USBB_UDDMAX_nextdesc(TX_EP) = (unsigned long int)&replyTransferDescriptor.nextDescriptorAddress; // Point at transfer descriptor
   AVR32_USBB_UDDMAX_control(TX_EP) =  AVR32_USBB_UXDMAX_CONTROL_LD_NXT_CH_DESC_EN_MASK; // Load that transfer descriptor

   LED_On(LED0);
   while ( (AVR32_USBB_UDDMAX_status(TX_EP) && AVR32_USBB_UXDMAX_STATUS_CH_EN_MASK) == 1 ) { // AVR32_USBB_UXDMAX_STATUS_CH_EN_MASK
      LED_On(LED0);
   };
   LED_Off(LED0);

   sof_cnt = 0;
   Usb_ack_in_ready_send(TX_EP);
}
The "Usb_ack_in_ready_send(TX_EP);" should not be needed, but it does not work without it. Probably because there is a bug somewere else. It also does not work if I don't blink the leds when sending data as seen above. Should be possible to exchange it for a number of NOP:s or a delay. Don't know.
 
 View user's profile Send private message  
Reply with quote Back to top
AgwanII
PostPosted: Mar 07, 2012 - 10:42 AM
Posting Freak


Joined: Mar 17, 2005
Posts: 1305
Location: Stockholm, Sweden

Perhaps the sof counting and Usb_ack_in_ready_send(TX_EP); is not needed. I did some experiments now and it worked at least with just minimal testing.
 
 View user's profile Send private message  
Reply with quote Back to top
daffniles
PostPosted: Mar 07, 2012 - 08:43 PM
Hangaround


Joined: Mar 28, 2010
Posts: 127
Location: Palmerston North, New Zealand

Hi Agwanll,

Exactly what I was after. I have been playing with it for about half as long as you have (as well as the USB OtG Host implementation as well) and like you I started with the CDC example. Can now do a code audit on my implementation and hopefully make it spot on.

Cheers

PS If u are ever in NZ, I'll buy u a beer.
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
Display posts from previous:     
Jump to:  
All times are GMT + 1 Hour
Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Powered by PNphpBB2 © 2003-2006 The PNphpBB Group
Credits