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*/
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.
_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);