The manual for the AU series says CCP (Configuration Change Protection) must be used with the LPM instruction when reading fuses and signature row.
This seems to be wrong. What am I missing? I use pgm_read_byte() to read the User and Production signature rows without using CPP, and it works fine with my Xmega128au chips. None of the examples I've seen on the internet that shows pgm_read_byte() and the __LPM macro it calls shows CCP being used.
Well, I see that using CCP disables interrupts for the duration of the CCP enable period. Maybe that can be beneficial?
In the AVR911 bootloader (Bandtank etc.) sp_driver.s, I see reading the signature rows and fuses without using CCP. I'm not an expert with the AVR assembler, but that seems to be the case.
; --- ; This routine reads the user signature byte given by the index in R25:R24. ; ; Input: ; R25:R24 - Byte index. ; ; Returns: ; R24 - Signature byte. ; --- .section .text .global SP_ReadUserSignatureByte SP_ReadUserSignatureByte: ldi r20, NVM_CMD_READ_USER_SIG_ROW_gc ; Prepare NVM command in R20. rjmp SP_CommonLPM ; Jump to common LPM code. ; --- ; This routine is called by several other routines, and contains common code ; for executing an LPM command, including the return statement itself. ; ; Note that R24 is used for returning results, even if the ; C-domain calling function expects a void. ; ; Input: ; R25:R24 - Low bytes of Z pointer. ; R20 - NVM Command code. ; ; Returns: ; R24 - Result from LPM operation. ; --- .section .text SP_CommonLPM: movw ZL, r24 ; Load index into Z. sts NVM_CMD, r20 ; Load prepared command into NVM Command register. lpm r24,Z ret