There are 11 languages that float to the top of the consideration pool when it comes to programming embedded systems. They range from general-purpose languages like C++ and Java to embedded-specific choices like Go and Parasail.
1.C
It makes sense that a language first developed to program telephone switches would be a reasonable choice for embedded system development. C is as close to a lingua franca as exists in the world of software development: It's available on nearly every advanced embedded system platform that exists. For some platforms where it's not directly available, it's still the basis for the dedicated language used in the SDK.
The odds are good that professional programmers have at least a passing knowledge of C already -- and if they don't, an investment in learning C should pay off for both the programmer's career and your enterprise development efforts in the future. In today's terms, C is a bit of a throwback: It's procedural rather than object-oriented, doesn't come with a built-in bias toward a graphical user interface, and is compiled rather than interpreted. All of those factors, though, make it a strong candidate for just about any IoT development effort.
2.C++
When the programming world began moving toward object-oriented languages in the early 1980s, procedural languages such as Fortran, Cobol, and C seemed destined to fade into obscurity. While Fortran and Cobol have become niche languages (sure, Cobol is a big niche, but still...), C retained its relevance due to the work of Bjarne Stroustrup, who developed an object-oriented pre-processor for C -- a pre-processor that came to be called C++.
C++ kept the spare nature of C but added data abstraction, classes, and objects. All of these features make C++ a popular choice for those who are writing embedded and IoT code for Linux systems. This programming language still is going strong after more than 30 years in the field.
3.Java
C and C++ were designed from the ground up to allow very direct control of the hardware on which they would run. That's a good factor when you're trying to do very fine-grained monitoring and control of that hardware, and it means that the code written is very specific to the hardware. In programming parlance, the code is not terribly portable.
Java was written to be an object-oriented language that is incredibly portable: There are very, very few hardware dependencies built into the compiler. In order to get the specific, fine control over particular pieces of hardware, Java depends on hardware-support libraries that are called from the generic code.
4.JavaScript
It would be easy to think that JavaScript is simply a variant of Java. It would be easy, but it would be wrong. The two languages touch in a couple of odd and useful ways (there are, for example, some libraries that can be used by both), but were developed separately and share no syntax or semantics.
JavaScript is, as the name implies, a scripting language that is heavily used for building web-fronted applications. If you wanted to use the Apache server on a Raspberry Pi to gather data from a network of Arduino-based sensors, for example, JavaScript would be a good starting point for the effort.
5.Python
A language designed during a holiday break and named after a famous comedy troupe seems an unlikely candidate for serious development. Nevertheless, Python has become one of the "go-to" languages in web development, and its use has spread to the embedded control and IoT world. Python is very flexible in many ways. For example, it is an interpreted language that can either be submitted to a run-time compiler or run through one of several pre-compilers so that compact executable code may be distributed.
The thing that makes Python good for programming teams, though, is its emphasis on readability. The design specs for the language mention the importance of readable code and compact, elegant syntax. Anyone who's ever tried to unravel someone else's optimized C code can appreciate the benefits of highly readable code.
As with so many of these languages, Python's possibility as an embedded language rests on having sufficient power in the embedded platform. For any applications that will take data, put it into any sort of database format, then draw upon the tables for control information, Python is a very real contender.
6.Go
First things first: "Go" is not "Go!" Got it? These are two very different languages for very different purposes. Go was developed at Google and is available on a wide variety of processors and platforms. While it is one of the many languages that owes a debt to C, there are a number of ways in which it's superior to C for certain types of embedded programming.
Go adds an explicit hash table type, as well as types that can be very useful for gathering data from and sending data to separate sensors and actuators. The ability to use a network of sensors and devices is further supported by a key Go facility -- though it introduces a risk.
Go supports concurrent input, output, and processing on many different channels. Used correctly, this allows the coordination of an entire fleet of sensors and actuators.
7.Rust
Rust was developed at Mozilla. Like the rest of Mozilla's software, Rust is an open source project that is evolving quickly. Rust shares many of Go's qualities, though it does solve one major problem of Go.
Because Go doesn't automatically share information between the different "channel" data structures, a program can develop something called a "race condition." It's basically a runaway situation in which a system can spiral out of control because different processes are working at odds with one another. Rust includes functions that eliminate race conditions, making it a less-risky language than Go for highly concurrent programs.
8.Parasail
Parasail is a language that you'll consider if you have a requirement for parallel processing in your IoT application. We've mentioned concurrency as a programming concept in languages such as Go and Rust. If you don't know (or your development team can't explain) the difference between concurrent and parallel programming, then you should do more research before you start coding.
Parasail is a compiled, object-oriented language that has evolved so that it can be programmed with syntax that looks like Java, Python, C#, or even (Heaven help us all) Ada.
9.B#
Where many of the languages mentioned here are large system languages that have been scaled down to fit into an embedded platform, B# was designed from the ground-up as a very small, very efficient embedded control language. The embedded virtual machine (EVM) that allows B# to run on a variety of different platforms only takes 24k of memory -- much smaller than the overhead needed for many of the other packages we've seen.
B# looks a bit like C# (which will be familiar if you or your team is accustomed to working on Microsoft .NET projects), but it strips out many of the features not required for embedded projects and adds support for the real-time control functions that are critical when making things happen in the real world.
If your project is going to live on embedded platforms that aren't as big and complex as a Raspberry Pi, then B# is a language that you will want to consider.
10.Assembler
When you want to go truly old-school, or you need to keep your project as compact as possible, then assembler is the path you'll take. Assembler is a way of packaging and building the pure machine code that's ultimately executed by the processor. The good news is that the overhead is absolutely minimal, and an expert can pull optimizing tricks simply not available in any other programming method.
The bad news is that assembler programming is coding without a net: You have practically no useful tools to keep you from making silly mistakes. It's also true that assembler code (and the skills for writing programs in it) are absolutely not transferable. Just because you can write for one processor, it doesn't follow that you can write assembler for any other.
11.Forth
Forth is another language designed and optimized for embedded system programming. While it's used primarily for system-level programming, there's one aspect of Forth that must be addressed: It's very much like a religion. You know the Esperanto speakers who approach you in the airport and want to converse in a language you just don't understand? Move them to the programming world, and they write in Forth.
Forth is a stack-oriented language. If you regularly use an old-school HP calculator (with its RPN operations), then you've got a major leg up on understanding Forth. A language that's been around since the 1970s, Forth is very productive and efficient in the hands of the right programmer -- and unusable and unreadable by everyone else.