KurtE
Senior Member+
While pulling out the last few my hairs trying to figure out why in the FS Integration thread: https://forum.pjrc.com/threads/68139-Teensyduino-File-System-Integration-including-MTP-and-MSC
why at times when we transfer a file to one of the storage areas on Teensy, sometimes we get incomplete transfers, other times maybe reboots... I thought I would play with Raw HID.
This is not completely random as a lot of the MTP USB code is very similar to the raw hid support. Also sounded like a fun distraction while waiting for inspiration or answers to some of the pending issues in the integration.
So I started playing with it and have some stuff working I believe. I have this up in a Fork/Branch of cores:
https://github.com/KurtE/cores/tree/rawhid_512
I also have it setup, on the T4.x to be able to build for either 64 or 512 by choosing different USB option... My boards.local.txt have:
Note: I added a couple of methods to RawHid to allow the sketch to see what is the size of transfers. As there are chances even if you build for 512 it will run at 64 if the host does not support High speed.
I updated the Host side code, so far only Linux as don't know how to build for windows... Have not tried yet, my guess is, it will require installing additional stuff...
With the Linux side, again there are methods to query the size of transfers.
I have not played yet with the writes on Teensy to host, as I am mainly interested in emulating the SendObject functionality. Still more testing there, like introducing delays.
Example sketch:
Linux code:
I have included here update Rawhid host download, which is my WIP including above program. Note Makefile updated to build this one instead of main example.
Does this make a difference?
Well the example sketch tries to upload logically a 22mb file. With normal Rawhid this takes about 88 seconds, converting to 512 this now takes < 11 seconds. As expected 8 times faster.
Again not sure if there is any interest in this... If not probably won't take it much farther.
There is a minor issue in the HID descriptor where I say the size is still 64 as the count field is one byte... Probably a way to update, but not sure if anyone actually looks.
Also might update USBHost_t35 hid support to handle it being plugged in, which would give a very fast transfer rate between two T4.xs...
Now back to playing
why at times when we transfer a file to one of the storage areas on Teensy, sometimes we get incomplete transfers, other times maybe reboots... I thought I would play with Raw HID.
This is not completely random as a lot of the MTP USB code is very similar to the raw hid support. Also sounded like a fun distraction while waiting for inspiration or answers to some of the pending issues in the integration.
So I started playing with it and have some stuff working I believe. I have this up in a Fork/Branch of cores:
https://github.com/KurtE/cores/tree/rawhid_512
I also have it setup, on the T4.x to be able to build for either 64 or 512 by choosing different USB option... My boards.local.txt have:
Code:
teensy41.menu.usb.rawhid512=Raw HID 512
teensy41.menu.usb.rawhid512.build.usbtype=USB_RAWHID512
teensy41.menu.usb.rawhid512.fake_serial=teensy_gateway
teensyMM.menu.usb.rawhid512=Raw HID 512
teensyMM.menu.usb.rawhid512.build.usbtype=USB_RAWHID512
teensyMM.menu.usb.rawhid512.fake_serial=teensy_gateway
teensy40.menu.usb.rawhid512=Raw HID 512
teensy40.menu.usb.rawhid512.build.usbtype=USB_RAWHID512
teensy40.menu.usb.rawhid512.fake_serial=teensy_gateway
Note: I added a couple of methods to RawHid to allow the sketch to see what is the size of transfers. As there are chances even if you build for 512 it will run at 64 if the host does not support High speed.
I updated the Host side code, so far only Linux as don't know how to build for windows... Have not tried yet, my guess is, it will require installing additional stuff...
With the Linux side, again there are methods to query the size of transfers.
I have not played yet with the writes on Teensy to host, as I am mainly interested in emulating the SendObject functionality. Still more testing there, like introducing delays.
Example sketch:
Code:
/* RawHID receive big
This example code is in the public domain.
*/
// RawHID packets are always 64 bytes
byte buffer[512];
int rx_size;
unsigned int packetCount = 0;
uint32_t last_packet_number = (uint32_t) - 1;
uint32_t packet_count = 0;
elapsedMillis em;
elapsedMillis emTotal;
bool run_active = false;
void setup() {
while (!Serial);
pinMode(13, OUTPUT);
Serial.begin(9600);
Serial.println(F("RawHID lots of input test"));
rx_size = RawHID.rxSize();
// rx_size = 64;
Serial.printf("RawHid RX Size: %d\n", rx_size);
em = 0;
Serial.println(F("Waiting for packets"));
}
void loop() {
int n;
n = RawHID.recv(buffer, 0); // 0 timeout = do not wait
if (n > 0) {
packet_count++;
digitalToggleFast(13);
// check Serial numbers
uint32_t packet_number = 0;
for (int i = 0; buffer[i] >= '0' && buffer[i] <= '9'; i++) {
packet_number = packet_number * 10 + buffer[i] - '0';
}
if (packet_number == 0) {
Serial.println("Looks like new run started");
last_packet_number = 0;
packet_count = 1;
emTotal = 0;
} else if (packet_number != (last_packet_number + 1)) {
Serial.printf("Missing? cnt: %u, Last: %u cur:%u\n", packet_count, packet_number, last_packet_number);
} else if ((buffer[8] != buffer[rx_size-2]) || (buffer[rx_size-1] != '\n')) {
Serial.printf("msg format error: %u\n", packet_count);
}
if (buffer[7] == '$') {
Serial.printf("Received end marker: %u %u Time:%u\n", packet_count, packet_number,
(uint32_t)emTotal);
}
last_packet_number = packet_number;
run_active = true;
em = 0;
if ((packet_count & 0x3ff) == 0) Serial.print(".");
if ((packet_count & 0xffff) == 0) Serial.println();
} else if (run_active && (em > 1000)) {
Serial.printf("\nTimeout: %u %u\n", packet_count, last_packet_number);
run_active = false;
}
}
Linux code:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdint.h>
#include <string.h>
#if defined(OS_LINUX) || defined(OS_MACOSX)
#include <sys/ioctl.h>
#include <termios.h>
#elif defined(OS_WINDOWS)
#include <conio.h>
#endif
#include "hid.h"
#define MAX_PACKET_SIZE 512
#define FILE_SIZE 22400000ul
int packet_size;
uint32_t count_packets;
int main()
{
int r;
char buf[MAX_PACKET_SIZE];
// C-based example is 16C0:0480:FFAB:0200
r = rawhid_open(1, 0x16C0, 0x0480, 0xFFAB, 0x0200);
if (r <= 0) {
// Arduino-based example is 16C0:0486:FFAB:0200
r = rawhid_open(1, 0x16C0, 0x0486, 0xFFAB, 0x0200);
if (r <= 0) {
printf("no rawhid device found\n");
return -1;
}
}
printf("found rawhid device\n");
printf("Starting output(%u)\n", count_packets);
printf("Rx Size:%d Tx Size:%d\n", rawhid_rxSize(0), rawhid_txSize(0));
packet_size = rawhid_txSize(0);
if (packet_size <= 0) {
printf("invalid size field");
return -1;
}
count_packets = FILE_SIZE / packet_size;
for (uint32_t packet_num = 0; packet_num < count_packets; packet_num++){
memset(buf, 'A' + (packet_num & 0xf), packet_size) ;
sprintf(buf, "%07u", packet_num);
buf[7] = (packet_num == (count_packets-1))? '$' : ' ';
buf[packet_size-1] = '\n';
rawhid_send(0, buf, packet_size, 100);
if ((packet_num & 0x1ff) == 0) printf(".");
if ((packet_num & 0xffff) == 0) printf("\n");
}
printf("\nDone...\n");
return 0;
}
I have included here update Rawhid host download, which is my WIP including above program. Note Makefile updated to build this one instead of main example.
Does this make a difference?
Well the example sketch tries to upload logically a 22mb file. With normal Rawhid this takes about 88 seconds, converting to 512 this now takes < 11 seconds. As expected 8 times faster.
Again not sure if there is any interest in this... If not probably won't take it much farther.
There is a minor issue in the HID descriptor where I say the size is still 64 as the count field is one byte... Probably a way to update, but not sure if anyone actually looks.
Also might update USBHost_t35 hid support to handle it being plugged in, which would give a very fast transfer rate between two T4.xs...
Now back to playing