xc8: see xc8

The project with my “beloved” Pic18 is nearly over, the one I’m starting is based on a Freescale ARM with enough horse-power to run a modest desktop. Nonetheless an interface (to the proprietary field bus) is still. . . You guessed, a glorious PIC 18. This is one of the reasons I keeping an eye on the Microchip tools strategy for these chips. The other one is that the nearly over project is likely to be maintained in the coming years to implement small changes and requests from the customer. So, what happened in their yard since the last time I wrote?
First, mplab has been driven into retirement and replaced by a customization of Netbeans, named Mplab X. This I consider a good move since I much prefer this IDE over the sadly ubiquitous Eclipse. The reason is long to tell and may be partly invalidated by the latest progress, but that’s enough matter for another post.
Mplab X is still young and that may be the reason for some clumsiness in migration from Mplab 8.
The other strategic move that Microchip is doing is the unification of the two families of compiler. Microchip had the low cost, under-performing mcc18, then re-branded as mplabc18, and the acquired, high cost, high performance HTC.
Microchip decided to dump mplabc18 and to add some compatibility into the HTC so that mplabc18 code could be smoothly recompiled. This new version has been called xc.
Given what I witnessed using mplabc18 for over 3 years, I thought this had to be a good idea.
Then I took a look at the xc8 manual and I discovered that the compiler is not capable of generating re-entrant code. Despite of this Microchip claims that xc is ANSI (89) compliant. I could rant on the fact that c89 is no longer the c standard at least since 12 years ago, but I will concentrate on re-entrant code (or lack of thereof).
A function is re-entrant when it is computed correctly even if it is called one or more times before returning.
The first case is the recursive algorithm. Many algorithms on trees are formulated quite intuitively in a recursive form. Also expression parsing is inherently recursive.
Do you need recursion on a PIC18? May be not, also because – as you may remember – the little devil has a hardware call stack of only 31 entries.
Is there any other case you need re-entrancy? Yes pre-emptive multi-tasking – a task executing a function may be pre-empted and another task be switched in, if you are unlucky enough then it may be entering the same function (in multiprogramming unluckiness is the norm).
You may correctly object that multitasking on an 8 bit is overkilling. I agree, even if I don’t like to give up options before starting to analyze the project requirements.
Anyway there is a form of multitasking you can hardly escape even on 8bits – interrupts.
Interrupts occur every time the hardware feels it right to do so, or – more precisely – asynchronously. And it is perfectly legal and even desirable to have some library code shared between the interrupt and non-interrupt contexts.
When I pointed this, Microchip technical support answered that this case is solved through a technique they call “function duplication” (see section 5.9.5 in the compiler manual). In fact if you don’t use a stack for passing parameters to a function you may use an activation record (i.e. the parameters and the space for return value) in a fixed position of the static ram. Of course this causes your code not to be re-entrant (that’s why you usually want a stack). But you can simply provide a two levels re-entrancy by duplicating the activation record and the right one according to the context you run in.
Note that you don’t duplicate the code, just the activation records.
Neat trick, at least until you realize that a) PIC18 has two interrupts levels, so you would need three copies of activation records and b) this is going to take a lot of space.
In this sense the call stack is quite efficient because it keeps only what is needed in the current execution point. You will not find, in the stack, anything that does not belong to the dynamic chain of function invocations. Instead, if you pre-allocate activation records and local variables you need that space always.
Well this may not be completely true since the compiler can actually perform convoluted static analysis and discover which functions are mutually exclusive. Say that function a() calls first b() and then c() and that b() and c() are never called elsewhere and that their address is never taken. In this case you may reuse the same memory space for activation records and locals first to host b() stuff and the to host c() stuff.
Note that this kind of analysis is very delicate and sometimes not even possible. In fact you may have function pointers, but you may also have assembly code calling at fixed address. So I don’t think this kind of optimization can be very effective, but I would need to run some tests to support my claim.
Let’s get back to my firmwares. The most complex one counts about 1000 functions. Nearly 700 of them require one or more parameters.
Almost every one of them use local variables.
Even if we count 1 byte per function (and I am underestimating) we are talking of 2k on a micro that has 3.5k of ram.
Yes, I have to admit that the static approach is very fast because addressing is fixed. In any point you know the address of the variable at compile time. You don’t have to walk the stack and direct access is fast.
Anyway what I wrote is enough to demonstrate that it is not possible to port trivially a complex code from mplabc18 to xc8.
A last case when you need re-entrancy is when you have several function wrappers that accepts function pointers. If the wrapped code calls another code that uses the same wrapper you are again in the need for re-entrancy.

All Inclusive

“And for this promotion it’s 9€ per months, are you already a client? “Well, yes indeed, it’s maybe 15 years I am still client to the same mobile phone provider.”
“So, it’s 19€ to activate”
Gosh, no one mentioned that in the commercial aired on TVs… What if I would not have been a client?
“Then it would have been free”

Actually it seems it is worth to periodically change provider.

Ugly Code

Unfortunately I’m a sort of purist when it comes to coding. Code that is not properly indented, global and local scopes garbled up, obscure naming, counter-intuitive interfaces… all conjures against my ability to read a source and causes headache, acid stomach and buboes.”Unfortunately” I wrote, meaning that’s most unfortunate for the poor souls that have to work with me to whom I should appear as sort of source code taliban.
Recently my unholy-code-alarm triggered when a colleague – trying unsuccessfully to compile an application produced by a contractor – asked me for advices.
More and more I delved into the code, more and more my programmer survival instinct screamed. The code was supposedly C++ and the problem was related to a class, that I would call – to save privacy and dignity of the unknown author – SepticTank. This class interface was defined inside a .cpp and then again in a .h. Many methods were inlined by implementing them in the class interface (and this possibly was part of the problem).
After resolving some differences, the code refused to link because there was a third implementation of the SepticTank destructor in a linked library. I claimed that such code couldn’t possibly work (even after disabling the dreaded precompiled headers – never seen a Visual Studio project working fine with precompiled headers), even if we could manage to get it compiled and linked the mess was so widespread that nothing good could came.
My colleague tried to save the day removing the implementation of the SepticTank destructor so to leave the implementation found in the linked library.
At the end he had to give up because the code was broken beyond repair and even if it compiled and linked it crashes on launch (not really surprising).

What stroke me most basically because it caused a slight fit of dizziness, was the sight of the mysterious operator below –

My brain had some hard moments trying to decode signals from eyes. Then it figured out that the coder was redefining the implicit conversion to class pointer so to use instances and references where pointers where expected… why on the Earth one should want something like that?!?
Implicit conversions if not handled correctly are a sure way to kick yourself on the nose and this is enough a good reason to stay away. But… trying to enter the (criminal) mind that wrote that code, what’s the purpose? Just to avoid the need for the extra ‘&’ ? Or is it a Javism? Maybe it is better to stay out of some minds…