Yahoo Groups archive

AVR-Chat

Index last updated: 2026-04-28 22:41 UTC

Message

Fuse detection

2004-06-10 by Bruce Parham

All, 

I just got nailed by a miss programmed (by me of course) M128 fuse. After spending a few 
hours tracking down the problem, it occured to me that my application probably should
check for this kind of situation at startup and do something if things aren't right. 

The code below is the first cut; it just reads and displays the current settings. It will 
fail if the M128C fuse is programmed (haven't figured out the best way to detect that yet) 
but otherwise works fine. 

The code was written for the ICCAVR compiler but should be adaptable to others.

Bruce

---------------------------------------------------------------------------

struct M128_FUSES
{
    unsigned cksel      : 4;    // low byte
    unsigned sut        : 2;
    unsigned boden      : 1;
    unsigned bodlevel   : 1;
    
    unsigned bootrst    : 1;    // high byte
    unsigned bootsz     : 2;
    unsigned eesave     : 1;
    unsigned ckopt      : 1;
    unsigned spien      : 1;
    unsigned jtagen     : 1;
    unsigned ocden      : 1;
    
    unsigned wdton      : 1;    // extension byte
    unsigned m103c      : 1;
    unsigned unused     : 6;
    
    unsigned lb         : 2;    // lock bit byte
    unsigned blb0       : 2;
    unsigned blb1       : 2;
};

union   FUSES
{
    struct M128_FUSES f_bits;
    unsigned long fuse_state; 
} fuses;

unsigned long get_fuse(void)    // get fuses to test clock source and stuff...
{
    asm
    (
        "ldi    r26, 9    ; BLBSET & SPMEN         \n"
        "mov    r0, r26   ; to read fuses          \n"
        "ldi    r26, 0x68 ; spmcsr                 \n"
        "ldi    r27, 0                             \n"
        "ldi    r30, 0    ; start with FLB         \n"
        "ldi    r31, 0                             \n"
        "st     x, r0     ; prime the pump         \n"
        "lpm    r16, z+   ; fuse low byte -> R16   \n"
        "st     x, r0                              \n"
        "lpm    r19, z+   ; lock byte -> R19       \n"
        "st     x, r0                              \n"
        "lpm    r18, z+   ; fuse ext byte -> R18   \n"
        "st     x, r0                              \n"
        "lpm    r17, z    ; fuse high byte -> R17  \n"
        "ret                                       \n"
    );
    return(0); // keep the compiler from whinning
}

void show_fuses(void)   // display M128 fuses @ startup
{
    fuses.fuse_state = get_fuse();
    
    printf("\nProcessor Fuses:\n\n");
    
    printf("  cksel = %1u      sut = %1u    boden = %1u   bodlevel = %1u\n", 
    fuses.f_bits.cksel, fuses.f_bits.sut, fuses.f_bits.boden, fuses.f_bits.bodlevel);
    
    printf("bootrst = %1u   bootsz = %1u   eesave = %1u      ckopt = %1u\n", 
    fuses.f_bits.bootrst, fuses.f_bits.bootsz, fuses.f_bits.eesave, fuses.f_bits.ckopt);
    
    printf("  spien = %1u   jtagen = %1u    ocden = %1u      wdten = %1u\n", 
    fuses.f_bits.spien, fuses.f_bits.jtagen, fuses.f_bits.ocden, fuses.f_bits.wdton);
    
    printf("  M103c = %1u       lb = %1u     blb0 = %1u       blb1 = %1u\n", 
    fuses.f_bits.m103c, fuses.f_bits.lb, fuses.f_bits.blb0, fuses.f_bits.blb1);
}

Attachments

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.