Unable to read fuses with NVM controller

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

Hi.

I am having trouble reading fuse values on an XMEGA128A3U and 128D3. When I read the fuses I get 0x00 for fuses 0, 1 and 2. Fuses 4 and 5 give me the correct values.

I have verified with a JTAGICE3 that fuses 0, 1 and 2 are not 0x00. Fuse 2 in particular should read 0xBF.

I tried the older Atmel driver (SP_ReadFuseByte) and the ASF driver (nvm_fuses_read) and both return the same result. As far as I can tell there are no special requirements such as being the bootloader section, it should just work.

Has anyone managed to read the fuse bytes correctly? I see some public bootloader code that claims to but it all seems to be broken (designed for older AVRs with three fuses, not XMEGA).

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

Well, I've read the Fuses, but in Basic, not C.
It was one of the earlier tasks I worked on, hence a lot of notes and repetition in the notes about how to do this.

You may, however, spot something different in this approach and in your approach that leads you to a solution for your fuse reading issue.

JC

Readfuses:
   'Read the Xmega's Fuses
   'Store the 6 Bytes that comprise Fuse data.
   'Calc a simple CheckSum
   'Fuse Bytes 0 1 2 4 5 7
   'On Exit have: The Xmega's Fuse data in the RFD() array, Loc 1-6.

   'This Reads the Xmega's Fuses, to then Upload them to the PC.
   'Method:
   'LCD Msg
   'Enter PDI Mode
   'Give PDI Controller Read Fuse Command and the Fuses ADDR
   'Store it, repeat
   'Exit PDI Mode

   'Read the PDI memory mapped memory for the Xmega's Fuse data.
   'Send the Address Little-Endian, ie reversed order, LSByte First.

   'PDI Write LDS Long Addr (4 bytes), and  Byte Data
   'Use Little-Endian Addr order, i.e. LSB Byte first

   'In the PDI Memory Map the Fuses are at Addr: 0x08F0020.
   'The 6 Bytes holding Fuse Data are then at Offsets: 0 1 2 4 5 7

   'First Enter PDI Mode and adjust GuardTime
   'Then Read the Signature for good measure

   Gosub Enablepdi    'Sub to Enable PDI Interface
   Gosub Setguardtime    'Shorten Xmega Rx Tx Guard Time
   Gosub Readsignature   'Read the Xmega's Signature

   'Now read the Xmega's Fuses:

   'Try Writing Read NVM Command to NVM Controller, first, before using the
   'PDI LDS to Read the PDI Memory Map of the Application Section.
   'Doing this works.  Without loading the Read Instr to NVM Controller first, it
   'doesn't work.  But, use the PDI Mem Map Addrs and Commands, NOT the NVM
   'Controller Addrs and Data space.

   'Use PDI STS Cmnd to send NVM Read Cmnd to the NVM Controller.
   'Use Little-Endian Addr, LSByte first.
   'The Data byte = the Read Fuse Command for the NVM Controller.
   'Write this to the NVM Command Register, using 4-Byte Addr.

   Ptd = 76     'PDI STS Cmnd
   Gosub Pdicmndreg 'Send Instr to NVM Controller Command Reg

   'Now send the NVM Cmnd: NVM Read Fuse, as the Data byte for the PDI STS Cmnd
   Ptd = 7       'NVM Read Fuse
   Gosub Pditxbyte  'Send it

   'Now Read the data from the PDI Memory Map:
   'The Base Memory for the PDI Memory Map for the Fuses is:
   '0x08F0020 (Hex)   0 143 0 32 Dec
   'The Offsets for the Fuse Data are NOT sequential.
   'The Fuse Bytes are at Offsets: 0, 1, 2, 4, 5, 7  (Skip 3, 6)
   'Just straight code the Low byte of the Addr for now.
   'Could use a table, later, if desired.

   For Rfdi = 1 To 6
      'PDI LDS Instr, Long Addr, Byte data
      Ptd = 12       '
      Gosub Pditxbyte   'Send it

      'Now Send 4-Byte Addr, LSByte first:
      'Addr LSByte
      If Rfdi = 1 Then
         Ptd = 32    'Base Addr for Fuses
      Elseif Rfdi = 2 Then
         Ptd = 33
      Elseif Rfdi = 3 Then
         Ptd = 34
      Elseif Rfdi = 4 Then
         Ptd = 36
      Elseif Rfdi = 5 Then
         Ptd = 37
      Elseif Rfdi = 6 Then
         Ptd = 39
      Else
         '
      End If

     'Send Addr Low Byte, Incrementing
      Gosub Pditxbyte   'Send it

      Ptd = 0           'Addr
      Gosub Pditxbyte   'Send it

      Ptd = 143         'Addr
      Gosub Pditxbyte   'Send it
      Ptd = 0           'MS Byte Addr
      Gosub Pditxbyte   'Send it
      nop

      'Now Read in Xmega's PDI's Transmitted response, a Byte.
      Gosub Pdirxbyte   'Read in a Byte: PRD
      Rfd(rfdi) = Prd   'Save it
      nop
   Next Rfdi

   Gosub Exitpdi   'Exit PDI Mode

   'Now calculate and store the CheckSum for the 6 Bytes of Fuse information
   'to  be uploaded to the PC.
   'CheckSum is the 8 bit sum of the 6 Data Bytes, excludes the Start-of-Packet Char.
   'Ignore any carry outs from the 8 bit sum.

   Rfd(7) = Rfd(1)   'Calc CheckSum
   For Rfdi = 2 To 6
      Rfd(7) = Rfd(7) + Rfd(rfdi)  'Add them up
   Next Rfdi

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

It's interesting that you seem to be sending absolute addresses, where as the Atmel code just loads the fuse number into the NVM address registers.

I will try it on Monday.

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

Unfortunately that didn't help either.

Does anyone have any confirmed working code that reads the fuses on the device itself, rather than via PDI?

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

Hmm... NVM_EXAMPLE41 runs okay in the simulator but produces the wrong value, and when I run it via the JTAGICE3 it gets stuck in an infinite loop in nvm_fuses_read().

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

I have code to read fuses that works as expected on an A4U. I haven't tried it on an A3U. I'll do that later today when I have access to my A3U hardware.

Code is pretty simple:

for (i = 0; i < 6; i++)
{
	buffer[i] = nvm_fuses_read(i);
}

It uses ASF version 3.5.1, if that's relevant.

Jeff Nichols

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

On an Xmega256A3U this returns {0xff, 0x00, 0xbe, 0xbe, 0xf3, 0xe8} which agrees with the fuses read through the programming interface (Noting that FUSEBYTE3 doesn't exist).

Jeff Nichols

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

Thanks Jeff, much appreciated. It looks like somehow I have managed to get the NVM controller into a state where it returns rubbish, but at least it is somewhere to start from.

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

I figured it out. If you set the EPRM bit in NVM.CTRLB the fuses reads back 0xFF. Clearing the bit fixes the problem.

Strange because the datasheet doesn't mention that setting EEPROM Power Reduction Mode breaks reading fuses with the NVM controller. Sounds like a silicone bug! I looked on Atmel's web site but couldn't see an email address for reporting bugs, so does anyone know how to do it?

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

Quote:

I looked on Atmel's web site but couldn't see an email address for reporting bugs, so does anyone know how to do it?

Here? http://support.atmel.com/bin/cus...

Pure speculation: If these bits live in an "EEPROM" area and not a "flash" area, it might make sense that that control bit is gated to this info?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Thanks theusch.

The datasheet doesn't make it clear where they live, other than that they can only be accessed by the NVM controller. Even if they do live in the EEPROM it says in the EPRM bit description that "if access is required, the bus master will be halted for a time equal the start-up time from idle sleep mode."

Interestingly I can read fuses 4 and 5 okay with the EPRM bit set, just not fuses 0, 1 and 2.

I have submitted a report to Atmel.

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

Heard back from Atmel, they have confirmed the issue. Yay, my first silicone bug!

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

Quote:

Yay, my first silicone bug!

Next you can get a collection of "silicone" bugs:

Attachment(s): 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

I had exactly the same problem on a Xmega256A3U, fuses 4 and 5 are ok, but fuses 0, 1, 2 always return 0xFF. Solved it by turning off EEPROM Power Reduction Mode in NVM.CTRLB

 

Last Edited: Mon. Oct 24, 2016 - 02:12 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Deleted

 

Last Edited: Mon. Oct 24, 2016 - 02:28 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I edited my post in the meanwhile. But still, thanks for your response. But actually, the first 3 fusebytes were causing troubles, not the lockbyte.