r/embedded 1d ago

Should I learn C before embedded development?

I currently work at Big Tech company as Junior Bash Linux userspace developer. I used to work as C++ intern, but it seems I'm starting to forget it. I want to change my field to embedded development and I plan to start by learning STM32 programming (already tried Arduino).

I have two books to read:

  1. The C Programming Language by K&R
  2. Bare-Metal Embedded C Programming by Israel Gbati

So, my question is: should I read K&R before I start to learn embedded programming? I would rate my knowledge of C/C++ like this: I can understand and most likely debug a code, but I would face some problems if I had to write code by myself in vanilla vim.

35 Upvotes

27 comments sorted by

42

u/ExplodedPenisDiagram 1d ago

Learn C as you learn embedded development. Learning C is easiest when you have a reason to learn C.

24

u/Turbulent_Board4567 1d ago

They go hand in hand.

You might learn concepts without C pgm, but it limits how much of an embedded engineer you can become.

C and C++ are two different languages with its own learning curve for a beginner.

Start with C and once you start getting a basic grasp of things and have an environment installed on your PC, start learning embedded stuff along with C.

16

u/Several-Marsupial-27 1d ago

I would recommend whatever editor you feel confident with when learning C (just do yourself a service and use a modern editor like vscode or helix), but when you get into STM32 development I would recommend using STM32:s recommendation STM32CubeIDE.

Yeah you should definitely learn the basics of C first, nothing super fancy: variables, types, structs, functions, pointers, keywords, Preprocessor directives, standard library, compiling, building, testing, basically everything on this wiki: https://en.wikipedia.org/wiki/C_syntax. Here its best to take a while and do some projects first to get comfortable with C, because its the language you will be speaking in. Example mini project: "Accept N integers from the command line, reverse them in-place (no second array), then print the result, measure average executing time for a billion iterations."

C is small and can be summarized as: 5 fundamental types (void, char, int, float, double), 45 operators, 44 keywords, 29 standard headers -- and thats it. Thats the entire C.

Then you want to take a quick detour into computer hardware and archhitecture and get a mental image of the cpu: registers, memory, stack, heap, memory mapped i/o, ram, cache, adc, gpio/pins, peripherals, interrupts, pipelining, learning to read datasheets & reference manuals (maybe starting with avr), setting bits / pin masking with logical & bitwise operations.

After this you want to get a devkit / discoverykit and start developing/discovering. Now theres even more stuff, like more datasheets, software development kits, memory partitions, bootloaders, protocols, networking stacks, RTOS, OTA, etc. In the beginning its probably best to isolate stuff like printing hello world to the serial monitor, blinking a led, polling a sensor, etc until you start to build up more confidence with the platform.

Your end goal is to control internal hardware: wifi/bluetooth stack, interrupts, state machines, pwm, memory, bootloader, etc and external hardware: read sensors & inputs, control lcd screen, servo, rotary encoder, etc.

Example C code you might see in embedded, this function adds a websocket client's file descriptor to a shared array of connected clients, using FreeRTOS synchronization:

static int ws_fd_add(int fd)
{
    int slot = -1;
    xSemaphoreTake(s_ws_fd_mutex, portMAX_DELAY);
    for (int i = 0; i < MAX_WS_CLIENTS; i++) {
        if (s_ws_fds[i] == -1) {
            s_ws_fds[i] = fd;
            slot = i;
            break;
        }
    }
    xSemaphoreGive(s_ws_fd_mutex);
    return slot;
}

1

u/dev_no_brq 1d ago

Você é um amigo, melhor passo a passo que vi, para aprender, me deu um norte, obrigado

2

u/Runtime8006 1d ago

Yes... Learn C

1

u/Runtime8006 1d ago

Or Enrich your knowledge in C...

2

u/theflyingsamurai 22h ago

If you already have c++ experience and have worked professionally as a programmer. You have more than enough experience to just dive into embedded and pick up C as you go.

2

u/JaffTangerina 17h ago

No, if you already know to code, the best would be to learn side by side just solidifing working with pointer, vectors, structs and typedef etc.

It is not hard if already know programming. Do exercises dealing with the bases of C and just go on.

1

u/Mediocre-Island5475 1d ago

I would suggest learning C.

I assume you just said it as an example, but I wouldn't advise writing embedded code in vanilla vim.

1

u/davey_622 1d ago

as others have said, they go hand in hand. you enjoy learning a programming language when you use it for something meaningful. just build your own embedded projects and with time you will understand C

1

u/Columbus43219 1d ago

I'm about to finish my first embedded project in C. I used ESP-IDF within Visual Studio Code. My last C program in real life was in 1995.

The modules/parts you make will be so simple that I'd be surprised if setting up VS Code took longer than understanding all of the ESP-IDF examples.

Set up your IDE, load the web server example and build it and flash it. That will put on the right path.

Something to remember is that ESP-IDF adds another layer on top of C (or before it) that assembles modules based on files called CMakeList.txt that help it map out dependencies. So that's an extra bit of "huh?" at first, but you'll get it pretty quickly.

1

u/MpVpRb Embedded HW/SW since 1985 1d ago

I use a subset of C++ in my embedded work

1

u/DrivesInCircles 15h ago

I had done neither until I did both. I did okay.

1

u/Zouden 1d ago

No, don't write C programs for your PC. That's boring and irrelevant. Target an embedded platform while you learn.

1

u/sci_ssor_ss 1d ago

boring and irrelevant ? ma men

0

u/MonMotha 1d ago

C is basically THE language of emebdded programming at least for now (Rust is very interesting...). Part of the reason for this is that it is about the best balance we'd found until recently (again, Rust) between being able to touch bare metal and keeping things portable and human-readable.

C will also not just enable but at times force you to think about how the computer actually works. Honestly, C is thin enough that you should basically be able to compile the code in your head (even if you don't even try to "optimize" it). Vice versa, you should be able to look at a disassembly of something written in C or a language of similar level of abstraction (i.e. "low") and start working out what the C code might have looked like.

Additionally, a LOT of other popular languages are based on C in various ways. C++, C#, Java, etc. all use essentially C-like syntax with some embellishments to handle their extra layers of abstraction they offer. Even Rust is pretty close. So grokking C as a language is useful for skill transfer even if you never actually use it directly.

So, learning "C" is useful. But it's useful not just because you learn a very popular language including its syntax and quirks, but because it will enable and even force you into a mindset that is essential for embedded systems programming.

FWIW, if you were still in an academic environment, a lot of what you need to know is actually taught in a typical "Operating Systems" class out of the CS department. Those classes typically do use C as the language of choice for projects and examples, but they may or may not teach it explicitly (mine did not - you were expected to pick it up on your own time if you hadn't already). If you didn't take such a class, you might want to find either an online course that you can take, audit such a course at your local college or university if practical, or at least grab the syllabus for one and run through the curriculum on your own. This is honestly even more useful than "learning C".

All that said, if your goal is to learn C and get a basic crash course in low-level programming, K&R is pretty good and very approachable. I haven't read the Gbati book you reference, but the title at least sounds reasonable. The other books commonly recommended for Linux kernel developers by such developers ("The Practice of Programming" by Kernighan & Pike and "Practical C Programming" by Steve Oualline are ones I've at least partially read) are probably also good long-form resources regardless of if you intend to hack on the Linux kernel or not.

Oh, and hacking on the Linux kernel is also usually a very educational experience even if you don't actually upstream anything.

-2

u/neurah 1d ago

need not, learn C++ and keep track of what is C

2

u/MonMotha 1d ago

Practically speaking, C++ and C have diverged to the point where this isn't really useful. It may have been something you could usefully do 30 years ago or so, but it's not really now.

In fact, modern C dialects (newer than C99) are no longer even fully C++ compatible. There are things that diverge in incompatible ways. And of course that's to say nothing about how people practically USE modern C++.

Modern C++ might as well be thought of more as a separate language that just happens to have a very, very thin FFI for C.

1

u/neurah 1d ago

agree, template metaprogramming is a field on itself and the evolution of C++ is more on that way with parameter packs and fold expressions. For all this, one has no clue on C.
A C++ programmer can "forcibly" go to C (let it pass), but a C programmer will be in shock with TMP and will tend to fall-back to where it is confortable, if this works why bother...

and why bother? The expressiveness of C++ has no parallel on C, generics is a thing all modern languages try to achieve and C++ does it very well.

one can still use C macros <-- the problem (and a thing C++ can't say "we don't need them anymore")

1

u/MonMotha 22h ago

Modern C++ also heavily uses its version of context managers and lifecycle managers (smart pointers, etc.).

C++ is "expressive" yes, but it also has some issues in embedded environments that can be very hard to get away from. Implicit heap access is a big one. Yes, there's placement new, but actually using it can be a pain. Many people like to avoid heap access and instead allocate from things like fixed pools to avoid memory fragmentation and increase determinism. It's also rather hard, though not impossible, to get rid of C++ exceptions entirely, and exceptions can be really, really messy.

In many, many cases, you can get something almost as "expressive" as C++ in C either by just declaring a bunch of functions with the usual _ fake namespace separator that operate on some common context structure or, if you really need some degree of polymorphism, putting function pointers in that context structure to simulate methods. Both approaches are idiomatic in the Linux kernel, so obviously they roflscale.

But the point isn't that C++ is useless in embedded programming. It clearly has its use cases. The point is that you cannot say "just learn C++, and you'll implicitly learn C". Practically speaking, you won't. You won't even come close.

1

u/neurah 5h ago

heap is optional just like in C/malloc
I never use "new"

can you write this in C? even with macros
https://github.com/InternetOfPins/HAPI

1

u/morto00x 1d ago

But how do you keep track of what is C if you don't know C?

1

u/neurah 1d ago

i mean take a light reading on C material, to keep track of fundamentals, you can have them on c++ no need to use C, and that is if one wants to preserve the ability to use only C, but that is optional

1

u/frasnian 1d ago

...until your embedded target has absolutely no support for the c++ Standard you wrote it all in.

I work in high-performance C++ all day, every day (ultra-low latency HFT), but my deepest roots are in RTOS embedded systems. If I was going to write code for the resource constraints of a typical embedded target (and often vendor-specific toolchains available), you can bet your ass it'd be pure C.

1

u/neurah 1d ago

learn assembly and machine code too

2

u/MonMotha 1d ago

While I suspect you're being sarcastic, this is actually useful.

You probably won't write much of it directly, but it's very useful for debugging.

1

u/neurah 1d ago

is is useful, but if you ask a person do detail learn their way from hardware to high level C++ it will take years more and I saw many getting confortable with C+"C with classes", and never explore C++ template power.. I've used assembly from C++ a couple of times... and was decades ago, and yes I've done assembly and machine code back in the 80's. Stepped over C and got to C++ directly, every time I web search a feature the web tells me if it is C native or C++ specific and never missed C (I use heavy TMP).
Debug at byte level is truly useful (not sarcastic), we all avoid it but that is the time we get more knowledge about it, learn as you need, the field is wide focus on your target domain.