EmbeddedRelated.com
Forums

C# for Embedded ?...

Started by Chris November 4, 2016
On 05/11/16 04:02, Paul Rubin wrote:
> George Neuner <gneuner2@comcast.net> writes: >> JVM does not directly support tail calls. CLR does directly support >> tail calls and so better supports languages that require them. F# is >> an example of this - there is no ML family language for JVM. > > This is apparently a real issue, but I'm not sure why, since tail calls > can be compiled into jumps. I wonder how Scala, Clojure, and Frege (all > JVM functional languages) deal with it.
ISTR it is to do with the lack of specific JVM instructions. There are plans to add new instructions like "invokedynamic" but they don't seem to get anywhere. (I'm out of touch on the specifics, and what has/hasn't been added) I suspect their importance is reduced by new features being added to Java that are claimed to give many of the advantages of functional programs. I haven't formed an opinion as to whether such additions are worth it, but fear they might enable people to write even more incomprehensible code. History shows that languages tend to start out simple, pure and comprehensible, but mutate into a less comprehensible mish-mash that attempts to be all things to all people. Java is not immune to those tendencies.
On 05/11/16 00:35, Paul Rubin wrote:
> Tom Gardner <spamjunk@blueyonder.co.uk> writes: >>> C++ core guidelines >> Your suggested actions w.r.t. C/C++ are ameliorations, not cures. > > The guidelines basically say to use the current reasonably safe subset > of C++ rather than the leftover legacy stuff. C++ itself can't get rid > of the old stuff because old programs would break, but new code can > avoid it straightforwardly.
Yes, but "legacy" => "sand", and very few programs are completely new code.
> >> Even if (and it is a big if) they were a cure, how could you guarantee >> that /everybody/ (in whatever company) that produced any code that >> ends up in your product has fully followed the recommended practices. > > 1) Most (not all) of the guideline recommendations are statically > machine checkable and the guideline discusses that for each item.
Such guidelines are certainly a significant help, but for safety critical work /guarantees/ are valuable. Other languages are a better starting point where guarantees are required.
> 2) Critical code even in Ada usually has multi-person code reviews that > should be able to spot departures from coding rules.
Of course. You can create a bad/dangerous/stupid system in any language.
> 3) Stuff like excluding the use of certain runtime libraries can be > enforced by replacing those libraries with versions that signal errors.
Dangerous in an embedded safety-critical application. Avoidance by design and construction is highly preferable. While not completely achievable, other languages get you considerably closer to nirvana.
> 4) The same "amelioration" issues apply to C (MISRA guidelines for > acceptable practices), Ada (Spark subset and profile), etc. > >> Using C/C++ for safety critical system is "building a castle on sand". > > C and C++ these days are completely different languages and Stroustrup > likes to say "I take most uses of the compound C/C++ as an indication of > ignorance." (http://www.stroustrup.com/bs_faq.html#C-slash)
He's said many things over the decades, of course :) To me what's important is what the average programmer *doesn't* have to know/worry about. Most want to (and are paid to) drain a swamp, not fend off alligators.
> The C++ FQA sometimes is used to support the view that C++ is more > dangerous than C.
C++ /is/ more dangerous in that it is more poorly specified and more misunderstood by typical programmers (and language implementers, if anecdotes from those involved in such things are to be believed). In other respects they are equally safe/dangerous. The question then becomes how much damage a typical programmer could inflict knowingly or inadvertently.
> Having used C++ for a while now, my current > subjective impression is that if you follow the core guidelines and use > traditional coding/debugging processes, C++ is safer than C, especially > with modern (C++11 and later) dialects. Ada is probably safer than > either. I definitely choked a little when I heard that the Tesla car > and SpaceX rocket are both programmed in C++.
Gag :(
> C has better static analysis tools like Frama-C that I'd like to try > using, which could be considered an advantage of C over C++. I > currently haven't used them though.
And that's a problem: not many people do use them. Tools like valgrind are used because they uncover very common classes of problem that are completely avoided by using "more advanced" languages and managed environments that give you extra guarantees.
>> "what does the standard mean by X?" and "how do we simultaneously >> resolve the standard saying X and Y?". That doesn't warm the cockles >> of my heart. > > Yep. It's still like that. You also can see that type of thing in > comp.lang.ada, so it's not C specific.
Agreed, but the issue is more widespread and significant in C++ and (to a slightly lesser extent) in C.
lauantai 5. marraskuuta 2016 9.47.34 UTC+2 Don Y kirjoitti:
> On 11/4/2016 11:52 PM, Paul Rubin wrote: > >> Still, this thread is (or was) not about micowave ovens, but about a > >> safety-critical automotive application, which I suspect is larger than > >> a microwave-oven controller. > > > > It seems to me that microwave ovens these days would usually be > > programmed in C rather than BASIC, but Ada is perfectly well suited for > > almost anything C is suitable for. For that matter, the Arduino was > > built around AVR microcontrollers with 1k or 2k of ram, and the > > "official" programming language for the Arduino environment was/is C++, > > which is even more complex than Ada. > > Note that I'd not claimed microwave ovens WERE coded in BASIC but, > rather, used BASIC as an example of how "complex (simple)" the > application is. > > (Too!) Many small applications are still coded in ASM in the > belief that this gives better control over resources/application > size. > > We have a MCU controlled *toaster*; wanna bet the application > is two pages of ASM? > heating_element(ON) > while (temperature < setpoint) { > blink_LED() > } > eject_toast() > I'd wager the code in our furnace isn't much more complex -- and > there much primarily to report errors for troubleshooting > (blinkenlites) > > The complexity of the user interface seems to be a driving factor in > the complexity of the codebase in many deeply embedded products. > I.e., the control algorithms being simpler than the interactions > with the user.
You have mentioned ASM, BASIC and Lisp here as examples of programming languages which can be used to create "tight code" or which can be used as embedded programming languages implementing the microwave oven. Yes, you are right. Why not? However, there is more in software engineering than just being able to write "tight code" or the language can be used to write a controller for a device. The languages you have brought up (ASM, BASIC, Lisp) in addition with the C and C++ has very poor type system. The compiler (or the interpreter in case of Lisp or BASIC) nor the runtime environment cannot make sure, for example, that the variables are not assigned values that are outside the intended numeric range, nor the compiler or the runtime environment cannot validate that the table indexes are within the table bounds. Those languages just perform actions without any knowledge whether or not the action was valid or just plain wrong. Worst yet, the software engineer cannot specify the valid numeric range of the variables that it is expected to hold. It is also very hard for the humans reading the code to validate that the operations and actions are within the intended boundaries. That is why the programming language needs to have a built-in, strict and rigorous type checking mechanism which is able to automatically validate each and every action, assignment, computation and table access through out the program. Ada has a very strong type checking system. The SPARK subset of Ada has even an ability to mathematically prove the program to behave as expected. Ada has automatic, built-in runtime checks for variable and table range checking as the compiler knows what values are allowed for the variable and the table index. You may argue that the strict type and the run-time checking costs too much. Well, the compilation time type checking doesn't cost anything at the runtime, so no penalty here. You can enable or disable the runtime checks as you will, so you can tune the performance as needed. Languages like C, C++, BASIC, Lisp or ASM just don't have built-in capabilities and expressiveness that provide the software engineer the power to express his/hers intentions and requirements which will be rigorously checked through out the programming project, nor the compiler enough information the perform rigorous and extensive compilation time and runtime checks. Br, Kalvin
On 11/5/2016 4:03 AM, kalvin.news@gmail.com wrote:
> lauantai 5. marraskuuta 2016 9.47.34 UTC+2 Don Y kirjoitti: >> On 11/4/2016 11:52 PM, Paul Rubin wrote: >>>> Still, this thread is (or was) not about micowave ovens, but about a >>>> safety-critical automotive application, which I suspect is larger >>>> than a microwave-oven controller. >>> >>> It seems to me that microwave ovens these days would usually be >>> programmed in C rather than BASIC, but Ada is perfectly well suited for >>> almost anything C is suitable for. For that matter, the Arduino was >>> built around AVR microcontrollers with 1k or 2k of ram, and the >>> "official" programming language for the Arduino environment was/is C++, >>> which is even more complex than Ada. >> >> Note that I'd not claimed microwave ovens WERE coded in BASIC but, rather, >> used BASIC as an example of how "complex (simple)" the application is. >> >> (Too!) Many small applications are still coded in ASM in the belief that >> this gives better control over resources/application size. >> >> We have a MCU controlled *toaster*; wanna bet the application is two pages >> of ASM? heating_element(ON) while (temperature < setpoint) { blink_LED() >> } eject_toast() I'd wager the code in our furnace isn't much more complex >> -- and there much primarily to report errors for troubleshooting >> (blinkenlites) >> >> The complexity of the user interface seems to be a driving factor in the >> complexity of the codebase in many deeply embedded products. I.e., the >> control algorithms being simpler than the interactions with the user. > > You have mentioned ASM, BASIC and Lisp here as examples of programming > languages which can be used to create "tight code" or which can be used as > embedded programming languages implementing the microwave oven. Yes, you are > right. Why not?
The example offered has nothing to do with "tight code" -- a microwave oven isn't particularly challenging even with the slowest processor using an interpreted language! Rather, it's just matching the complexity of the problem to the complexity of the solution. Likewise wrt costs. You wouldn't bring a backhoe onto your property to plant daisies. Nor use a spade to excavate for a swimming pool! Using a backhoe to plant daisies requires you to hire someone capable of operating a backhoe. Using a spade to excavate a swimming pool requires you hire someone who has a strong back. You wouldn't use a Cray to control a microwave oven nor an 8b MCU to process airline reservations -- though BOTH could be done (poorly!)
> However, there is more in software engineering than just being able to write > "tight code" or the language can be used to write a controller for a > device. > > The languages you have brought up (ASM, BASIC, Lisp) in addition with the C > and C++ has very poor type system. The compiler (or the interpreter in case > of Lisp or BASIC) nor the runtime environment cannot make sure, for example, > that the variables are not assigned values that are outside the intended > numeric range, nor the compiler or the runtime environment cannot validate > that the table indexes are within the table bounds. Those languages just > perform actions without any knowledge whether or not the action was valid or > just plain wrong. > > Worst yet, the software engineer cannot specify the valid numeric range of > the variables that it is expected to hold. It is also very hard for the > humans reading the code to validate that the operations and actions are > within the intended boundaries. That is why the programming language needs > to have a built-in, strict and rigorous type checking mechanism which is > able to automatically validate each and every action, assignment, > computation and table access through out the program. > > Ada has a very strong type checking system. The SPARK subset of Ada has even > an ability to mathematically prove the program to behave as expected. > > Ada has automatic, built-in runtime checks for variable and table range > checking as the compiler knows what values are allowed for the variable and > the table index. > > You may argue that the strict type and the run-time checking costs too much. > Well, the compilation time type checking doesn't cost anything at the > runtime, so no penalty here. You can enable or disable the runtime checks as > you will, so you can tune the performance as needed. > > Languages like C, C++, BASIC, Lisp or ASM just don't have built-in > capabilities and expressiveness that provide the software engineer the power > to express his/hers intentions and requirements which will be rigorously > checked through out the programming project, nor the compiler enough > information the perform rigorous and extensive compilation time and runtime > checks. > > Br, Kalvin >
On Fri, 04 Nov 2016 13:12:57 +0000, Chris wrote:

> Hi, > > I've been invited to a meeting to discuss am automotive like engineering > project with a high level of safety critical requirements. > > They are using Simulink for some of the top level design work, but are > programming the whole lot in C#, with some of the code already written. > Not sure at this stage which rtos is being used, if at all.
> ...
C# or Java (C# is essentially MS/Java) are not suitable for embedded systems, and in a safety critical environment with very likely also some realtime constraints, is the worst possible choice ever. In those contexts even C++ (which runs circles around C#/Java performance wise) would be a suboptimal choice.
On Sat, 5 Nov 2016 04:03:32 -0700 (PDT), kalvin.news@gmail.com wrote:

> >Ada has a very strong type checking system. The SPARK subset of Ada has even an ability to mathematically prove the program to behave as expected. > >Ada has automatic, built-in runtime checks for variable and table range checking as the compiler knows what values are allowed for the variable and the table index. > >You may argue that the strict type and the run-time checking costs too much. Well, the compilation time type checking doesn't cost anything at the runtime, so no penalty here. You can enable or disable the runtime checks as you will, so you can tune the performance as needed. > >Languages like C, C++, BASIC, Lisp or ASM just don't have built-in capabilities and expressiveness that provide the software engineer the power to express his/hers intentions and requirements which will be rigorously checked through out the programming project, nor the compiler enough information the perform rigorous and extensive compilation time and runtime checks.
When designing user/kernel mode switching APIs or similar programs, you absolutely first things is to check the validity of the call parameters. PERIOD. Such as if it is accessability from the calling (user) mode. These annual checks should give a clean well defined (version independent) error codes. Letting the program access deeper than that and any run-time error code could be anything and as such useless.
On 05/11/16 12:40, asdf wrote:
> In those contexts even C++ (which runs circles around C#/Java > performance wise) would be a suboptimal choice.
Surprisingly to those that have a narrow knowledge of computing research and practice, that's wrong. The core problems are that: 1) lack of GC leads many programmers to be more defensive than is necessary in a managed environment. Typically that manifests itself as "unnecessary copies", which is a real problem since memory is usually the bottleneck nowadays. 2) C/C++ can only optimise what it /guesses/ will happen at runtime. HotSpot optimises what /actually/ happens. If you doubt the efficacy of that, consider the results of the 25 year old "Dynamo" results. The TL;DR is take optimised C running on processor X, then instrument what actually happens at runtime by running it inside a emulator of X running on X. Naturally that is slow. Then optimise the binary and run it inside the emulator of X running on X. Sometimes the *emulated* C binary code is *faster* than the *native* C binary. FFI, see http://www.hpl.hp.com/techreports/1999/HPL-1999-78.html N.B. those that are /very/ interested in low predictable latencies use Java. The "high performance trading" mob are perfectly happy to spend $600m on laying their own trans-Atlantic fibreoptic cable, or buying up and using the old microwave links between Chicago and New York. Why? To shave a few *milliseconds* off the round trip time. They also like to cast the trading /algorithms/ and network stack in *hardware*, i.e. FPGAs. If Java was slow, it would be out the door in an instant; instead it is becoming the normal platform.
On 11/5/2016 6:39 AM, upsidedown@downunder.com wrote:
> On Sat, 5 Nov 2016 04:03:32 -0700 (PDT), kalvin.news@gmail.com wrote: > >> >> Ada has a very strong type checking system. The SPARK subset of Ada has >> even an ability to mathematically prove the program to behave as >> expected. >> >> Ada has automatic, built-in runtime checks for variable and table range >> checking as the compiler knows what values are allowed for the variable >> and the table index. >> >> You may argue that the strict type and the run-time checking costs too >> much. Well, the compilation time type checking doesn't cost anything at >> the runtime, so no penalty here. You can enable or disable the runtime >> checks as you will, so you can tune the performance as needed. >> >> Languages like C, C++, BASIC, Lisp or ASM just don't have built-in >> capabilities and expressiveness that provide the software engineer the >> power to express his/hers intentions and requirements which will be >> rigorously checked through out the programming project, nor the compiler >> enough information the perform rigorous and extensive compilation time and >> runtime checks. > > When designing user/kernel mode switching APIs or similar programs, you > absolutely first things is to check the validity of the call parameters. > PERIOD.
There are many things that "best practices" can bring to (a variety of different) implementation languages to improve quality/accuracy/reliability. I use invariants heavily on gazintas and cumzoutas -- in addition to any other place in the code when I'm sure of expectations. This serves both as a way of verifying that the actual implementation is "as expected" as well as leaving succinct notes for those who follow regarding the "contracts" that the code makes with its callers. Likewise, there are things in the operating environment (e.g., OS) that can protect against things that no amount of automated checking or type-checking can enforce.
> Such as if it is accessability from the calling (user) mode. > > These annual checks should give a clean well defined (version independent) > error codes. > > Letting the program access deeper than that and any run-time error code > could be anything and as such useless.
On Sat, 5 Nov 2016 12:40:21 +0000 (UTC), asdf <asdf@nospam.com> wrote:

>On Fri, 04 Nov 2016 13:12:57 +0000, Chris wrote: > >> Hi, >> >> I've been invited to a meeting to discuss am automotive like engineering >> project with a high level of safety critical requirements. >> >> They are using Simulink for some of the top level design work, but are >> programming the whole lot in C#, with some of the code already written. >> Not sure at this stage which rtos is being used, if at all. > >> ... > > >C# or Java (C# is essentially MS/Java) are not suitable for embedded >systems, and in a safety critical environment with very likely also >some realtime constraints, is the worst possible choice ever. >In those contexts even C++ (which runs circles around C#/Java >performance wise) would be a suboptimal choice.
With truly safety critical systems (such as nuclear reactors), you throw in as much hardware as required, cost is absolutely not an issue. In this thread, there has been an attitude of claiming that a specific programming language would "solve" any programming safety issues. In practice, the worst errors are made in the design phase, typically written in plain (English) text. Noting that for safety critical projects, there is a _huge_ amount of paperwork done before any single line of a computer programming language line is actually written, For truly safety critical systems, the programming language used, is not really an issue. Even assembly language is quite acceptable due to the huge paper work.
kalvin.news@gmail.com writes:
>> heating_element(ON) >> while (temperature < setpoint) {... > Worst yet, the software engineer cannot specify the valid numeric > range of the variables that it is expected to hold.... > Ada has a very strong type checking system.
I have trouble believing that a sane toaster would have software-controlled at all. Most toasters use an electromechanical thermostat, so when when it reaches the right temperature, the thermostat trips the spring that pops the toast up. But, in the old days, that stuff was written in asm, which was even more typeless than something like BASIC. These days even in cheap appliances I suspect C prevails.