[Icc-avr] Reading Fuses on Mega88

Johannes Assenbaum jassenbaum at htp-tel.de
Thu Nov 29 14:09:34 PST 2007


The problem is, that const values must be in Z-pointer, i.e. R31:R30, and that LPM instruction must be executed in time. C may allow a solution, but it's hard job, so I prefer asm like this:

<file avrreadfusesbyte.s>
; unsigned char readfusebyte(unsigned int ioaddr, unsigned int fuseaddr);
;
_readfusesbyte::
 movw r26,r16  ; load X-pointer with ioaddr
 movw r30,r18  ; load Z-pointer with fuseaddr
 clr  r18      ; clear interrupts-enabled flag
 brid readfusesbyte1
  ldi r18,1    ; set interrupts-enabled flag
  cli          ; disable interrupts
readfusesbyte1:
 ldi  r16,0x09 ; bit names change but not the values. Yet...
 st   X,r16    ; write SPM control register
 lpm  r16,Z    ; read fuses
 sbrc r18,0
  sei          ; re-enable interrupts if enabled before
 ret
</file avrreadfusebyte.s>

Add file to project and in C then write:

//...
unsigned char readfusebyte(unsigned int fuseaddr);
//...
void ReadFuseLock(void)
{
 unsigned char Fuse[4];

 // Read lock bits
 Fuse[0] = readfusesbyte(SPMCSR,0x0001);

 // Read low fuses bits
 Fuse[1] = readfusesbyte(SPMCSR,0x0000);

 // Read high fuses bits
 Fuse[2] = readfusesbyte(SPMCSR,0x0003);

 // Read extended fuses bits
 Fuse[3] = readfusesbyte(SPMCSR,0x0002);

 // and so on
}

Best regards,
Johannes


> The data sheet states that the fuse and lock bits can only be read
> within three clock cycles of setting SPMCSR. After that reading is
> disabled. This is even more restrictive than the four clock cycle
> access to the watchdog timer which also catches out a lot of people.

> Unfortunately C does not give you any means of accessing the Z
> register directly before attempting to read the Flash. You might be
> lucky and get it to work if you force 'ptr' to be in registers, use
> an intermediate register variable and change the order of your code as follows:

> void ReadFuseLock(void)
> {
>    register const unsigned char* ptr;
>    register unsigned char temp;
>    unsigned char Fuse[4];

>    // Read lock bits
>    ptr = (const unsigned char*)(0x0001); // 0x0001 to read lock bits
>    SPMCSR = 0x09;        //  (BLBSET | SPMEN) to read fuse and lock bits
>    temp = *ptr;
>    Fuse[0] = temp;

>    // Read fuse low bits
>    ptr = (const unsigned char*)(0x0000);
>    SPMCSR = 0x09;
>    temp = *ptr;
>    Fuse[1] = temp;

>    // Read fuse high bits
>    ptr = (const unsigned char*)(0x0003);
>    SPMCSR = 0x09;
>    temp = *ptr;
>    Fuse[2] = temp;

>    // Read extended fuse bits
>    ptr = (const unsigned char*)(0x0002);
>    SPMCSR = 0x09;
>    temp = *ptr;
>    Fuse[2] = temp;
>   }

> This code is untested and just an idea, so you'll need to compile it
> and have a look at the list file to check the timings. You may find
> that 'ptr' and 'temp' are allocated in registers anyway so you don't
> need to declare them as such. If all that fails, then you'll have to
> go to assembler as Richard says.

> All the best for now,
> John


> At 11:31 29/11/2007, you wrote:
>>Does anyone know how to read fuses on a mega88?
>>
>>I have tried the following but the results are incorrect.
>>
>>void ReadFuseLock(void)
>>{
>>   const unsigned char* ptr;
>>   unsigned char Fuse[4];
>>
>>   // Read lock bits
>>   SPMCSR = 0x09;        //  (BLBSET | SPMEN) to read fuse and lock bits
>>   ptr = (const unsigned char*)(0x0001); // 0x0001 to read lock bits
>>   Fuse[0]=*ptr;
>>
>>   // Read fuse low bits
>>   SPMCSR = 0x09;
>>   ptr = (const unsigned char*)(0x0000);
>>   Fuse[1]=*ptr;
>>
>>   // Read fuse high bits
>>   SPMCSR = 0x09;
>>   ptr = (const unsigned char*)(0x0003);
>>   Fuse[2]=*ptr;
>>  }
>>
>>The values returned are:
>>
>>Lock Bits       0xC0            (should be 0xFF)
>>
>>Fuse Low Bits   0x31            (should be 0xE6)
>>
>>Fuse High Bits  0xC4            (should be 0xD8)
>>
>>Any ideas anyone?
>>
>>Regards,
>>
>>Ian James
>>--
>>Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
>>
>>_______________________________________________
>>Icc-avr mailing list
>>Icc-avr at imagecraft.com
>>http://dragonsgate.net/mailman/listinfo/icc-avr

> _______________________________________________
> Icc-avr mailing list
> Icc-avr at imagecraft.com
> http://dragonsgate.net/mailman/listinfo/icc-avr


> --
> No virus found in this incoming message.
> Checked by AVG Free Edition.
> Version: 7.5.503 / Virus Database: 269.16.10/1159 - Release Date: 29.11.07 11:10





More information about the Icc-avr mailing list