This course offers microcontroller programming for beginners, as well as experienced mobile and desktop software developers. It is built around a mobile device accessory project to measure bicycle speed and distance.
An understanding of the limitations of embedded processors is essential for embedded software developers. In Embedded Systems Programming: Getting Started, you’ll learn the essential skills for reading and writing I/O lines, configuring peripherals such as analog and digital converters, counter/timer modules, and the serial interface or UART. First, you'll discover how to configure the clock system of the processor to balance performance and power consumption. Later, you'll explore digital and analog inputs and outputs, and write interrupt service routines to handle real-time tasks quickly. Finally, you’ll delve into the basics of powerful debugging tools by putting the processor to sleep to extend the battery life of the system, and ultimately learn to refactor and organize your code. By the end of this course, you'll have the fundamental skills necessary for embedded firmware development, helping you design and build products of your own.
Jeremy Willden has gone from hardware engineering to software development, his career ranged from the smallest startups to multinational corporations, creating products to give a competitive edge and fuel rapid growth.
Course Overview Hi everyone. My name is Jeremy Willden. Welcome to my course, Embedded Systems Programming: Getting Started. I'm an Embedded Systems Developer with Constellation Labs. Did you know that microcontrollers, the tiny chips that run everything from your dishwasher to aircraft control systems, outnumber computer and mobile processors by a longshot? You can learn how to program these tiny, cheap, low-power computers. In this course, you'll learn essential programming techniques for embedded systems. Some of the major topics that we will cover include analog and digital input and output to interact with the real world, running the processor at high speed for high performance and stopping it completely to save power, debugging techniques so you can see exactly what's going on in the entire chip, refactoring and architecting your code to make it more reusable, maintainable, and extensible. By the end of this course, you'll understand the key principles of microcontroller programming having completed a practical, hands-on project. Before beginning the course, you should be familiar with programming in at least one language. From here, you should feel comfortable diving into embedded systems programming with courses on embedded C++, real-time operating systems, MISRA coding standards for high-reliability systems, energy harvesting and ultra-low power development, and developing for the Arduino and Raspberry Pi platforms. I hope you'll join me on this journey to learn how to sense, control, and automate the world around you with the course, Embedded Systems Programming: Getting Started, at Pluralsight.
Digital Peripherals for Binary Signals Welcome back to Embedded Systems Programming: Getting Started. This is Jeremy Willden. I'm an embedded systems developer with Constellation Labs. For this course, the idea is to cover the basics of embedded firmware development using the example project of an accessory to mount on the fork of a bicycle to track the speed of the bicycle and the distance ridden. In previous modules, you learned about some of the tradeoffs you'll face when choosing a microcontroller for your project, examined some key factors when choosing the clock speed, you were encouraged to use source code control tools effectively, and saw firsthand how the resources of the processor can be consumed quickly by overuse of library functions and larger-than-necessary data types as we stepped through the code in the debugger. Of course, none of that matters if the microcontroller doesn't interact with the real world. The express purpose of an embedded system is almost always to somehow sense, control, and otherwise interact with the world around it. Perhaps the most basic way it will sense is through a digital input pin, and to control is through a digital output pin. We often need more precise timing for the digital inputs and outputs than can be accomplished through direct software control, and the key piece of hardware we'll learn about is the timer/counter module. It has no other job than to measure or control a digital I/O line or other event. Simple 1s and 0s are great, but more complex messages demand a more capable protocol, and the Universal Synchronous/Asynchronous Receiver/ Transmitter, the USART or UART, fits the need for sending and receiving data through one or more serial interfaces.
Constant Interruptions Are Not a Problem Welcome back to Embedded Systems Programming: Getting Started. This is Jeremy Willden. I'm an embedded systems developer with Constellation Labs. In earlier modules, you've already seen some of the benefits of hardware interrupts. They allow time-critical tasks to occur more quickly and deterministically than would be possible otherwise. They simplify program flow, allowing your main code to execute relatively long and complicated algorithms without denying CPU time to time-critical events. Even if you use a real-time operating system and don't use any interrupts directly, it's likely that the OS task scheduler uses interrupts to maintain the task list and execution priorities, interrupting one task and allowing others to run. In this module, we delve further into how interrupts work, allowing the code to be put on hold at almost any time while an interrupt service routine handles a time-critical task. Some of the events that may be able to trigger an interrupt include UART transmit or receive complete, timer overflow or wrap, ADC conversions complete, timer capture or compare match, imminent power failure, or an I/O line state change, and error conditions such as illegal memory access, UART receive parity error, watchdog timeout, or a power supply under voltage or brownout, and many more.
Refactoring and Architecting Welcome back to Embedded Systems Programming: Getting Started. This is Jeremy Willden. I'm an embedded systems developer with Constellation Labs. It's time to do some cleanup and organization of the scenario project, the Bluetooth-connected bicycle wheel sensor for health-conscious smartphone users. Through the course, we've added a lot of functionality, and certainly there is more to be done before the product ships, but after a while, software tends to become disorganized and difficult to navigate. You've added feature after feature, and it seems like the product is ready to ship, right? Before your enthusiasm, or more likely your supervisor's anxiety, leads to a premature shipment, it's time to take a step back and examine the big picture. One thing to consider is whether this is a one-off product or whether it is just one in a series of related products. Many systems I have worked on began as a single product with a single set of features, but then a second somewhat different version was developed, then another, and ultimately 10 or more variants were released to the market. In at least one case, the same core feature set existed across multiple processors and even on processors from different manufacturers with disparate register sets and unique I/O and peripheral interfaces. In these projects, I found it was extremely beneficial to create abstraction layers for different platforms. They might be called hardware or Platform Abstraction Layers, and you might create additional layers to enable code reuse, but whatever their name, they provide a common interface for your core code to access. A real-time operating system acts as an abstraction layer in some respects as well, but if you need to target more than one RTOS, then another layer of abstraction may be justified.