Recommend an X86 single board computer - Page 1
Forum section: electronics / general

author: snarkysparky
author_rank: Frequent Contributor
timestamp: July 16, 2020, 05:38:58 pm
content: I need to use an X86 computer to run software for an embedded application.OS will be linux.But I need to get data quick out of this computer to another bit of hardware. ( no ethernet port available on destination HW).Can probably live with 1Mbit / sec.SPI is the preferred method.Previous setup used a Raspbi Pi. But new software is not available for ARM linux.Thanks

author: ebclr
author_rank: Super Contributor
timestamp: July 17, 2020, 12:31:49 am
content: This Video maybe usefull for you

author: MarkF
author_rank: Super Contributor
timestamp: July 17, 2020, 02:47:16 am
content: What about a serial port on anIntel® NUC Board NUC7i3DNBE

author: Nominal Animal
author_rank: Super Contributor
timestamp: July 17, 2020, 03:20:19 am
content: TheOdroid H2+might be an option, but it doesn't seem to expose a SPI bus, onlytwo UARTs and two I2C buses. It does support an USB 1.1I/O boardbased on PIC18F45K50 withSPI, I2C, UART and other interfaces, and a megabyte per second transfer rate is achievable.Personally, I'd consider using aTeensy 4.0as an USB 2.0 peripheral, doing the I2C transfers with the device you need. It is programmed in the Arduino environment using theTeensyduinoadd-on. Even with the standard serial interface, you can get 2-3 megabytes per second in real life (16-24 Mbits/s), full duplex (i.e. 2-3 megabytes per second to the Teensy 4, and the same down, at the same time; I've verified this using a real-world ping-pong test program in Linux).(Using bulk USB transfers you should get much higher. Teensy 4.0 has 480 Mbit/s USB support, but I haven't yet discovered the practical bandwidth it can reach with bulk USB transfers.)That way, it doesn't matter much what computer you use, as long as you can port the software transferring data to the Teensy. Also, since you can have a DMA buffer of almost 512 kbytes (somewhere around 480,000 bytes without any issues), you can use the RAM on the Teensy as a buffer, so in case your program/"driver" is slightly delayed because the computer is under a high load, you shouldn't lose data. Since Teensy runs at max. 600 MHz (well, almost at a GHz if you add cooling), you can use very high SPI clock (38 MHz at least, with some clock management, at least 60 MHz, possibly 120 MHz).For added safety, you could even build a small carrier board with isolation for the SPI bus.

author: snarkysparky
author_rank: Frequent Contributor
timestamp: July 17, 2020, 03:09:34 pm
content: Thanks for the suggestions.One primary concern is that the board remains available. Leaning toward the intel Nuc board for this reason.I understand serial can go up to 961 K bits / sec. I am beginning to like serial because it is more standard than SPI on single board computers.If you set this rate I wonder if you can actually get that or is the OS going to get in the way sending the bytes.Thanks

author: snarkysparky
author_rank: Frequent Contributor
timestamp: July 17, 2020, 03:13:00 pm
content: Nominal,Can you provide a link for using a board as a peripheral. That's new to me.Thanks

author: MarkF
author_rank: Super Contributor
timestamp: July 17, 2020, 05:24:15 pm
content: Quote from: snarkysparky on July 17, 2020, 03:13:00 pmNot sure what he is suggesting applies to your case?Basically, a PC/Laptop will send data over USB to the Teensy and then the Teensy would forward the data over SPI to your peripheral. A very simplistic hardware only example would be one of those USB to Serial cables. In the Teensy case, you would need to write software for the Teensy to do the forwarding.I do this with a very old DLP Design board. It gives you a lot of flexibility, but I'm not sure you can get the data transfer rates you want. Certainly not the 961Kb/s you mentioned.

author: snarkysparky
author_rank: Frequent Contributor
timestamp: July 17, 2020, 06:00:55 pm
content: Moving toward putting a FT232 chip and USB socket directly on the hardware board.datasheet claims up to 3M bits / sec. Only question is queuing latency if any slowing down transfers.Then I can use just about any single board X86 computer.Any thoughts?Thanks

author: MarkF
author_rank: Super Contributor
timestamp: July 17, 2020, 06:31:51 pm
content: What data rate are you trying to obtain?Like I said, I'm using a DLP Design board (attached datasheet) with a FTDI FT2232 USB 2.0 at 2Mbits/sec claimed data rate. I was never able to obtain that rate. Your actual continuous throughput rate will be much lower.Things to consider are the max buffer size you can transfer and the max delay between transfers. In my case, the max buffer size to the pic16f877a with a 20MHz clock is 80 bytes. And the USB connect delay in Windows between transfers can be up to 4ms. Then there is the time required to process that data.The 3Mbits/sec is the bit transfer rate. You can not maintain a continuous transfer. There are transfer breaks between buffers and processing overhead time.You also need to consider the FIFO size inside the FTDI chip.

author: snarkysparky
author_rank: Frequent Contributor
timestamp: July 17, 2020, 06:57:46 pm
content: Mark,Was the limiting factor the PIC. Could I set a 200k bit buffer size in the PC application and transfer this whole thing in one go?The downstream receiving device is only buffering this to memory so it would not be limiting.Thanks

author: MarkF
author_rank: Super Contributor
timestamp: July 17, 2020, 07:17:57 pm
content: The max USB 2.0 buffer size is 256 bytes high-speed and 64 bytes full-speed.The FIFO size in the FT232 is 128 bytes.I would say the max buffer size you want to send is 128 bytes.If you use a 200KB buffer the operating system break it apart into smaller buffers (if it doesn't just refuse that size). You are probably better off building the smaller buffers yourself.

author: MarkF
author_rank: Super Contributor
timestamp: July 17, 2020, 07:22:06 pm
content: By-the-way, Windows also has max buffer sizes for serial ports.I used 4096 byte buffer sizes (default is smaller). Don't remember the max size.

author: Nominal Animal
author_rank: Super Contributor
timestamp: July 18, 2020, 01:52:28 am
content: Quote from: MarkF on July 17, 2020, 05:24:15 pmWrong. The numbers I quoted are from real world tests, assuming you send and receive multi-byte chunks.The issue is that one must write the firmware for the microcontroller – Teensy in my case, although I do have used this with the cheap "Pro Micro" clones (using an ATmega32U4). These have native USB, and even the ATmega32U4 can reach 1Mbytes/sec via USB serial. Teensy 4.0 is high-speed USB (whereas older Teensies and Pro Micro clones are only full-speed, 12 Mbit/s). In my real-world ping-pong tests, I found that with the Teensy 4.0, the Linux tty layer started to become a bottleneck, but I haven't yet had time to write an USB bulk transfer test (using 256 byte blocks).

author: Nominal Animal
author_rank: Super Contributor
timestamp: July 18, 2020, 02:08:46 am
content: Quote from: snarkysparky on July 17, 2020, 06:57:46 pmWith Teensy 4.0 (I recommend it because of its price/performance ratio, just USD $20), that would be trivial. With USB serial, you would get at least 2 Mbits/s, so the transfer would take less than a tenth of a second. Yes, I have tested and verified this in real life; someones suspicions are worth shit against empirical evidence.As to links for using USB devices as a peripheral; since you used a Raspberry Pi before, you already did that: the ethernet port is actually an USB peripheral. I don't exactly understand what kind of links you want. Maybe look at the PJRCblog postsshowcasing other peoples projects?As to myself, I'm using Teensies and Pro Micro clones to interface to sensors, as both a hobby and a scientific endeavour (helping with a fusor project at an university).I never use USB-to-serial converters myself, because they don't have any logic or any serious buffering capability. With a microcontroller, I can fix any issues in firmware; and since the ones I use have hardware USB, they can appear as any USB device I want.(I have used a Pro Micro clone to help write a Linux driver for a vinyl cutter without having one myself, by making the Pro Micro clone respond according to a real-world USB dump if the correct data was sent.)

author: MarkF
author_rank: Super Contributor
timestamp: July 18, 2020, 03:26:24 am
content: Quote from: Nominal Animal on July 18, 2020, 01:52:28 amI don't doubt you can obtain those data rates for small multi-byte blocks.However, there will be a delay between transmission bursts.In Windows that delay can be as much a 4ms. It varies for every transfer.Not sure what the context switching time is in Windows 10 and the newest processors.My numbers come from a 10 year DLP Design board with a FTDI chip and a 20MHz PIC16F877A with limited RAM.And I did rewrite their firmware and was able to get a 10 fold increase in speed.The larger the data blocks are, the higher your through-put will be.But, the Windows context switching is a real speed killer.I don't know what a realistic through-put speed is now with a Windows operating system.So, the question is: "What through-put speed can you maintain for say a 60sec period or longer?"or"How long does it take to transfer a 200KB buffer?"

author: Nominal Animal
author_rank: Super Contributor
timestamp: July 18, 2020, 03:47:16 am
content: Quote from: MarkF on July 18, 2020, 03:26:24 amWrong. Thetestswere generally done over 5,120,000 bytes, with round-trips (so including latencies at both ends); and the 2.5 - 2.8 Mbytes/s rate calculated for one direction.And that particular test actually rantwoteensies in parallel, with only one 512-byte message in flight per Teensy. So, it wasn't even full-duplex, just half-duplex.For unidirectional transfers, Teensy to Host rates areconsistently about 25.7 Mbytes/sec, or 200+ Mbits/s, over tens of megabytes of data.Note that that test also uses a PRNG to produce random data, and verifies it on the receiving end.If snarkysparky is interested, I can whip up the opposite case, host Linux machine sending say 256 kbytes (262,144 bytes, or 2,097,152 bits) of data to a Teensy 4.0, which verifies it (using a small header block that contains the size and a seed for the checksum/hash function), and responds with a status message after verification. If the sender measures wall clock time from before sending the first byte, to receiving the last byte of the verification message, we reliably time a single operation. To benchmark this, I'd run this in a loop, at least several hundred times but typically a few thousand times (mostly dictated by time), and report the minimum, maximum, and median time taken.Look. I do high-performance computing, and have benchmarked computing cluster for well over a decade now. I know the difference between a microbenchmark and a real benchmark. I know this stuff, and am not just telling you all what I think: I'm telling you all what I have observed in real life.

author: snarkysparky
author_rank: Frequent Contributor
timestamp: July 18, 2020, 03:21:24 pm
content: I will be consuming the serial data in an ARM M4F family micro running at 48 MhZ. I think I can read and process the UART buffer very quickly.My concern is how fast the X86 pc can put out the data.Nominal.. Is the Teensy reading in the USB stream through a UART. If so that is similar to my proposal.Going to try to set up a test next week with just a USB to serial cable and measure transfer times with a scope.Thanks everyone

author: Nominal Animal
author_rank: Super Contributor
timestamp: July 18, 2020, 04:24:43 pm
content: Quote from: snarkysparky on July 18, 2020, 03:21:24 pmNo. The USB support is native. (The D+ and D- USB pins are directly connected to dedicated pins on the microcontroller, without any other ICs in between.) "USB Serial" is the name of an USB protocol intended for USB devices that wish to expose a serial port like device to applications. In Linux, a built-in kernel driver supports this protocol, so no special drivers are needed.ATmega32U4 ("pro micro" clones, Arduino Leonardo, Teensy 2.0) and Teensy LC and Teensy 3.x all have Full Speed USB support, 12 Mbit/s. Due to USB protocol overhead, these all can sustain (continuous) about a megabyte per second per direction. I have verified this on ATmega32U4 on raw metal (avr-gcc and avr-libc), in the Arduino environment, and for Teensy LC, 3.0, 3.1, 3.2, and 4.0, using large amounts of data (hundreds of kilobytes or more; these are sustained rates, not short peaks).Teensy 4.0 has High Speed USB support, 480 Mbit/s. Using USB Serial protocol – where without installing any drivers, the Teensy will look like a standard serial port (/dev/ttyACMN, or a symlink if you setup a suitable udev rule) –, sending a 200 kbit (25,000 bytes) "packet" to Teensy 4.0 will take a few milliseconds. (I can verify it, if you like; I have a Teensy 4.0 nearby.) Teensy 4.0 has several UARTs and SPIs, and can use DMA with SPI and UARTs, or you can use just a simple loop to talk with the actual target device when the bit block has been received. Teensy 4.0 has a megabyte of RAM, of which about 480 kb is continuous (3.84 Mbits) in Arduino. (That is, you can declare a static array of about 480,000 bytes. Actually, two, but they need to be separate, because half of the megabyte is tightly coupled memory, and half not. There is no real speed difference, it's just an architectural thing.)I have a 12+ -year-old Acer Aspire One netbook running Linux (a really old Intel Atom processor; a 32-bit x86 architecture) I can use for the userspace application to transfer the data to the Teensy, for microbenchmarking. It'll be much less powerful than any x86-based Linux SBC now available, and therefore will work as a reliable minimum limit.Again, it would make more sense to test this, if I knew your actual real-world data transfer needs. (200 kbits up, no down? Or some sustained bandwidth over time? Ping-ponging requests and responses across?)

author: snarkysparky
author_rank: Frequent Contributor
timestamp: July 19, 2020, 12:36:45 pm
content: Nominal,Thanks for all this good info. The high bandwidth need is from the X86 to the micro. Reverse traffic is very small consisting of 4 byte messages issued at most 10 / second.I will look into the Teensy. Do you happen to know if they guarantee availability of the part for X number of years?

author: Nominal Animal
author_rank: Super Contributor
timestamp: July 19, 2020, 02:16:42 pm
content: Quote from: snarkysparky on July 19, 2020, 12:36:45 pmWhat's the typical packet size? (I.e. bytes from host to device, between responses.) Or is it just a continuous stream, with device-to-host responses completely separate from the host-to-device transfers?Quote from: snarkysparky on July 19, 2020, 12:36:45 pmNo, but they still support Teensy 2.0 (ATmega32u4), introduced in 2009. For technical questions, seethe PJRC forum.I am sure there are other high-speed USB microcontrollers out there, but Teensys (and ATmega32u4) are the ones I personally am familiar with, and they are programmable in the Arduino and PlatformIO environments. For one-off (or very small number) of interfacing boards – that's how I use them – they're a good fit for me.You can develop your own NXP MIMXRT1062-based microcontroller, although the Teensy design is proprietary. Another interesting microcontroller family (that I have looked at, but not used myself) is the PIC32MZ family: they also have a native high-speed USB 2.0 interface (480 Mbit/s max. theoretical bandwidth). There is at least mikroEFlip&Click PIC32MZdevelopment board with a PIC32MZ, likely others, that are already supported in Arduino and PlatformIO. I've looked at the PIC32MZ family datasheet and application notes, and it does look like a particularly easy MCU to create a board for. Also, Olimex has anOpen Hardware PIC32-HMZ144dev board with PIC32MZ that has high-speed USB, if you prefer the MPLABX development environment; if you are making your own board, then looking at the board files for that one cannot hurt.The key here is that these microcontrollers have a native USB interface on the microcontroller itself. All of the USB full-speed (FS, 12 Mbit/s) microcontrollers I've used, including 8-bit ATmega32U4, can reach about a megabyte per second (8 Mbit/s) using USB Serial protocol, and a trivial userspace program (written in any language; I've tested C and Python using the built-in termios module) even on a slow machine can reach that. With USB bulk transfers and 64-byte packets, you can reach even slightly higher bandwidth.For high-speed USB (HS, 480 Mbit/s) – Teensy 4, PIC32MZ, and so on –, the USB Serial protocol kernel driver side can slow things down a bit, so you won't reach the ~ 48 Mbytes/sec bandwidth, even if the hardware is able to. A simple test shows that on my Linux machine, the kernel tty layer cannot get much above 30 Mbytes/sec, simply because it was not designed for high bandwidth. Using USB bulk transfers (64 or 256 byte packets) completely bypasses that, and has much less overhead; and is much more efficient on both the device and the host computer end.(The nice thing about USB Serial in Linux is that you need absolutely zero drivers (other than the kernel built-in USB ACM driver), or extra libraries, to write efficient code. All you need is a bit of termios glue code, to set the tty layer properties for the USB Serial character device. Trivial in C and Python3.)I do expect microcontrollers like PIC32MZ and Kinetis K26 (with high-speed USB interfaces) to also be able to reach around 20-25 Mbit/s (150-200 Mbit/s) using USB Serial, but somewhat more if using USB bulk transfers. (Again, from Teensy to Host I'vemeasureda reliable, sustained data rate of 25+ Mbytes/s = 200+ Mbits/s, measured by transferring 100,000,000 bytes from a Xorshift* PRNG to the host, and the host verifying each byte matches the byte it generated using the same PRNG.)Because of how the USB bus interfaces to the host computer processors, the host computer processor will not be a bottleneck, if it is capable of running a standard Linux distribution (debian, armbian, etc.). A very simple test is to use an USB 2.0 -based external hard disk, and measure read bandwidth using e.g.dd bs=524288 dev=raw-unmounted-device of=/dev/null count=200(i.e., read 100 megabytes off the raw disk in 512k blocks). If it is less than 40 Mbytes/sec, then you have a problem (or a really slow external hard disk).The reason I haven't yet measured the data rate from Host to Teensy 4, is because if I do it, I want to do it in an actually relevant manner; as closely matching the real-world requirements as possible. As before, I don't expect anyone to just take my word for it, as I've published the whole benchmarking code before, so that anyone can verify the results for themselves.

author: snarkysparky
author_rank: Frequent Contributor
timestamp: July 20, 2020, 06:17:39 pm
content: Mark,Suppose I use .net command.public void Write (byte[] buffer, int offset, int count); with my full file in buffer and count set to the file length.Do you know if this is a blocking call or does it transfer to the driver and move on.Will this incur a 1 ms penalty ever 64 bytes ?Thanks

author: MarkF
author_rank: Super Contributor
timestamp: July 20, 2020, 08:39:42 pm
content: Quote from: snarkysparky on July 20, 2020, 06:17:39 pmI can not help you with .netI mainly program in C/C++If you're asking about the write() command in C++ on Linux, I believe it is a blocking command and will wait for the transfer to complete.The penalty I was talking about (4ms as I remember, not 1ms) is due to task switching by the Windows XP operating system (Yes, it's been that long ago). I have not tested this with Linux. We are talking a bit of apples and oranges here too. And my buffer size limit was due to limited RAM memory in the pic16f877a.If you're thinking of something like a Teensy, I recommend you get one and run a few tests. They are not that expensive. See what rates you are able to achieve in your environment.

author: Nominal Animal
author_rank: Super Contributor
timestamp: July 21, 2020, 09:15:14 am
content: Quote from: MarkF on July 20, 2020, 08:39:42 pmIt depends on both theO_NONBLOCKflag (specified when opening the character device, or set/cleared viafcntl()), and on the termios.ccand.ccsettings, actually. And bothread()andwrite()can return a short count: not all of the buffer is always read/written.If you want blocking reads and writes, do not useO_NONBLOCK, and set.ccto 1 or greater. Set.ccto zero, or to the number of deciseconds (tenths of a second) you are willing to wait between incoming bytes. (If this time limit elapses,read()will return either a short count or zero.)For fully asynchronous communications, set.cc=0and.cc=0, and useselect()orpoll()to check or wait until more data can be read/written, or use separate threads for reading from and writing to the microcontroller.(If you look at myping-pong testcode at PJRC forums, you'll see how it manages communicating with many Teensies in parallel. It is not what I'd use for async comms with a single microcontroller, though.)In snarkysparky's case, it might be useful to write the data transfer section as a function that transfers a big logical block of data, and calls a helper function for each completely received response. In that case, the data structure I would use would look likeCode:struct device {int descriptor; /* File descriptor to the USB CDC ACM device */unsigned char *send_data; /* Transmit buffer */size_t send_size; /* Size of the transmit buffer */unsigned char *send_next; /* First/next buffered byte */unsigned char *send_ends; /* After last buffered byte */unsigned char *recv_data; /* Receive buffer */size_t recv_size; /* Size of the receive buffer */unsigned char *recv_next; /* First/next buffered byte */unsigned char *recv_ends; /* After last buffered byte */int (*receive)(unsigned char *, size_t);};Thereceive()function pointer is the function called for each complete response from this particular device. Of course, if your program will only ever communicate with one microcontroller, then all of these can be global variables (and instead of a function pointer, the comms handling function will just call some function directly).(The reason the next/ends are pointers and not indexes to the buffer, is simply my own habit/coding style.)Quote from: MarkF on July 20, 2020, 08:39:42 pmOh, now I understand!No, Linux hasn't suffered from that sincecompletely fair schedulerwas mainlined in 2007 or so. This, and other currently used schedulers in Linux, are not limited to fixed-duration time slices, and actually switches tasks whenever they become runnable (if possible), at very high granularity (down to nanoseconds, but depends on the hardware). In other words, you won't see that kind of scheduler latency in Linux, unless the CPU is overburdened – and even then you can avoid it by giving the device-talking process a higher CPU and IO priority than normal applications.Since then, there has been quite a few additional enhancements, especially for multi-processor systems and multi-core processors; with a few scientific peer-reviewed articles written about the schedulers in Linux. It's pretty advanced stuff, really.This can still bite oneself if using a really, really old vendor-provided Linux distro. Because of this, I recommend only using those single-board Linux machines that have full support in Debian or Debian variants not in sole control of the vendor (meaning, the project and its sources are available on the net, and not just as an image or "SDK" from the vendor's FTP site). For x86-based SBCs this is usually not an issue, except possibly for specific display drivers (which can be a huge pain in the butt, too), and very rare occasions an oddball Ethernet/WiFi chipset without mainline Linux support. For ARM-core SBCs, quite a few of the manufacturers are working with Linux developers to mainstream the support; including Amlogic, Samsung, Rockchip, and others. Good stuff for us!Quote from: MarkF on July 20, 2020, 08:39:42 pmAbsolutely agreed. And if you are more familiar with some of the other microcontroller families, there are other just as good alternatives there; I'm talking about Teensy here only because I'm familiar with it, not because I claim it to be the be-all end-all; it ain't.If I knew how (not why, just ballpark figures) the host and the Teensy would be communicating, I'd already have written and tested (and published the sources underCC0-1.0here for others to test it too) Teensy 4.0.

author: snarkysparky
author_rank: Frequent Contributor
timestamp: July 21, 2020, 02:47:33 pm
content: I tried a standard USB to RS232 Cable with this codeCode:SerialPortInterface.BaudRate = 921600;void Button1Click(object sender, EventArgs e){uint filesize = 101420;byte[] messagebuf = new byte;for(int i = 0; i < filesize; i++){messagebuf = (byte)(i & 0x000000ff);}DateTime DeTime = DateTime.Now;textBox1.Text = "started";SendBytesToSerial(messagebuf, filesize);textBox1.Text = (((Double)(DateTime.Now.Ticks - DeTime.Ticks))/10000000).ToString();}uint SendBytesToSerial(byte[] ByteMessage, uint length){uint RetVal = 0;SerialPortInterface.Write (ByteMessage, 0, (int)length);return RetVal;}Finished in about a second.But it's still too slow.Going to try the FT232H chip and see if i can send using the usual virtual com port at much higher speed.My micro has a USB peripheral. But after looking into that mess I decided I don't have time to bake my owncode for that as well as HID code in dot net.My backup plan will be the Teensy.Thanks

author: Doctorandus_P
author_rank: Super Contributor
timestamp: August 19, 2020, 01:26:16 am
content: Why x86?Olimex makes a bunch of ARM boards for around EUR40, and for a modest extra amount (about EUR15) you can have a linux capable board with "industrial" specifications.Olimex also makes a big point about long term availability. They have a contract with Alwinner so they can buy obsolete chips, and Allwinner starts up the factory just to make more chips for Olimex. A few years ago they had a blog post about an order of 50000 A13 chips, which in themselves have been obsolete for years, but Olimex apparently still has customers asking for them.You say you need "speed", but 1Mb/s is nothing. Any simple uC can do that.