Posts Tagged ‘AVR’

Hardware costs versus development costs

Thursday, December 24th, 2009 Nigel Jones

Earlier this year I posted about how to solve the problem of PIC stack overflow. As part of that article I asked the question as to why does anybody use a PIC anyway when there are superior architectures such as the AVR available? Well, various people have linked to the posting and so I get a regular stream of visitors to it, some of whom weigh in on the topic. The other day, one visitor offered as a reason for using the PIC the fact that they are cheap. Is this the case I asked myself? So I did some rough comparisons of the AVR & 8 bit PIC processors – and sure enough PIC processors are cheaper to buy. For example comparing the ATmega168P vs the PIC16F1936 (two roughly equivalent processors – the AVR has more memory and a lot more throughput, the PIC has more peripherals) I found that Digikey was selling the AVR for 2.60 per 980 and the PIC for $1.66 per 1600. A considerable difference – or is it?

Most of the products I work on have sales volumes of 1000 pieces a year, with a product life of 5 years. Thus if I chose the AVR for such a product, then my client would be paying approximately $1000 a year more for say 5 years. Applying a very modest 5% discount rate, this translates to a Net Present Value of $4,329.

This is when it gets interesting. Does the AVR’s architecture allow a programmer to be more productive? Well, clearly this is a somewhat subjective manner. However my sense is that the AVR does indeed allow greater programmer productivity. The reasons are as follows:

  1. The AVR’s architecture lends itself by design to being coded in a HLL. The PIC does not. As a result, programming the PIC in a HLL is always a challenge and one is far more likely to have to resort to assembly language – with the attendant drop in productivity.
  2. The AVR’s inherent higher processing speed means that one has to be less concerned with fine tuning code in order to get the job done. Fine tuning code can be very time consuming.
  3. The AVR’s greater code density means that one is less likely to be concerned with making the application fit in the available memory (something that can be extremely time consuming when things gets tight).
  4. The AVR’s superior interrupt structure means that interrupt handling is far easier. Again interrupts are something that can consume inordinate amounts of time when things aren’t working.

Now if one is a skilled PIC programmer and a novice on the AVR, then your experience will probably offset what I have postulated are inherent inefficiencies in the PIC architecture. However what about someone such as myself who is equally comfortable in both arenas? In this case the question becomes – how many more days will it take to code up the PIC versus the AVR and what do those days cost?

Of course if you are a salaried employee, then your salary is ‘hidden’. However when you are a consultant the cost of extra days is clearly visible to the client. In this case, if using an AVR reduces the number of development days by even a few, the cost difference between the two processors rapidly dwindles to nothing. Thus the bottom line is – I’m not sure that PICs are cheaper. However I suspect that in many organizations what counts is the BOM cost of a product – and perhaps this finally explains why PIC’s are more popular than AVR’s.

As always, I’m interested in your thoughts.
Home

Checking the fuse bits in an Atmel AVR at run time

Friday, May 15th, 2009 Nigel Jones

In general I try and post on topics that have broad appeal in the embedded world. Today I’m going to partially break with that tradition to show how to check the fuse bits in an Atmel AVR class processor. However, before I do so, I’d like to discuss my motivations for wanting to do this.

The AVR processor family, together with the PIC and other processor families contain fuse / configuration bits. These bits are settable only at program time and are used to configure the behavior of the processor at run time. Typical parameters that are configured are oscillator types, brown out voltage detect levels and memory partitioning. Now as I lamented in this post, there is no great way of communicating to the production staff how you want these fuse bits programmed. As a result I consider there to be a very high probability that a mistake will be made in production – and that all my efforts on crafting perfect code will thus be for naught. Thus while it is much better to prevent mistakes, if you can’t do so, then the next best thing to do is to detect them. As a result on one of the products that I am working on, I have as one of the startup tests a check to ensure that the fuse bits are indeed what they are supposed to be. While I recognize that if the fuse settings are dreadfully wrong it is unlikely that my code will run, I’m actually more concerned with the case where the fuse bits are set mostly correct – and thus that the code works most of the time.

So how do I do this on an AVR? Well if you are using an IAR compiler the work is mostly done for you. Here it is:

#include <intrinsics.h>

/* Macros to read the various fuse bytes */
#define _SPM_GET_LOW_FUSEBITS()  __AddrToZByteToSPMCR_LPM((void __flash*)0x0000U, 0x09U)
#define _SPM_GET_HIGH_FUSEBITS()  __AddrToZByteToSPMCR_LPM((void __flash*)0x0003U, 0x09U)
#define _SPM_GET_EXTENDED_FUSEBITS()  __AddrToZByteToSPMCR_LPM((void __flash*)0x0002U, 0x09U)

/* Structure to store the fuse bytes */
typedef struct{
uint8_t  fuse_low;      /* The low fuse setting */
uint8_t  fuse_high;     /* The high fuse setting */
uint8_t  fuse_extended; /* The extended fuse setting */
uint8_t  lockbits;      /* The lockbits */
} FUSE_SETTINGS;

/* Storage for the fuse settings will be in EEPROM */
static __eeprom __no_init FUSE_SETTINGS Fuse_Settings @ FUSE_VALUES; 

void fuses_Read(void)
{
 FUSE_SETTINGS value;

 value.fuse_low = _SPM_GET_LOW_FUSEBITS();
 value.fuse_high = _SPM_GET_HIGH_FUSEBITS();
 value.fuse_extended = _SPM_GET_EXTENDED_FUSEBITS();
 value.lockbits = _SPM_GET_LOCKBITS();
 __no_operation();

 Fuse_Settings = value;
}

The macro __AddrToZByteToSPMCR_LPM() is defined in intrinsics.h. Essentially it takes care of all the necessary finicky register usage required to read the fuse bits. You’ll also notice that I have used a macro _SPM_GET_LOCKBITS() to read the lockbits. This macro is also found in intrinsics.h. The really observant reader may wonder why there isn’t a macro in intrinsics.h for reading the fuse bits? Well there is – it’s just for reading the low fuse byte – which is all the early AVR processors had. I’ve pointed this out to IAR and they have promised to address this in the next release (thanks Steve!).

Before I leave this topic, I’ll also point out that I don’t read the fuse settings directly into EEPROM. Instead I read them into RAM and then copy the entire structure to EEPROM. I do this because writing to EEPROM messes with the same registers used for reading the fuse bits – and thus bad things happen. This also explains the __no_operation() statement before the data are copied to EEPROM.

Incidentally, I don’t know of a way to read the configuration bits of a PIC at run time. Chalk this up as one more reason why an AVR is superior to a PIC!

Home

PIC stack overflow

Saturday, April 25th, 2009 Nigel Jones

For regular readers of this blog I apologize for turning once again to the topic of my Nom de Guerre. If you really don’t want to read about stack overflow again, then just skip to the second section of this posting where I address the far more interesting topic of why anyone uses an 8-bit PIC in the first place.

Anyway, the motivation for this post is that the most common search term that drives folks to this blog is ‘PIC stack overflow’. While I’ve expounded on the topic of stacks in general here and here, I’ve never explicitly addressed the problem with 8 bit PICs. So to make my PIC visitors happy, I thought I’ll give them all they need to know to solve the problem of stack overflow on their 8 bit PIC processors.

The key thing to understand about the 8 bit PIC architecture is that the stack size is fixed. It varies from a depth of 2 for the really low end devices to 31 for the high end 8 bit devices. The most popular parts (such as the 16F877) have a stack size of 8. Every (r)call consumes a level, as does the interrupt handler. To add insult to injury, if you use the In Circuit Debugger (ICD) rather than a full blown ICE, then support for the ICD also consumes a level. So if you are using a 16 series part (for example) with an ICD and interrupts, then you have at most 6 levels available to you. What does this mean? Well if you are programming in assembly language (which when you get down to it was always the intention of the PIC designers) it means that you can nest function calls no more than six deep. If you are programming in C then depending on your compiler you may not even be able to nest functions this deep, particularly if you are using size optimization.

So on the assumption that you are overflowing the call stack, what can you do? Here’s a checklist:

  • Switch from the ICD to an ICE. It’s only a few thousand dollars difference…
  • If you don’t really need interrupt support, then eliminate it.
  • If you need interrupt support then don’t make any function calls from within the ISR (as this subtracts from your available levels).
  • Inline low level functions
  • Use speed optimization (which effectively inlines functions)
  • Examine your call tree and determine where the greatest call depth occurs. At this point either restructure the code to reduce the call depth, or disable interrupts during the deepest point.
  • Structure your code such that calls can be replaced with jumps. You do this by only making calls at the very end of the function, so that the compiler can simply jump to the new function. (Yes this is a really ugly technique).
  • Buy a much better compiler.

If you are still stuck after trying all these, then you really are in a pickle. You could seek paid expert help (e.g. from me or some of the other folks that blog here at embeddedgurus) or you could change CPU architectures. Which leads me to:

So why are you using a PIC anyway?

The popularity of 8 bit PICs baffles me. Its architecture is awful – the limited call stack is just the first dreadful thing. Throw in the need for paging and banking together with the single interrupt vector and you have a nightmare of a programming model. It would be one thing if this was the norm for 8 bit devices – but it isn’t. The AVR architecture blows the PIC away, while the HC05 / HC08 are also streets ahead of the PIC. Given the choice I think I’d even take an 8051 over the PIC. I don’t see any cost advantages, packaging advantages (Atmel has just released a SOT23-6 AVR which is essentially instruction set compatible with their largest devices) or peripheral set advantages. In short, I don’t get it! Incidentally, this isn’t an indictment of Microchip – they are a great company and I really like a lot of their other products, their web site, tech support and so on (perhaps this is why the PIC is so widely used?). So to the (ir)regular readers of this blog – if you are you using 8 bit PICs perhaps you could use the comment section to explain why. Let the debate begin!

Home