About the Author |
|
xv | |
About the Technical Reviewer |
|
xvii | |
Acknowledgments |
|
xix | |
Preface |
|
xxi | |
|
Part I Software Architecture and Design |
|
|
1 | (148) |
|
Chapter 1 Embedded Software Design Philosophy |
|
|
3 | (26) |
|
Challenges Facing Embedded Developers |
|
|
5 | (4) |
|
7 Modern Design Philosophy Principles |
|
|
9 | (11) |
|
Principle #1 Data Dictates Design |
|
|
10 | (1) |
|
Principle #2 There Is No Hardware (Only Data) |
|
|
11 | (2) |
|
Principle #3 KISS the Software |
|
|
13 | (1) |
|
Principle #4 Practical, Not Perfect |
|
|
14 | (2) |
|
Principle #5 Scalable and Configurable |
|
|
16 | (1) |
|
Principle #6 Design Quality in from the Start |
|
|
17 | (1) |
|
Principle #7 Security Is King |
|
|
18 | (2) |
|
Harnessing the Design Yin-Yang |
|
|
20 | (1) |
|
Traditional Embedded Software Development |
|
|
21 | (1) |
|
Modern Embedded Software Development |
|
|
22 | (4) |
|
The Age of Modeling, Simulation, and Off-Chip Development |
|
|
26 | (1) |
|
|
27 | (2) |
|
Chapter 2 Embedded Software Architecture Design |
|
|
29 | (26) |
|
A Tale of Two Architectures |
|
|
32 | (1) |
|
Approaches to Architecture Design |
|
|
33 | (3) |
|
Characteristics of a Good Architecture |
|
|
36 | (2) |
|
|
36 | (1) |
|
|
37 | (1) |
|
Architectural Design Patterns in Embedded Software |
|
|
38 | (9) |
|
The Unstructured Monolithic Architecture |
|
|
38 | (1) |
|
Layered Monolithic Architectures |
|
|
39 | (3) |
|
Event-Driven Architectures |
|
|
42 | (3) |
|
Microservice Architectures |
|
|
45 | (2) |
|
Application Domain Decomposition |
|
|
47 | (5) |
|
|
48 | (1) |
|
|
49 | (1) |
|
|
50 | (2) |
|
|
52 | (1) |
|
|
52 | (3) |
|
Chapter 3 Secure Application Design |
|
|
55 | (30) |
|
Platform Security Architecture (PSA) |
|
|
56 | (27) |
|
PSA Stage 1 Analyzing a System for Threats and Vulnerabilities |
|
|
58 | (10) |
|
|
68 | (7) |
|
PSA Stage 3 Implementation |
|
|
75 | (6) |
|
|
81 | (2) |
|
|
83 | (2) |
|
Chapter 4 RTOS Application Design |
|
|
85 | (34) |
|
Tasks, Threads, and Processes |
|
|
87 | (3) |
|
Task Decomposition Techniques |
|
|
90 | (26) |
|
Feature-Based Decomposition |
|
|
90 | (2) |
|
The Outside-In Approach to Task Decomposition |
|
|
92 | (14) |
|
|
106 | (1) |
|
Task Scheduling Algorithms |
|
|
106 | (2) |
|
Verifying CPU Utilization Using Rate Monotonic Analysis (RMA) |
|
|
108 | (3) |
|
|
111 | (5) |
|
|
116 | (3) |
|
Chapter 5 Design Patterns |
|
|
119 | (30) |
|
|
119 | (11) |
|
|
120 | (1) |
|
|
121 | (2) |
|
Interrupt Design Patterns |
|
|
123 | (6) |
|
Direct Memory Access (DMA) |
|
|
129 | (1) |
|
RTOS Application Design Patterns |
|
|
130 | (8) |
|
|
131 | (3) |
|
|
134 | (4) |
|
Publish and Subscribe Models |
|
|
138 | (2) |
|
Low-Power Application Design Patterns |
|
|
140 | (3) |
|
Leveraging Multicore Microcontrollers |
|
|
143 | (5) |
|
|
145 | (1) |
|
|
146 | (1) |
|
|
147 | (1) |
|
|
148 | (1) |
|
|
148 | (1) |
|
Part II Agile, DevOps, and Processes |
|
|
149 | (108) |
|
Chapter 6 Software Quality, Metrics, and Processes |
|
|
151 | (28) |
|
Defining Software Quality |
|
|
152 | (1) |
|
Structural Software Quality |
|
|
153 | (16) |
|
|
154 | (3) |
|
|
157 | (12) |
|
Case Study -- Capstone Propulsion Controller |
|
|
169 | (7) |
|
|
176 | (3) |
|
Chapter 7 Embedded DevOps |
|
|
179 | (18) |
|
|
180 | (2) |
|
DevOps Principles in Action |
|
|
182 | (2) |
|
Embedded DevOps Delivery Pipeline |
|
|
184 | (3) |
|
CI/CD for Embedded Systems |
|
|
187 | (3) |
|
Designing a CI/CD Pipeline |
|
|
190 | (3) |
|
Creating Your First CI/CD Pipeline |
|
|
193 | (1) |
|
|
194 | (1) |
|
|
194 | (3) |
|
Chapter 8 Testing, Verification, and Test-Driven Development |
|
|
197 | (22) |
|
Embedded Software Testing Types |
|
|
198 | (1) |
|
Testing Your Way to Success |
|
|
199 | (3) |
|
|
202 | (2) |
|
Regression Tests to the Rescue |
|
|
204 | (1) |
|
|
205 | (3) |
|
Introduction to Test-Driven Development |
|
|
208 | (3) |
|
Setting Up a Unit Test Harness for TDD |
|
|
211 | (6) |
|
|
212 | (2) |
|
Leveraging the Docker Container |
|
|
214 | (1) |
|
|
215 | (2) |
|
|
217 | (2) |
|
Chapter 9 Application Modeling, Simulation, and Deployment |
|
|
219 | (22) |
|
The Role of Modeling and Simulation |
|
|
219 | (2) |
|
Embedded Software Modeling |
|
|
221 | (5) |
|
Software Modeling with Stand-Alone UML Tools |
|
|
222 | (1) |
|
Software Modeling with Code Generation |
|
|
223 | (2) |
|
Software Modeling with Matlab |
|
|
225 | (1) |
|
Embedded Software Simulation |
|
|
226 | (8) |
|
|
226 | (6) |
|
Software Modeling in Python |
|
|
232 | (1) |
|
Additional Thoughts on Simulation |
|
|
233 | (1) |
|
|
234 | (3) |
|
Stand-Alone Flash Tools for Manufacturing |
|
|
235 | (1) |
|
CI/CD Pipeline Jobs for HIL Testing and FOTA |
|
|
236 | (1) |
|
|
237 | (4) |
|
Chapter 10 Jump-Starting Software Development to Minimize Defects |
|
|
241 | (16) |
|
A Hard Look at Bugs, Errors, and Defects |
|
|
242 | (2) |
|
The Defect Minimization Process |
|
|
244 | (9) |
|
|
244 | (2) |
|
Phase 2 Build System and DevOps Setup |
|
|
246 | (2) |
|
Phase 3 Test Harness Configuration |
|
|
248 | (1) |
|
Phase 4 Documentation Facility Setup |
|
|
248 | (1) |
|
Phase 5 Static Code Analysis |
|
|
249 | (1) |
|
Phase 6 Dynamic Code Analysis |
|
|
250 | (2) |
|
Phase 7 Debug Messages and Trace |
|
|
252 | (1) |
|
When the Jump-Start Process Fails |
|
|
253 | (2) |
|
|
255 | (2) |
|
Part III Development and Coding Skills |
|
|
257 | (136) |
|
Chapter 11 Selecting Microcontrollers |
|
|
259 | (18) |
|
The Microcontroller Selection Process |
|
|
259 | (10) |
|
Step #1 Create a Hardware Block Diagram |
|
|
260 | (3) |
|
Step #2 Identify All the System Data Assets |
|
|
263 | (1) |
|
|
264 | (1) |
|
Step #4 Review the Software Model and Architecture |
|
|
265 | (1) |
|
Step #5 Research Microcontroller Ecosystems |
|
|
266 | (1) |
|
Step #6 Evaluate Development Boards |
|
|
267 | (2) |
|
Step #7 Make the Final MCU Selection |
|
|
269 | (1) |
|
The MCU Selection KT Matrix |
|
|
269 | (4) |
|
Identifying Decision Categories and Criterions |
|
|
270 | (1) |
|
|
271 | (1) |
|
Choosing the Microcontroller |
|
|
272 | (1) |
|
Overlooked Best Practices |
|
|
273 | (2) |
|
|
275 | (2) |
|
Chapter 12 Interfaces, Contracts, and Assertions |
|
|
277 | (24) |
|
|
277 | (2) |
|
|
279 | (3) |
|
Utilizing Design-by-Contract in C Applications |
|
|
280 | (2) |
|
|
282 | (11) |
|
|
283 | (2) |
|
When and Where to Use Assertions |
|
|
285 | (2) |
|
Does Assert Make a Difference? |
|
|
287 | (1) |
|
Setting Up and Using Assertions |
|
|
287 | (4) |
|
Three Instances Where Assertions Are Dangerous |
|
|
291 | (2) |
|
Getting Started with Real-Time Assertions |
|
|
293 | (5) |
|
Real-Time Assertion Tip #1 Use a Visual Aid |
|
|
294 | (1) |
|
Real-Time Assertion Tip #2 Create an Assertion Log |
|
|
295 | (1) |
|
Real-Time Assertion Tip #3 Notify the Application |
|
|
296 | (2) |
|
Real-Time Assertion Tip #4 Conditionally Configure Assertions |
|
|
298 | (1) |
|
A Few Concluding Thoughts |
|
|
298 | (3) |
|
Chapter 13 Configurable Firmware Techniques |
|
|
301 | (32) |
|
Leveraging Configuration Tables |
|
|
302 | (2) |
|
An Extensible Task Initialization Pattern |
|
|
304 | (10) |
|
Defining a Task Configuration Structure |
|
|
305 | (3) |
|
Defining a Task Configuration Table |
|
|
308 | (3) |
|
Initializing Tasks in a Task_CreateAll Function |
|
|
311 | (3) |
|
Autogenerating Task Configuration |
|
|
314 | (17) |
|
|
315 | (2) |
|
Creating Source File Templates |
|
|
317 | (5) |
|
Generating Code Using Python |
|
|
322 | (9) |
|
|
331 | (2) |
|
Chapter 14 Comms, Command Processing, and Telemetry Techniques |
|
|
333 | (28) |
|
Designing a Lightweight Communication Protocol |
|
|
334 | (4) |
|
Defining a Packet Protocol's Fields |
|
|
335 | (2) |
|
A Plethora of Applications |
|
|
337 | (1) |
|
Implementing an Efficient Packet Parser |
|
|
338 | (9) |
|
The Packet Parsing Architecture |
|
|
338 | (2) |
|
Receiving Data to Process |
|
|
340 | (2) |
|
Packet Decoding As a State Machine |
|
|
342 | (4) |
|
|
346 | (1) |
|
Command Processing and Execution |
|
|
347 | (7) |
|
Traditional Command Parsers |
|
|
347 | (3) |
|
An Introduction to Command Tables |
|
|
350 | (3) |
|
Executing a Command from a Command Table |
|
|
353 | (1) |
|
Managing System Telemetry |
|
|
354 | (4) |
|
Telemetry As a "Global" Variable |
|
|
355 | (2) |
|
|
357 | (1) |
|
|
358 | (3) |
|
Chapter 15 The Right Tools for the Job |
|
|
361 | (32) |
|
The Types of Value Tools Provide |
|
|
361 | (2) |
|
Calculating the Value of a Tool |
|
|
363 | (5) |
|
The ROI of a Professional Debugging Tool |
|
|
365 | (3) |
|
|
368 | (22) |
|
|
368 | (3) |
|
|
371 | (5) |
|
|
376 | (14) |
|
Open Source vs. Commercial Tools |
|
|
390 | (1) |
|
|
391 | (2) |
|
Part IV Next Steps and Appendixes |
|
|
393 | (62) |
|
|
395 | (6) |
|
|
395 | (1) |
|
|
396 | (1) |
|
|
396 | (2) |
|
|
398 | (3) |
|
Appendix A Security Terminology Definitions |
|
|
401 | (4) |
|
|
401 | (4) |
|
Appendix B 12 Agile Software Principles |
|
|
405 | (2) |
|
12 Agile Software Principles |
|
|
405 | (2) |
|
Appendix C Hands-On -- CI/CD Using GitLab |
|
|
407 | (28) |
|
|
407 | (1) |
|
Building STM32 Microcontroller Code in Docker |
|
|
407 | (1) |
|
Installing GCC-arm-none-eabi in a Docker Container |
|
|
408 | (3) |
|
Creating and Running the Arm GCC Docker Image |
|
|
411 | (2) |
|
Creating an STM32 Test Project |
|
|
413 | (2) |
|
Compiling the STM32 Makefile Project |
|
|
415 | (1) |
|
Configuring the Build CI/CD Job in GitLab |
|
|
415 | (1) |
|
|
416 | (2) |
|
Connecting Our Code to the Build Job |
|
|
418 | (3) |
|
Build System Final Thoughts |
|
|
421 | (1) |
|
Leveraging the Docker Container |
|
|
421 | (1) |
|
|
422 | (1) |
|
Integrating CppUTest into a CI/CD Pipeline |
|
|
423 | (1) |
|
Adding CppUTest to the Docker Image |
|
|
423 | (2) |
|
Creating a Makefile for CppUTest |
|
|
425 | (4) |
|
Configuring GitLab to Run Tests |
|
|
429 | (1) |
|
Unit Testing Final Thoughts |
|
|
430 | (1) |
|
|
431 | (1) |
|
|
432 | (1) |
|
|
433 | (1) |
|
Deployment Final Thoughts |
|
|
434 | (1) |
|
|
435 | (20) |
|
The Heater Module Requirements |
|
|
435 | (1) |
|
Designing the Heater Module |
|
|
435 | (2) |
|
|
437 | (1) |
|
|
438 | (1) |
|
Test Case -- Setting to HEATER_ON |
|
|
439 | (3) |
|
Heater Module Production Code |
|
|
442 | (7) |
|
|
449 | (2) |
|
|
451 | (2) |
|
|
453 | (2) |
Index |
|
455 | |