Not really.
Only the AVR series chips from the Atmel acquisition have this support, when using the open source GCC suite. And even then, their official compiler build is pretty old.
Not really.
Only the AVR series chips from the Atmel acquisition have this support, when using the open source GCC suite. And even then, their official compiler build is pretty old.
This is a rant.
Need Moar C++11 In Embedded Software
We really need to embrace the use of C++11 in embedded software development with proper, type-safe, interrupt-driven events and callbacks, and we need to do this as natively as possible.
Since IAR finally released a C++11-compatible compiler this year, it should be the goal to actually make use of C++11 now that all of the “Big 3” (IAR, Keil, and GCC) support it.
(Shame on you, IAR, for taking this long to make this possible.)
I’d really like to see a clean C++ API on embedded chips taking advantage of C++11 features, running as close to the metal as possible.
mbed is close, but I’ve definitely seen many odd behaviors where it wraps the low level APIs provided by vendors and ends up blocking, crashing, or doing other stupid things that aren’t anticipated in the mbed API.
Which leads me to my next point.
Procedural, Embedded C With Blocking APIs Needs To Die
We should stop writing procedural C APIs for microcontrollers. Apple’s IOKit object-oriented driver architecture shows us a better way, and it was invented decades ago, even if not that many people ended up using it.
We should also stop using blocking APIs on as many microcontrollers as possible.
The bare-metal HALs and SDKs that offer these types of code examples should remove them because they tend to encourage bad programming practices, even when an RTOS is in use (because most microcontroller RTOSes don’t tend to properly handle event-driven wakeup on I/O and leave this to the user anyways).
I’ve seen too many examples of code where reading a serial port involves:
Think about this: In one millisecond, a 12MHz processor can run 12000 instructions, more or less. Let’s say it takes the unskilled program 20 instructions to set up the registers to receive a byte on the serial port and enter a while loop.
The processor will busy-wait for 11980 cycles, consuming 100% power. This is idiotic.
The primary benefit of thinking in events and callbacks is power-related, we really should avoid sleeps that are not real sleeps.
It kills me to see people still using superloops without proper sleep / WFI / WFE calls. Pretty much all Arduino code falls into this category.
My experience with mbed is also that its power consumption is quite atrocious. It insanely does not yet have a tickless scheduler as part of its RTX RTOS codebase, making it essentially useless for battery-powered devices.
Goals Hardware Manufacturers Should Pursue
Every hardware manufacturer has something that slightly odd about its software offerings. I never understood this. NXP has LPCOpen, which is a set of C SDKs for their LPC microcontrollers, but each chip has its own SDK ZIPfile blob which may or may not have a consistent API with other LPC microcontrollers. STM has its STMCube software which is in a similar position. Atmel and Atmel Studio is pretty good, but their chips often seem to be pretty expensive and they just automate away some of these issues via clever IDE wizards. Cypress and TI have decent hardware, but the PSoC C APIs never seemed all that easy to get around and I have no idea who pays for Code Composer Studio.
NXP has a decent set of development tools, STM does not make its own (seriously, WTF), neither does Nordic Semiconductor (who just leaves you to puzzle through their horrendously-architected nRF5 SDK and fight multiple times with various not-well-documented headers just to get printf
with RTT working and to struggle with integrating multiple projects together to get the various types of hardware working together).
Silicon Labs has a fantastic development environment, with amazing debug, energy measurement (AEM is amazing), and low-power state management (setup EM4!) but no one really uses them. So sad.
But at the end of the day, I feel like I’m always porting, even between chips in the same family, from the same company.
So here’s what I wish these damned hardware manufacturers would actually do:
while(delay) { NOP() }
.sdk_config.h
file, and by a statically-defined variable, and by a variable in a configuration struct pointer somewhere. (I’m looking at you, Nordic Semiconductor.)Why is this so hard to get right? Baseline functionality should have me doing less plumbing and more coding on my own application and it is high time, in 2017, to get this right.
The rest of the programming world moved to object orientation years ago, and the resources available on today’s microcontrollers should allow us to place greater value on programmer time and programmer effectiveness.
We need to stop chasing the smallest possible firmware and start chasing the most bang-per-line-of-code and bang-per-minute-of-programmer-time.
Postscript
Whenever I see the code example:
1
2
3
4
5
6
7
8
|
int main(void)
{
while (1)
{
read_some_sensor();
delay_ms(1000);
}
}
|
I want to punch someone at Arduino for wasting so much electricity.
A year and a half ago, I wrote up a post lamenting the problems caused by counterfeit USB to serial adapter chips.
One of the primary issues was the inability to tell the adapters apart on the USB device tree when hooked up to the same computer. (There were, of course, other problems.)
Amazingly, after revisiting the thought recently, I discovered that any of the cheap adapters built atop the Silicon Labs CP210x chipset would in fact allow you to set the serial number to a value of your choosing!
I’ve written some code to help exactly measure the ISR stack usage on ARM mbed:
ARM mbed OS derives its thread management capabilities from ARM’s RTX realtime operating system.
When a thread crashes due to a stack overflow or other HardFaults, it can be unclear what code is causing the issue. Also unclear is how the threads are initially created, as ARM mbed OS defines its stack sizes via a handful of preprocessor #define
s and linker provide
s which aren’t well documented at all.
Here are some notes on the things I’ve had to figure out by reading the source.
Continue reading Stack, Heap, and Thread Crash Hunting in mbed OS