Friday 23 September 2011

HLD – High Level Design



A high-level design provides an overview of a solution, platform, system, product, service, or process. Such an overview is important in a multi-project development to make sure that each supporting component design will be compatible with its neighboring designs and with the big picture.

The highest level solution design should briefly describe all platforms, systems, products, services and processes that it depends upon and include any important changes that need to be made to them.

A high-level design document will usually include a high-level architecture diagram depicting the components, interfaces and networks that need to be further specified or developed. The document may also depict or otherwise refer to work flows and/or data flows between component systems.

In addition, there should be brief consideration of all significant commercial, legal, environmental, security, safety and technical risks, issues and assumptions. The idea is to mention every work area briefly, clearly delegating the ownership of more detailed design activity whilst also encouraging effective collaboration between the various project teams.

Today, most high-level designs require contributions from a number of experts, representing many distinct professional disciplines. Finally, every type of end-user should be identified in the high-level design and each contributing design should give due consideration to customer experience

High Level Design (HLD) is the overall system design - covering the system architecture and database design. It describes the relation between various modules and functions of the system. Data flow, flow charts and data structures are covered under HLD.

Low Level Design (LLD) is like detailing the HLD. It defines the actual logic for each and every component of the system. Class diagrams with all the methods and relation between classes comes under LLD. Programs specs are covered under LLD.

 
High Level Software Design

High level software design, also called software architecture is the first step to analyze and consider all requirements for a software and attempt to define a structure which is able to fulfill them. For this also the non-functional requirements have to be considered, such as scalability, portability and maintainability. This first design step has to be more or less independent of a programming language. This is not always 100% possible, but a good high level design can be further refined into a low level design, which then describes the implementation in any desired programming language.

The Architecture

The first step in designing software is to define the architecture. Simply speaking this is a very high level outline of the components and layers of software. There may be some requirements which explicitly ask for some of the below named features, but even if there are no explicit requirements it is a good design style to adhere to these principles:

Design layers which at least make the functional part of the software independent of a hardware platform. Any specialties which have to be covered when running on a certain platform have to be in a special hardware abstraction layer.
  •  Design an adaptation layer to adapt to a special operating system (if necessary). Operating systems may offer services and semaphores, but never use them directly in your functional software. Define your own services and semaphores and go through an adaptation layer to adapt them to the operating system 
  • Design any additional layers inside your functional software as appropriate.
  • Design components inside your functional software. Depending on your requirements and future strategies it may be wise to e.g. design communication protocol components in a way that they can be easily removed and replaced by another protocol, to adapt to different platforms and systems. E.g. in the automotive industry the CAN bus is widely used for communication between the various electronic systems in a vehicle. However some customers require different proprietary protocols. Your software can be designed in a way to modify the protocols easily. Almost as easy as "plug and play", if the design is done properly.
  • Design an own framework which controls the calls and interactions of your functional software.
  • Design an own framework which controls the calls and interactions of your functional software.

Of course this was only a very rough outline of how architecture may look like and what we found to be the best way for many applications. However, your own system may require some additional features of the architecture. 

Object Orientation

Object orientation is nowadays usually associated with certain design methods like UML and programming languages like C++ or Java. However the principles of object orientation were developed long before these methods and programming languages were invented. The first steps of object oriented design were done by using C. And indeed object orientation is a principle of design rather than a tool or method based feature. Some of these principles are:
  •   Orientation of program components at the real physical world. This means that the division of a software package is done according to the real outside world of a system and according to main internal tasks of such a system.
  • Combining of all elements of software (i.e. data, definitions and procedures) into an object. This means that everything that is needed to handle an element of the system is grouped and contained in one object
  • Access to the object's data and functions via a clearly defined narrow interface and encapsulation of elements which are not required for the outside world to be hidden in the object.


Interfaces

The design of your interfaces is another element which adds to the stability, portability and maintainability of your software. The following things have to be observed:
  1. Only use function calls as interfaces and refrain from using memory pools or any other globally shared elements as interface.
  2. Make your interfaces as narrow as possible. I.e. use simple basic data types rather than complicated proprietary structures at the interfaces. It is sometimes amazing how simple interfaces can be if the functionality is distributed in a sensible way in appropriate components.
  3. Preferably make your interfaces uni-directional. This means that higher level components acquire data from lower level components and layers. Try to avoid bidirectional interaction between the same components.
  4. Describe your interfaces clearly. Even at a high level design the kind of information, the data width, resolution and sign has to be determined. This can be done on an abstract level i.e. there is no need to define them in terms of data types of a special programming language.
More details will be given in the description of low level design related to the programming language C.

Operating Systems and Timing

Basically there are two categories of microcontroller systems. The first one is EVENT driven, as e.g. cell phones and other modern communication equipment.

The other kind of application is TIME driven. These microcontroller systems usually have the task to measure and evaluate signals and react on this information accordingly. This measuring activity means that signal sampling has to be performed. Additionally there may be activities like feedback current controls which have to be performed. Both activities imply by the underlying theories that sample frequencies have to be as exact as possible.

Both categories of systems are called REALTIME SYSTEMS, but they are like two different worlds!

         The EVENT driven systems are comparatively simple. The are usually in an idle state until one of the defined events triggers a task or process, which is executed sequentially until it is finished and the system returns to the idle state. During the execution of such a task these systems usually do not react on other events. This "first comes first serves" principle e.g. can be seen in a cell phone, where incoming calls are ignored after you started to dial an outgoing call.

          TIME driven systems are much more complicated. Usually all possible inputs to the system have to be sampled and all outputs have to be served virtually simultaneously. This means that time slices have to be granted to the various activities and their duration has to be defined and limited to ensure the overall function of the system. It would be too much to go into more details here. However there are some general rules which should be considered:

The CPU selection should be made according to the application. There are some CPUs which support time driven application in an optimized way. E.g. it is recommendable to have sufficient interrupt levels, CAPCOM units and I/O ports which can be accessed without delays for time driven applications. It is sad to see that in recent years some well known microcontrollers which originate in the event driven world were pushed into the time driven market. The ease of development and stability of the systems suffer from this. Although the attempt was made by the CPU manufacturer to cover for that by designing suitable peripheral units, the whole situation still looks like an odd patchwork rather than a sound design.Operating systems can be event driven and non-preemptive for EVENT driven applications.Operating systems should be time driven and preemptive for TIME driven systems.Standard operating systems may fail you for high speed tasks, such as 250 us tasks for feedback current controls. In this case you have to do this by tricks and timer interrupts outside of the operating system. Therefore have a close look at the OS from the shelf before you base your system on it.

A Word about Modern Design Methods and Tools

Most of our ideas concerning high level design were outlined above. To some this may look outdated, because there are so many design tools around which promise to make life easy. However there are a few things we want to point out concerning modern high level design methods and tools.

           There would be a lot to say about modern design methods, such as UML, SDL and others. But there are a lot of good web-sites which specialized on this. Tools are available which allow high level design in one of these methods and even make an automatic code generation. Praises are sung that these 4th level "programming languages" will be the future way of designing software and leave the skill of coding to an automatic code export triggered by a simple hit on a button. There are certainly applications where this makes sense and where this is a sensible way to go, as e.g. the use of such a tool (SCADE) for the programs in nuclear power plants. But does this also make sense for high volume microcontroller applications? There are a few stumbling blocks for this which may not be cleared away so easily in near future:

Autocoders still generate a big overhead in resource consumption (RAM/ROM/Runtime) which can not be optimized.

Autocoders usually generate highly cryptical code which thus fails to be subject to any further human inspection or test. This means that all testing that can be done on a low level has to be done by the respective design tool. Some tools support this (SCADE and SDT) where the demand for an "executable specification" is met and thus a sufficient testing is possible. But this also means that a decision for such a method is at the same time a decision for higher resource consumption and a decision to have no mixed design, i.e. all the code has to come out of the tool otherwise it fails to be testable.

For safety critical applications the tool and auto coder has to be certifiable. I.e. it has to be subject to checks by organizations such as the TÜV. A shoe which is too big for many modern tools, but a step which is necessary to lift a toy to the status of a real tool.

So far none of the well known design methods and associated tools is able to consider the timing aspect in microcontroller systems in a satisfying way. Interrupt service routines, and especially preemptive operating system tasks in microcontroller systems are not supported in these methods and tools. But they are one of the most important aspects of design for microcontrollers.

Some of these design methods and tools may be justified in appropriate environments, but the conclusion and our recommendation for high volume microcontroller systems is:

Use design methods and associated tools for rapid prototyping. This may be a big advantage to develop functions, but do not try to bring this tool output into series production for high volume microcontroller systems. You will hopelessly fail.

Use design methods to specify and describe complex functionality even for a microcontroller system. This may make the way of design easier, it uses a syntax which can be trained and understood by others, but be prepared to have a deliberate break in the tool chain where you set up a proper low level design and coding.

Do not attempt to use such a design tool to design your interrupts and operating system tasks. Although some tools recently offer the inclusion of a standard microcontroller operating system, this usually does not allow preemptive tasks and does not support interrupt service routines.
   

No comments:

Post a Comment