In today's design model, MCU and traditional DSP programmers often partition their code development into two separate groups, interacting only at the system boundary level where their two functional worlds meet. This makes some sense, as two separate groups of designers can develop their own sets of design practices based on application requirements. For instance, signal processing developers may want to implement techniques to improve performance. Another group may have opposing design goals—MCU programmers, for example, may prefer implementing a turnkey system and letting it perform all tasks without user intervention.
Another reason for the historical separation of MCU and DSP development groups is that the two processors have two separate sets of design imperatives. From a technical standpoint, engineers responsible for architecting a system often hesitate to mix a "control" application with a "signal processing" application on the same processor. Their most common fear is that non-real-time tasks interfere with hard-real-time tasks. For instance, programmers who handle tasks such as the graphical user interface (GUI) or the networking stack should not have to worry about hampering the system's real-time signal processing activities.
What's more, there are historical differences in the programming models for MCUs and DSPs. MCUs typically use on-chip instruction and data caches that allow a hands-off approach to managing code and data. In other words, the MCU will automatically manage the flow of code and data without any programmer intervention. The downside is that cache behavior can be hard to predict and even harder to control—making it hard to obtain real-time performance.
In contrast, DSPs use static memory systems. Under software control, DMA channels shuttle data between peripherals and memory systems without using up valuable core processor cycles. This arrangement allows the fine tuning controls sought by DSP programmers, but it presents complexities that most MCU programmers are not prepared to deal with.
Operating system (OS) support is also key. Several layers of tasking can be realized by supporting an operating system or real-time kernel. An interrupt controller that supports multiple priority levels is needed to ensure that targeted performance is still achievable. Context switching must be attainable through hardware-based stack and frame pointer support. This enables developers to create systems that include both worlds—control and real-time signal processing—on the same device.
Historically, DSPs have had limited OS support. The main reason for this is that most DSPs do not include a Memory Management Unit (MMU). An MMU permits OS support for memory protection. This allows one task, via a paging mechanism, to block memory or instruction accesses by another task. An exception is generated whenever unauthorized access is made to a protected area of memory. The kernel services this exception and takes appropriate action.
Legacy code also plays an important role. MCU code is likely to assume byte addressing, 32-bit operations and a 32-bit address space. In contrast, legacy DSP code typically assumes 16-bit addressing, 16-bit arithmetic, and a 16-bit address space.
What's more, MCU code is usually written in C. Historically, DSPs have performed poorly on compiled code. Compiling C code for a DSP often resulted in code that is both bloated and slow. Conversely, legacy DSP code is often written in assembly language. This code can be small and fast, but it is difficult to port.
The final reason for the separation of MCUs and DSPs has to do with performance. MCUs are optimized for control tasks, and they often do not offer enough performance for intensive signal processing workloads. For example, many MCUs lack the multiply-accumulate (MAC) hardware found in DSPs. Similarly, DSPs are optimized for signal processing, and often perform poorly on control tasks. For example, DSPs frequently operate at lower clock rates than MCUs.
Convergent processors meet the challenge
In light of these challenges, a new class of processors has emerged that melds the features of MCUs with the features of DSPs. This class of processors is known by several names; for the purposes of this article we will refer to them as "convergent" processors. One example of this class of processors is the Blackfin processor family from Analog Devices. At the core, Blackfin processors have a 16/32-bit architecture with dual-MAC and Single Instruction, Multiple Data (SIMD) capabilities. This enables the processors to take on challenging DSP workloads. The processors also have features typically found in microcontrollers and microprocessors, such as byte addressability, an MMU, a watchdog timer, and real-time clock.
The melding of MCU and DSP features in a convergent processor can even extend to the memory system. On some convergent processors, such as Blackfin devices, the memory system can be configured as cache (as in an MCU), as static memory (as in a DSP), or as a mix of the two. This allows development teams to use whichever programming model is most appropriate.