As embedded software systems have grown in number, complexity, and importance in the modern world, a corresponding need to teach computer science students how to effectively engineer such systems has arisen. Embedded software systems, such as those that control cell phones, aircraft, and medical equipment, are subject to requirements and constraints that are significantly different from those encountered in the standard desktop computing environment. For example, embedded systems must frequently address challenges that arise from severe resource restrictions (e.g., low memory and network bandwidth), heterogeneous hardware platforms, and safety-critical operations. Software architecture has been shown to be an effective means for coping with such issues, yet traditional courses on embedded software development rarely focus on software architectural abstractions. Instead, they have concentrated on lower-level issues such as programming languages and hardware interfaces. Since 2005 at the University of Southern California, Los Angeles, a unique course has been developed that affords students the opportunity to gain experience and insights on developing software architectures for embedded systems. At the heart of the course is a middleware platform, Prism-MW, that helps students use software architectural principles to construct embedded systems and understand the important challenges of the embedded systems domain. This paper describes this course through the explanation and evaluation of four years of class projects, weaving together the course, the middleware platform, and the relationship of each to three key pedagogical goals that drove the formulation of the course curriculum.