I think it mostly refers to the build in functions in Ada for Bit fiddeling.
You can represent registers and bitmaps in Ada data structures and use relatively simple to understand functions on them instead.
https://learn.adacore.com/courses/intro-to-embedded-sys-prog...
There are a lot of aspects where Ada is better than C. Just a few things that came to mind:
General lack of dumb C stuff like switch fallthrough, null terminated strings (Arrays in Ada are passed with fat pointers), undefined behavior, no need for memcpy, no preprocessor bullshit etc.
Ada is more like C++ in functionality so it has Generics, Tasks (Threads), Exceptions, Packages, Strong types, Design by contract etc (All much much saner than C++ stuff)
I know berating C is trendy, but it feels a bit gratuitous and uncalled for in your comment...
> Ada is better than C
> lack of dumb C stuff
Back to your comment, strong types and generics look super nice for embedded. Not sure I would like fat pointers, exceptions and threads in my embedded code though.
Tasks in Ada aren't threads, per se, unlike how many people describe them. They can be implemented with threads, but they don't have to be. For embedded and real time systems you likely have a task system suitable for that sort of environment (I'd hope) and Ada compilers targeting such systems will use an appropriate task system.
>I know berating C is trendy, but it feels a bit gratuitous and uncalled for in your comment...
Sorry about that, English is not my first language so i might sound rude sometimes. I actually dont hate C, but if you used it you know its flaws. I think stuff i mentioned about C is objectively bad, hence why i called them dumb stuff.
>Not sure I would like fat pointers, exceptions and threads in my embedded code though
Fat pointers are just pointer + size of an object. You have to pass array size anyway, so its just convenient. Obviously, if you need to just pass a pointer there are ways to do that.
As for exceptions and threads: As i said, you can disable or modify them just by using Restrictions pragma. Its a language defined thing. For example, Ada 2022 defines two profiles for safety-critical hard real-time computing:
> Sorry about that, English is not my first language so i might sound rude sometimes
No offense taken, not a native here either ;-)
> if you used it you know its flaws
Indeed, I've been using C for almost 20 years now. I won't say it's without flaw for sure, it has its quirks, but overall I do think it's quite okay for the job.
> Fat pointers are just pointer + size of an object
Yeah I know what fat pointers are, I even resort to handcraft some form in C for some neat performance hackery on x64.
But the thing is, we're talking embedded here. Most ucontrollers I use have 8b address space, no MMU or any form of virtual memory, separated instruction/data bus (MVHA). That kind of thing don't play well with funky fat pointers.
Sure if your definition of embedded is "64b ARM" all is good, but I guess we're on a spectrum.
Exceptions are pretty much non existing as well, since that would require some form of runtime, which you often just cannot afford on a small chip (if not just form the sheer size of it).
Threading is a no go as well. To get threads, or any form of multitasking really, you have to rely on an operating system, which by definition is a bit weird to have on an embedded IC.
>But the thing is, we're talking embedded here. Most ucontrollers I use have 8b address space, no MMU or any form of virtual memory, separated instruction/data bus (MVHA). That kind of thing don't play well with funky fat pointers.
I personally think that its 'representation clauses' are a really awesome feature for bare-metal programming. It's a shame other languages haven't borrowed this idea.
Wouldn't it be nice in C to be able to define how a struct is laid out in the machine representation? In Ada, you can and it is part of the standard, so it is portable:
It's difficult for someone with 0 knowledge of the language to really understand representation clauses. It does seem to be similar to enum values in C++?
// Ada
for Day use (Mon => 2#00000001#,
Tue => 2#00000010#,
Wed => 2#00000100#,
Thu => 2#00001000#,
Fri => 2#00010000#,
Sat => 2#00100000#,
Sun => 2#01000000#);
// C++
enum Day {
Mon = 0b00000001,
Tue = 0b00000010,
Wed = 0b00000100,
Thu = 0b00001000,
Fri = 0b00010000,
Sat = 0b00100000,
Sun = 0b01000000,
};
As for the record representation, my understanding is that it is equivalent to having a normalized __attribute__((__packed__)), where smart compiler padding is disabled and you can arbitrarily decide the memory layout of your struct?
Representation clause is just language defined way of how struct (Record in Ada) Enum or Array are actually laid out in memory. So, for example, you can define a struct that represents a register, overlay that register address and use it like this:
procedure Enable_USB_Clock is
begin
Registers.PMC_Periph.PMC_SCER.USBCLK := 1;
end Enable_USB_Clock;