Skip to main content

Posts

Showing posts with the label embedded

Lowest-latency Ethernet: Byte-oriented NICs? (deleted from StackOverflow...)

Back in 2017 I had a kinda esoteric question about Ethernet NICs with less-than-frame latency, based on my experience with networking software and hardware, and the evidence for something "atypical" being in use by High Frequency Traders. So I posted my question to Stack Overflow. The question got a lot of pushback, which I found bizarre. It had to be moved across 3 SO sites... and finally it stayed in SO proper, where anyway the only response I got was my own, when some days later I found the necessary information myself. Aaand a couple of years of inactivity later, the question just got deleted. 🤷‍♂️ I thought it was an interesting question (why would I ask it otherwise); it was an interesting collection of pushback; and had an interesting answer. So I saved them and here they are for posterity.

Bluetooth audio latency, codecs, when does it matter

These are some random-ish observations regarding Bluetooth audio latency vs "codecs". This started life as a long comment trying to untangle a messy thread in Wirecutter's review of bluetooth speakers, but since it covers a lot of things that I periodically forget about, I'll have it now as a refresher for myself next time I'm checking BT headphones. A couple of pre-clarifications: Different people measure different things, sometimes without even realizing, so it's important to make sure that one understands what a number means. Algorithmic delay? Hardware (+firmware) implementation? Hardware + software? Which software: OS + encoding + decoding, or just the OS piping things around? Is there some app involved? Each layer not only adds delay (lag, latency), but also variation (jitter).

YOU could have invented the LMAX Disruptor... if only you were limited enough!

This is about a shocking realization I got while learning about the LMAX Disruptor – a data structure / architecture that got published in 2011 and made some waves across the web because it allowed LMAX to process +6M transactions per second on a single thread. In Java. Which was interesting because Java was (still?) supposed to be too slow for that kind of thing. By then I was already a couple of years out of the Java world and getting into embedded C, so I took a mental note to look into it just out of curiosity. But, as could be expected, the note was promptly forgotten. I'm now looking again into Java, so finally I managed to take a peek at the Disruptor. Shock: this is just a description of what I was implementing in C while I was still learning it! But it's not that I'm a genius; it's that this is probably the only way to do things when in a limited environment. In fact, the basic architecture is the one used typically in drivers and in Linux's NAPI networ...

An IS_DEFINED() C macro to check whether another macro is defined

Every C programmer knows to use #defines and #ifdefs to disable compilation for a piece of code. But not everyone knows that there are better ways; the problem with this strategy is that the code becomes invisible to the compiler (and "smart" indexers), which means that it stops being checked for correctness. Also, if the rest of the code changes substantially, like variable renaming, function changing their signatures, etc, the disabled part falls out of sync and will need possibly serious work when re-enabled. There are easy improvements to the #ifdef strategy, with the inconvenience that they add boilerplate and/or waste cycles on runtime (important on embedded environments). But there's also a way to remove both the boilerplate AND the runtime checks!

6 tips to survive Codility tests

Well, it happened. When applying for a job, I got sent to a Codility test. And even though I already had some good practice with them, I managed to do badly in stupid ways – ways that 2 years ago I had already identified and even taken notes on. Just, in the heat of the moment I forgot about those rules of thumb. And in fact I think these hints should be given by Codility themselves – because otherwise you are practically ambushed, even more so if you didn't take the time to thoroughly explore how they work. So here are my hints-to-self, now for everyone. The summary is: don't think of Codility as a coding interview; this is primarily about getting something (anything!) working, ASAP.

My first hardware bug report?

I have found what looks like a hardware bug in the AT90CAN128! I guess I could be happy in a geeky way, but the number of hours spent trying to track the problem make it a bit difficult :P. The thing is that aborting a pending MOb in the CAN controller embedded in the AT90CAN128 can leave CONMOB in an unexpected state. I am not totally sure if this is a hardware bug… or could be Atmel's library at90CANlib_3_2 being buggy AND misleading.

Atmel Studio 6 and blank Solution Explorer

Atmel Studio 6, which is (ununderstandably!*) based on Visual Studio (2010?), suddenly stopped showing anything in the Solution Explorer pane. The pane was there, it just remained empty, blank, apart from the "Properties" button (and the "Show all files" button shows up too, depending on the frontmost pane).

Taking a snapshot of the ports in an AVR (AT90CAN128)

A small inline function to take a snapshot of all the ports as simultaneously as possible, which means 7 cycles from first to last, which means less than 0.5 usec from first to last at 16 MHz. Can't be faster. Had to be done in asm inline because if not gcc prefers to interleave the input instructions with store instructions. Done this way, the inputs come first and the storage comes later, generated automatically.

Memory access stride in loops change loop timing in AVR C!

I found a strange situation when programming in C for AVRs. I have a bunch of structures to be worked on, but any of them can be flagged "active" or not at any given moment, to signal whether they need further work. My first approximation was to add a (uint8_t volatile: set in main, checked in interrupt time) member variable named "active" to the struct, to quickly check/set each structure. Shock: only looping through the array checking the "active" member variables was taking an enormous amount of time – about 20 clock cycles per access !