Discover millions of ebooks, audiobooks, and so much more with a free trial

Only $11.99/month after trial. Cancel anytime.

Embedded Expert's Guide to C
Embedded Expert's Guide to C
Embedded Expert's Guide to C
Ebook284 pages3 hours

Embedded Expert's Guide to C

Rating: 0 out of 5 stars

()

Read preview

About this ebook

That popularity means a great many books have been written on how to write C. So you might - quite reasonably - ask if the world really needs another one. The answer: "probably not."


But this isn't another book on how to write C - it's a book on how not to write C. And that's something the world desperately does need, because d

LanguageEnglish
Release dateSep 6, 2023
ISBN9781913579524
Embedded Expert's Guide to C

Related to Embedded Expert's Guide to C

Related ebooks

Programming For You

View More

Related articles

Reviews for Embedded Expert's Guide to C

Rating: 0 out of 5 stars
0 ratings

0 ratings0 reviews

What did you think?

Tap to rate

Review must be at least 10 words

    Book preview

    Embedded Expert's Guide to C - Chris Rose

    9781913579517.png

    Embedded Expert’s

    Guide to C

    Embedded Expert’s

    Guide to C

    The Secrets

    to becoming a

    Reliable Embedded

    C Expert

    Dr Chris Rose

    Copyright ©2023 Dr Chris Rose.

    Published: 2023 Ladey Adey Publications, Ancaster, Lincolnshire UK.

    Dr Chris Rose has asserted his right to be identified as the author of this Work in accordance with the Copyright, Designs and Patents Act 1988.

    ISBN: 978-1-913579-51-7 (Paperback).

    ISBN: 978-1-913579-52-4 (e-publication).

    All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmitted in any form or by any means - for example, electronic, photocopy, recording - without the prior written permission of the publisher. The only exception is brief quotations in printed reviews.

    British Library Cataloguing-in-Publication Data.

    A catalogue record for this book is available from The British Library.

    Cover Design by Abbirose Adey, of Ladey Adey Publications.

    Neither the author nor the publisher can be held responsible for any loss, claim or damage arising out of the use, or misuse of the suggestions made, the failure to take business, financial or legal advice or for any material on third party websites.

    The author and publisher has made every effort to ensure the external websites included in this book are correct and up to date at the time of going to press. The author and publisher are not responsible for the content, quality or continuing accessibility of the sites.

    If you enjoyed this book please leave a review for Chris on Amazon.

    Foreword

    This is the foreword, skipped over by everyone. Dive right into the code! It’s what you are here for after all isn’t it? Come back to it later, in a year or two, if ever. With C the problems are perennial so the comments here will still be the same next year. On the other hand you could read it now. To understand why, here is some context for the book, C and embedded systems.

    You may be asking do we need yet another book on C programming. There are several reasons why we do. However, this not a book about how to write C, there are already far too many of those. It is more a book of how not to write C and that is very important. More about this later.

    The constant thing about C is that C is always changing. The original Kernighan and Ritchie (K&R) first book on C, published in 1978, is less than 1/10th the size of the current C standard and most programmers haven’t read any C standard. (Have you read one?) Some of the constructs in K&R 2nd Edition, 36 years ago (or 45 years for the 1st edition), have changed, often silently, and are still changing. Worse still problems in the C standard are often not being fixed but new things piled on them.

    Therefore, C programmers are working with a constantly changing language that may not behave as it used to or how the programmer expects it to. Then you have the problem that many, most, or possibly all(?) compilers tend not to fully implement the C Standard or restrict parts of it and then add their own extensions. There is very little you can assume about C. I note that for one static analyser they had over 100 different configuration files for C compilers to tweak the checking for the (different) C each compiler used. Hence rigorously defined sub-sets like MISRA C and Barr C that try to highlight problem areas. Like the C standard, for 25 years, MISRA C has also been expanding to keep pace. After nearly three decades of being involved with the ISO C standard, including 5 years as UK Convenor, and also being involved with MISRA C since the mid-1990s: I would say, I don’t know any one person who can claim to know the C Language fully. They know some parts well and others less well. They know enough to know where to look to find out in the standard. Though as mentioned you also need the compiler documentation as well. So, if you meet someone who claims to know C they are going to be deluded. Any real expert I know has more sense to say that without several caveats. I seem to recall Dennis Richie saying there would be no K&R 3rd edition because the language had moved on so far from the one that he had developed that he didn’t know it fully.

    Secondly, most books on C are aimed at people writing apps on a generic OS like Windows or Linux. Programming in C for bare metal or an RTOS system is a very different game. This is where you really need to understand the subtleties of how the language handles the hardware and indeed the pitfalls of the hardware. There may not be…. Well, anything a desktop system would expect. Also as mentioned above there are many variations in C, as the author shows in the following chapters, many are permitted by the C Standard, but many others are compiler extensions. So knowing C is not enough for embedded developers, they also need to know the hardware and how the specific compiler deals with it. It is not just endianness. We all know there is big-endian and small-endian though I have worked on an MCU with three types of endian on the chip! The problem gets bigger with the storage of long and long long, depending on how the hardware works. But you all knew that didn’t you? In the same way you know why you never use printf for debugging.

    So, unlike most learn C books, this book looks at many things that are essential for embedded developers that desktop OS programmers on Windows, Macs and Linux never encounter or, often, they are not even aware of. That said, even desk-top programmers will learn a lot from large parts of this book.

    I have said that this is more a book of how not to write C and that is very important. The author looks at some of the less than obvious pitfalls of C and how to avoid them. This is where it is how not to program in C. Why you should not be doing things that for often subtle reasons probably won’t do what you expect. In K&R or C90/95 it may have worked but not in in the same way in C99. In some cases, urban myths about register, volatile, constant and static that may have been true on a popular compiler or two 30 years ago are simply not true now. Others never were. When you start looking into these things you start to realise why MISRA C and Barr C exist.

    In 2018 I had a meeting with Michael Barr to discuss the new MISRA C and Barr C versions so that they were not incompatible. Michael does a lot of consultancy and his Barr C was born out of seeing the same problems time and time again in development teams. Three decades earlier in 1993-6, when the UK automotive companies were seeing exactly the same problems, they began the work that gave birth to the first MISRA C. This is the same way that CERT C was developed, although with a different result than MISRA and BARR. When I attended a course run by Chris Rose, the author of this book, some of the questions asked by those attending were the same questions that have been asked for the last 30 years, often by people who have been programming for years.

    I was surprised to discover that the first static analyser (the original Lint) was developed by part of the K&R team in 1976 before they finished developing the language because people were misusing legal but dubious constructs. Yes, even K&R over 40 years ago realised programmers were misusing C. That it compiled clean was no guarantee of it being correct or doing what the programmer intended.

    In many ways it is more important to learn how not to write C than how to write C. So many problems are caused by programmers doing things that don’t work as expected. The other very important thing is that whilst this book does highlight these, very many areas (though not all 400 plus that I know of) it does not detail all the problems. Most are way outside the scope of a book like this but it does point you at where to look for answers. The one constant with embedded systems is they are all different, therefore not all the problems will apply to all developments, even if you should be aware of them in principle. Also, as I said, no one person is a complete expert. This is why the author points you at places where there are experts on the specific area rather than explain himself.

    So, in short, learn how not to write C for embedded systems. It will make the C you do write robust and solid. Then the code should even do what you intended and crucially not do anything you didn’t intend.

    Good luck

    Chris Hills

    Phaedrus Systems. Tamworth

    January 2023

    Introduction:

    Yet Another Book on C?

    The C programming language has existed for almost 50 years. The C Programming Language , the book on the language written by Brian Kernighan and Dennis Ritchie – was first published in 1978. Since then, there has been a second edition (which coincided with the first attempt to standardise the language) and countless other books on the topic. So, what possible reason could there be for another one?

    The answer: while many books acknowledge the many shortcomings of C, relatively few are written with the embedded programmer in mind. They are written for those who write software for PCs, servers and other general purpose platforms. This is somewhat surprising since embedded applications is one key area where C continues to dominate; more modern programming languages tend to be preferred in most other contexts.

    In my experience, and that of many others I have spoken to, the modern, general purpose programmer is woefully ill-equipped to program embedded systems. They lack the necessary knowledge of hardware and of how microprocessors really work. During their training, they are sometimes told such untruths as, hardware is easy, software is hard. This book is specifically written with embedded systems in mind.

    The internet has revolutionised the computing and wider software industries. It is now generally accepted by end-users that the software they use will require continuous updates. This allows programmers to become complacent about bugs – coding errors that cause software to misbehave – they can simply be corrected later. Speak to anyone who has ever written safety-critical software and they despair at this attitude. If you cannot immediately see why, ask yourself how comfortable you would be travelling if the aerospace industry had a reputation for releasing regular updates for their control software. Even the word bug is frowned upon by many – it trivialises the devastating consequences the errors can have; the word defects is preferred to emphasise their seriousness. Although not always inappropriate, cycles of repeat updates are often not an option in embedded applications. Assuming a continuous internet connection (or even a connection at all!) is hardly good practice; more importantly, a single defect can cause enormous damage before being detected. The consequences of defective software should be required knowledge for any programmer. Updates would not have helped the victims of Therac-25 or saved the maiden flight of Ariane 5. While the consequences might not always be so serious, there are countless other cases where there is little or no opportunity to correct the defects later.

    The embedded systems you work with may not be safety critical, but there are still many areas where embedded software differs from its general purpose relative. For example, the traditional first task for a computer programmer learning a new language is to display the words, Hello World to the screen. In C, like most languages, this is a simple task once you have discovered the printf function. At least, it is until we consider embedded systems.¹ I often work with hardware that have only numerical displays – or no display at all! It is somewhat meaningless to display words on a non-existent display. Even for embedded systems which do include a display, there is no reason to assume that printf will write anything to it (although, since the function is part of the C Standard Library, it is included with every compliant C compiler.² There are many other examples of standard functions that are likely to exhibit anything other than the expected behaviour when used in embedded software.

    #include

    /* A program to say hello, then exit. */

    int main(void)

    {

    printf(Hello, world. \n);

    return 0;

    }

    Fig I.1 The classic Hello, World program written in C.

    Although no book can make you write perfect, defect-free software every time or teach you everything there is to know about any language, this book will at least highlight the areas where they are most likely to creep in when using the C language. Crucially, it is intended to offer practical advice and guidance rather than be a treatise on programming theory. It will also help you to develop better practices so that your style and attitude to programming is one that inherently favours reliability and safety. Unfortunately, C is a particularly problematic language when it comes to writing reliable, safe software.

    Given the well-documented shortcomings of C, you might question why it has enjoyed such enduring success. The answer is that C is flexible, portable in most cases and compilers are generally able to produce efficient machine code. The widespread availability of C compilers is also a major factor; there is a C compiler for almost every platform currently in use. In embedded applications, the low-level features of C make it particularly suitable. The lack of an extensive run-time environment makes it possible to write stand-alone code which does not require any underlying system to support it – this is also why C has remained popular as a language for developing operating systems. Alternatives do exist: Pascal, C++³ and Ada have all competed with C at some point; more recently, it has been suggested that Google’s Go language may displace C as the preferred systems programming language (personally, I am sceptical, but only time will tell).

    What exactly are embedded systems?

    You may already have your own ideas about what qualifies as an embedded system, but sadly there is no definitive example of what one is. It is simply too broad a category to precisely define. The phrase covers the vast majority of modern digital electronics, from digital alarm clocks to the flight control computers of spacecraft. This includes telecommunications technology, traffic management equipment, computer peripherals, medical devices, and the electronic systems in modern vehicles. I know an embedded system when I see it, and they are everywhere.

    Ask a dozen engineers how they define an embedded system and you will likely receive a dozen different answers based on individual experiences. Some will assure you that embedded systems are small, but this need not be true. Others will assure you that they have little or no means of user control, again, this is only sometimes the case. It is also not true that operating systems are not used with embedded systems – they often are, and many operating systems have been developed for exactly this purpose. There are, however, some common features that will regularly appear in the various definitions you hear. There will likely be some reference to well-defined tasks – embedded systems are typically not intended as general-purpose tools; they have a specific list of functions to perform. Often low-level hardware access is required to interface with the various elements in an embedded system without the convenience of abstraction granted when programming for general-purpose computers. Strict timing requirements and constrained resources are other common features of embedded systems. Handling these constraints requires a different mindset compared to programming a system where memory is in abundance and timing is rarely critical. Finally, embedded systems can be used to handle safety-critical tasks; above all else, this is a very good reason to treat them differently to other systems. The consequences of writing poor software for safety-critical applications are not limited to reputational damage or lost profit: people can lose their lives.

    The range and variety of embedded systems is constantly evolving. In recent years, the Internet of Things has become a common topic of discussion. Most of the things that comprise this novel, loosely defined concept are embedded systems of one form or another. This adds another dimension to the responsibilities of every embedded engineer: that of information security. As data is transported and stored in ever increasing quantities, and much of that data is personal and identifiable, it is crucial that the means by which it is collected and processed is protected, both from deliberate misuse and from negligent disclosure. While the consequences of bad software may not be so immediately severe as those in safety-critical systems, releasing somebody’s credit card details or location is hardly an insignificant mistake.

    Although this may help explain how embedded programming differs from other more general styles, it does not really answer the seemingly simple question posed at the beginning of this section. Unfortunately, the best I can do in that regard is to offer a general, vague definition: An embedded system is a computer which performs dedicated functions as part of a larger system.

    What exactly is C?

    You already know that C is a programming language (if you did not, I would be very surprised that you chose to pick up this book), but that is only a partial description. A more complete explanation would be that C is a general-purpose, procedural programming language – it does not attempt to limit the type of programs that can be written in the language and each program consists of building-blocks known as functions. Every C program has at least one function – almost always called main¹ – but most have more; indeed, too much code in the main function (or any other function) is generally a sign of a poorly written piece of software. From a more practical perspective, before diving into how we use C, it is worth clarifying a few points.

    When we refer to C it may appear as though we are referring to a single programming language. Although this is true to an extent, it is necessary to be aware of that there no fewer than five versions of standardised (ISO) C, not including amendments:

    The most recent of which (at the time of writing) is C18 (the 2018 version).

    You may also come across ANSI C, which was the first attempt at standardisation.

    ANSI C (C89) and

    the first version of ISO C (C90) are, from a practical standpoint, equivalent.

    In addition to

    Enjoying the preview?
    Page 1 of 1