chipKIT32 / chipKIT-core

Downloadable chipKIT core for use with Arduino 1.6 - 1.8+ IDE, PlatformIO, and UECIDE
http://chipkit.net/
Apache License 2.0
59 stars 53 forks source link

avoid copeing to buffer when sending #446

Closed chromhelm closed 5 years ago

chromhelm commented 5 years ago

Hi This i a performance optimization.

The code i used to test it is:

#include <USB.h>
#include <Timer.h>

#include "CDCSCM_F.h"
#include "USBManager_single.h"

Timer4 counter;

const uint32_t BUFFER_SIZE = 100000;

byte buffer[BUFFER_SIZE];
volatile uint32_t extraCounts = 0;

USBFS usbDriver;
USBManager USB(usbDriver, 0x04d8, 0x0f5d);
//USBManager_single USB(usbDriver, 0x04d8, 0x0f5d);
CDCACM usbOrig;
CDCACM_F usbFast;

void __USER_ISR isr() {
      extraCounts++;
      clearIntFlag(_TIMER_4_IRQ);
}

void setup() {

    Serial.begin(2000000);
    Serial.setTimeout(500);
    Serial.println("CDC speed test");

    USB.addDevice(usbFast);
    USB.addDevice(usbOrig);
    USB.begin();

    counter.setPrescaler(256);
    counter.setPeriod(0xFFFF);
    counter.setClockSource(TIMER_PB);
    counter.attachInterrupt(isr);

    for(uint32_t i = 0; i< BUFFER_SIZE;i++)
      buffer[i] = i & 0xff;
}

int32_t measure(Stream* s, uint32_t bytesPerWrite)
{
  counter.reset();
  extraCounts = 0;

  if(bytesPerWrite == 0)
  {
    uint32_t p = 0;
    counter.start();
    for(p = 0; p < BUFFER_SIZE; p++)
      s->write(buffer[p]);
  }
  else if(bytesPerWrite >= BUFFER_SIZE)
  {
    counter.start();
    s->write(buffer, bytesPerWrite);
  }
  else
  {
    uint32_t p = 0;
    counter.start();
    for(p = 0; p < BUFFER_SIZE-bytesPerWrite; p += bytesPerWrite)
      s->write(buffer+p, bytesPerWrite);
    if(BUFFER_SIZE-p) s->write(buffer+p, BUFFER_SIZE-p);
  }

  while(s->availableForWrite());
  counter.stop();

  extraCounts = (extraCounts <<16) + counter.getCount();

  double time = 1.0 / (((double)getPeripheralClock() / 256) / extraCounts);
  double bytes_per_secound = 1/time*BUFFER_SIZE;

  return bytes_per_secound;
}

//#define TEST_COUNT 36
//const uint32_t byteCounts[TEST_COUNT] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,20,21,22,23,25,27,28,30,31,32,33,63,64,65,255,256,257,BUFFER_SIZE};

#define TEST_COUNT 7
const uint32_t byteCounts[TEST_COUNT] = {0,1,2,4,8,32,BUFFER_SIZE};

void loop() 
{
  Serial.println("\n\n-------------------------");
  Serial.println("       |  Orig  |  fast   ");
  Serial.println("--------------------------");

  for(int i = 0; i < TEST_COUNT; i++)
  {
    Serial.print(byteCounts[i]);
    Serial.print(" | ");
    Serial.print(measure(&usbOrig, byteCounts[i]));
    Serial.print(" | ");
    Serial.println(measure(&usbFast, byteCounts[i]));
   // delay(2500);
  }
}

You will need a relay fast terminal or just pipe it to null device to see the speed improvement. I used: stty -F /dev/ttyACM1 2000000 raw -echo -echoe -echok && cat /dttyACM1 > /dev/null

I have seen speeds over 480k without -O3 option. Over 500k with -O3 and block over 8 bytes. The original with -O3 470k The original without optimization is around 420k

chipkitbot commented 5 years ago

Can one of the admins verify this patch?

EmbeddedMan commented 5 years ago

ok to test

On Mon, Mar 11, 2019 at 3:31 PM chipKIT Bot notifications@github.com wrote:

Can one of the admins verify this patch?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/chipKIT32/chipKIT-core/pull/446#issuecomment-471717302, or mute the thread https://github.com/notifications/unsubscribe-auth/AAbeCNWgdNug52QcaGoOGskIwD44IPQGks5vVr0GgaJpZM4bpfrA .

EmbeddedMan commented 5 years ago

@majenkotech Any issues with the rest of the changes?

majenkotech commented 5 years ago

I haven't had a chance to test it yet, but on the face of it, it looks good to me.

chromhelm commented 5 years ago

Hi I have other changes that can increase transfers over 1M per second. But that are bigger changes. Should i add it on this pull request or should i do it in a new one.?

EmbeddedMan commented 5 years ago

Probably make a new PR for that. Once Matt has a chance to test these changes, we'll merge this one in.

On Tue, Mar 12, 2019 at 2:53 PM Wilhelm Wiens notifications@github.com wrote:

Hi I have other changes that can increase transfers over 1M per second. But that are bigger changes. Should i add it on this pull request or should i do it in a new one.?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/chipKIT32/chipKIT-core/pull/446#issuecomment-472156201, or mute the thread https://github.com/notifications/unsubscribe-auth/AAbeCCuuu2DwDf_K3R-dp-tjNkfKCoxEks5vWAXNgaJpZM4bpfrA .

chromhelm commented 5 years ago

Hi again The change is actually smaller than i thought. I had additional changes to remove redundant code. But without that it quite simple. Have a look at PR #447

majenkotech commented 5 years ago

This looks good to me. I vote merge.

I'm getting around 180k/s on a 40MHz Lenny, and about 450k/s on a WiFire using USBHS.

EmbeddedMan commented 5 years ago

That's fantastic!

On Wed, Mar 13, 2019 at 6:59 AM Majenko Technologies < notifications@github.com> wrote:

This looks good to me. I vote merge.

I'm getting around 180k/s on a 40MHz Lenny, and about 450k/s on a WiFire using USBHS.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/chipKIT32/chipKIT-core/pull/446#issuecomment-472393156, or mute the thread https://github.com/notifications/unsubscribe-auth/AAbeCH-HLZ39hTckmg6qeWjnnlSQROObks5vWOgegaJpZM4bpfrA .

majenkotech commented 5 years ago

HOLD ON MERGE

Paul S's test code gives this on a Lenny:

USB Fast Serial Transmit Bandwidth Test, capture this text.
USB Fast Serial Transmit Bandwidth Test, capture this text.
USB Fast Serial Transmit Bandwidth Test, capture this text.
USB Fast Serial Transmit Bandwidth Test, capture this text.
1USB Fast Serial Transmit Bandwidth Test, capture this text.
USB Fast Serial Transmit Bandwidth Test, capture this text.
USB Fast Serial Transmit Bandwidth Test, capture this text.
USB Fast Serial Transmit Bandwidth Test, capture this text.
USB Fast Se1ial Transmit Bandwidth Test, capture this text.
USB Fast Serial Transmit Bandwidth Test, capture this text.

A random "1" inserted every so often. I think something is off with the buffer strategy somewhere.