Programming
Words of wisdom... PDF Print E-mail
Written by JLangbridge   
Monday, 30 January 2012 15:19
Brian Kernighan

"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian Kernighan

 

Words of wisdom from one of the best. Very philosophic, very intense.

 

Tim O'Reilly reposted this quote in a Google+ feed. A few comments followed. This quote make sens, but what did he really mean? Does that mean that the average developer cannot debug? Does it mean that you shouldn't try your absolute best? Maybe a mis of the two, with a dash of a few other things here and there. Let's think about it. There are 2 ways of writing code, the easy to read way, and the highly optimized way. I'm an optimization evangelist, but even I don't optimize everything. Coding can be like writing a book, and the story unfolds itself as time goes by. When I starded, I might have wanted to do something specific, but that all changes as I encounter unforeseen details, or when I run into problems. I don't start optimizing everything, and indeed, I never optimize the first time round. I want something I can read easily, or that someone else can read easily. I have no guarantee that I will still be working on a particular project, and that someone will not be in my place, continuing my code. Part of being a software consultant is knowing that I won't be doing absolutely everything. Sooner or later, my code will be in someone else's hands. That person has to be able to debug what I do. In order for him to be able to debug it, my work has to be simple. Yet another quote:

Any fool can write code that a computer can understand.  Good programmers write code that humans can understand.  ~Martin Fowler

When training non-IT people about what developers do, I often play a little game, putting myself in the place of a robot. I will follow their instructions, to the letter, no more, no less. We have had some fun doing simple things like et a glass of water, or pick up a folder and put it on the table. Learning to speak to a computer isn't all that easy, it does take some getting used to. Talking to a computer so that someone else can easily understand takes some time, and effort. As they say on the bottle of shampoo, lather, rinse, repeat. Sooner or later, you run out of shampoo.

All this sums up my favorite quote:

[A]nd then it occurred to me that a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things.  They are, in short, a perfect match.  ~Bill Bryson


Last Updated on Monday, 30 January 2012 15:40
 
The wonderful world of Zend... PDF Print E-mail
Written by JLangbridge   
Friday, 06 January 2012 09:46
A few years ago, I was the head of my own company, making light CMS systems for small businesses here in France. Heavy PHP work, not using any framework of any sort, just creating everything I needed. I figured that nothing existed that was exactly what I needed, so I just built everything from scratch. When a friend asked me for a hand with a web site, I started looking into frameworks. There was Symfony, which I liked, and Zend that my boss has been keeping on at for some time now. I looked into the 2 frameworks, and tried an alpha run with both. I liked Symfony, but "unfortunately" I started with the newer version, Symfony 2, and the deployment onto a production server was a little chaotic. That has probably changed by now, but with the deadline that I had, I just couldn't use it. I will, however, look into it again in the future. Zend, however, I stuck with. I managed to whip up a site in no time, and it is up and running with pretty good performance. Felt good to dive back into PHP, but the last time I did anything, it was in PHP4, this time I got to play with PHP5. Yet another thing on my to do list, explore PHP a little more!
 
Goodbye DMR PDF Print E-mail
Written by JLangbridge   
Friday, 14 October 2011 14:51

Dennis RitchieThe news is full of the same thing; we lost Steve Jobs, ex-head of Apple, and quite a guy. Now yes, it is a shame when anyone dies of cancer, and yes, Steve jobs has done a lot, I am not saying the opposite. However, as far as I am concerned, Apple was and always will be Steve Wozniak. Posts have been made on Google+ and Facebook, and one of the polls was "How has Steve Jobs changed your life?". Well, to be perectly honest, he hasn't really. He has a bit, of course, but indirectly.

However, something that went passed completely unnoticed, and I only found out about it from a post on Google+, two days later, was the death of Dennis MacAllister Ritchie, the inventor of C, and co-author of the best C programming book I have ever read. There is little to say of the man; he was a genius, and was extremely humble. He revolutioned the computer industry with a "simple" idea, and nwas never one to boast about what he had accomplished.

This is someone who really has changed the way I work every day; mainly because my work evolves so much around Unix and C.


UNIX is basically a simple operating system, but you have to be a genius to understand the simplicity. --Dennis Ritchie

 
Autopsy PDF Print E-mail
Written by JLangbridge   
Monday, 08 November 2010 10:17
The patient arrived on my desk, and I had to perform an autopsy. I had to know the reason of death, what happened, and exactly how it was possible. What went wrong? How could this have happened? And what could I suggest that would make things safer. I looked at the "client" with a sense of sadness. Far too young to die. Hardly even a month old. The embedded system lay dead on my desk.

I took my time. Everyone wanted to know what happened, but they were told, politely, but firmly, to go away. I had things to do, and they would take time. Everyone would be informed when it was over, but in the mean time, I needed to be alone. As far as embedded systems go, this one was big. From the exterior, a metal box. A screen on one end, and connections on the other. I spent my time looking at every angle, every curve and every little imperfection. I was looking for traces; did it fall? Did something hit it? Was there an electrical discharge? Nothing visible. Whatever happened, it wasn't external.

I cleared my desk. I made sure that every screw, every jumper and every cable was far, far away. I had space all around. I needed to perform an autopsy, and open it up. Almost like a surgeon, my tools were lined up, ready for use. Little dishes were available, to place the organs and other parts I needed to cut away. I selected a torx screwdriver, and looked at the first screw. The paint was still on, no signs of tampering; no-one had taken it apart. The first screw came loose with a little force. It had been assembled correctly. One down, 11 other screws to go. A few minutes later, all the screws were removed, and placed in a little dish.

I placed a screwdriver delicately under the plate and turned. It opened up just a bit. I finally cut my client open. I removed the plate, inspecting it as I went. The cuts were clean and no metal scraps or shards were on the plate. It was well cut and well prepared. That was my first suspicion; I've seen too many systems die because of small or microscopic metal fragments dropping onto the circuitry. It was doubtful that anything fell into the machine, creating a short circuit. The root cause had to be something else. I put the plate down on the desk, and grabbed the torch.

I took my time to look at every component, starting from the power supply. There were no visible effects; no burnt surfaces, no marks on the epoxy suggesting intense heat, and all the solder points looked well done. This board was done professionally; the solder was done in a machine, not by hand. Only one component was done by hand, the tool connector, with a total of 15 solder points, but they were all done correctly. If a component had failed, it had done so silently.

I must have spent about 40 minutes looking at every single component, every connector, every solder joint, looking for any signs, but I couldn't find one. It was time to try a more direct approach. I plugged in the mains, and, carefully, turned it on. It didn't blow up. The screen back light came on, and the power light, but that was it. Looking at the schematics confirmed what I thought; both the backlight and the power light were controlled directly from the power supply, not from the CPU. The power looked good, but no activity from the CPU. I connected the oscilloscope and had a look at the debug connections .The clocks looked good, power levels were well within their tolerances, but the bus was silent. No activity anywhere. Time to dig deeper.

I plugged in a JTAG debugger on the debug port, and tried to connect. The auto-diagnostics took a second or two, and the interface came up. Connected. Awaiting order. Ok, so the CPU looks good. Run. Frozen. Ok, something must be wrong in the flash. The only problem is, if the system cannot start (if the memory is corrupted or any other problem), then the boot-loader is supposed to come up. Maybe the flash circuit is dead? Let's dump it out into a file. The debugger started to flash, and a few seconds later, the contents of the AMD 29F800B were on file. No problems there, apparently the CPU managed to read everything in. Strange. If the flash worked, the boot-loader was supposed to kick in, why didn't it? Hex editor, vector tables. Zero. Hang on... The first 64k of the flash were zeroed out, all the rest had data. This shouldn't be. I had my theory, but I needed to test it. On the shelf was another embedded system, identical to the one being taken apart, except for the "R&D" sticker. I booted it up into maintenance mode, and ran an internal program that can erase and re-flash the boot-loader. I erased it and crashed the system whilst loading the new boot-loader. The system remained on, the lights flickering, holding on. Then it went silent. I restarted it, and there it was. Silent. Exactly the same behaviour. Plugging in the JTAG debugger confirmed it; the first 64k of the flash were zeroed.

It was murder. Cluedo. The professor, in the lab, with the flash tool. I now knew how it died. But was it really dead? If I could talk to the CPU via JTAG, then I could surely re-flash the beginning of the flash chip. I rooted around to find an entire distribution; boot-loader, stage 1, system, libraries and data. I re-flashed the entire chip on the victim, whilst remembering to do the same on the R&D test victim. Afterwards, I unplugged the debugger, and the system rebooted. Everything was silent for what seemed to be a dozen seconds, but in reality it must have been more like a single second. Then it flickered, and a version number appeared on the screen. A second later, the entire system booted up. Just like in 2010, there was the same emotion, where Doctor Chandra reconnects HAL, and HAL says "Good morning Doctor Chandra, this is HAL. I'm ready for my first lesson". The system was alive. It was brand new, and had no memories at all. It didn't know what happened to it, and it had no recollection of its death, or any detail before then. It had no idea it was in a factory, and that it was doing an important job. For all it knew, it had just been reborn. It went off to intensive care, where it would be put through all the hardships of a new system; test cycles, wear and tear, and the usual burn-in, to make sure that everything was OK.

Time to file my report, and let everyone know what had really happened. How did a technician manage to get hold of an application to erase the boot sector? That wasn't my problem, someone else would do that. My job ended here, but I still needed to revive the R&D machine...
 
Agile - More than one year afterwards PDF Print E-mail
Written by JLangbridge   
Tuesday, 09 February 2010 09:26

When you move rapidly from one project to another, you need to adapt, fast. Some clients take the time to create a project, laying out every detail before acting. Others simply do not have the time to prepare, and set out the foundations while working on the project, even if that means doing some of the work twice and seeing some of that work deleted. Some clients literally cannot wait.

Agile is one of the methodologies that I've used, and it was also one that I really liked. I have a tendency to read about everything I can on a subject before deciding what I really think of it. I don't rush in head first, only to find myself in the middle of a mess I really don't like. I take my time to study and think (which doesn't necessarily stop me from finding myself in the middle of a mess). Agile was one of the subjects that I came to learn, and one that I liked from the beginning.

My first experience with Agile was with Ripple Motion, and right from the beginning I had my doubts. The idea of post its everywhere was a little strange, but the visualization that it offered was compelling. I followed in their tracks, but I also read around on my own side. And slowly, I started to find out little details that just didn't sound right. Ripple Motion self-proclaimed themselves as "leaders" in the Agile community, even of they were just two people, running very small software projects. Applications that geolocalize you, or applications that give you "love tips" do not count as major projects. After a few weeks, I noticed that they were using the principles to their own advantage, and to my disadvantage. They were breaking simple rules, and ones that I could quote from a book. It became a situation where I had to apply to the rules, but the direction were free to stray from the tracks. Of course, in any company, the direction is free to do as they please, but not as far as methodology is concerned. Agile was used to point fingers at people, and one principle that should never be used, show who is "slow" and who isn't being part of the team. There were charts showing exactly who did what, personalizing each member of the team where it was supposed to show only what the team did. Members were frightened more than anything else. Scrum allows us to highlight potential problems before they arise, so that we can adapt. If someone is having problems with a particular aspect of the code, he is free to say so, and others around him know that he has a problem, and can offer help, advice or resources. With Ripple Motion, that was clearly used to point fingers at people and blame them for everything that went wrong. Ultimately, my contract at Ripple Motion was terminated for that; while it is written Java on my CV, it is not my strong point, and when I took a long time on a Java ticket, I was accused of not seeing Agile advantages, and I was laid off.

I've learned one thing -  anything that is good can be made bad by evangelists. It was hard enough having Mac evangelists that consider it to be a question of life and death to show that Macs are better than any other machine for everything, but evangelizing a methodology is even worse. From time to time I really considered myself to be in a church, and was openly asked to "preach" their cause outside of work.

Gwaredd Mountain said it right in his blog - "The hype and dogma of Agile evangelists has left in its wake a trail of broken projects, ruined businesses and misguided neophytes bleating the tired doctrines of their long departed prophets."

After this experience, I'll admit that I was a little lost. A tool that is used to help and guide people was used against me, and it cost me my job. The advantage is I didn't need to print a resignation letter, they did it for me, and the next day I had something else. That something else was BlueKanGo, a company that makes SAS applications. They use Agile, they use Scrum. They saw that I use to, but they also noticed that I was a little confused, so they sent me off for some training, some real training, in the form of Laurent Morisseau, a consultant in Rennes that does Agile training. I finally had the answers to my questions, and I returned confident, knowing that I was right. Then I saw Agile applied for a team of up to 20 developers (in 2 teams), on a project that had close to 3 million lines of code. There were no evangelists, only people sincerely interested in the project and the team. Everything that was done was done to show what the team had accomplished. Some developers were better than others, some of them were slower, it didn't matter. Everyone was doing the best he could to get the project done. People have their good days and their bad days, and people do make mistakes. When a mistake was made, and found, it was corrected. No fingers pointed, no accusations made. If someone said that they had a problem, they were guaranteed to have a helping hand within the hour. Now this is what Agile is all about. The development team were transparent, and had confidence in their leaders, and spoke to them in terms they could understand. In exchange, the leaders trusted their developers, and gave them the ressources necessary to complete their task.

Today I am no longer using Agile, but only because the current client  doesn't use it. If the opportunity comes up again, I wouldn't say no, so long as I'm working with professionals.

 

Last Updated on Tuesday, 09 February 2010 10:17
 
ARM C optimizations PDF Print E-mail
Written by JLangbridge   
Wednesday, 07 October 2009 07:56

Whilst most of the time, you can get away with just about anything on a desktop or server system, embedded systems programming is sometimes thought of as an art. Optimized might take longer, but there are huge benefits to writing highly optimized code; the system might cost less because you don't need a high end processor, or you might get a strategic advantage because your systems runs longer on the same charge.

 

Timed speedups

 

The best way to show what optimizing can do is to have a simple example. Here is a very simple example. After each change, I recompiled the code to see the size and also the time it took to run the code.

Everything around me is calculated in giga-hertz; the 2 PCs at my desk, the netbook I bring to work, my home PC... The development board infront of me is running at 400MHz. Embedded systems cannot scale like PCs; their processing power is limited, you have to be careful. There are a few tricks you can follow, that can drastically speed up the system. It was also time for me to see all the bad habits I had picked up whilst doing development for x86 and x86_64 platforms.

Let's start off with a basic routine, a simple loop:

 

void loopit(void) 
{ 
   u16 i; //Internal variable 
 iGlobal = 0; //Global variable 
 
 //16 bit index incrementation 
 for (i = 0; i < 16: i++) 
 { 
 iGlobal++; 
 } 
}

 

This is extremely simple; it loops 16 times, each time incrementing a global variable. Compiled, transferred, run. The application code comes in at 24 bytes, and on the dev platform, it runs in 138µs. Most people would think that is great, but embedded engineers go pale with this. There is nothing strictly wrong with the code, it is perfectly good C code, but there are things you can do. ARM systems, and indeed a lot of systems, actually do better when they count down to zero. The reason is simple; every time you make a calculation, the processor automatically compares it to zero, and sets a processor flag. On this platform, the bit in question is Z in the CPSR register. At the end of each loop, we compare i to an integer. If we decreased to zero, we could add a jump condition if Z is true, saving cycles. So, let's make a quick change, and count down to zero:

 

void loopit(void) 
{
 u16 i; //Internal variable
 
 //16 bit index decrementation
 
 for (i = 16; i != 0: i--)
 {
 iGlobal++;
 }
}


The size of the code remains unchanged, we are still at 24 bytes, but the execution time is faster; 124µs. That is a bit of a speed gain, but there is still a lot we can do. The code here uses a variable that is 16-bits long, presumably to save space. Our loop will only loop 16 times, so why bother having a 32-bit variable? 16 should do. Actually, it does, but it isn't a good idea. This particular ARM core is 32-bit native, and using 16-bit values takes up valuable processor power, since the processor has to convert a 16-bit variable to 32-bit, work with it, then re-transform it to 16 bits. Working with the native size can help. So let's turn that into a 32-bit variable:

void loopit(void)
{
 u32 i; //Internal variable
 iGlobal = 0; //Global variable
 
 //32 bit index decrementation
 for (i = 16; i != 0: i--)
 {
 iGlobal++;
 }
}


We haven't done a lot here; all we have dones is to declare a new variable and use that for the loop instead. Once again, there is no size change; there are new codes for accessing a register, but we don"t have the codes to access RAM. The fact that our variable is now in a register is a considerable speed boost; our execution time os now down to 52µs. But we can still do better... The loop creates a lot of overhead, and if possible, unrolling a loop can help:
 

void loopit(void)
{
 u32 i; //Internal variable
 u32 j;
 iGlobal = 0; //Global variable
 
 //32 bit index decrementation
 for (i = 4; i != 0: i--)
 {
 j++; j++; j++; j++;
 }
 iGlobal = j; //Copy the local variable's value to the global variable
} 


The Art of optimizing

Art, with a capital A. Optimizing isn't that simple, it takes time and effort to have something that is truly optimized. From experience, it is difficult to have code that is truly optimized when you are pushed to the limits by deadlines, but careful planning and solid foundations are the key. The very first thing to do is to read the technical specifications of the processor you are going to use, all your code needs to be written specifically for this system. Generic ANSI C code can be ported to almost everything, but that doesn't mean that it is going to work well on this platform. Learn the strengths of the CPU, and use them. Learn the weakness of the CPU, and avoid them. In this example I'm using an ARM, and they are exceptionally good in low-power embedded systems. Most of my ARM development has been done with mobile phones, where battery life is crucial. We couldn't have done it with anything else. Their weak point is division, avoid where possible. More on that later.

 

Choose wisely

Most engineers will not start off with highly optimized code, but just good code. Indeed, I advise you not to start off optimizing everything, just write clever code. Later on, you'll get to choose. Optimization comes at a cost, and it takes much longer to create optimized code than just good code. It might take you two hours to create that routine that will scan the memory looking for some data to work on, but optimizing it could take days. Write the program first, then profile your application and see where optimization is needed. Optimizing a large routine that is called just once might not be as critical as optimizing a small routine that is called hundreds of times. Shaving off 50 milliseconds from boot time might not be as important as saving a few microseconds during an interrupt. Know when to optimize, and when to say that your code is just "good enough".

 

General rules

 There are a few rules to follow concerning C development on ARM, and this applies to almost any processor out there.

Integers

Integers are a vital part of any development. Processors were designed to handle integers, not floating point or any other type of numeral. Most integer operations can be done in just a few cycles, with one notable exception that we will go into later on. Generally, always use integers that are the same width as the system bus, this will avoid unwanted calculations later on. While an u16 might be all you need to hold in the data, if the variable is heavily used on a 32-bit system, making it a u32 will speed things up. When reading in a u16, the processor will invariably read in a u32, then do some operations to transform it into a u16, which costs cycles. Also, if you know that your variable will only handle positive numbers, make it unsigned. Most processors can handle unsigned integer arithmetic considerably faster than signed (this is also good practice, and helps make for self-documenting code). Always try to make your code use integers. If you need 2 decimal places, multiply your figures by 100 instead of using floating point.

Division
This is the Achilles heel of the ARM processor. General rule: if you can avoid dividing, avoid it. ARMs cannot natively devide, they rely on external libraries for this. A 32-bit division can take up to (and in some cases more than) 120 cycles. Sometimes you can get away with multiplying instead of dividing, especially when comparing. (a / b) > c can sometimes be rewritten as a > ( c * b ).
Division by 2

There is an exception to the division rule, dividing by 2. This, technically, isn't a division, and the compiler will not do the same thing. The compiler ends up doing a shift, which costs considerably less in terms of cycles. This applies to powers of 2; dividing by 2, 4, 8, 16, 32, etc., will simply shift the contents of a register.

Last Updated on Thursday, 13 September 2012 11:04
 
Hello, World! PDF Print E-mail
Written by JLangbridge   
Sunday, 21 June 2009 21:02

hello world"Hello World!" is a simple computer program, typically the simplest possible, that prints "Hello World!" to a display device. It is often used as a way of learning a computer language, and can also be used on embedded systems as a way of verifying that a platform works. In some cases, the text can be replaced by other output possibilities; a flashing LED light or a few beeps. On the hx4700, "Hello World!" on the screen meant that we had a working kernel, and that the essential code was in place, allowing us to program the machine, and have a means of reading the output. From here, things were looking good! I've also used it extensively when using new frameworks or programming languages. When "Hello World!" was printed on the screen, it was time to forget about research, and do some development.

I can't remember the amount of programming languages I've used, or at least tried to play about with. I started like most geeks, by fiddling about with BASIC. My first attempts were on an Apple IIe, then on the ZX80/ZX81 family. From there, I made a "strange" choice for some, I bought a copy of DevPac, an IDE for 680x0 assembly development. Assembly on the 68k was fun (especially when compared to x86 assembly), but I still went for AMOS. There is a game, there, somewhere on Internet, signed by me. If anyone finds a copy of Kitten Curse, let me know. If was a really basic game, made for the Amiga, and released into Public Domain. Somewhere around 1992. Anyway.

When I arrived on the x86 platform, I tried assembly language, but the x86 is a nightmare, or more precisely, I wasn't used to the x86 platform and the lack of an IDE that looked like DevPac. I had fun with BASIC shipped with MS-DOS. They day Windows 95 came out, I switched to Linux. I had played around with it before, but that was the day I went Linux full-time. In march 1999, GNOME was released, and I started with C, using the GTK toolkit. From there, C++ was a logical step, but I've played about with a few others. Python, Java and Objective C to name a few. Today I'm mainly using Java, but I'll switch to C and Python as soon as I can. I have an application to maintain in C, and that is my joy at work right now.

Today I decided to start a little collection of "Hello World!"s, in different languages, using different toolkits. A quick reminder of my roots, and a little bit of fun. If you have any, don't hesitate to send me an email, or to contact me!

Last Updated on Thursday, 13 August 2009 10:14
 
<< Start < Prev 1 2 Next > End >>

Page 1 of 2