Read fuse bits in runtime

Go To Last Post
12 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

I want my firmware to check that the correct fuse bits has been set. I am trying to do this like this:

#define LOWFUSEBITS (*((volatile char *) 0x0000))
#define LOCKFUSEBITS (*((volatile char *) 0x0001))
#define EXTENDEDFUSEBITS (*((volatile char *) 0x0002))
#define HIGHFUSEBITS (*((volatile char *) 0x0003))

And then use it as normal read only variables.

 

But I cant seem to get the correct data, I just read 0, 64, 0 64.

 

Is there anything obvious I am doing wrong? Im using the ATmega32C1.

 

Thanks,

/Anders

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

24.7.9 in the datasheet. I won't paste the entire section here but in case your datasheet copy is numbered differently to mine the section you are looking for starts like this:

 

So, no, it is NOT as simple as:

#define LOWFUSEBITS (*((volatile char *) 0x0000))

..

  uint8_t low = LOWFUSEBITS;

Remember that the AVR is a Harvard architecture processor so that instead of one single, big address map with everything in it (von Neumann) it has various data in separate memory maps each of which has an address 0x0000. If you just make an LDS/LD access to address 0x0000 what you get is ""RAM" location 0x0000 (in fact the AVR has the CPU registers mapped to the first 32 locations in RAM so what you actually get is the contents of R0). Similarly flash has an address 0x0000 and you access that one using LPM. EEPROM too has it's own address 0x0000 and you get to that one with EEAR/EEDR/EECR. The FUSE and LOCKBIT memories are each separate too and each has their own location 0x0000. To get to those you do what it says in 24.7.9

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are attempting to read R0 by absolute addressing.

It may well work,  but you need to put the relevant data into R0 first.

 

It seems far simpler t use < avr/boot.h >

#include <avr/boot.h>

void print_val(char *msg, uint8_t val)
{
    Serial.print(msg);
    Serial.println(val, HEX);
}

void setup(void)
{

    Serial.begin(9600);
    while (!Serial) ;
    print_val("lockb = 0x", boot_lock_fuse_bits_get(1));
    print_val("ext fuse = 0x", boot_lock_fuse_bits_get(2));
    print_val("high fuse = 0x", boot_lock_fuse_bits_get(3));
    print_val("low fuse = 0x", boot_lock_fuse_bits_get(0));
#define SIGRD 5
#if defined(SIGRD) || defined(RSIG)
    Serial.print("Signature : ");
    for (uint8_t i = 0; i < 5; i += 2) {
        Serial.print(" 0x");
        Serial.print(boot_signature_byte_get(i), HEX);
    }
    Serial.println();
#endif
    Serial.print("Serial Number : ");
    for (uint8_t i = 14; i < 24; i += 1) {
        Serial.print(" 0x");
        Serial.print(boot_signature_byte_get(i), HEX);
    }
    Serial.println();

}

void loop(void)
{
}

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ah, I see, I misread a post found using google. It seems AVR-GCC has functions prepared for reading the fuse bits. But I am using CodeVision AVR.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I found a macro now that should do the correct read:

#define boot_lock_fuse_bits_get(address) \
	(__extension__({                                           \
    uint8_t __result;                                      \
    __asm__ __volatile__                                   \
    (                                                      \
        "sts %1, %2\n\t"                                   \
        "lpm %0, Z\n\t"                                    \
        : "=r" (__result)                                  \
        : "i" (_SFR_MEM_ADDR(__SPM_REG)),                  \
          "r" ((uint8_t)(__BOOT_LOCK_BITS_SET)),           \
          "z" ((uint16_t)(address))                        \
    );                                                     \
    __result;                                              \
})) 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Then do what I just told you and read 24.7.9 and do what it says there.

 

(OTOH maybe Codevision offers something like gcc's avr/boot.h ?)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am sure that I have written an "equivalent" CV  header file in the past.

 

However,   I suggest that you look at the "flash.c" and "flash.h" files in the Codevision examples/AVR109

 

Effectively,  there is one helper function and you use the appropriate macro like you would with GCC boot.h

#define _GET_LOCK_BITS() __AddrToZByteToSPMCR_LPM( (void flash *) 0x0001, 0x09 )
#define _GET_LOW_FUSES() __AddrToZByteToSPMCR_LPM( (void flash *) 0x0000, 0x09 )
#define _GET_HIGH_FUSES() __AddrToZByteToSPMCR_LPM( (void flash *) 0x0003, 0x09 )
#define _GET_EXTENDED_FUSES() __AddrToZByteToSPMCR_LPM( (void flash *) 0x0002, 0x09 )

unsigned char __AddrToZByteToSPMCR_LPM(void flash *addr, unsigned char ctrl)
{
#asm
     ldd  r30,y+1
     ldd  r31,y+2
     ld   r22,y
     WR_SPMCR_REG_R22
     lpm
     mov  r30,r0
#endasm
}

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for all help. I have been trying all the different suggestions, but unfortunately I am getting stuck on the SPMCSR. Like in Davids suggestion, I get an error "Unknown instruction or macro" on

     WR_SPMCR_REG_R22
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Did you read the full "flash.c" and "flash.h" files?

 

I would guess that WR_SPMCR_REG_R22 is a specific CV macro for an m328-style target.

Just build the AVR109 project that is most appropriate to your chip.    Examine the Listing file.

 

Oh,  the CV IDE is a lot more pleasant than Studio when you want to search for a macro or text.

 

David.

Last Edited: Tue. Apr 5, 2016 - 10:13 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Codevision AVR does not have any flash.h or c file.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Found what was wrong with

     WR_SPMCR_REG_R22

It was just a macro which was

sts 0x57,r22

But still not working.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AgwanII wrote:

Codevision AVR does not have any flash.h or c file.

Of course it does not have system files of that name.

I suggested that you built one of the AVR109 projects from CV examples.

 

Most Compilers come with some examples.   Codevision comes with Help files and Examples.

 

David.