3.5 Writing to Configuration Change Protection (CCP) Registers

Attempting to write to a protected register without following the appropriate CCP unlock sequence leaves the protected register unchanged. The sequence, specified in the device data sheet, typically involves writing a signature to the CPU.CCP register and then, within four instructions, writing the desired value to the protected register.

The CCP signatures are provided by the device header file, as presented below.

/* CCP signature select */
typedef enum CCP_enum
{
    CCP_SPM_gc = (0x9D<<0),    /* SPM instruction protection */
    CCP_IOREG_gc = (0xD8<<0),  /* I/O register protection */
} CCP_t;

The following example shows how to write to a register under CCP using an IOREG signature. The main clock prescaler division will be set to 16.

CCP = CCP_IOREG_gc; /* Write the needed signature to CCP*/
CLKCTRL.MCLKCTRLB = CLKCTRL_PDIV_16X_gc; /* Set the prescaler division to 16 */

The following example shows how to write to a register under CCP using the SPM signature.

CPU.CCP = CCP_SPM_gc; /* Write the needed signature to CCP*/
NVMCTRL.CTRLA = NVMCTRL_CMD_FLPER_gc; /* Flash Page Erase Enable*/
CAUTION: These are not the recommended ways of writing to registers under CCP. To write to registers protected by CCP, after writing the signature to the CCP register, the software must write the desired data to the protected register within four instructions. To meet the timing requirements, writes to CCP registers are often handled by assembly code.

Thus, the recommended way of writing to a protected I/O register is by using the ccp_write_io function. To use this function, the following header file must be included.

#include <avr/cpufunc.h> /* Required header file */

The following code example provides the same functionality as the example presented above, but using the ccp_write_io function.

/* Set the prescaler division to 16 */
ccp_write_io((void *) & (CLKCTRL.MCLKCTRLB), (CLKCTRL_PDIV_16X_gc)); 

Alternatively, a macro is defined to write a value to a CCP register. This is protected through the XMEGA® CCP mechanism, which implements the timed sequence that is required for CCP.

Note: Since the CCP registers were introduced with the XMEGA family of AVR devices, the header file that contains _PROTECTED_WRITE and _PROTECTED_WRITE_SPM macros is xmega.h, which must be included as shown below.
#include <avr/xmega.h> /* Required header file */

These macros must be used to write to the desired registers, as presented in the code examples below.

/* Select the 32 kHz internal Ultra-Low Power oscillator */
_PROTECTED_WRITE(CLKCTRL.MCLKCTRLA, CLKCTRL.MCLKCTRLA | CLKCTRL_CLKSEL_OSCULP32K_gc);
/* Write page command */
_PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_PAGEWRITE_gc);
Note: Both the XC8 Compiler (MPLAB X IDE) and GCC (Atmel Studio 7) support the usage of these macros.