Why does ARM mbed rely on C++? Is C++ the future? - Page 1
Forum section: electronics / general

author: 5upercircuits
author_rank: Contributor
timestamp: March 26, 2018, 06:53:21 am
content: Hey guys,I recently got into ARM mbed and was quite surprised that they are heavily relying on C++. Up until that point I thought that using C++ for low-level development was not a good idea. Typical arguments supporting this are:Note: not all of these arguments are my own, googled before I asked the question.- C++ is slow. (real-time, soft-realtime, etc.)- C++ produces bloated machine code.- Objects are large.- Virtual functions are slow.- Abstraction leads to inefficiency.On the other hand, we have ARM one of the industry leaders who decided to create a new low-level OS in C++. I suppose ARM has many experts who know what they are doing, when they decided to go for C++.Now to my question, did we reach a point where it is advisable for an electrical engineer / embedded software engineer to learn C++? Is C++ the future for embedded?

author: ataradov
author_rank: Super Contributor
timestamp: March 26, 2018, 07:08:42 am
content: ARM mbed is a poorly conceived framework, barely any better than Arduino. ARM sells IP, they don't really care about the software. The more generic it is, the less amount of money they need to spend on engineering resources that are not contributing to a bottom line. The more bloated it gets, the more money they get (hey you need a more powerful core to blink that LED).C++ can be better than C in embedded if you understand what you are doing. The problem is that it is very easy to slip if you don't constantly check, especially in a team with different level of expertise.All those things you have listed are bad. Except for machine code size. I worked on a reasonably big project in C and simply using C++, we got a reduction in binary size of a few percent. All with GCC. But C++ templates can be used to a great advantage, and especially in embedded, where you need to get creative at times to get the code size down.

author: rounin
author_rank: Regular Contributor
timestamp: March 26, 2018, 07:19:50 am
content: I've actually always used C++ for embedded (AVR8 / STM32 / PIC32 / Automotive PowerPC) (and cluster/hpc stuff). It can blow your foot off if you don't know what you are doing, but it can be much nicer than C with very little extra overhead.Most of the slow features are optional. My favorite is when old guard C programmers gripe about C++ constructors being slow... not only are they optional but every real C library I have seen has an init function to set the struct members, or a call to memset(0). Not really a difference then....Things like virtual functions are not much slower than a function call through a pointer offset / indirection, which is usually fast.Real-time and soft-real time are about provably bounding your execution run time ---- This is a much different statement than saying C++ is slow. C++ is fine, just make sure you are using deterministic features. Eg, no heap. Or only special heaps. Using C doesn't magically make you hard-real time safe.C++ can generate code that is large in bytes, especially in debug mode, mostly though bloat that templates make. No defense there.Abstraction can make code that is slightly slower then no abstraction (as in, ~few extra pointer indirection for a virtual function call), but having a set of peripheral drivers written against a base hardware abstraction class is really nice. It makes switching architectures or even to eg linux simple. IMO abstraction isn't really optional. It is just how you do it, and doing it will have a non-zero cost unless you use C macros to hard-compile in your HAL layer.For a contrived counter example, on a desktop pc with -O3 -march=native turned on, I've seen C++ templated code run 6x faster than C because the compiler had more information to optimize (alignment, etc) with so it used the perfect AVX instruction instead of the more general sse code the C version used.Template code can eat up all your L1 cache fast though. And all your flash. and take forever to compile. But is is very worth it to never have macros infest a program. It is a balance, depending on what you are doing it might actually help L1 cache usage, if you use the same templated function a lot.C++11/C++17 added a lot of nice features. Templates + constexpr can make a lot of magic happen at compile time, and are easy for the compiler to verify that they are functionally pure, so tend to inline and optimize well, which would generate nice machine code.

author: rounin
author_rank: Regular Contributor
timestamp: March 26, 2018, 07:23:50 am
content: But yeah, please don't dynamic_cast up a hierarchy in a tight loop, looking for the "right" type to pun to. Even on your 48 core 4GHz server. It'll make me cry. (This is when virtual functions get expensive... just call the virtual function! then it is cheap)

author: ikrase
author_rank: Regular Contributor
timestamp: March 26, 2018, 07:33:46 am
content: QuoteThat's too bad. I had found mbed to be useful when I used it in college.What framework would you suggest for somebody who finds Arduino to be toylike (but so many easy-to-use libraries!) but has found most other microcontroller programming enviroments to be impenetrable at every step of the process?

author: ataradov
author_rank: Super Contributor
timestamp: March 26, 2018, 07:36:18 am
content: Quote from: ikrase on March 26, 2018, 07:33:46 amExactly. That's as much use as you gonna get out of it. Good for prototyping/learning. You must be very stupid to base a long term project on it. Or you can start a project, just be prepared to replace modules one by one once you reach the limit of their usefulness. This will not lead to a great architecture in the end, so be prepared for some refactoring as well.Also, the number of MCUs supported by mbed is very limited. And chip vendors are not rushing to invest resources into something that will make their MCU look like all others and be easily interchangeable.Quote from: ikrase on March 26, 2018, 07:33:46 amNone. Read the datasheet and write the code. It is not that hard, and gets easier as you go.

author: rounin
author_rank: Regular Contributor
timestamp: March 26, 2018, 07:48:12 am
content: QuoteWhat ataradov said. There are so many assumptions baked into a given library implementation. For things like embedded drivers, it is pretty easy for those to not work once you start stressing the design a little, when you want to start using DMA or deferring interrupt handling, or using *all* the modules at the *same* time, with the buffers held on external memory, with a 3rd party RTOS...And most silicon vendor's drivers and example code are trash. Just useful enough to help you find the part of the manual to read. Maybe they are all written by 1st year interns. I've had awful luck with the PIC32 auto-gen drivers.

author: igendel
author_rank: Frequent Contributor
timestamp: March 26, 2018, 08:48:44 am
content: Embedded.fm's last episode is very interesting and relevant to the "C++ on Embedded" debate:https://www.embedded.fm/episodes/137repeat(my subjective impression is that this debate is mostly over, people realized C++ is fine if you know what you're doing)

author: tggzzz
author_rank: Super Contributor
timestamp: March 26, 2018, 09:00:01 am
content: Quote from: rounin on March 26, 2018, 07:19:50 amThat's true as far as it goes. Unfortunately hardware also screws hard realtime guarantees, especially if there are memory caches and/or interrupts in the system.Theonlyhard realtime embedded system I know is xC running on xCORE processors; the IDE willguaranteetimings by examining the binary code. That's important since any system that is based onmeasuringexecution times relies on the code happening to execute worst cases - and that's bloody difficult to guarantee if caches are in the system

author: 5upercircuits
author_rank: Contributor
timestamp: March 26, 2018, 09:09:17 am
content: QuoteI would have totally agreed with you a couple years ago. I was also writing all the drivers by myself, accessing hardware registers, reading the datasheet etc. There are two problems with this though:1. The approach to start with a baremetal system and then code everything yourself is fine if you've got 20 engineers and a big budget $$$. What do you do if you're a freelancer, startup? You can't start with preparing your libraries for 2 years before releasing something that also makes money...2. While I spend 3 weeks coding a driver, getting it to work and ironing out bugs, the mbed or Arduino kiddy just create a fully functional BLE app with LFS filesystem, Ethernet webserver, etc. in the same timeI agree mbed and Arduino may be trash, but they are also so much more efficient in the short run. Maybe we should not write our own libraries but improve the public libraries like Arduino and mbed?Note: I have to admit, I'm not a pro software guy, but a pro hardware design guy, so have mercy on me

author: andersm
author_rank: Super Contributor
timestamp: March 26, 2018, 09:47:48 am
content: Quote from: 5upercircuits on March 26, 2018, 06:53:21 amThe question you should ask is, compared to what? Most larger C codebases tend to reinvent some form of classes with virtual functions, but with the limitations of C the result is always worse. Also, when you've seen the exact same arguments about C++ being to large/slow for microcontrollers repeated for twenty years, while at the same time their performance has increased by orders of magnitude, you know the problem isn't the language.C++ has a steep learning curve, but you can also use it as a "super-C" with improved type safety, adopting features as you go along. Templatized constexpr functions are the macro language you always dreamed C had.

author: Fire Doger
author_rank: Regular Contributor
timestamp: March 26, 2018, 09:59:03 am
content: Quote from: 5upercircuits on March 26, 2018, 09:09:17 amThat would be perfect, but someone has to make them public first and they must be good to attract other experienced software guys. Did you plublished free the libs you wrote?

author: Jeroen3
author_rank: Super Contributor
timestamp: March 26, 2018, 10:01:55 am
content: Quote from: 5upercircuits on March 26, 2018, 06:53:21 amYes. Embedded projects become more and more complicated that managing everything in C becomes tedious and architectures become more susceptible to simple errors. If you can cherry pick features from C++ to make managing big projects easier, you should.Quote from: ataradov on March 26, 2018, 07:08:42 amThe purpose of Mbed was not to provide a high performance framework to use in your products. It's a rapid prototyping platform developed to make ARM accessible. It succeeded, and now supports other chip vendors than NXP, an OS and various other stuff. Looking at the objective it was launched for, I say it still succeeded.Quote from: ataradov on March 26, 2018, 07:08:42 amThe same applies to complicated pointer architectures in C because of features missing from C.Quote from: 5upercircuits on March 26, 2018, 06:53:21 am- You can simplify pointer syntax, because that what your referring to I think. C++ implicitly adds some dereferencing.- You can use less LOC to achieve similar results.- You have real objects!- You don't have to write code multiple times.- You save development time.Imagine only using objects and inheritance of C++. My life becomes so much easier.Sometimes you don't have to write perfect assembly, but good code that your coworkers can support.

author: JPortici
author_rank: Super Contributor
timestamp: March 26, 2018, 10:02:33 am
content: Quote from: 5upercircuits on March 26, 2018, 09:09:17 amat the moment i'm the only guy developing hw/sw here.1. In the same amount of time you can either understand how the peripherals in your system works and write the driver or use the provided driver and when it doesn't work learn how the peripheral work, try to understand what the hell the guy was thinking when he wrote the library and proceed to write a new one because it's all blocking code and/or can't do something and/or it can be used with SPI1 to SPI4 and i'm using SPI5.2. in the exorbitant amount of 2 days i wrote my first application using sd card with fat32 (also with can and ble) using a new processor family. i used the vendor-provided libraries for SD/Filesystem, in the SD library only i had to replace the peripheral library call with my much simpler functions (as i don't need to reconfigure on the fly, i can substitute entire functions with a single line of code and a comment which explains the bit settings.) and everything was just working.Then, in the afternoon of the first day i started writing the actual program functions (write string, get string). on Day 2 the first prototype was being tested.After that, i spent many days on testing and finishing the application, ironing out bugs but the point is that it didn't take much time to prepare a first draft, compared to arduino or mbed or whatever.

author: legacy
author_rank: Super Contributor
timestamp: March 26, 2018, 11:58:34 am
content: Quote from: 5upercircuits on March 26, 2018, 06:53:21 amthis happened several years ago in its childhood, then C++ (and C++11) has grown becoming grown-tool for grown men (at the beginning it was a toy, for students, giving good points for researchers to improve it)oh, of course, you need to know HOW to use it

author: legacy
author_rank: Super Contributor
timestamp: March 26, 2018, 11:59:31 am
content: is C++ the future?nope, the future is C++11 (or C++n*)

author: ikrase
author_rank: Regular Contributor
timestamp: March 26, 2018, 12:33:44 pm
content: While I definitely don't know much about the more technical side of C++ vs C, I found some of the extremely limited use of some C++ features like the mostly-static use of objects (like are used in Arduino code) to be kind of nice from a writing-the-code perspective.Serial1.write("stuff\n"); is much preferable to mucking around with structs.I agree that doing embedded stuff without any insight into your hardware and ability to work with drivers/libraries is a losing proposition. However, I have just found the barriers to entry to be overwhelmingly high compared to what should be -- and is -- possible.Being tossed a 100+ page datasheet and a header file full of register memnomics to just read values out of an ADC is not my idea of efficiency, and is clearly going to be duplicated effort between every single user.In my experience just getting toolchains installed and functioning can be amazingly painful. Meanwhile, in the time I was working with it, mbed seemed to be fairly functional as a "Arduino for adults" product.

author: tggzzz
author_rank: Super Contributor
timestamp: March 26, 2018, 01:04:08 pm
content: Quote from: legacy on March 26, 2018, 11:59:31 amQuiteAlthough I'd probably add ".... and always will be\n".

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 26, 2018, 03:10:53 pm
content: I wouldn't touch mbed even with safety gloves.That said, C++ has some benefits over C, but it's a monster that some highly-regarded people consider should never have existed (including Linus Torvalds and Niklaus Wirth, who are not exactly dumbasses).I rarely see any reason to use it in embedded settings, where we often see, when C++ is used, very trivial stuff encapsulated ad nauseam for no good reason whatsoever, except maybe looking hype. Especially on small targets like microcontrollers. And it can also make debugging a lot harder.Some may object (no pun intended) that GUIs, for instance, are much easier to design with object-oriented languages. There are some nice GUI libraries in C for embedded development though, that are fairly straightforward to use. YMMV.For bigger targets than small microcontrollers, higher-level languages than C may have some benefits. I would personally tend to favor ADA to C++ in this case. Granted ADA is kind of a huge monster too, but at least it gets object orientation and safety features right IMO.As to what is the "future", it's kind of hard to predict. Whereas C++ is actually declining in use overall, and Java is starting to as well (after a two-decade raise), C is still going strong for embedded development, so I don't think it's going away anytime soon. And why is mbed using C++, I'm not sure. Some tech decisions in big companies are not as rational as you may think.

author: ataradov
author_rank: Super Contributor
timestamp: March 26, 2018, 03:17:10 pm
content: Quote from: 5upercircuits on March 26, 2018, 09:09:17 amYou absolutely can and should. Sure on day 1 you will feel behind, but after a few weeks, you will be at the same point, but you will have a code base that you know. Plus the code does not go away, once you write it, it travels from project to project.Quote from: 5upercircuits on March 26, 2018, 09:09:17 amAn then they spend the rest of the product life cycle trying to find subtle bugs in a system they don't know how to debug.You can start with rmbed or Arduino if it feels more comfortable, jut do it with explicit goal to replace things as fast as possible, so don't get comfortable with the whole framework, just pick the "hard" parts here and there, do the easy parts yourself.

author: tggzzz
author_rank: Super Contributor
timestamp: March 26, 2018, 03:28:10 pm
content: Quote from: SiliconWizard on March 26, 2018, 03:10:53 pmI've seen people wasteyearson C++ GUIs, when there were alternatives (Smalltalk or Objective C then, add Java now). Those alternatives would have allowed them to skip past the problems inherent in C++ and allowed to concentrate on their problems, not the tools.There are swamps that need draining, and C++ is an aligator.QuoteYes, but there are some other alternatives.QuoteC and C++ will be around for a long time, just as COBOL is. But for new projects COBOL isn't the language of choice - and neither should C++ be.

author: rstofer
author_rank: Super Contributor
timestamp: March 26, 2018, 05:24:29 pm
content: Quote from: ataradov on March 26, 2018, 03:17:10 pmMy little mbed LPC1768 project was pretty simple: receive a stream over SPI, mangle the data and send it to a LaserJet printer over TCP/IP.I had to write the interrupt driven SPI Slave (no big deal) but I didn't have to write the TCP/IP stack.I had the project done in a couple of days instead of spending weeks and weeks re-inventing the network stack. In the end, I would have copied something, from somewhere, and hoped for the best.

author: ejeffrey
author_rank: Super Contributor
timestamp: March 26, 2018, 05:49:37 pm
content: Quote from: 5upercircuits on March 26, 2018, 06:53:21 amThis is not really true. There are some parts of the language that are slow, and in some cases there is a little extra overhead. But generally when you do the same thing as C, it will be within a few % of the C implementation. And it isn't really a big deal for "realtime" -- it's not like a garbage collected language where things may pause non-deterministically. Real time doesn't imply fast, it just requires predicable execution times, and C++ can certainly accomplish that.QuoteThis is less true than it used to be (compilers have gotten better). Also it really depends on what you are doing. C++ is generally more aggressive about inlining than C which can cause machine code bloat but also be good for performance. Uncautious use of templates can also cause code bloat, but proper use can provide better performance and lower memory footprint than the alternatives.QuoteThese are sort of at odds. C++ uses virtual method tables, where each instance has a single vtable pointer to a static array. Compared to the typical implementation of virtual dispatch in C (multiple method pointers per instance) this is more compact but potentially slightly slower. Of course you can do virtual method table in C, and that is what you would do if your object had a lot of virtual methods and you wanted to save space. In that case the performance would be similar or worse than C++. The same implementation in C++ will usually be faster as it provides more hints to the compiler to allow for optimization. For instance, changing the vtable pointer of an already initialized object is illegal in C++, but not in C. So if you are making a virtual method call in a loop, the C++ compiler is more likely to be able to be able to hoist the virtual method address load out of the loop.QuoteThat's always a risk, but C++ lets you choose your level of abstraction when it makes sense.Exceptions and RTTI are both features that are commonly suggested to be slow and bloated. Again, compilers have gotten better about this over time, so the early criticisms are maybe overblown. The point here is to not use them if you don't need them. On the other hand, if you really do need them, any kludge you come up with in C is probably going to be slower and more bloated than C++.

author: NorthGuy
author_rank: Super Contributor
timestamp: March 26, 2018, 06:44:52 pm
content: Quote from: 5upercircuits on March 26, 2018, 06:53:21 amYes. Inefficiency is the future. If you don't like inefficiencies produced by C++, get over it. By the time you make peace with C++, there will be something even less efficient - Linux, Python, whatever. The whole generation of designers (software and hardware alike) grew during the period of tremendous growth in hardware technologies. During this period, a strategy of getting quickly into a newer cutting-edge technology (as opposed to creating solid efficient designs for existing technology) was winning big time. Thus, if you want to be ahead, jump as far as you can. When you consider C++, don't think if it's efficient or not, rather be afraid that it might be already obsolete.Of course, you may hope that the efficiency era may return, and this might be indeed the case, but I wouldn't count on that being any time soon.

author: ejeffrey
author_rank: Super Contributor
timestamp: March 26, 2018, 07:03:57 pm
content: blah blah blah, get off my lawn you damn kids.

author: nctnico
author_rank: Super Contributor
timestamp: March 26, 2018, 07:05:12 pm
content: Quote from: NorthGuy on March 26, 2018, 06:44:52 pmThese discussions remind me of the C versus assembly discussions from a few years ago. What people tend to overlook is that projects become more complicated while the time to create the software has become less. Usually a lot of time is lost on debugging so if you can use a language which allows to prevent mistakes like passing variables by reference instead of a pointer, having OO built into the language instead of re-creating it, make software portable, etc, etc you can make a product cheaper. Hardware is cheap. Time is not.The next thing we'll probably see on microcontrollers are script based languages like Python or Lua. Not because they are space efficient (speed isn't much of an issue) but because they allow to produce less buggy code quicker because people can concentrate on the problem at hand and not deal with low level stuff all the time. For example: C/C++ require you to do things like range checking yourself and be aware of endianess, pointer arithmetics, etc.

author: andyturk
author_rank: Frequent Contributor
timestamp: March 26, 2018, 07:15:54 pm
content: Quote from: NorthGuy on March 26, 2018, 06:44:52 pmThe "efficiency era" (nice term!) is still here for some of us. If you're working on a wearable or other "IoT" device, power consumption is important and uA matter a great deal.C++ is just as good as C at low-level efficient code, and vastly better than plain C at exposing problems at build time (rather than run time). IMO, C++ is a *better* tool for embedded development than C for that reason.

author: JPortici
author_rank: Super Contributor
timestamp: March 26, 2018, 08:37:18 pm
content: and what happened between 2016 and 2018?

author: ataradov
author_rank: Super Contributor
timestamp: March 26, 2018, 08:38:45 pm
content: Quote from: JPortici on March 26, 2018, 08:37:18 pmPeople gave up on programming altogether and all went into marketing.

author: JPortici
author_rank: Super Contributor
timestamp: March 26, 2018, 08:41:26 pm
content: Quote from: 5upercircuits on March 26, 2018, 06:53:21 amenjoy.of course, the result depends on the compiler.i don't use C++ because the MCUs i use the most only have C compilers, otherwise i would certainly be happy to use some of its features.Quote from: ataradov on March 26, 2018, 08:38:45 pmmore work for usor maybe they siwtched to power-point as their main language?

author: NorthGuy
author_rank: Super Contributor
timestamp: March 26, 2018, 10:20:44 pm
content: Quote from: nctnico on March 26, 2018, 07:05:12 pmYou must admit hardware may be a little bit expensive:https://www.digikey.com/product-detail/en/xilinx-inc/XC7V2000T-G2FLG1925E/XC7V2000T-G2FLG1925E-ND/3981901(which is far from being the most expensive one).Quote from: nctnico on March 26, 2018, 07:05:12 pmI don't think it has anything to do with buggy software. Perhaps, this is because you can hire (admittedly) cheaper Python programmers who are not aware of endianness and pointer arithmetics. The less they aware of, the cheaper they cost. Nobody knows who your programmers are, but everyone sees the hardware you ship. Marketing teaches us that it's better to cut costs on something invisible, right?John Hammond is certainly fictional, but he explains the problem well: "no expense was spared", yet no money (or effort) spent on hiring a decent software programmer. As you remember, in the end, one bad programmer caused the whole enterprise to collapse.

author: NorthGuy
author_rank: Super Contributor
timestamp: March 26, 2018, 11:34:31 pm
content: Quote from: wilfred on March 26, 2018, 11:03:35 pmIt might be. Xilinx has an engine which lets you program FPGA in C. Not to mention MicroBlaze. Thus the growth in FPGA popularity must reflect on the popularity of C.It is all bogus anyway. I don't think there are many C programmers who would google "C programming".

author: nctnico
author_rank: Super Contributor
timestamp: March 26, 2018, 11:42:37 pm
content: Quote from: wilfred on March 26, 2018, 11:03:35 pmThere is a good reason: C and C++ are very standard and very portable.

author: C
author_rank: Super Contributor
timestamp: March 26, 2018, 11:51:26 pm
content: There is no compiler for ____Seen this excuse many times over the years.Foundation is a messy hard to parse language with poor rules.Simple can be powerful an create great programs. messy foundation just leads to more and more problems.If all the compiler writers time is spent fighting foundation problems, how much time is left to add smarts.Got to compile to machine code.Really, Memory speed has always been a bottle neck.With storage speed more so.Think of X bytes of machine code Vs X bytes of info to small program in cache.Best choice would be having a choice as one size does not fit all.If the language does not define things the compiler can not assist.Simple things line this line of code is adding a temperature to a pressure.But compiler does not know it's a temperature or pressure if a language does not define types to assist in error checking & programmer does not use them you get wasted time & bugs.If you study history, C started as an assembler replacement.A lot of the newer languages think they know better and fix a problem by forcing one way. The world is messy an wants options. Some like more then one, I like many displays.Many works great with groups.Current trend looks to be making computer work in human and not computer. To/From human takes time. To human & from human should be a used to interact with the human.Is it so hard to program show computer & show human and pick which by detestation?There are many examples where things were different.Operating systems have been written in high level languages where you would be hard pressed to do same in C or C++ in same time, with as few errors and machine speed.Simple fact is the more a programmer inputs into a program the more a compiler could help.If all you have learned and worked with is "C" then understanding the benefits of something different is hard.There are bad things in hardware also.Many things are binary ratios. A binary value to the right of decimal point. You do what's easy for you to do and work around problem instead of fixing hardware & languages.Think about current "C" programmers, should they protect their mountain or assist in building a new one?

author: 5upercircuits
author_rank: Contributor
timestamp: March 27, 2018, 09:02:24 am
content: Thank you everybody for all the educated and detailed answers. Awesome!I'll conclude all statements and compare the different opinions.Things that most people agreed upon -usefulness of C++ in embedded:1.1 C++ seems to have useful and superior features for embedded, the problem/difficulty is to learn/teach people how to use them.1.2 Using C++ in embedded without a proper knowledge basis can create bad embedded code.Conclusion of the two points listed above: The problem seems to be that when you compare C and C++, C++ has much more powerful tools that can become quite dangerous. However, in C most amateurs will just play with simple small code and never even reach the code base that professional C software engineers are handling on a daily basis. When amateurs start to use C++ then they play with powerful tools that they might not fully understand and accidentally create a basis for bad code.RegardingmbedandArduino, most people seem to agree:2.1 mbed and Arduino do have a place2.2 mbed and Arduino are good if you just want to get a fast prototype working or if you're just starting out/learning embedded development2.3 mbed and Arduino are not suitable if you are looking for customization, flexibility, scalabilityRegarding "Is C++ the future" we are divided:3.1 Some people believe that C++ is crap altogether and should and will slowly vanish. Not only in embedded but in general3.2 Some people believe that today's embedded projects have become so complicated and advanced that we will need a new programming language other than C (but maybe not C++)3.3 Some people seem to be completely ok with using C++ for embedded and are also not looking for other languages.From what I've read, I believe that a change to a different language is likely. We do have a demand for more advanced features.It kind of feels like with C you get a ten pages book and then you gotta write the remaining 90 yourself (usage patterns, encapsulation, etc.). With C++ you get a 500 page book but you gotta memorize that you are only allowed to use 100 randomly spread pages. In my opinion both choices are not ideal. One language lacks crucial features and the other is overloaded with features that are not feasible for embedded development. Maybe in the future we should/will have a language that is more optimized for embedded only.Conclusion, I would say that 3.2 will happen in the future. Maybe mbed and Arduino also serve the purpose to get more creative and try out different stuff. Maybe that is also the reason why ARM decided to develop mbed in C++ to encourage change?Note: I'm not a journalist or anything of the sort, just wanted to conclude all the answers a bit to create a basis for further discussion

author: tggzzz
author_rank: Super Contributor
timestamp: March 27, 2018, 10:51:58 am
content: 5upercircuits, that's a pleasantly succinct, accurate and nuanced summary of the various PoVI wish more postings were like that!I would modulate your statements by adding that:languages, like scientific theories, are only replaced as their practitioners retire => C/C++ will be around for a long time. There are other languages being used for embedded systems, but it remains to be seen how they will progress. I don't expect an answer before I diewith C++ you have to ensure that all developersand libraries and compilation optionsare using the same subset of C++ and usage patterns, or at least not subsets/patterns that fight with each othera couple of decades ago the C/C++ committee was facing a dilemma: should it become a systems/embedded or general purpose language. Either would have been acceptable and internally consistent. They tried to do both, and IMHO failed: Java is the general purpose language, and C++ is too arcanely complex and poorly specified to be a good embedded language

author: Karel
author_rank: Super Contributor
timestamp: March 27, 2018, 11:10:34 am
content: Does nobody wonder why in operating systems and drivers only "C" and assembly is used? There are many good reasons to stick with "C".

author: hans
author_rank: Super Contributor
timestamp: March 27, 2018, 11:55:45 am
content: What is dangerous about C++ is that it is very easy to create bad code. One template or class that uses run-time polymorhism called in an interrupt or other critical section could explode the binary size and execution time, thus killing performance. In embedded projects that often renders the final executable useless. It only requires 1 slip up of someone in the team (that is perhaps not very familiar with the platform and it's limitations) to do this.What I find ironic is that C++ also offer tools that should allow better scaling of software projects and teams, yet alot of them are more dangerous. You cannot expect everyone on a team is as qualified or sharp everyday, and you only need 1 screw up..So what do we do? Basically all we're doing in embedded is defining "safe subsets" of the language that we should use. Other subsets should not be used, but we cannot go as far as changing the compiler/language standard to remove library functions, keywords or constructs. We end up with a compromise; and for some the compromise is better in C++ or C.I think what is an upcoming in other fields (e.g. digital logic design) is to use EDSL (Embedded Domain Specific Language) to describe your system or software in a high level language, where there are no "illegal subsets". All operations you can perform are legal and have as little side effects as possible. This also simplifies the language as there is less to worry about.Drawbacks:- Arguably there is some overhead in creating only a safe set of operations, which is sometimes not acceptable in embedded code. This also relies partially on how good the compiler is for your problem; e.g. can it perform optimizations or transformations on the code to mitigate this.- EDSL are intended to be small and thus application specific; which means that new "languages" are invented for each case. That introduces the problem that one needs to learn moresimplelanguages. It could be possible, but it seems not something a lot of people (especially in industry) are interested in.- To some degree, creating an EDSL with the use of metaprogramming in C++ is possible. However as said, investing the time first to create "safe" libraries could take a considerable amount of effort, perhaps not worth it to small teams. But in C++ you do get benefits from e.g. the STL and other static library variants, which avoids that one is implementing a circular buffer for the 100th time..For me, I think C++ is making a better trade off than C, but different opinions always will exist. I think if there ever will be a language that's "perfect" for embedded code with enough baggage (e.g. RTOS', protocol stacks and libraries) available, there will always be legacy projects and people convinced they don't need better tools.

author: andersm
author_rank: Super Contributor
timestamp: March 27, 2018, 12:19:33 pm
content: Quote from: Karel on March 27, 2018, 11:10:34 amCounterexample:IOKit. Some of the designers have later said that the decision to use only a language subset was a mistake, and it wouldn't actually have been difficult to support the full feature set. AFAIK NeXT used Objective-C for drivers.

author: tggzzz
author_rank: Super Contributor
timestamp: March 27, 2018, 01:29:33 pm
content: Quote from: Karel on March 27, 2018, 11:10:34 amThe assertion is false, and there are manymanygood reasons to leave C/C++. You may not know them, but that is a characteristic feature of the myopic C/C++ community. Fortunately youngsters aren't that hidebound, and alternatives are appearing.One of the things that attracted me to Java was Gosling's original whitepaper way back in 1996. In it he discussed the various features that had been shown to work in other environments, why he rejected some and why the ones he included complemented each other.In contrast the C/C++ community resolutely insisted on going their own way, not understanding the consequences of all the misfeatures they were throwing together in the next versions of the language. (One example: the committee didn't believe that a valid C++ program could cause the compiler to emit the never-ending sequence of prime numbersduring compilation- until somebody rubbed their noses in it!)

author: C
author_rank: Super Contributor
timestamp: March 27, 2018, 02:21:50 pm
content: Quote from: Karel on March 27, 2018, 11:10:34 amNot hard to say that above is not a true statement.A lot of papers have been written.Think actions do speak loud.HP Pascal/Modcal was early 1980.Left out "USCD Pascal Operating System" that also existed back then.Oberon (operating system)https://en.wikipedia.org/wiki/Oberon_(operating_system)Granted this is research.ButHewlett-Packard used pascal & modified pascal internally for many years.HP 3000https://en.wikipedia.org/wiki/HP_3000QuoteHP Modal was a big thing inside some parts of HP.HP series 200 of which the HP9826 model is one of series, had all most all code written in Modcal.The System & the languages were written in Modcal with very little Assembly.Need to remember that Modcal foundation is Pascal or an extension of Pascal.It is a fact that HP Pascal for many systems was actually the internal Modcal compiler with the ability to set a compiler switch removed.Back then a lot of products were made for internal use in HP and only later sold to public.HP did not tell the world what had a foundation based Modcal. Even if you looked at the code, the change from pure pascal was very small.So how many others used other than "C" and thought of it as internal secret?When you have a good compiler that understands Pascal rules that do not exist in "C", It is not hard to change source syntax(what you type) to have a different input syntax.This above is all pascal like languages.Forth (programming language)https://en.wikipedia.org/wiki/Forth_(programming_language)This was often used for embedded systems.If what I read is correct, it is becoming the initial boot language for PC'sAn this does not count the many language X to "C" output methods.Gain the benefit of better source checking and still use "C" as final step when needed.What is really needed is not just a compiler, but an IDE that can do source syntax & language rule checking while editing the program.The higher level languages often have many ways to look at source. These views also need to be a part of the IDE.Sad to say but "C" has little capability to adapt to Newer/other things with out creating a bigger mess.And most if not all of "C"'s problem areas have been fixed more than once. Changes that can not be added to "C" with out breaking existing code.Little things can make a huge difference to the compiler writer.Poor syntax is a big one.When you remove the "FORWARD" key word from pascal this is a huge change.With "FORWARD" you can have the headers for procedures or functions before the actual source code for the procedure or function. You can have a two pass compiler. This is where the source code is read two times to get code output. This also lets compiler function with less memory as only global & current is needed.With out forward you get a global find problem where syntax matters.With good foundation you can add to language.You could have "Interrupt" function where hardware directly calls language function and no middle hidden code needed to get a "C" function to run.It's a simple fact that the more you type, The better job the compiler can do. The more the compiler can help finding errors.Type more or input more and save time later in process.

author: rstofer
author_rank: Super Contributor
timestamp: March 27, 2018, 02:27:30 pm
content: Quote from: tggzzz on March 27, 2018, 01:29:33 pmAnd go where? ADA ain't it! Neither is Java. I haven't seen any OS code written in anything other than C. Sure, I lead a sheltered life but it seems to me the language decision has been made. Whether aspects of C++ are worth importing is debatable, everything that needs doing can be done in C.I will concede that STL looks attractive. I don't like having to code up yet another circular queue so maybe I'll go back to one of my projects and try the library. I just worked through one of the sample programs and it works quite well. I need to get the linker map to find out just how much space the queue code used. The overall binary is about 70k and that includes stream output. There are many platforms that don't even have 70k of RAM!I have a question: WHERE did the library put my queue elements? On the heap, I imagine. I want them put in a specific area of memory. The LPC1768 has two blocks of memory devoted to buffers and I want my queue data in one of them (16k block). Therefore, the queue has to be defined such that it consumes no more than 16k and it has to be at a specific area in memory. I wonder how I make that work... It's pretty trivial with GCC. Oh, and I want the maximum queue size pre-allocated - really an array of chars (in one case) with a head and tail pointer.You know you are using the special buffers when the RAM map shows 45.1k used out of 32k available.I remain unconvinced!

author: nctnico
author_rank: Super Contributor
timestamp: March 27, 2018, 02:41:15 pm
content: Quote from: rstofer on March 27, 2018, 02:27:30 pmI'm sure that the Linux kernel will be smaller, faster and easier to maintain if it is rewritten using C++. It is all OO already anyway so why not use a language which supports it and can be better optimised by using compile time linking instead of runtime (as it is happening now).QuoteYou need to read more! If you write your own low level allocator you can use any kind of memory you want AND use the library.

author: tggzzz
author_rank: Super Contributor
timestamp: March 27, 2018, 02:44:27 pm
content: Quote from: rstofer on March 27, 2018, 02:27:30 pmJave certainly notIt is a general purpose language. C++ could have aimed into that space, but chose not to - and is now caught between a rock and a hard place.I suspect that one of your limitations is that you aren't considering RTOSs.ADAisgood for embedded, certainly at the RTOS level.Then there are the RTOSs that are implemented directly in hardware, e.g. the rather good XMOS xCORE processors running xC.In addition to the others noted by "C" above, I'll point to Smalltalk-80 and derivatives, where "80" means 1980QuoteJust so. Tell me about itOne of the things that pleasantly surprised me about Java was that within a year of release (by early 97) there were all sorts of complex libraries that plugged and played well with each other. That was something the C/C++ community had failed to achieve in a decade! That's telling.From what I can work out, good luck trying to debug embedded applications using the STL and exceptions!QuoteI'm unconvinced aboutwhatwill supplant C/C++ in embedded applications, butsomethingwill.

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 27, 2018, 03:00:05 pm
content: I would add one point to what we all said.I personally think that any non-standardized language should not even be considered for professional work.And whereas C, C++ and ADA all have robust standards that have been evolving on a regular basis for several decades now, this is far from being the case for a lot of other languages that have been mentioned here.If anyone can mention any language (other than the 3 above) that has a good standard and is adapted for embedded development, please do so!

author: rstofer
author_rank: Super Contributor
timestamp: March 27, 2018, 03:00:33 pm
content: Quote from: C on March 27, 2018, 02:21:50 pmI have a LOT of experience with UCSD Pascal. The language compiled to P code that was interpreted by machine specific code written in assembly language. Every bit of the low level code was written in assembly.This was great for portability. All that was required to port the system to a new platform was the low level interpreter. But it was written in assembly code!QuoteI love Pascal! I used it one time to build an 8051 control system. It was elegant. The code just looks nice on the printed page!QuoteA long time ago I was writing CP/M BIOS drivers for SCSI drives. The drive manufacturer used Forth for all of their final test processes. This was neat because the code was built from the bottom up (by definition) and new tests could simply be piled on top of the existing code. A completely different kind of test might take one or two lines of Forth.In one implementation (maybe all), a code block had to fit on the screen. The idea was to be able to see all of the function code without having to scroll through multiple pages. If you couldn't define a function in one page, you didn't understand the problem.Forth is perfect for people who love RPN. If you think in terms of stacks, Forth is the language for you!Forth is not quick and I don't see any application for it in an embedded device. My toaster will work fine with C code.The reason C exists is that it is as close to assembly language as necessary while still providing a high level syntax. It works at the hardware level and, AFAICT, it does it better than any other language. We're talking bit-twiddling, not solving world hunger. We had a language for world hunger (PL/I) but it was too far ahead of its time. It came out in '64 and is still in use although it certainly has its detractors. COBOL came out 1959, so it's only a few years older than PL/I and it is still in use. They even added objects! Fortran came out in '57 and is still in use. C is a 'johnny come lately' language as it came out in '72. I've been writing code since 1970 - starting with Fortran and continuing to use it to this day.

author: cstratton
author_rank: Regular Contributor
timestamp: March 27, 2018, 03:05:21 pm
content: Quote from: ikrase on March 26, 2018, 12:33:44 pmThis is one of the points where trying to use mbed in a serious project started to cause difficulties. Unfortunately, the initialization for those objects runs before main(), so if you need to do some pre-setup before they run, you end up having to modify the lower level startup code. In contrast, in a C project you typically only start configuring hardware peripherals in main()The way some of the configuration is done is also a bit inconsistent - going well out of the way to maintain runtime flexibilty in some places, making large and mostly undocumented assumptions in others.QuoteYou typically only do substantial "mucking around with structs" when configuring hardware peripherals. Writing to them is typically just a function call regardless of language.Last I checked mbed's serial input routines were not interrupt/buffered, even optionally, and you actually had to implement your own ISR and buffering.Using mbed did get the project sort of working quickly, which proved the idea. I think in the end though getting it to actually work right required more time behind the scenes figuring out and fixing what was actually going on, than writing against a lower level library would have. Granted, time early in a project when you are trying to demonstrate viability can be more valuable than time later.

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 27, 2018, 03:18:42 pm
content: Quote from: rstofer on March 27, 2018, 03:00:33 pmI've always found Pascal and its derivatives very elegant. I cited Niklaus Wirth in my first post, for whom I have a deep respect and think he's not received the consideration he deserves.As a relatively recent derivative, there is Oberon(-07). It has never really taken off but it's very elegant and concise at the same time. One company is selling compilers for ARM MCU targets:http://www.astrobe.com/Oberon.htmI would not consider it for several reasons, the first being that it's not standardized as I said before, and also that there are almost no tools except this one, but it's still interesting to play with.It features modules and a no-nonsense object orientation model, and is very easy to learn.

author: rstofer
author_rank: Super Contributor
timestamp: March 27, 2018, 03:26:49 pm
content: Quote from: tggzzz on March 27, 2018, 02:44:27 pmThere are many RTOSs but I'll bet the majority are written in C. I know that FreeRTOS is written in C and it seems to be pretty popular.QuoteWhy? What we have works fine, there's a ton of code in the wild and there's no motivation to change just for the sake of change. If anybody cared, there would be a lot more Ada being written.As to standards: What standards? They keep moving the goalpost, adding features that seem 'gee whiz' but aren't really necessary. C++98, C++03,C++11,C++14,C++17 and the yet to be released C++20. C++ is a moving target! Of course, C is no better. Once a language has an ISO committee, they have to earn their keep by changing stuff.We know Unix is written in C, Linux is written in C, how about Windows?

author: rstofer
author_rank: Super Contributor
timestamp: March 27, 2018, 03:50:55 pm
content: One of the problems with trying to sort out languages for 'embedded' work is defining the system. In my view, embedded implies a fairly small CPU with very limited memory. Like that LPC1768 with 32k of RAM unless you use the two 16k buffers. Clearly, the Arduino has limited resources.OTOH, we could discuss embedded in the context of a Raspberry PI where memory isn't even a consideration. I haven't seen hardware level projects for the platform (replacing Linux, for example) so I don't know what language would be used but I'll bet it isn't Python!For the resource limited devices, we need tight code (or a bigger CPU) and I don't see how other languages can compete with C in terms of code size. The video posted earlier about C++ and embedded just about changes my mind but the problem I have with it is that you need to be a ninja warrior with C++ to get those results. Of the dozens of ways the problem could be coded, ONE of them results in no overhead. It remains an exercise to figure out which one.And, when the code is done, the underlying principles aren't really obvious. Why was it coded the way it was? C, OTOH, is pretty obvious when you look at it (mostly).There's is something to be said for simplicity. It is a hallmark of C. A nice simple language.These language wars go on endlessly. The thing is, they really serve a purpose. It's true that I don't know C++ at any significant level and I certainly don't know it at the level of Jason Turner in that video. None of the books I have on C++ go anywhere near that level of coding. Maybe I need better books!Or an application... I don't learn anything until the day I need it!

author: technix
author_rank: Super Contributor
timestamp: March 27, 2018, 03:56:22 pm
content: Quote from: rstofer on March 27, 2018, 03:26:49 pmAFAIK the Windows kernel is also written in C. OTOH the driver layer of macOS is written in a limited subset of C++ (a good portion of C++ standard library is missing in macOS kernel so only that limited subset is usable) while the kernel proper is C.

author: nctnico
author_rank: Super Contributor
timestamp: March 27, 2018, 04:00:16 pm
content: Quote from: SiliconWizard on March 27, 2018, 03:00:05 pmThe problem with this statement is that 'embedded development' is and has been a moving target.

author: C
author_rank: Super Contributor
timestamp: March 27, 2018, 04:08:02 pm
content: Easy to put on blinders to make statements.Yes UCSD compiled to PCODE and itls interpreter was written in assembly.But as with all narrow statements, facts prove this was not only option.A CPU existed that ran PCODE directly with out an interpreter.A lot of Pascals could compile to many different output languages.An once you have a language running and can compile to assembly language for a CPU it is easy to compile the interpreter from the high level and even improve it in the process.Back then the common thing for a new CPU was assembly language.It's a chicken & egg problem. Need to get started on something new and can not use the language until started.Today a cross compiler is the method after getting past first run problem.Need to ask why some want more and more standards.Could the simple answer be that the foundation started full of holes in first place.Keep seeing complain where and expendable language is bad.And they are using "C" which is extended by adding functions.What makes this a good idea and also at same time of not allowing new data type extensions.It is just defining how things look in source, checking rules and code generation.Smoke and mirrors hiding what could be easy.Same can be true for new or expanded commands.You the programmer just have to have access to underling functions that the language needs.Think of simple exampleYou have an integer as a base type. Being able to define a new type and have access to it's memory allocator makes working with many memory areas easy.One size does not fit all.Step one should be defining to language what it has to work with.How hard is it to have the facts about A CPU & SYSTEM such that the language can check for errors?The code generator can check for errors?

author: tggzzz
author_rank: Super Contributor
timestamp: March 27, 2018, 05:11:52 pm
content: Quote from: SiliconWizard on March 27, 2018, 03:00:05 pmxC, from XMOS. (Don't bother to say it!).Effectively the RTOS is cast in hardware in the xCORE processors.It is essentially Tony Hoare's Communicating Sequential Processes (from the mid 70s) with a C-like syntax. It is designed for parallelism from the ground up, and enableshardrealtime guarantees on their 4000MIPS MCUs. The core concepts have been used in processors (e.g. TI DSP processors) and software continually since the mid 80s.Some features of CSP are re-appearing in modern languages, e.g. Rust and Go. We will see where they go...

author: tggzzz
author_rank: Super Contributor
timestamp: March 27, 2018, 05:22:29 pm
content: Quote from: rstofer on March 27, 2018, 03:26:49 pmC or assembler, with the interesting ones being implemented in hardware.QuoteBut itdoesn'twork well enough. As Hans Boehm pointed out,you cannot implement threads in C.http://www.hpl.hp.com/techreports/2004/HPL-2004-209.pdfQuoteNever underestimate inertiaThe people that care about correctness use ADA. I wonder how the self-driving cars will interact with the law and the insurance industry.I always remember the concept that, if you don't have to get correct results, you can develop your programs arbitrarily fast and they can execute arbitrarily fast.QuoteYou contradict yourself. If "what we have works fine" then there wouldn't need to be so many versions of C/C++ struggling to catch up with problems that were apparent in the 1960s! That may be becoming less true now, with the latest versions of C/C++

author: tggzzz
author_rank: Super Contributor
timestamp: March 27, 2018, 05:24:59 pm
content: Quote from: rstofer on March 27, 2018, 03:50:55 pmThere's a lot to be said for simplicity. Simplicity isn't the hallmark of C: count the pages in the standards and then add in the "this is how you ought to use (and not use) it" documents.

author: rstofer
author_rank: Super Contributor
timestamp: March 27, 2018, 05:41:21 pm
content: Quote from: C on March 27, 2018, 04:08:02 pmYes, and I had one: MT Pascal for CP/M. In fact, the beauty of the Pascal Language is the simplicity of the compiler. There's something about recursive descent that I find elegant. Wirth's syntax diagrams made writing the compiler very straightforward. It's all in the syntax!Yes, there was an LSI-11 chip repurposed to Pascal. I didn't have one but I would have liked to. A bunch of years ago, I decided to do an FPGA project to run P-code directly. I got the hard parts done but I stumbled when I had to call system routines to do things like floating point arithmetic. It was going to be a blistering fast Pascal system based entirely on the CDC 6400 version, P4. I was going to bump the word length from 60 to 64 bits since a 'set' was defined within a single word.QuoteI haven't run across that but why not? It's just code generation. There was also a version of Pascal for parallel computing. I have the Report on that but I have never given it much thought.But, without extending the language, there was no concept of registers and interrupts/vectors.Turbo Pascal is still fun to play with. I wrote the flood-fill algorithm for MicroMouse in TP and displayed the maze and mouse using Turbo Graphics. Works well!Today, FreePascal is readily available and runs under "Bash On Windows" of Win10. It obviously runs on Linux. A very nice package!

author: technix
author_rank: Super Contributor
timestamp: March 27, 2018, 05:56:48 pm
content: Quote from: tggzzz on March 27, 2018, 05:24:59 pmThrow away the pages that is only applicable to hosted environment, which embedded programming rarely is. Now the manual looked a lot thinner isn't it?On a technical aspect running the freestanding C language code requires only a stack. That is usually set up in a small assembler stub, or even in hardware (for example Cortex-M.) That is where the simplicity comes in to play.

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 27, 2018, 06:06:41 pm
content: Quote from: tggzzz on March 27, 2018, 05:11:52 pmxC is not bad indeed. But right now it's only targeted at XMOS products AFAIK and has no standard. It may even be seen as a proprietary language I guess, even though there seems to be an open-source initiative (XCore?) That said, the XMOS architecture is pretty interesting.For the record, C11 introduces thread support. I've read this version of the standard and contrary to what some have said here, I still find it quite reasonable (which is not the case for the C++ standard). Apart from some nice additions and precisions, there is nothing fundamentally divergent from the C89 version (and even less from the C99 one), so I wouldn't call this a 'moving target' by any means.

author: rstofer
author_rank: Super Contributor
timestamp: March 27, 2018, 07:04:36 pm
content: Quote from: nctnico on March 27, 2018, 02:41:15 pmSo, I went to Dr Dobb's and read an article on allocators written by one of the fellows on the standards board. It's a great article but, in the end, if I want to put my queue in a specific location, I have to write a ton of C++ and, by the way, it has to comply with the standard if it is to interoperate with the std:: library.In C it looks like this:Code:[font=courier]#include "mbed.h"#include "queue.h"// there is only 16k available in the memory segment// we use it all#define QSIZE (16384)#define QFULL (16300)#define QREFILL (16000)static char queue __attribute__((section("AHBSRAM0")));volatile int qhead, qtail = 0;volatile int busy_flag = 0;volatile int qcount = 0;DigitalOut ioBusy(p15);void queueInit(void) {ioBusy = 1;}// this is called from an interrupt routinevoid enqueue(unsigned char byte){int temp;if ( (temp = ((qtail+1) & (QSIZE-1))) == qhead); // we have a problem but don't update qtailelse {qtail = temp;queue = byte;qcount++;}if (qcount > QFULL) {busy_flag = 1;ioBusy = 0;}}unsigned char dequeue(void){unsigned char temp;if (qhead == qtail) // emptyreturn 0;else {qhead = (qhead + 1) & (QSIZE - 1);temp = queue;__disable_irq();if ((busy_flag == 1) && (qcount < QREFILL)) {busy_flag = 0;ioBusy = 1;}qcount--; // protect this code!__enable_irq();return temp;}}Pretty simple and intuitive. In std:: all of the queue operations are hidden. We have to take it on faith that the STL works will all data types although, in this case, the queue has only unsigned char.

author: C
author_rank: Super Contributor
timestamp: March 27, 2018, 07:08:37 pm
content: I have seen great pascal source.A large part that is was great was due to the great compiler,I do not consider FREEPASCAL great for many reasons.The source is a mess.The compiler does not prove the source code is correct,There are many, many more.A good foundation keeps paying back the higher or larger you get.The better a compiler gets, the better the compiler can get.If you keep fixing the low level problem areas in the compiler, then all programs using that compiler gain.Embedded and hardware only need a few extensions for pascal to be great.Same it true for system programming & threads. As a programmer you just need access to some low level details.Oberon (programming language) actually has fewer syntax rules then Pascal and yet is more powerful.So the only reason to use P4 is so you have a compiler that can build the better compiler.The code generator for the pascal I used back then generated very good 68000 code. An assembly language programmer would be hard pressed to do better it was that good.When HP used it internally and had the source, little reason existed not to make it better.Think of the foundation. Code generation is just picking the best of many ways the same code could be written.One place you want speed, another space or something else.In addition when you just had to have assembly for some reason very little assembly had to be written.The big problem for higher level languages is the very poor text editor. As a programmer you need to see many areas of code at same time. The compiler knows how to find the areas but the editor is often guessing if doing that much.Look at some simple facts.A compiler can create a better compiler.Source syntax is just one part of language.Want to get how many DOT Net compilers can have many languages as source? But this also highlights a problem. If the compiler is not written in the same language it might not gain as foundation improves.Part of the foundation is the base types.Part of the foundation is the many ways arrays can be created.Then you have simple concepts that need added syntax.Interrupt, Event, ERROR, Threads, Programs, Modules, Classes. Operators.It you think of foundation these are all just versions of a C function call with a more readable name. And due to that name can have additional rules checking the code.QuoteShows sad state of hacks and patches being done to C.This existed in the pascal I used in the 1980's.

author: nctnico
author_rank: Super Contributor
timestamp: March 27, 2018, 07:44:02 pm
content: IMHO the problem with Pascal is that it has been designed to teach structured programming and not for actual work. I've used Pascal in the past but it just doesn't fit very well with how software is developed. Pascal requires to fix the structure of a program at the beginning and not change it later on. Especially in an agile programming environment (where the structure of a program may change at any time) having a rigid structure just doesn't work.

author: C
author_rank: Super Contributor
timestamp: March 27, 2018, 07:48:50 pm
content: rstoferMight want to think about your code some.I would say a queue that disables all interrupts is not good code.But of course I use to work with CPU's that could safely handle an interrupt happing while in an interrupt.So stating the facts1. Interrupt in, main code out.2. main code in, interrupt out.3. Interrupt#x in, Interrupt#y out.Most can be fixed by only one side updating a value.Some can be fixed by knowing that CPU will read x bits as a chunk.For chunks larger then CPU safe chunk size. A reread the value flag can work wonders.With less messing with interrupts, you can have less bugs to find.

author: C
author_rank: Super Contributor
timestamp: March 27, 2018, 08:01:45 pm
content: nctnicoFixed sizes was true for the educational language compiler.The compiler I used allowed dynamic creation and deletion.Little changed in the source code.From memory two functionsByteSizeOf(___) and BitSizeOF(___)With a New that allowed creation size.Remember that a Pascal that is used to create Systems & Compilers has many needs not in the educational version.These can be added and still work with Pascal syntax rules.

author: rstofer
author_rank: Super Contributor
timestamp: March 27, 2018, 08:02:33 pm
content: In my play with std::queue I came up with a question: Is it interrupt safe? There's a bit of a problem messing around with the pointers while interrupts are enabled (assuming push() is coming from the ISR). Yes, I can write even more code and put a mutex around the pop() operation but it just brings back the same issue that was solved in C.And, yes, Pascal was originally a teaching language. The book "Algorithms + Data Structures = Programs" is one of my favorites. There's a lot of CS education in that little volume.I didn't realize that Niklaus Wirth ported Oberon to the ARM:https://www.inf.ethz.ch/personal/wirth/Oberon/Oberon.ARM.Compiler.pdfA commercial version is here:http://www.astrobe.com/default.htmI have been tempted to buy it just to play with the language.

author: technix
author_rank: Super Contributor
timestamp: March 27, 2018, 08:13:55 pm
content: Quote from: C on March 27, 2018, 07:48:50 pmI do agree that code smells a little. No two interrupt should have access to the same memory, and I doubt there exists a processor architecture that allows an interrupt to interrupt itself. When you split interrupts and overall code into well defined objects, the necessity of disabling IRQ's just goes away, since no two objects share memory anymore.BTW, when I speak of objects, I am referring to object-oriented programming, not a specific language. You can do OOP in plain C just fine.As of C, AFAIK most recent additions are hosted environment only or are standard library imports (C11 threads? That minus thread-local storage is really just an import from POSIX threads which is already standardized and very common in hosted environments. Thread-local storage is an import from C++.) The language itself, OTOH, is stable.

author: rstofer
author_rank: Super Contributor
timestamp: March 27, 2018, 08:54:10 pm
content: I got the quotes all messed up so I'll just write my stuff:I'm pretty sure I need a hardware interrupt on an SPI channel running at 11 MHz. I sure couldn't use polling because the CPU is bogged down doing the real work.I'm pretty sure there is only 1 interrupt and it is the SPI Slave Receive ISR. The shared object is the qcount. I need to guarantee atomic increment/decrement.There is always a problem with queue code if one end is in an ISR. You can't compare pointers if one is changing out from under the evaluation. Yes, multiple evaluations is one way to handle it but not the only way. If the results disagree, you wind up making the comparison 3 times. Fine, but you have to get it done pretty quick, those bits are flying down the wire and they aren't going to wait around. DMA would work well... In fact, if I ever revisit the project, I might consider that. As long as I can guarantee there won't be any wrap-around.It is possible to disable individual interrupts, and it's a good idea, but there is only one interrupt in the entire project, why bother playing with the NVIC? Set it and forget it!BTW: The IBM 1130 had no instructions to enable/disable interrupts.

author: andyturk
author_rank: Frequent Contributor
timestamp: March 27, 2018, 08:56:38 pm
content: Quote from: rstofer on March 27, 2018, 07:04:36 pmIt's more likely that the STL implementation is correct than any personal equivalent we might write. I'm not knocking your code specifically, but STL has gotten a great deal of exposure and most of the kinks have (hopefully) been worked out.Queues and FIFOs are an interesting thing in the embedded world. A friend of mine once observed, "Seems like every firmware engineer has their own FIFO implementation. Why is that?"You've got one. I've got one in C++ too (and it's not STL). Most large embedded codebases seem to have at least one FIFO implementation buried somewhere.I think the fact that there are so many different versions of the same idea comes from one of C's deficiencies: it's not easy to reason about a piece of code and know how it will perform generally. You've got to test it in your own environment to be sure that it works for what you need it to do.The queue implementation you posted has architecture-specific calls that are probably important, but might not be available on my system. There are hard coded sizes, linker directives and various things in there that might break if I try to modify it casually. E.g., what if I want my queue to be only 100 elements deep? What if I want more than one queue?I don't agree with tggzzz on much (in this thread), but he's very correct in pointing out that straight C code is anything but simple.

author: C
author_rank: Super Contributor
timestamp: March 27, 2018, 09:16:30 pm
content: technixQuoteYou can do this easy with most CPU'sThe old Z80 makes this easy if it's wanted.You can have a section of high speed interrupt code and slower hanging off the same interrupt.For Z80 you just do a Push of slower code start point.Fast returns to slower which returns to main.The 68000 allowed interrupts to interrupt interrupt code.With 68000 you have interrupt levels.rstoferThe best reference to pascal I have found is"The Pascal Handbook" by Jacques Tiberghien SYBEXHP had a special print run that added the "railroad tracks" for HP Pascal.Very little syntax changed to compile system code.Most of the time was just a RULE change.Often the compiler switch that enabled MODCAL (the system compiler flag) allowed access to compiler internal data.With System compiler flag enabled you had control of everything in a safe way. It really just made possible lower level details that is normally hidden in compiler output.As for Oberon, to truly make use of it you need compiler source.For example, In great compiler source, it is quick to change the pointer size to match the system. In fact a compiler that can compile for many processors changes this based on CPU type.Like all things, if you start out with a great foundation then change is easy. If you start out locked into the idea of"ONE"then change is hard.You might want to check out"GitHub - vishaps/voc: vishap oberon compiler"Oberon source in and C source out.There are also come compilers that use DOT NET as foundation.Think about something simple.PCODE is often seen as bad. A version or minor change is replace the interpreter with calls.You often hear that "RISC" CPU's are great. This greatness is inside the CPU, Outside the memory bus takes a hit which is already at limits. So you add cache to make the big problem smaller. Your code generation becomes more complicated as you need to stay in cache to gain benefit.Now think of a Risc CPU running PCODE. Code is already small and a cache miss could be pulling higher level code.The net result is that it could be faster running PCODE or called code then native machine code.A CSC CPU could be built with microcode & Risc and lower memory use.Most only state the best part of idea where total system is what counts.build your fifo from a circle buffer then you can have side separation if you are careful of when you access values.Note that C is well known for reordering code which can readily break code that needs a safe order.

author: rstofer
author_rank: Super Contributor
timestamp: March 27, 2018, 09:19:21 pm
content: Well, the reason there are so many FIFOs is the need for elasticity. Particularly on input, it may not be possible for the CPU to use polling. For output, it is simply more efficient to stuff the data in a queue and let the IO handler deal with it.The same project uses an array of array of chars to build up TCP packets. Each array of chars is filled to somewhere around 500 bytes (the actual length depends on the incoming text so there is room for a little extra) and the outer array is treated as a queue. Once the packet is filled, it is marked as available for the TCP/IP stack. This structure uses the other 16k buffer.There's a lot going on in the program: An 8 bit code comes in and the bit pattern is actually a CalComp 1627 step command. There is one byte per step, 100 steps per inch. I accumulate similar steps because I will eventually convert the total number of similar steps to an HPGL sentence that makes the entire vector in one command. I have to accumulate commands in the pen-up position but I don't have to write them until a pen-down command comes along. These HPGL sentences are stuffed into the output array and ultimately drive the LaserJet.It works well! And, yes, it is non-portable. Most embedded projects are! At some point you just have to get down to the hardware level.Why? Well, I have an FPGA implementation of the IBM1130 and the real machine had the CalComp plotter. It was a great tool for a young fellow wandering through EE school while working for a living at a company that allowed me unlimited access.

author: rstofer
author_rank: Super Contributor
timestamp: March 27, 2018, 09:28:33 pm
content: Quote from: andyturk on March 27, 2018, 08:56:38 pmYes, it will be very well developed. It's the assumptions and side effects I worry about. Under the conditions for which it is applicable, it will work perfectly. Under 'my' conditions, well, I wonder. So, test it! When I go out on the Interwebs and find out that containers aren't necessarily interrupt safe, I have to wonder how they are applied. Clearly they must work in that environment, it is just a matter of figuring out how to do it. Somebody knows how!

author: tggzzz
author_rank: Super Contributor
timestamp: March 27, 2018, 09:29:22 pm
content: Quote from: andyturk on March 27, 2018, 08:56:38 pmJust so. The number of times that wheel has been (poorly/incorrectly/incompatibly) reimplemented is ridiculous.C is touted as a language that is good for embedded systems work. Given that, I find it astounding that as late as 2004 (and probably after 2011) it was impossible to write queues for multithreaded environments. Even Java was better than that after a mere couple of years (courtesy of Doug Lea and a sound foundation) rather than C's working lifetime!But then the poor C/C++ committee was (in the early 90s) tied in knots foryearsabout whether "casting away constness" was mandatory/forbidden (there are good arguments for either!). And there are too many other such examples, e.g. whether the template language is Turing complete (it is, but the committee denied it until someone rubbed their faces in it). Hans Boehm, and he wasn't the first to point that outhttp://www.hpl.hp.com/techreports/2004/HPL-2004-209.pdfQuoteYou're forgiven

author: tggzzz
author_rank: Super Contributor
timestamp: March 27, 2018, 09:34:04 pm
content: Quote from: rstofer on March 27, 2018, 09:28:33 pmThere are oldengineeringmaxims: "you can't test quality into a product" and "testing can only demnostrate faults, it cannot demonstrate absence of faults".Why is that so hard for software weenies to comprehend?

author: tggzzz
author_rank: Super Contributor
timestamp: March 27, 2018, 09:35:47 pm
content: Quote from: rstofer on March 27, 2018, 09:19:21 pmWell, no. That's a valid argument as to why there are so manyinstancesof FIFOs, but not why there are so manyimplementationsof FIFOs.

author: NorthGuy
author_rank: Super Contributor
timestamp: March 27, 2018, 11:29:40 pm
content: Quote from: rstofer on March 27, 2018, 08:54:10 pmIt's very easy to implement a thread-safe FIFO (provided that one thread only writes and the other only reads). And it will work fine between two ISRs (despite statements here about the horrors of sharing variables between interrupts). The only thing you need is atomic read and atomic write with the variables which represent sizes and offsets (say 8-bit variables would be ok on 8-bit MCU, but larger sizes wouldn't work).You can do it in assembler. You can do it in C. You can do it in C++. You could do it in Pascal if you had a compiler. So, all these languages are good for me for writing FIFO code - they let me do things that I want to do.You couldn't do it with Java, Python, C# or anything of that sort. Instead of writing simple code, I would need to write something complicated, and even then I would get something which works worse than my simple code would. Thus, these languages are bad for me. Instead of helping me, they stand on my way. Why would I ever need them?

author: rstofer
author_rank: Super Contributor
timestamp: March 27, 2018, 11:46:21 pm
content: Quote from: NorthGuy on March 27, 2018, 11:29:40 pmI don't see how a language, any language, creates an atomic read-modify-write (or replace-add-one) if the underlying hardware doesn't have such a feature. Some hardware can increment a memory location in a single instruction, some can not. If the hardware can't provide the atomic increment/decrement, there is every probability that an interrupt will occur during the instruction sequence.I took a quick look at the ARM Instruction Set and I didn't find such an instruction. Maybe someone with more experience can point it out.

author: tggzzz
author_rank: Super Contributor
timestamp: March 27, 2018, 11:57:36 pm
content: Quote from: NorthGuy on March 27, 2018, 11:29:40 pmI'm afraid you've got that the wrong way round w.r.t. C/C++/Java and I presume C#. I make no comment about Python..Until very recently youcould not implement any threading code in C (including FIFOs),unlessyou relied on implemenation specificsoutsidethe C specification. See the Hans Boehm paper I've referred to twice in this thread for the subtle reasons why not. Until you have understood what he is saying, you are living in blissful ignorance. You should realise that Boehm knows more about C/C++ that most people: google him!OTOH, Java was specifically designed to allow threading and context switches: it has the necessary primitive instructions and memory model. Note: to a thread on a multiprocessor machine, there is no difference between a context switch due to an interrupt and a context switch due to another processor's activity. Think of an interrupt as being a context switch from a very very simple non-homogenous processor.C/C++ did not, by design, have any concept of a memory model. I'm told C/C++ has now caught up with Java in this respect - two decades later and five decades after the problems were understood (in the 60s).

author: C
author_rank: Super Contributor
timestamp: March 28, 2018, 12:03:59 am
content: To get atomic you need a good base.For example the Z80 can read & write 8-bit or 16-bit values with out interruption. DMA can only happen after the complete instruction.So one side modifies variable and other side just reads variable.The problem is that the Z80 has no read-modify-write as an atomic operation.Many documents state ways around lack of atomic operations. Care must be taken for all.Z80 could modify 8-bits and Check 16-bitsNeed to remember that Time passes between the read & write with out atomic operation.When you add a language that reorders code, you have problems that can be good at assembly level.For larger processors, look for something likeTest & SetThe CPU reads memory and changes it, in the process CPU flags are often set and/or registers are changed.Google "arm atomic operations"A PDF ARM Synchronization Primitives Development Article - ARM Infocenterhttp://infocenter.arm.com/help/topic/com.arm.doc.dht0008a/DHT0008A_arm_synchronization_primitives.pdf

author: NorthGuy
author_rank: Super Contributor
timestamp: March 28, 2018, 12:04:59 am
content: Quote from: rstofer on March 27, 2018, 11:46:21 pmYou do not need atomic read-modify-write for FIFO. You need two separate things:- atomic read- atomic writeAny hardware I worked with had this.The language doesn't create anything for you. It lets you using the things which are already in the hardware, or it doesn't. Any C compiler I worked with didn't have any problems with that.If you wanted atomic read-modify-write and your CPU had this, then the C compiler might give you access to it, or it might not (thus forcing you into assembler).

author: C
author_rank: Super Contributor
timestamp: March 28, 2018, 12:20:03 am
content: NorthGuyYou should be aware that I came across a problem talked about on a linux thread where Atomic.read - Atomic. write became a fail do to code reorder putting code in different order.Some places you have to have a Atomic.Test&Set or something like this with compiler code reordering things.

author: andyturk
author_rank: Frequent Contributor
timestamp: March 28, 2018, 12:22:07 am
content: Quote from: rstofer on March 27, 2018, 11:46:21 pmSeeLDREX and STREX.

author: westfw
author_rank: Super Contributor
timestamp: March 28, 2018, 03:00:40 am
content: QuoteBut not for embedded... A lot of "taught" C++ is about the STL and various other libraries, and they're swell until you try to use them on a chip with severely limited resources, no "exception" OS support (or no OS at all), requirements that prohibit dynamic allocation, and etc. Then you're back to implementing things yourself.(I suppose that arguably, "severely limited environments" will just disappear. (hah!))QuoteAFAIK, you can't "implement threading" in ANY language other than asm. You get the choice of putting in a bit of assembler, or using a threading implementation that has been put into the language for you. That's swell if it happens to meet your needs. In general, you get a choice between simple languages (C, asm) that make it easier for you to do things yourself, and complex languages that try to do everything for you, and end up with "bloated" implementations. (it's EXACTLY the same problem that vendor-provided "low-level libraries" have - by the time you get it to do everything possible, you have an implementation that no one wants to use.)Last I heard, "Java Embedded Micro Edition" ran on "as little as 1MB/128k", and Embedded C# implementations were similar. And aren't getting much traction, despite people wanting standard-ish GUI interfaces (for example) on their embedded projects (for which these ought to be ideal.) (OTOH, micro-Python is catching on, and interpreted tokenized BASIC still has a significant following. So "performance" doesn't necessarily seem to be the limiting factor...)Quotebecause the usual embedded system doesn't need or want a full general FIFO implementation that can be used on any data structure, allocates dynamic memory as needed, throws exceptions on errors, catches exceptions from lower levels, is fully thread-safe for any number scheduling algorithms, etc, etc. And the "simple" FIFO code that they do need is pretty easy to write. And read. (I'm sure the STL is wonderful in its way. But the few times I've looked at an STL implementation of some algorithm, to see how it did something, I was faced with a relatively unintelligible mass of generalization, standardized but ugly internal names, and pretty advance C++ features (I'm sure it all make sense to someone who works ON STL. But I don't think the beginner or average C++ programmer has much of a chance. Sigh.)

author: technix
author_rank: Super Contributor
timestamp: March 28, 2018, 04:14:44 am
content: Quote from: C on March 27, 2018, 09:16:30 pmWhat I mean is an interrupt interruptingitself, not two interrupts interrupting each other. What I mean is, for example, IRQ 5 fired inside IRQ 5 handler.

author: andyturk
author_rank: Frequent Contributor
timestamp: March 28, 2018, 06:43:00 am
content: Quote from: westfw on March 28, 2018, 03:00:40 amTrue dat.I really like STL for use on big iron. It's handy to be able to whip out a std::map for unit tests that run on unix. But the memory management of STL has always seemed opaque/scary (a reflection on me, not STL) so I've never used a std::map or std::vector in a bare metal build. I have compiled code written by others for a Cortex-M that did use std::map, and all I can say is, "it seemed to work". Given time, I probably would have ripped that stuff out.Interestingly, I've had good luck usingEigenon bare metal. On it's face, Eigen is at least as scary as STL, but turns out to straightforward (as I remember) in terms of memory management. And boy, is it fast. With optimization, those templated loop expansions turn into amazingly efficient code.YMMV, of course.

author: legacy
author_rank: Super Contributor
timestamp: March 28, 2018, 06:56:11 am
content: Quote from: NorthGuy on March 28, 2018, 12:04:59 amSGI used #pragma to have it on their big-irons with a lot of CPUs per rack.

author: legacy
author_rank: Super Contributor
timestamp: March 28, 2018, 06:58:31 am
content: Quote from: technix on March 28, 2018, 04:14:44 amwhat you really mean is you'd best avoid it.

author: technix
author_rank: Super Contributor
timestamp: March 28, 2018, 09:46:19 am
content: Quote from: legacy on March 28, 2018, 06:58:31 amIf in interrupt can nest with itself the ISR would have to implement locking or mutex, otherwise as long as each interrupt have its own RAM they should not conflict.

author: tggzzz
author_rank: Super Contributor
timestamp: March 28, 2018, 10:21:24 am
content: Quote from: westfw on March 28, 2018, 03:00:40 am(You are replying to my point, but that is difficult to see since you combined many posts into yours.)That entirely depends on what you think of a "language" and "asm".For example, the Java JVM has the necessary memory model and bytecode instructions that are created directly by the Java compiler. Yes, those aren't "primitive instructions" at the hardware level and there is some C/asm underneath, but...The 80x86 asm instructions aren't "primitives instructions" either: they are internally interpreted by the hardware into a sequence of microoperations.OTOH, have a look at the XMOS xCODE processors and xC. They have direct hardware support for multiprocessing - a put or get from a FIFO is a single blocking instruction. Plus they have direct hardware support enabling threads to sleep until one of several conditions is met (e.g. a timeout). Thus a "wait until input or timeout" is a single instruction, and when input/timeout occurs the core continues executing the code with 10ns latency. Eat your heart out ARMQuoteI've been completely underwhelmed by the Java Micro, Real Time and other variants, and wouldn't touch them.

author: legacy
author_rank: Super Contributor
timestamp: March 28, 2018, 01:58:00 pm
content: Quote from: technix on March 28, 2018, 09:46:19 amhave you ever done it? for a paid job? when you are in the rush? under deadlines?and have you ever considered HOW MUCH TIME it takes for debugging this?if so, it's more than clear that norm-people won't do that.

author: C
author_rank: Super Contributor
timestamp: March 28, 2018, 02:24:57 pm
content: legacySometimes helps to have a real world example to copy from when writing code.A Gatling gunBullets in, lead out one spot, shells out second spot. used resources back waiting for new bullet.The bullet in is the interrupt. Where does the interrupt stop?Is the lead the main program or is the shell the main program?Do you have two main programs or something else?Not a bad model to follow for a One in and Many out chunk of code.

author: tggzzz
author_rank: Super Contributor
timestamp: March 28, 2018, 02:46:17 pm
content: Quote from: legacy on March 28, 2018, 01:58:00 pmWhile I tend to agree, it isn't quite that clearcut - particularly in multicore systems.I'll start by presuming that one thread does not mutate the memory of other threads, except via well-defined and well-implemented RTOS features, e.g. put/get "messages" with FIFOs, or fork/join operations. If that isn't the case, then I'm not interested in debugging the messAt the system design level the principal operations are the threads and the messages between threads. On multicore systems you will, of course, have multiple threads on different cores sending messages at unpredictable times, sometimes simultaneously. That leads to the possibilities of deadlock and livelock, unless there are clear system design principles that avoid it in a specific application.Now add interrupts to the equation. There is vanishingly little difference between a message from another core and a message from a peripheral (often called an interrupt). Think of the peripheral as being another core, albeit a very simple and asymmetric core.Hence there is a good argument that if your system design is sufficient for multiple thread in a multicore system, then multiple simultaneous interrupts are not a major extra problem.A good commercial example of that philosophy is in the xCORE processors (up to 32 cores, 4000MIPs), which manage hard realtime operation - unlike ARMs etc.

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 28, 2018, 02:53:56 pm
content: Quote from: tggzzz on March 28, 2018, 02:46:17 pmAgree with that.

author: C
author_rank: Super Contributor
timestamp: March 28, 2018, 03:04:16 pm
content: One of the problems with low level is the lack of understanding o a higher level.For example, if the foundation of a language does not implement type checking properly, then any type checking errors will be hit or miss. That miss is a killer and puts the burden on the programmer for type checking.With a language missing something needed, you might be able to get what is needed with careful use of tool a different way.With language not understanding the need for separation, then forced separation can make sense if you can get access to proper hooks.One way to force separation is to use separate programs with a low level separation of what the language uses.

author: tggzzz
author_rank: Super Contributor
timestamp: March 28, 2018, 04:00:24 pm
content: Quote from: C on March 28, 2018, 03:04:16 pmUnfortunately many of the younger and more naive C/C++ advocates believe the stories that C/C++ is necessary and sufficient for low level code. In reality it is neither necessary nor sufficient.While not being necessary isn't a problem because it implies there are alternatives, not being sufficientisa problem. As you allude to, there is the concept of building castles on sand.

author: legacy
author_rank: Super Contributor
timestamp: March 28, 2018, 04:42:28 pm
content: Quote from: tggzzz on March 28, 2018, 02:46:17 pmummm, Multi-cores are a different matter, but about microcontrollers and mono-core stuff, even the documentation made by Microchip/Atmel warns the user from using nesting in their XMEGA line.I have to say I agree with them! Well written, to warn people about the risk of wasting time in extra complexity during the debug phase.

author: technix
author_rank: Super Contributor
timestamp: March 28, 2018, 04:50:33 pm
content: Quote from: legacy on March 28, 2018, 01:58:00 pmYes. In two of my jobs. Do keep in mind that this is China and all the boss wants is to rush a product to the market as soon as possible before anyone else can. It is the rule to rush absolutely everything or get fired even without a pushing deadline so his sales team can take their sweet time to prepare their sales pitches. I am forbidden from considering however much time it would take unless the problems actually arise (and rush through those too,) and once I do make some preemptive consideration I got fired for this.

author: tggzzz
author_rank: Super Contributor
timestamp: March 28, 2018, 04:52:33 pm
content: Quote from: legacy on March 28, 2018, 04:42:28 pmAtmel may have their own reasons for cautioning against it; I don't know. It wouldn't be the first time that hardware problems are avoided by "doing or not doing X" in the softwareIn any case, it still isn't perfectly clearcut in single core systems.It is well to realise that multicore systems are becoming ever more prevalent (e.g. BeagleBone, xCORE, many ARMs, and outliers), and are the way of the future. Best to get ready for the future now.

author: nctnico
author_rank: Super Contributor
timestamp: March 28, 2018, 05:00:08 pm
content: Quote from: rstofer on March 27, 2018, 11:46:21 pmThe only requirement is to have an atomic write for the size of the FIFO index counters (which every CPU has). When an index counter is incremented doesn't matter. Only the update of the variable in the memory matters.

author: nctnico
author_rank: Super Contributor
timestamp: March 28, 2018, 05:05:11 pm
content: Quote from: legacy on March 28, 2018, 06:58:31 amNot necessarily. Think about multiple devices sharing one interrupt and software demultiplexes the interrupt towards the various interrupt handlers. IIRC this happens on a PC with many PCI devices.

author: andyturk
author_rank: Frequent Contributor
timestamp: March 28, 2018, 05:13:07 pm
content: Quote from: tggzzz on March 28, 2018, 04:00:24 pmOne can boot a Cortex-M processor and an application without a single line of hand-coded assembly (or asm statements). Standard C/C++ code is all that's required.Why would C/C++ not be sufficient for low-level code on a Cortex-M?

author: tggzzz
author_rank: Super Contributor
timestamp: March 28, 2018, 05:37:29 pm
content: Quote from: andyturk on March 28, 2018, 05:13:07 pmI refer you to the context of the conversation, specifically that you cannot write threading code in C/C++ without relying on behaviour that is outside the language. See Hans Boehm's paper referred to earlier (and google Han Boehm) to see that hedoesknow what he is talking about. that may have changed in the latest variant of the languages, >20 years after Java Got It Right and 50 years since the problems and solutions were understood.

author: technix
author_rank: Super Contributor
timestamp: March 28, 2018, 05:40:13 pm
content: Quote from: andyturk on March 28, 2018, 05:13:07 pmI'd second that. C/C++ with that all-so-common inline assembler extension (different syntax across compilers, but most compilers have them nonetheless) is likely adequate on 99% the times.

author: tggzzz
author_rank: Super Contributor
timestamp: March 28, 2018, 05:41:33 pm
content: Quote from: nctnico on March 28, 2018, 05:05:11 pmOr any microprocessor where the interrupt is signalled by alevelon a line, not an edge. The 6800 (and most others of that vintage) worked well in that respect, with many peripherals wire-or'ed on the IRQ line.

author: tggzzz
author_rank: Super Contributor
timestamp: March 28, 2018, 05:42:52 pm
content: Quote from: technix on March 28, 2018, 05:40:13 pmBut that merelydemonstratesthe inadequacy of C/C++!Yes it works, but blows the "C/C++ is sufficient" postulates out of the water!

author: rounin
author_rank: Regular Contributor
timestamp: March 28, 2018, 05:48:05 pm
content: Quote from: tggzzz on March 28, 2018, 05:37:29 pmC++11 does standardize a memory and threading model, and atomic operations. It was way overdue. I've used the <atomic> features and verified that it uses the reserved form of the load and store instructions (on powerpc mcu) needed for multithread/multicore. C++17 is fixing some more things too.Actually /using/ std::thread on a microcontroller though, yeah no. No libstdc++ supports your favorite embedded RTOS. But <atomic> works, so you can fence data correctly, std::atomic_thread_fence can force a memory sequence point...

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 28, 2018, 06:37:52 pm
content: Quote from: tggzzz on March 28, 2018, 05:42:52 pmSomewhat yes.But as can be seen with the example of XMOS/xC, I don't think you can properly put general thread-aware constructs inside any language without designing the underlying architecture first.All attempts of doing that and targetting many different and existing architectures is very difficult and usually bound to fail. That's why C has favored including pthreads-like stuff in the standard than adding specific native constructs, and of course this part is not mandatory and is not guaranteed to be available for any given specific target.C++ (which again is a monster) latest attempts are interesting in this area, but again are not guaranteed to be completely available on any given target, especially such as microcontrollers.A proper multi-threading model, IMO, would have to be designed upfront and in close conjunction between the languages and the hardware architectures. That's pretty much what XMOS did.

author: tggzzz
author_rank: Super Contributor
timestamp: March 28, 2018, 07:08:20 pm
content: Quote from: SiliconWizard on March 28, 2018, 06:37:52 pmI don't know enough to go quite that far, but I'm sure that the future multicore/processor systems will stress traditional tools beyond breaking point. That implies that there will have to be a significant rethink of the tools and how to create systems. That, in turn, isn't an unsurmountable problem since we've done it in the past, e.g. distributed systems and the internet/web.There will, of course, be valiant but futile attempts to recast old concepts for the brave new world, but they will fail. For example, in the web arena SOAP was the "triumphant reinvention" of RPC over HTTP; fortunately that was manifest nonsense, and it only took a decade for the REST philosophy to become dominant.QuoteUntil recently C explicitly absolved itself of anything to do with multiprocessors/multithreading, declaring they were the libraries' responsibility. Pthreads (and others) then took up the challenge, but had to rely on language features that were explicitly left, um, vague and incomplete.=> Castles built on sand.QuoteSomewhere in the mid naughties I remember the triumphant announcement of the firstcompleteC++ implementation of the latest standard. That was5/6 years afterthe standard was published. That was a Big Red Flag.QuoteNot sure. A large part is going to depend on the level of abstraction chosen. But you may well be right.

author: andyturk
author_rank: Frequent Contributor
timestamp: March 28, 2018, 07:37:04 pm
content: Quote from: tggzzz on March 28, 2018, 05:42:52 pmThat's just being argumentative.

author: legacy
author_rank: Super Contributor
timestamp: March 28, 2018, 07:49:44 pm
content: Quote from: nctnico on March 28, 2018, 05:05:11 pmThe Atlas board is a good old-school example. When an interrupt arises, a signal on the Cop0 goes down to "0" (it's negative logic), and the Cop0 decodes on which line (16lines-to-4binary), then it issues a machine exception to the RISC-ish CPU.The pipeline is stalled, the BU is flushed, the PC is saved into EPC, and reloaded with the proper exception address, whose first instruction is usually a "disable interrupts". At this point the CPU checks on which line the exception cames from, and which subtype of exception is. There could be many pending events here, waiting to be served. You need to clear the bit to say "event got processed". Once understood and decided which one needs to be processed (priorities here are flexible), there is a simple "function call" to the proper sub exception routine that handles the whole task, and once completed, it returns back to the handler, that clears the proper event-bit and resumes the CPU from the exception mode. Exceptions are then re-enabled by the last instruction, and PC is assigned with EPC, thus the CPU is again ready to go on as nothing had ever happened (from the user-mode point of view).It's a simple, efficient, and deterministic way to process things. And note that nothing is interruptible in exception-time (it might be, the hardware support it, but it's discouraged since it also confuses the debugger). One event triggers the machine-exception, with a priority, of course, and nothing can interrupt it. It's the best way to debug complex stuff happening in kernel space.On my MIPS manual for the Atlas board, there is the same warning that is also written on the Microchip/Atmel manual about their XMega.I think, there must be a reason for that.

author: tggzzz
author_rank: Super Contributor
timestamp: March 28, 2018, 08:06:46 pm
content: Quote from: andyturk on March 28, 2018, 07:37:04 pmAh, by "argumentative" you presumably mean "I don't like it, but itisaccurate".I'll listen to reasoned counterpoints.

author: legacy
author_rank: Super Contributor
timestamp: March 28, 2018, 08:21:15 pm
content: Quote from: tggzzz on March 28, 2018, 05:41:33 pmIn that board, you have 16 IRQ-lines for peripherals. Sixteen devices can be allocated. Usually, it's the best choice for low latency peripherals: each peripheral iswire-or'ed onits IRQ line.Of course, you can also have many peripheralswire-or'edon the IRQ line, but in this case, the handler needs to query "hey? oh! who has issued the exception?", usually issuing a bus request to know who had issued it, to which the requesting device must answer within a time window, otherwise, the exception is assumed by the cop0 as a bus error (with the high severity of being anhardfail)When the interrupting device answers the request of Cop0, it usually sends its ID, so the exception handler knows which is *THE driver* to call (it gets it from a table, that maps IRQ-line-to-address) line, and it also knows which is the sub-device.

author: technix
author_rank: Super Contributor
timestamp: March 28, 2018, 08:35:49 pm
content: Quote from: legacy on March 28, 2018, 07:49:44 pmThose warnings is exactly why most modern interrupt controllers, be it APIC on x86 or NVIC on Cortex-M, does not allow an interrupt handler being interrupted by another interrupt of the same priority level. This, plus the design decision that no two interrupt handlers shall operate on the same memory and/or peripherals except when making use of a well defined IPC mechanism, makes all the above arguments of memory conflicting goes away in most cases. There is no way an interrupt handler can race against itself (due to the hardware guarantee) and no two interrupt handlers can interfere each other (guaranteed by design) most of the code does not need any atomics. As of the IPC mechanism, that is where atomics and thread-local storage might be needed, and being a small library after all, I am okay writing that portion (along with the swapper) using inline assembler.

author: nctnico
author_rank: Super Contributor
timestamp: March 28, 2018, 09:34:46 pm
content: Quote from: tggzzz on March 28, 2018, 08:06:46 pmTo the point where it doesn't matter. What would that language you are referering to be written in? It is likely C or C++ at some level.

author: Bassman59
author_rank: Super Contributor
timestamp: March 28, 2018, 09:51:55 pm
content: Quote from: tggzzz on March 28, 2018, 07:08:20 pmLook how long it took the synthesis vendors to update their tools to support VHDL-93! And then VHDL-2002! And then look how long it takes them to update their documentation ... too much of the examples they use still have the VHDL-87 idioms.

author: tggzzz
author_rank: Super Contributor
timestamp: March 28, 2018, 09:59:33 pm
content: Quote from: nctnico on March 28, 2018, 09:34:46 pmIt matters in that youngsters shouldn't be taken in by glib alt-facts. (I specifically exclude AndyTurk from that!)QuoteIrrelevant. What matters is the language you are using to develop your product. The tools should support abstractions that enable you to express intent clearly, succinctly, unambiguously, and correctly.All the other tools that have been used to allow you to get to the point where youcandevelop your product are completely irrelevant. If you don't accept that, then where do you draw the line? VHDL/Verilog, Spice/ADS, diffusion furnaces, smelters, baskets on the head of Congolese miners etc?

author: NorthGuy
author_rank: Super Contributor
timestamp: March 28, 2018, 11:36:06 pm
content: Quote from: tggzzz on March 28, 2018, 09:59:33 pmThe language is a tool. You don't express the intent. You simply use the tool to accomplish your task.If you want to sink a nail, you do not express your intent to the hummer, you just swing it. And it work the same regardless of the intent - whether you're building a cathedral or a coffin. The intent doesn't matter.

author: tggzzz
author_rank: Super Contributor
timestamp: March 28, 2018, 11:39:13 pm
content: Quote from: NorthGuy on March 28, 2018, 11:36:06 pmOh dear. That's not right. That's not even wrong. (with apologies to Wolfgang Pauli)How to enlighten you?... I suggest starting with "Zen and the Art of Motorcycle Maintenance" by Robert Persig.

author: andyturk
author_rank: Frequent Contributor
timestamp: March 29, 2018, 01:26:27 am
content: Quote from: NorthGuy on March 28, 2018, 11:36:06 pmWell put!And if the hammer sinks nails sufficiently well, it doesn't really matter whether the creator of said tool actually set out to build a screwdriver and missed.Corollary: A good tool has utility beyond its original design goals.

author: andyturk
author_rank: Frequent Contributor
timestamp: March 29, 2018, 01:35:49 am
content: ^^^ Multiple inheritance.

author: westfw
author_rank: Super Contributor
timestamp: March 29, 2018, 07:26:09 am
content: QuoteYeah, but you get into trouble pretty quickly if your compiler hasn't implemented the ARM-recommended intrinsic functions for doing things like turning on interrupts. (although, it's a really good thing that ARM standardized these!)The sad thing is that "embedded programming" (at least in the "small embedded sense) doesn't seem to be a big enough market for language developers to get excited about. We're stuck with cast-offs and kludged subsets of the 'real' languages. Java, C++, C#, and etc keep getting bigger and bigger, ignoring or contradicting the "needs" of the embedded market (for example, C (or perhaps just avr-gcc) added "named address spaces" to better deal with harvard architectures, but the C++ folks won't include it...) The closest we get it an occasional "systems programming language", but it's not quite the same. C (IMO) succeeded because the base definition is very "pure", easy to port to new architectures, and didn't actually require a full implementation of the various "standard libraries" to be useful. C++ is mostly following suit, with a fair number of useful new features.What SHOULD probably happen is that someone should work on defining subsets of languages and embedded libraries. Arduino and mbed are efforts in that direction, but ... they're being defined by hobbyists, artists, and hardware vendors. The computer scientists and language experts aren't very interested, and the occasional industry group seem mired in the past ("you should use Ada!"; "We'll disallow everything that has ever caused a bug." (I mean, really - disallowing dynamic memory allocation pretty much turns off the last 30 years of algorithm development.)) Or perhaps we embedded programmers are mired in OUR past - insisting on performance at the instruction-count level long after we should have accepted that faster CPUs make things like (horribly redundant) run-time type checking reasonable after all.)(and then, there's the customer, willing to accept less reliability in return for better performance and a lower price... Sigh.)

author: andersm
author_rank: Super Contributor
timestamp: March 29, 2018, 08:23:43 am
content: Quote from: rounin on March 28, 2018, 05:48:05 pmI believe RTEMS supports C++11 threads, but they have ported the GNU toolchain to target their OS. I haven't looked at the libstdc++ implementation to see if it provides some generic hooks so you can add support with less effort.

author: andersm
author_rank: Super Contributor
timestamp: March 29, 2018, 08:37:01 am
content: Quote from: westfw on March 29, 2018, 07:26:09 amThe control registers are set up so that nothing is masked by default, and everything is ready to go. The enable bits and priority registers for individual external interrupts are memory-mapped.

author: legacy
author_rank: Super Contributor
timestamp: March 29, 2018, 02:53:58 pm
content: Quote from: westfw on March 29, 2018, 07:26:09 amyup, sir. And it has saved our lives several and several times in avionics

author: andyturk
author_rank: Frequent Contributor
timestamp: March 29, 2018, 03:14:22 pm
content: Quote from: legacy on March 29, 2018, 02:53:58 pmFor other applications, a watchdog timer is sufficient. And necessary!

author: legacy
author_rank: Super Contributor
timestamp: March 29, 2018, 03:23:31 pm
content: About Ada ...bad news: gnat-gcc got removed from a few linux-distros in favor of gnat-gpl whose quality is inferior, and this breaks dependencies especially on PowerPC/BE (e.g. PowerMachintosh G4 and G5)IBM POWER9/LE (promoted and used by DARPA, in USA) is also affected, and, even if they have their copy of Gnat-Commercial-version, every Gnat-gpl version I have tried has miserably failed(and Java got removed, too .... except IBM-JDK that comes with a terrible license)Code:2018-03-24--15-00-48---2018-03-24--15-07-58 - [ dev-lang/gnat-gpl ] - failure - root@dev2.29.1/7.3.02018-03-24--15-13-52---2018-03-24--15-14-06 - [ dev-lang/gnat-gpl ] - failure - root@dev2.29.1/7.3.02018-03-24--15-18-03---2018-03-24--15-20-44 - [ dev-lang/gnat-gpl ] - failure - root@dev2.29.1/6.4.02018-03-24--15-28-44---2018-03-24--15-30-31 - [ dev-lang/gnat-gpl ] - failure - root@dev2.29.1/6.4.02018-03-24--15-33-03---2018-03-24--15-34-48 - [ dev-lang/gnat-gpl ] - failure - root@dev2.29.1/5.4.42018-03-24--18-43-31---2018-03-24--19-17-03 - [ dev-lang/gnat-gpl ] - failure - root@dev2.29.1/5.4.42018-03-24--20-43-26---2018-03-24--23-59-49 - [ dev-lang/gnat-gpl ] - failure - root@dev2.29.1/4.4.72018-03-25--00-22-40---2018-03-25--00-24-48 - [ overlay/gnat-gcc ] - failure -root@dev2.29.1/4.4.72018-03-25--01-40-42---2018-03-25--02-14-15 - [ overlay/gnat-gcc ] - failure - root@dev2.29.1/4.4.72018-03-25--13-29-49---2018-03-25--16-47-39 - [ overlay/gnat-gcc ] - failure - root@dev2.29.1/4.4.7NOTE: GCC back-end/PPC32.BE generated by gnat-ppc/x86, compiled with commercial GNAT Version2018-03-27--15-38-02---2018-03-27--17-52-54 - [ overlay/gnat-gcc ] - success - root@dev2.29.1/4.4.7Anyway, I have bought the commercial version of gnat (x86/32bit), and I am moving it to my own Softcore intended to directly support high-level language features in hardware such as tagged, boundary-protected memory.That is very elegant, powerful, and makes me feel comfortable with the debugger since it simplifies a lot of stuff.I will also ask some companies with skills at stickers making, to prepare a nice one "Ready for Ada" to then stick it (with "pride") on the plastic box that will contain the fpga whose bitstream maybe, soon or later, will be able to be uploaded with the output of an Ada-cross-compiler from my PowerMacOh, does it mean (at least for me) that the future is Ada?

author: Gibson486
author_rank: Frequent Contributor
timestamp: March 29, 2018, 09:06:46 pm
content: All those arguments on C++ were true years ago, but 32 bit MCUs make it a non factor. Yes, you can get carried away with objects if you are not careful, but the whole argument of objects taking lots of space is now moot with MCUs that have way over 2 KB of ram space. At the end of the day, yes, C is still the choice I go to, but making an object can just simply things so much.

author: Bruce Abbott
author_rank: Frequent Contributor
timestamp: March 29, 2018, 11:16:47 pm
content: Quote from: Gibson486 on March 29, 2018, 09:06:46 pmYes, the argument is mootwithMCUs that have way over 2K of RAM, but a lot don't. 'So just use a bigger chip!' But a bigger chip costs more. The cheapest STM32s only have 4k, and after you have used most of that for essential data it's not enough to support an inefficient 'higher level' language.Of course this won't matter in the future, because everyone will need Megabytes of RAM to run their favorite bloated language. The minimum supported platform will be a Raspberry Pixxx running Linux. It will have embedded WiFi to access the Cloud because your code won't work standalone, need constant firmware updates to fix vulnerabilities, and next week it will stop working if you haven't paid the subscription!

author: westfw
author_rank: Super Contributor
timestamp: March 30, 2018, 12:19:05 am
content: I might also point out that in something like the Arduino core (with it's somewhat "mild" use of C++ features), more of the inefficiencies that people complain about are due to design choices (or mistakes) of the programmers, rather than limits imposed by C++(It ought to be easy to check mbed for similar?)

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 30, 2018, 12:32:49 am
content: And it will take ages to start. Forget the ability for your systems to be operational within a couple ms after power-up/reset.There will still be a lot of areas - outside of general-purpose computing - where software bloat won't be acceptable, be it for performance or for validation reasons.People favoring a reduction of coding time by using bloated dev solutions obviously have never been concerned with software validation. When validation is required, the time spent for coding is actually such a small part of your overall schedule that it doesn't really matter and trying to reduce it would be completely vain.Of course, in companies shipping stuff that barely works, the time spent coding does matter. All depends on your perspective.

author: nctnico
author_rank: Super Contributor
timestamp: March 30, 2018, 12:38:24 am
content: Quote from: Bruce Abbott on March 29, 2018, 11:16:47 pmSaving a few cents on a microcontroller is often bad economy because you'll spend way more on development time. I've written it before and I'll write it again: the cost of hardware is usually pretty clear but the real costs of software development is often severely under estimated. You need to move a lot of units to reduce the software development costs to several cents per unit.

author: andyturk
author_rank: Frequent Contributor
timestamp: March 30, 2018, 12:55:02 am
content: Quote from: SiliconWizard on March 30, 2018, 12:32:49 amWhatwill take ages to start? Are you talking about a language or an operating system?

author: Vasi
author_rank: Regular Contributor
timestamp: March 30, 2018, 07:30:12 am
content: C++ on 8 and 32bit micros is a masked way to differentiate the final code of the beginner from a commercial application that has a corporate behind.Who migrated from Arduino Wiring language to the bare metal C language knows the difference. It is the same on Arduino Wiring language written on top of HAL that in itself is also a masked way to increase your final code size. For STM32 the best solutions are SPL or LL. LL has some support on the STM32CubeMX "designer" but lots of errors and HAL is pushed strongly forward.Let C++ and Ada (used it on ATmega but dropped it seeing the huge code size it generates - no need for extra activities and checking on a small micro that has to switch a relay, read a sensor and light a LED) be used for PC applications where the final data processing is done.

author: hans
author_rank: Super Contributor
timestamp: March 30, 2018, 07:46:10 am
content: Quote from: nctnico on March 30, 2018, 12:38:24 amI think it depends on the industry. If you're making very simple and "dumb" devices then perhaps you don't want/need the extra tools that a language like C++ has to offer, especially if they will cost you memory which @ 10M units can be worth a few months of engineering salary.But I think few people in "high tech" will find themselves in that position. The trend for electronics is that embedded software is used as a sponge for sucking up the complexity. Analog designs get pushed into digital domain, we have more and faster communication interfaces, more options, graphical user interfaces, feature creep, etc. It does not make sense to then not invest in good tools that scale well, i.e. the classic "struct with function pointer" vs C++ classes argument.

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 30, 2018, 11:10:15 am
content: Quote from: andyturk on March 30, 2018, 12:55:02 amI was actually replying to this:Quote

author: tggzzz
author_rank: Super Contributor
timestamp: March 30, 2018, 12:30:47 pm
content: Quote from: SiliconWizard on March 30, 2018, 11:10:15 amNote to everybody: that's why including context is so helpful -- and why stackexchange will never be useful for more than "which button should I press" questions.

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 30, 2018, 12:58:23 pm
content: Quote from: tggzzz on March 30, 2018, 12:30:47 pmYeah. I usually always include a quote in my replies, but sometimes tend to avoid quoting when my reply is directly to the last post, to avoid...bloated threads.Unfortunately someone else just posted something right before I submitted my own post and I didn't notice. My bad.

author: NorthGuy
author_rank: Super Contributor
timestamp: March 30, 2018, 12:59:24 pm
content: Quote from: nctnico on March 30, 2018, 12:38:24 amWhy do you think that designing bloated software is cheaper than doing efficient designs?

author: C
author_rank: Super Contributor
timestamp: March 30, 2018, 02:04:55 pm
content: When talking about higher level languages there is one thing I do not see being talked about.Where a thing , idea or concept is done.For example type checking can be done at compile time. Some languages push this to run time. At compile time you have no effect on CPU running program.Pushing type checking to running CPU can sometimes make running code better.So I thinkC would be lower level, Pascal a step up and the language that gives programmer a choice, another step up.Other changes could be classed as adding an identifier to a use.You use call back functions. Changing the word function to callback improves readability of source and lets more checks happen with little happening to code generator. Lack of word change makes these checks much harder to do. What could be a two pass code generator becomes a three pass or mess.Think that keep it simple should apply to language user and as much as passable to the code generator.Think of how much time is saved by more readable code.And some push

author: andyturk
author_rank: Frequent Contributor
timestamp: March 30, 2018, 02:53:47 pm
content: Quote from: C on March 30, 2018, 02:04:55 pmYeah, the worst thing ever is shitty code that works.Code that doesn't work (shitty or not) is replaced. It doesn't last long, so doesn't cost that much. But if some chunk of code works well enough to survive the prototyping phase, it puts down roots and starts attaching itself to other parts of the codebase. Bad code exerts an influence on everything around it through APIs and data structures.At some point, the original developer leaves and someone else has to fix the shitty code that formerly "worked". Then you're stuck because as the engineer tasked with fixing a problem, you don't want to (or can't) re-write vast parts of the system to deal with a bad decision in one place. So you end up having to fix the problem (and possibly add new features requested by marketing) with the added requirement of "maintain the original, shitty API".How to avoid this? IMO, one has to set a high standard for what is acceptable in code, and don't relax that standard when a project is in the early stages. If anything, you get more bang for the buck by being a stickler at the start than when the horse has already left the barn (or the product shipped).

author: technix
author_rank: Super Contributor
timestamp: March 30, 2018, 03:08:32 pm
content: I really want to mention the Swift-compatible-Objective-C and Swift language again. Since its memory management is implemented as compile-time static code analysis on those languages, the same code analyzer Apple pushed into clang actually also checks for various code smells and bad forms. Just tru run your code, even just plain C or C++ code, through the latest version of clang with -Wall -Wextra flags, and see the static analyzer catching those code smells and emit warnings for you.

author: C
author_rank: Super Contributor
timestamp: March 30, 2018, 04:06:54 pm
content: Quote from: andyturk on March 30, 2018, 02:53:47 pmYou are talking the great non standard standard to fix a problem.Think the better choice letting you specify this in the language. Then the language can assist in checking.Just how hard it it to typeInterruptCallbackThreadEventand many more in place of "function".A simple word change gives you a lot.

author: nctnico
author_rank: Super Contributor
timestamp: March 30, 2018, 04:44:42 pm
content: Quote from: NorthGuy on March 30, 2018, 12:59:24 pmYou need to define efficient first. Not needing to do optimisation for speed and/or size saves a lot of time. Using a well tested (trusted) but bloated library which speeds up the software development phase considerably can be well worth the extra hardware costs. The most efficient way is the one which -in the end- results in the most profit.

author: andyturk
author_rank: Frequent Contributor
timestamp: March 30, 2018, 05:01:45 pm
content: Quote from: C on March 30, 2018, 04:06:54 pmWell, I wasn't addressing the language issue at all, but rather the social issues that lead to "bloated code". Which programming language you use is only part of it.To your point, having a naming convention that clearly distinguishes "Interrupt" (a hardware thing) from "Callback" (a coding technique) is a great idea.

author: NorthGuy
author_rank: Super Contributor
timestamp: March 30, 2018, 05:43:43 pm
content: Quote from: nctnico on March 30, 2018, 04:44:42 pmEfficient design is simple. You take your time in the beginning to simplify things. Then you spend less money on the hardware, less time on the software development, and finally you get something which is cheaper and much easier to work with.If your design uses 3% of MCU resources, this is grossly inefficient. Chances are that by using more resources you can make your design simpler and thereby better.If you use 100% of MCU resources and now you're forced to crumble your design to fit into the allotted space, this is grossly inefficient too. You should have thought of this situation before you started the design.Quote from: nctnico on March 30, 2018, 04:44:42 pmThis is because the design was made backwards. You didn't analyze your timing (or your memory usage) well enough, and now you created something which you have to optimize. One of the problems with using huge libraries is that you don't know the insides of these libraries well and thus cannot think the entire design through. Therefore, you either use lot more resources than you actually need (like you buy a Ferrari when you actually need a tricycle), or you're risking getting into the situation where you need to optimize. However, it is hard to optimize if you don't know the internals of your libraries and you cannot really alter them. In such conditions, your "optimization" will be very hard and very time consuming - it's like trying to catch a black cat in the dark room. No wonder you hate it.Quote from: nctnico on March 30, 2018, 04:44:42 pmIs there such thing as "trusted"? The libraries get developed over time and new bugs are just around the corner. Sticking with older versions of libraries is not fun neither - they have known bugs and exploits you do not want. What you're really using is a black box, which can easily bring you any surprises, and such surprises may eat months of your development time. And here's where the bloat comes into the picture - the bigger the library, the more is the probability of surprises, hidden bugs, potential exploits etc. Using something lean is much safer, and much more predictable.

author: nctnico
author_rank: Super Contributor
timestamp: March 30, 2018, 06:02:19 pm
content: Quote from: NorthGuy on March 30, 2018, 05:43:43 pmTime = money so your method isn't efficient by definition if you start by taking time. Read up on agile software development and how a shorter time to market makes a product more profitable. You could nerd out on a design to make it fit on the smallest hardware and getting maximum performance but then the result will be too little, too late and too expensive. Also changing customer requirements during the development phase may throw a wrench in the wheel. The biggest challenge is to choose a solution which allows some flexibility in the design so when a last minute change comes in it doesn't mean the hardware doesn't fit and / or entire software must be rewritten. Nowadays products aren't designed from A to Z before the coding starts because it has been proven that such a method doesn't work: the end result doesn't fit the customer's needs and development takes too long.

author: C
author_rank: Super Contributor
timestamp: March 30, 2018, 07:11:40 pm
content: Some people think writing code is doing something. Making a huge program.Think of what you want a computer to do, it's not run programs, it is to process data.A poor decision can lead to a huge program that is actually slower then simple.Smoke & Mirrors,RISC processors are great, truth should add bad for memory. Cache is what lets RISC work.So think of simple foundations that have existed and apply that knowledge to today.A run time is not good or bad. It becomes bad if you only need a little part of huge run time. Cure is really simple in just compiling what is needed, linking what is needed.You should be asking why C programs are so huge. Why there are so many patches to C programs.Simple answer is that C makes the programmer manage a lot of details and offers little help.Not seeing a typo is easy. Not adding a range check is easy.The more you type that the language defines the better the program.To me type checking is a huge deal. Takes little time to state that this var is a temperature and this var is a pressure and getting an error message from compiler when I goof.With a little work on my part, I make the language and compiler work for me. But compiler need facts & knowledge to do this.When I look at C++ source, I am seeing more readable source & better chance of compiler working for me.That format does not have to mean multiple inhabitance or some kind of garbage collection.Today you often deal with out of box needs.changing from Function to Request gains many things.Very simple for compiler writer to copy a chunk of code and make a few changes to become Request.Just name change gains more readable source. Compiler changes gets you some error checking and you have not touched the code generator. You could even make this part better.Simple thingsIn C you have a header file and a code file and get an object file that is then linked.Poor linker causes C to mangle names. Now C is haveing to somehow find out if two mangled names are the same because it's not using the source names directly.Then you have does that header file really belong to that object file. If not positive waste time.Some compilers play the magic guess game. You have the magic guess as to what file contains ___. With some you get a magic guess as to what shortened var name is expanded to. Think about this two or more libraries that have the same short var name. Does the language force you to use the long name?There are all kinds of foundation problems. You should ask/check how much of the latest standard change is patching past problems. Latest standard should be simple, we added these key words and enabled these checks. I think more is a sign of a bad foundation that is likely wasting some of your time.So if a language like C is so great, why is something mainly written in C so complicated? The Oberon system is small by comparison, what is the differences?The Pascal compiler I was using in the 1980's was very small. Changing just one bit or byte flag turned it into a System compiler that let you create operating system with Pascal's error checking still enabled.Part of the reason is that Pascal has good syntax & good rules.Granted there were some things missing.It's nice to think compiler give no errors so if logic is good you have a good program.Need to ask if that API connects to simple code or a mess.Think of those define statements and how many versions of code they create. Then ask how many have been tested?Where is that define pin = x range checked. Little hard for a program to change a pin on package that does not exist.Little things add up.

author: technix
author_rank: Super Contributor
timestamp: March 30, 2018, 07:34:45 pm
content: Actually the latest C compilers can catch a lot of those errors the poster C above said and emit warnings (especially at -Wall and -Wextra levels,) but the big problem is that a lot people doesn't read through all the warnings and determine if they hint at a problem - the code builds and it is good to go - NOT if you don't iron out the warnings. If you have a deadline to meet maybe you can let warnings slip, but before anything regarding the next revision can be done you need to iron out those warnings first.This is also part of the management's fault, since way too many managers consider delivery of product the finish of the task. Sure the team must deliver before the deadline and have to let some warnings slip to production, but before adding any new feature you need to iron out existing bugs, or they may become so deep in the design that it becomes permanent in the code and brew a maintenance hell. Especially in this day and age of Internet of Things, it is becoming of so simple to implement over-the-air software upgrades even in the tiniest of places, and long-term maintenance through OTA isn't unheard of.Quote from: nctnico on March 30, 2018, 06:02:19 pmIf all the project is an one-shot job, sure you can cut all the corners you like. A lot of people misunderstood agile development as cutting corners, instead of using the best tools and build on the best foundation possible to the project without reinventing any wheels. If you don't use a solid foundation you are cutting corners, and the project will crumble. If there is any long-term plan involved taking the quick route can screw you over when you have to touch upon the code two years down the road.

author: nctnico
author_rank: Super Contributor
timestamp: March 30, 2018, 07:46:53 pm
content: Quote from: technix on March 30, 2018, 07:34:45 pmYou are also misunderstanding / twisting words. I'm not saying to cut corners. I'm saying to take the least costly route to get to a good end product. That is what agile software development is about (among other things)!My initial statement was that people tend to go for lowest cost hardware and then ending up needing to do a lot of optimisation to make the software fit on the hardware. This either means missing the deadline or releasing a half baked product.

author: technix
author_rank: Super Contributor
timestamp: March 30, 2018, 08:07:45 pm
content: Quote from: nctnico on March 30, 2018, 07:46:53 pmWay too many managers in China have that kind of understanding though - agile development = cut corners whenever possible. *sigh*When the lowest cost hardware is estimated to sell like hot cakes, it might make economical sense to force the engineering through that route even though it may take slightly longer, since the lower manufacturing cost will offset the higher R&D. Here in China general consumer electronic product sales are counted, by default, in millions - you don't break the million mark = you failed.

author: bson
author_rank: Unknown
timestamp: March 30, 2018, 08:31:50 pm
content: Quote from: rounin on March 26, 2018, 07:19:50 amMore importantly though, often when you implement a virtual method you're not always calling it through the base class, so the compiler can frequently know exactly which function you're calling and doesn't have to go through the vtable. In many cases the use of the virtual method is only for specific uses, such as collecting statistics, diagnostics, plumbing during standup, or teardown of more complex structures. Things that aren't performance critical but have great functional benefits (like clean layering; my personal philosophy is specialization and static link time resolution inside layers, while using vectored polymorphism between layers - unless there is a very specific reason to do otherwise). As a more specific example, you may have a bunch of things, like TCP, UDP, USB, and UARTs offering things that are a Connection abstract base class. But in most cases, such as inside TCP, it's a TCPEndpoint or such, not the abstract base class. For performance you specialize around a specific class (specialization being a template class); for non-performance you use the abstract Connection. (Note that a template class that operates on a specific type that implements a specific set of methods, and specializes for it, can itself implement a virtual base class - and hence encapsulate the performance-critical pieces.)While tables of function pointers are common in C (this is of course why C++ has virtual methods, since it fundamentally embodies good, common C practices) the language itself has no type formalism to express it, meaning the compiler has a much harder time figuring out what's what and hence deducing if you're actually calling the virtual method or some specific type's implementation of it. For example:Code:{// A is a BA a;((B&)a).foo();}This casts a to a B and calls a virtual method foo(). But the compiler knows a is really an A and that what's called is really A::foo(), so can omit the vtable indirection. It just becomes part of resolving constant expressions. A C compiler would in most cases find this impossible to figure out. (There are exceptions.)

author: andyturk
author_rank: Frequent Contributor
timestamp: March 30, 2018, 09:43:26 pm
content: Quote from: bson on March 30, 2018, 08:31:50 pmTo wit:LTO, Devirtualization, and Virtual TablesThe template specialization technique sounds interesting, although I personally might not want to go that route without first identifying a performance problem via measurement. "Premature optimization is the root of all evil" and all that.

author: NorthGuy
author_rank: Super Contributor
timestamp: March 30, 2018, 10:31:12 pm
content: Quote from: nctnico on March 30, 2018, 06:02:19 pmNot at all. Thinking upfront saves you much more time in the future.Thinking doesn't mean spending lots of time creating super-fast algorithms where you don't need them. It also doesn't mean creating the detailed design, drawing flowcharts and all that. It, sure as hell, doesn't mean using Agile rules. Thinking means inventing the design which brings you the biggest benefit.Quote from: nctnico on March 30, 2018, 07:46:53 pmYes, and other people use expensive hardware without any real need for it.Both cases are examples of doing before thinking. Selecting hardware which is not suitable for your project is a very bad mistake, which is very difficult to fix. But going for the most expensive (or most popular) hardware is not going to help. This will not shorten your development time. And you can get in troubles even with the most expensive hardware.

author: C
author_rank: Super Contributor
timestamp: March 31, 2018, 01:49:58 am
content: Sorry for not explaining better.Some is like trying to tell a 2D world person about a 3D world.There are many things in different languages that are great.Each option in a language can make it harder for compiler writer.So from the compiler writer view, fewer things and fewer options are good.Think there would be few fighting for assembly over C.That is just a step.As I have said, it's all the little things that add up, the good & the bad.A lot of the good compilers have not been open source or have no source. This leads to few good examples to follow.As the language gets higher level and still needing low level real world access, you get to a point where you need a simple editor that does all but code generation parts of compiler.When editor gets this smart, having different things defined in different places in source is no longer a problem.To work better with an ADA language program, you need an editor that understands more then the source format of ADA. Less then this becomes more of a burden on programmer. C puts huge load on programmer, ADA puts finding a burden on programmer.The compilers for the net framework have removed a lot from inside the compiler and put it in the framework.With so much in framework you gain more constant actions for all.Need to think of how much productive is loss by not using a higher level language in a good environment to create source code.The reverse side is that other then C and possibly C++ you are moving to a language with fewer using that language in embedded world.There is a few options that are not great where you use other language to create C or C++.But if you have access to source for these it gets some better.You have tools that for example setup chip pins for you, but I think you will find no or few that can read source and show pin use.So 5upercircuitsArm had C & C++, any thing else would be time and money.They did do a little to help other languages. But part of this is self serving as it also can help Arm.Some have said how great Turbo pascal was, That was a huge step down from the Pascal I used in my day job.Threads like this have existed for a very very long time.With all kinds of reasons to not change.

author: westfw
author_rank: Super Contributor
timestamp: April 01, 2018, 12:32:33 am
content: There are things that terrify me about modern programming languages. I've recently taken a couple of Python classes. Python is pretty neat, and it's one of those languages where you spend more time looking for libraries that have already been written than you do writing new code (or so it seems.) That's not so bad...But what it actually DOES is so ... opaque! I mean, take this little factorial example:Code:>>> prod = 1>>> for i in range(2,40):... prod *= i... print(i, prod)...2 23 64 245 120:10 362880011 3991680012 47900160013 6227020800--- Oh, that's cool. It didn't overflow at 32bits. Uses 64bit integers, I guess!14 8717829120015 1307674368000:28 30488834461171386050150400000029 8841761993739701954543616000000--- No, wait. This is more than 64bits. Did the nice efficient integers I thought I was using become BIGNUMs?--- Were they ALWAYS bignums? How slow is this going, anyway? What do I want to do if I want it to go faster?37 1376375309122634504631597958158090240000000038 52302261746660111176000722410007429120000000039 20397882081197443358640281739902897356800000000Similarly, people use "dictionaries" like arrays, only indexed by, say, strings. colorvalue["blue"] instead of colorvalue, and it's almost physically painful to think about how that must work.I feel like if I wanted to write Python professionally, I'd get mired in studying the internals until I understood the relative efficiencies. Sorta like those interpreted BASIC experts with the "Don't use comments except on lines that are never executed, and be sure to use short variable names!" rules. Ugh.(and I can't help but noticed that if I have a list of files, each of which has a list of "things", each of which has some associated values, which I want to write using json, that my life is easier if I just do:Code:a = {"foo.txt":{"one":1, "two":2, "three":3}, "bar.txt":{"one":10, "two":20, "three":30}}instead of wrapping a sensible object/structure around it. Sigh.)

author: C
author_rank: Super Contributor
timestamp: April 01, 2018, 02:21:15 am
content: bignumsBig integers is most often a limit of the language and compiler.All the 8-bit processors have the ability to do big integers.For most you have an ADD instruction & ADD with carry.A big number is just two or three arrays with a member size that these instructions can work on.In addition dymanic size bignumbers are no big deal at low level. Pascal stores strings as sturcture/array of Length followed string. As the string can contain any byte value, this is storage of integers up to 255*8 bit numbers or 2040 bit integer.As to the BlueSmart programmer could store the Blue in a B-tree and get a binary number that is then stored in the list to be searched. A second B-tree for binary number back to textWould not take much of list to make this faster & use less space.Higher level that is understood gives compiler & interpreter writers options.A good language should have a bit type and all integer bit sizes. In addition it should have the concept of a binary decimal point. A lot of hardware is actually a ratio device, talking ADC, DAC & PWM and the bit values match with binary to right of decimal point.You should note that Burr Brown which was well known for its ADC's & DAC's had left justified bit field .

author: technix
author_rank: Super Contributor
timestamp: April 01, 2018, 05:49:03 am
content: Quote from: westfw on April 01, 2018, 12:32:33 amThere is very likely some heuristics in the runtime to determine when to use what. Python seem to have good efficiency overall.

author: westfw
author_rank: Super Contributor
timestamp: April 01, 2018, 09:43:27 am
content: QuoteTell me about the relative performance of floats vs bignums on a Cortex M0? I mean, factorials probably means probability calculations, right? So I'll likely be dividing and multiplying as well as adding. And it's not so much that it's HARD, but that it's a "surprise." My supposedly quicker integer calculations now involve dynamic memory allocation, and counted loop code (just for addition), and don't really have any idea how expensive 4.0/factorial(52) is going to be in either cycles or memory. Pretty clearly I should have used floats from the beginning, but "it worked fine in the test code on my PC - these microcontrollers are just really slow, I guess... Can we get a faster chip?"

author: C
author_rank: Super Contributor
timestamp: April 01, 2018, 01:18:32 pm
content: westfwDid the factorials program crash?The other choices lose something to gain something.The big thing is higher level gives the compiler writer choices on how to get job done.Loops become easy for CPU in the down to Zero formHaving choice lets you the programmer state problem at higher level and lets compiler do the same.You can write simple to understand code at high level.The compiler could have factorials process change based on size, No fancy IF statements needed, CPU has the overflow bit in status register.Then is your dynamic memory allocation really dynamic allocation really dynamic? Lower level code forces ti to be so. A higher level can do better.With the right access some things become easy to describe.Back in the day, I did dynamic swap of things often.Think of starting new to programming and one of the first computers you see is one that gets dynamic patches & extensions while running the program.This is not all that hard to do.

author: NorthGuy
author_rank: Super Contributor
timestamp: April 01, 2018, 02:45:56 pm
content: Quote from: westfw on April 01, 2018, 09:43:27 amHow many factorials can you possibly calculate before the overflow? Not that many I guess. Thus, build a table with the pre-calculated factorials. Will be the fastest you can get.If you always need division, pre-calculate inversed values, trim to desired precision and convert to floats - it'll be even faster and more compact.

author: andyturk
author_rank: Frequent Contributor
timestamp: April 01, 2018, 05:01:21 pm
content: Quote from: C on April 01, 2018, 01:18:32 pmThat's a seriously magic compiler to be able to figure out from the text of the program itself, when bignums are needed or when fixed precision numbers will do the job.

author: C
author_rank: Super Contributor
timestamp: April 01, 2018, 05:25:00 pm
content: Quote from: andyturk on April 01, 2018, 05:01:21 pmThe magic is the simple CPU carry bit in the status register.When adding two binary numbers, the max is one bit larger then what you started with.When adding two unsigned byte values the max is a 9-bit value. When CPU get's the 9th bit it sets the carry bit in status register.So with CPU knowing what size to add it's simple.

author: andyturk
author_rank: Frequent Contributor
timestamp: April 01, 2018, 06:05:41 pm
content: Quote from: C on April 01, 2018, 05:25:00 pmI thought you were talking about what a compiler can do (not what can be done runtime).

author: C
author_rank: Super Contributor
timestamp: April 01, 2018, 07:26:52 pm
content: The compiler builds the code.The compiler is what limits access to CPU.The language puts limits on compiler.It is really not that hard to have variable bit size integers in language.I think every 8-bit CPU has larger then default size capability for integers.Less then CPU size is just using bit masks.Doing a good job in compiler for integers pays back in other areas also.How many smaller then byte size fields are used in a program?The net result is an easer to read program that compiler has more options to make faster.Does not take much for what you call a program to act like an operating system. This can be done at high level with proper compiler, often not even needing a language change or a very minor one.As I have said, the compiler I used was pascal based.It could compile programs or modules.A system programming switch let you treat a module like data while still keeping most pascal rules and error checks in tact.To select a custom printer driver was just loading & linking a module. This was all done in my program.A group of modules could become overlays with little more work.Threads took a little more work to share the code. as with out system, my program had to maintain many stacks.The smarter the compiler the less assembly is needed. It just keeps adding, better compiler can do more.The compiler created it's self and compilers and interpreters for other languages & many different OS's.That module capability gave easy access to many code generators.The hard part is coding a compiler to create the newer version of compiler & then cleaning up compiler source for new foundation.Think of C, how many C rules change for all sizes of integers. Do the rules change when your select statement uses a few bits of a var?What could the compiler hide with out needing a language change?Just a little change lets you have arrays that range from integer to integer and not 0 to integer-1It all adds up.

author: Korken
author_rank: Regular Contributor
timestamp: April 02, 2018, 02:52:22 pm
content: It's quite interesting to see that there are a lot of pros and cons when it comes to C++, so I though I would share a few things I use when developing in C++ for embedded (and more specifically ARM Cortex-M).The important thing is to use libraries that solve real problems, not use things just for the sake of using it.1. State Machine Language:https://github.com/boost-experimental/smlSML is a DSL (domain specific language) where you specify a state machine, and it generates optimized code for it.I am using it in all my current embedded projects as soon as I need a state machine, and it comes from 2 very important features:- There is a tool to convert the code you write for the state machine to a block diagram. This has saved me a lot of times.- I have tried and cannot beat the state machine generated in execution speed, amazingly fast.Thanks to it being generated at compile time, extra knowledge can be embedded in the DSL with allows for optimizations the compiler cannot see.And this is one of the things that really is useful in embedded, as we as embedded engineers have a lot of domain specific knowledge that we put to use.In the case of Template Metaprogramming, almost all of this knowledge and optimizations can be embedded into the DSL being created.2. CRECT(an event based scheduler computed at compile time):https://github.com/korken89/crectI am authoring an RTOS (if you can call it that) which generates an Stack Resource Policy scheduler for your system at compile time.After generating the connections between resources and jobs, the scheduler is mapped to the NVIC of the Cortex-M MCUs, making it extremely fast and efficient.I would recommend the interested to check the README in the link.CRECT uses a DSL to describe which jobs can take which resources, that in the allows it go guarantee deadlock and data race free execution (if not using resources outside the resource system).I presented this system at the emBO++ conference in March (embedded C++ conference) however the video is not online yet sadly.There I started a dare, if anyone could make a scheduler that is faster - as it uses the NVIC to make context switches manual code cannot beat it.A pleasant side-effect is that it is very easy to get sleep into the system, as when all event have been handled one can sleep (there is no code in main).3. Extra evening materialThere is a person call Odin Holmes which does a lot of talks on embedded and C++, and the systems being created.I would really recommend people to watch his talks and get inspiration:https://www.youtube.com/playlist?list=PL85B7uUiTlCFXO_XL_2x1tlr7B8Lg9NFpFor those who want to see the future of special function register abstraction can have a look atkvasir::bit.