36

I think you are misrepresenting the message of the "Modern C++ in Embedded Systems" video. The point is that there are people in the embedded world that write code and then test it by running the code in the debugger to verify that it does what they think it does. He argues that a better alternative is to use abstractions so that the compiler can verify that ...


35

No, not at all ! Abstractions and good practices can of course reduce the risks of errors. For example: language abstractions let the compiler generate code, that you would have to write yourself otherwise. For example, the C++ object model ensures that object constructed are destroyed as they supposed to be, without extra care on your shoulders; these ...


26

Your first problem is that you think of the design as "wrong." That's really not the right way to consider things. Rather, different designs make different design trade-offs. Any design has pros and cons that have weighed against each other. If there is a problem with the design it's not that is "wrong" but rather that it makes a poor choice of trade-offs. ...


22

This question basically boils down to "can you write bug free code the first time every time?” The answer is always going to be no. Yes, there are practices that can help, you can isolate modules. You can compile both for the embedded and desktop, then test and develop on the desktop. You can create hardware abstraction layers that help isolate those ...


20

Unless you have at least 3 use-cases where the algorithms will be used with different types and sizes, you are not going to do good job of the genericity anyway. So don't bother too much. I'd recommend writing it in plain C using custom typedefs for all types (except things that are obviously size_t, int or such) and #defines for any relevant sizes. Than ...


20

(Edit: 12/7/2017, a year later, I found an authoritative answer) In an article on software development for NASA space missions. https://www.nasa.gov/pdf/418878main_FSWC_Final_Report.pdf On page 31, the following table is in the graph showing a decent fit to a logarithmic increase in lines of code : (So, my 3K estimate was right on the money.) 1969 Mariner-...


14

This article in Wired makes it clear that the code was written in Fortran 5 and later ported to Fortran 77 and some elements are now in a version of C: The spacecrafts’ original control and analysis software was written in Fortran 5 (later ported to Fortran 77). Some of the software is still in Fortran, though other pieces have now been ported to the ...


12

Where I work, we create embedded systems and are also using scrum for our development. You're looking at things from a technical perspective, not a feature perspective. The first thing you should ask is "Why do we need to implement this?" For example: Why do you need SPI? Is it going to be used for EEPROM so you can store serial numbers? Or maybe hook up ...


12

I agree with you that it's overly pessimistic, but some (potentially historical) reasons: DO-178C Level A code requires Source Code to Object Code Traceability, which is much harder to prove manually with optimized code (and qualified compilers are very expensive) optimised code is harder to debug, which might prohibit scripted debugging opportunities there ...


11

If you don't provide a way to dispose the object, you are passing a clear message that they have "infinite" lifetime once created. If this makes sense to your application, I say: do it. Glampert is right; there is no need for destructors here. They would just create code bloat and a pitfall for users (using an object after its destructor is called is ...


11

If you refuse to abstract or change usart_error then consider using whitespace to take mercy on my eyes. if ( usart_error.CRCError || usart_error.DMATransferError || usart_error.FramingError || usart_error.NoiseError || usart_error.OverrunError || usart_error.ParityError ) { //... } This is reminiscent of Haskell style. It's ...


10

There are two basic types of software bugs: The code doesn't do what you intended. What you intended was the wrong thing to do. The choice of languages etc may (or may not) have an impact on the first type of bug, but it has no effect at all on the second. Note, by "what you intended" I mean the real-world observable behaviour of the software, not internal ...


9

The only thing I'm conscious is that I have to make sure I actually have 1KB of stack free when entering this function. Yes, and that is a strong constraint. You'll better be sure statically than you do have such a large space available on the stack. If the code is small, if you are using a recent GCC to compile your code, see this. BTW, some cheap ...


9

What is the simplest operating system or platform upon which we can do Software Engineering in this day and age? None. One of the main activities in Software Engineering is conceptual software design, and making concepts for a software does not necessarily require a specific platform. It can be done with pencil and paper, by drawing UML diagrams, data ...


9

I think you are making a common junior-level programmer error in your judgement here. Because the solution is not the way you would have done it, you want to redesign it. One of the most important things you need to become comfortable with is that whether the design is the way you think it should be doesn't matter. It really, truly doesn't matter at all. ...


8

With the processors used for embedded devices, there are three possibilities: The processor executes the code directly from flash/ROM. In this case, the code doesn't take any RAM away from the system at all. In this setup, the RAM and flash/ROM are typically mapped to different portions of the address space that the processor can address, so the maximum ...


8

This is all my experience/opinion, gathered from working in the field pretty close to the metal: "embedded systems" are usually situations where you have significant non-trivial memory or speed constraints as compared to desktop systems. Those embedded situations can include microcontrollers, but can also include x86 systems on a chip, and also systems like ...


8

The Software Toolworks C compiler for CP/M came on one 8" SSSD floppy, and compiled most of the language as of about 1982. It required a machine with 56K of memory and one floppy drive. I don't remember how much the resident portion of CP/M required. Turbo Pascal 1.0 required 64K on a CP/M machine, and included an IDE. It was a single-pass compiler, ...


8

This is actually the worst thing to do because you never know what resources will be needed in all cases meaning that your code can crash in the real world when it was fine in tests. It also means that if you try to debug with an ICE specific memory addresses do not map to specific functions or variables which is a nightmare. The best practice in the ...


7

For a small-systems, hardcore embedded OS, the first option is the only really viable one. The problem is that for nearly every chipset, you would have to make small adjustments to the interfacing with the hardware and that gives you a high risk that the OS needs to be re-compiled for the new chipset. So, the first option is not only the easiest for you, ...


7

Generate .a file Build a (web-based) library generator (again one .c and .h file) Neither of these is a good option. The former is, for the reason you covered, platform-specific. The latter leaves anyone wanting to alter the set of modules compiled into their binary dependent on you continuing to run a server that can generate a new version. You ...


7

Immediate questions are: Are TCP sockets and HTTP connections really specific to your Manager::Transport nested class? How will you unit test them if they're not accessible outside Manager? Will anything other than a Manager ever need a Transport? to which at a guess I'd probably answer No, With unnecessary difficulty, and Maybe, respectively. You don't ...


7

Critical importance here is context of interview for a semi conductor company without knowing the role description, therefore this is impossibly broad. Jumping into code with the information provided in the question is hopefully not what the interviewer was looking for. You need to find out some fundamental requirements.... Is the address able to be ...


6

Embedded software is very different. On a desktop app, abstractions and libraries save you a lot of development time. You have the luxury of throwing another couple megabytes or gigabytes of RAM or some 2+GHz 64-bit CPU cores at a problem, and someone else (users) is paying for that hardware. You may not know what systems the app will run on. In an ...


6

Your software is an abstraction over the hardware. Whether a particular signal is active low or not is a detail you are supposed to abstract away. You should choose names to reflect that. set and reset probably feel odd because they aren't abstract enough. Try other verbs, such as as enable/disable, activate/deactivate, or select/deselect for a chip ...


6

C++ can do it the same way C does. All C++ gives you is easier-to-use containers that wrap much of the low-level detail. For example, a string class can (and does) hold a block of memory on the stack for short strings, only allocating a heap buffer for larger ones. This buffer is exactly like a C string buffer, if the string resizes, the string class will ...


6

Your parser approach is definitely a step in the right direction. To deal with what you describe, you need to follow two well known software engineering principles as rigidly as possible: 1. Single source of truth You wrote changes ... need to be propagated to multiple places in the product's source code That is exactly the opposite of "single source ...


6

People tend to be cautious with a large stack, because it grows backwards in RAM and overwrites values of variables, leading to unexplainable behavior. It gets even worse, because you need to know the lowest possible stack pointer address and subtract the size to allocate when entering the routine. This is all a job for the hardware memory management (...


6

since we're implementing our own error code, the caller has to actively remind themselves to to check this value, making it easy to miss. Why not design the API in a way it becomes hard for the caller to miss an error? For example: design your function in a way it does not only return the result of the operation, but also explicitly an error code (for ...


6

By not treating all Interrupt Service Routines (ISR's) as the highest priority. The kernel of an RTOS is preemptible where as a GPOS kernel is not preemptible. This is a major issue when it comes to serving high priority process/threads first. If kernel is not preemptible, then a request/call from kernel will override all other process and threads. For ...


Only top voted, non community-wiki answers of a minimum length are eligible