In this Product How-To article, Mark Saunders of Cypress looks at the problems of hardware/software co-development from the point of view of the software designer using the company’s PSoC Creator to illustrate his exposition.
I’ve been in the embedded business for a good few years now, and I still cannot figure out whether “co-development” refers to a manager’s dream of hyper-efficient project scheduling or an instrument of torture for software developers. It probably just means that software is developed in parallel with the hardware platform design but if this isn’t a synonym for torture, I’m not sure what is.
In the embedded world, it is very common to write software for a board or chip that is simultaneously in the process of being designed. Sometimes the target is a complex ASIC design in simulation environments from EDA vendors like Mentor Graphics or Cadence Design Systems.
Sometimes it is for powerful FPGA designs, from companies like Xilinx or Altera, with embedded microprocessor cores interfacing to standards-based and custom IP blocks.
And sometimes it is for programmable systems-on-chip, that integrate programmable digital and analog functionality with microcontroller, like the PSoC devices. These are all powerful environments that enable fabulous innovation and have one torture-inducing feature in common; the hardware can change at a moment’s notice and the software developer will have to react.
I’m not suggesting we slow down the pace of innovation just to give software engineers a breather. Quite the reverse, actually. Hardware tools need to be better integrated with software IDEs in order to accelerate time-to-market. Designers need more tools and methodologies that isolate the application from hardware changes. I’m not talking about major communication blocks being added or removed from the design.
If that’s your problem, your software engineers should probably be working on something else because your hardware design is no where near ready for them! I am talking about minor changes to defined functional blocks occurring late in the design cycle, things like register addresses that move, bit meanings that get re-defined, buffers that change size, and so on. All of these “minor” edits cause ripple down into the software that can result in product defects and substantially re-work long after the reason for the hardware change is forgotten.
Software Engineers! It is time we stopped letting the tail wag the dog. Here are three ideas to change how we develop applications for moving targets. Don’t embark on your next project without them!
Idea #1: Don’t Write the HAL. Generate it!
The first change we need is for the hardware development tool to generate a software interface, often called a hardware adaptation layer (HAL). The HAL should include boot code that reliably initializes the programmable hardware and provide APIs to enable software control of the system. More than just simplifying firmware development, the HAL abstracts away the implementation from the interface. This means that small changes to the hardware can be implemented without perturbing the firmware.
There is nothing new in the idea of a HAL and many experienced designers have written intelligently about the need for consistent, intuitive naming conventions for constants, functions and variables. But, for programmable devices like FPGAs, CPLDs and PSoC, I would extend those requirements to include the need for the HAL to be generated by the hardware design tool itself. How else can the software engineers be guaranteed a reliable interface?
Figure 1: A snapshot of a PSoC Creator workspace showing the API files (HAL) for a system controller design using a FanController block and a pair of Comparators (Comp_Hi and Comp_Lo).
In a static or slowly-moving environment, such as a fixed-function MCU or large-scale ASIC project, it is reasonable to consider the HAL to be an independent suite of APIs and to modify it as part of a hardware design change.
But with modern programmable devices the hardware can change multiple times a day. Manual HAL maintenance is simply incompatible with this methodology and would guarantee errors in the implementation, not to mention a good deal of torture for the software engineers! In my opinion, automated HAL generation should be a must-have requirement for any programmable platform.
Idea #2: Integrates With My Favorite IDE
Programmable devices offer fantastic opportunities for innovation but, all too often, the tools required to design the hardware disrupt normal software development practices. Engineers are coerced into using tools that are simplistic, lack features, and do not mesh well with existing flows.
Most co-design environments have evolved out of the hardware design tools that have supported ASIC and FPGA, or CPLD, flows for years. As embedded CPUs have become more commonplace, the need to add software development to the tool portfolio has been obvious, leading to a single tool that supports two disciplines but is ideal for neither. As a result, engineers lose both features and, possibly even worse, choice.
The solution is not for tools companies to pick the industry-leading debugger, bolt it into hardware design tools, declare success and wonder why the software engineers keep moaning. Adding source code editors and debugging features to a hardware-focused tool is not really addressing the problem because the tool is still not integrated into the user’s flow. Source control interfaces, software test suites, automated builds, and so on are everyday faire for today’s developers and merging a hardware design tool into that is a real challenge.
The right approach is not to integrate debuggers, editors, or whole IDEs at all, but simply to enable development in traditional IDEs, that software developers actually like and use, from the very start of a project. While the hardware designers may still need the software features in their tool to create and run small test programs, the real application development should always be enabled in the engineer’s IDE of choice.
One approach to this requirement is to be able to export a project from one tool to another. For example, Cypress’s PSoC Creator can export PSoC designs right into the Keil µVision tool. In many programmable systems the “hardware” is, in fact, supplied as a block of data that gets programmed into the device at boot time to create the configured device.
Figure 2: The “IDE Export” GUI for PSoC Creator. This dialog is used to create, and update, Keil µVision projects for application development.
To software, that is just data and so exporting the design merely requires the hardware tool to generate a project file for the target product and populate it with the HAL source files and initialization code. The application can then be built on top of the hardware without interfering with the automated testing and source control systems that are used in modern environments.
Figure 3: The exported system controller project from above, opened in Keil µVision, and ready for application development.
Of course, a one-time export is not a complete solution for a dynamic hardware platform. The feature must include the ability to update the design seamlessly, without breaking the application. For IDEs that support libraries, this update process is simple because the design can be split into an application project and configuration library. This completely isolates the application and allows the hardware library, containing the configuration data and HAL, to be updated whenever the design changes.
Idea #3: Debug More than just the Software
The third feature designers need is improved debugging. The definition of a “processor” in modern devices extends beyond the register and instruction sets of the CPU.
These chips incorporate all kinds of extra functions on-chip starting with the obvious communications blocks and standard interfaces, but extending from ubiquitous timers and counters, to analog functions with digital interfaces for software, and sometimes custom logic and switchable routing.
This customization is, after all, usually the reason for co-designing in the first place, and a debugger that only supports the CPU is letting the software developer down badly. We need to be able peak and poke around the hardware to answer questions such as: does it boot, do the clocks start and settle, are peripherals functioning, do the communication blocks generate interrupts, transmit and receive data, and act as good citizens on the internal buses?
If this sounds scary, I am not talking about changing the hardware from the debugger – that would merely represent a role switch between the torturer and victim! I am just asking for a symbolic-based access to peripheral hardware so that I can monitor and control the state changes that impact my application.
The symbolic information must, of course, be generated from the hardware tool, just like the HAL above. With this simple addition, the debugging process becomes both easier and more empowered. It is easier because there is no need for constant documentation checks to find and verify addresses of key registers to view in the debugger.
It is more empowered because it enables more sophisticated debugging. In addition to quickly getting a snapshot of the state of peripheral blocks, it is sometimes possible to control the block from the debugger, allowing scenarios to be played out without having to write code to re-create the situation programmatically.
The typical method for exchanging this information is an XML file, generated by the hardware tool and consumed by the IDE. A great example of this is the ARM CMSIS-SVD (Software Interface Standard – System View Description) standard, which is an XML-based hardware description designed to enable debugger support of highly integrated microcontrollers.
CMSIS is a standard definition of a HAL for ARM Cortex-based microcontrollers that has been adopted by many vendors. The SVD extension is focused on the hardware description – registers, memory, peripherals, etc. – and is a real boon for developers working on programmable systems.
Figure 4: This is a snippet of XML code ( Click here to view larger image). It informs Cypress's PSoC Creator debugger about a register in the CAN implementation. The CAN_CSR_ERR_SR register has a defined address, size and description, plus five fields within the register with defined name, size and access rights.
An important aspect of sharing the hardware definition is the ability to define peripheral registers and, extending that, to provide access privileges for fields within those registers to ensure the debugger treats read/write-modifiable bits carefully.
Hardware gives us clear-on-read bits and zero-to-toggle bits and all kinds of other transistor-sensible, but software-crazy, ways of handling status interfaces. Only a well-defined, machine-generated, definition of the hardware can protect users from time-wasting and unexpected results when debugging registers, or individual bits, in peripheral blocks.
With these sophisticated views into programmable hardware, it becomes possible to do more than simply check status registers and error conditions. For example, if the hardware supports register-controlled switches to enable flexible routing of peripheral I/O to device pins, the software developer can manipulate the internal wiring of the device from the debugger!
This may sound a little scary to some but, if the SVD information is correctly generated, it should be possible to limit the changes allowed to “safe” edits such as multiplexor channel selection on digital signals or switching analog inputs between two physical pins.
When the hardware tools generate debug information for the software developer, there is an opportunity to cut application development time considerably. As if that were not enough, it also offers the invaluable opportunity for early detection of hardware design errors because the software developer is far more likely to recognize unexpected behaviors when confusion and code re-working is not the norm.
A Whole Product for Programmable Devices
These days, the concept of a “whole product” is well understood and widely accepted as an essential element of success. It is no longer sufficient to have the best point tool or the sexiest silicon. The programmable solutions we use today can take many forms. They can be full-custom ASICs, integrating ARM cores and multiple IP blocks into highly specialized solutions.
Or they can be more general-purpose platforms comprising programmable silicon and design tools, such as the FPGA solutions from Altera and Xilinx, or the PSoC devices from Cypress Semiconductor. As different as these environments are, they share an all-too common problem of hindering the application development by failing to efficiently migrate hardware changes into the software domain.
I believe that this failure is rooted in a blinkered approach to the hardware design tools and IDEs used in these projects. While it is fun for a software diehard like me to (jokingly, honest) put all the blame on the hardware tools and engineers, the reality is that both tool sets are too focused on their particular disciplines.
It is rare to see either side add the features I have touched upon because that does not resonate with their customers. I believe that is changing, with products like PSoC Creator supporting device configuration on the programmable hardware and also integrating third-party IDEs, like the Keil µVision IDE from ARM Ltd.
Enabling application development in the engineer’s IDE of choice and empowering that tool with unique and powerful insight and control over the hardware platform is surely the route to more efficient product development and faster time-to-market. And putting a stop to the torture of engineers isn’t a bad thing either!
Mark Saunders is a Senior Product Marketing Manager at Cypress Semiconductor. He has a First Class degree from the University of Leeds, England, and over 20 years of experience in embedded software and intellectual property (soft IP). He specializes in the development, support and marketing of embedded software tools, real-time operating systems, protocol stacks and middleware.