Electronic – How to enable the internal 32MHz clock on an XMEGA avr in assembly

avr-gccxmega

This is the C code that I currently use to enable the 32MHz clock:

CCP = CCP_IOREG_gc;
OSC.CTRL = OSC_RC32MEN_bm;
while(!(OSC.STATUS & OSC_RC32MRDY_bm));
CCP = CCP_IOREG_gc;
CLK.CTRL = CLK_SCLKSEL_RC32M_gc;

But this code needs to be compiled with some form of optimization enabled (-Os is suggested). Is there a way to do this in assembly without optimizations enabled?

Best Answer

Sure, if you are using Atmel Studio, the easiest way to do this is to compile your project using -Os and then view the contents of the *.lss file inside the debug directory. This file contains the C code in conjunction with the compiled assembly code:

CCP = CCP_IOREG_gc;
3226:   88 ed           ldi r24, 0xD8   ; 216
3228:   84 bf           out 0x34, r24   ; 52
OSC.CTRL = OSC_RC32MEN_bm;
322a:   82 e0           ldi r24, 0x02   ; 2
322c:   80 93 50 00     sts 0x0050, r24
while(!(OSC.STATUS & OSC_RC32MRDY_bm));
3230:   80 91 51 00     lds r24, 0x0051
3234:   81 ff           sbrs    r24, 1
3236:   fc cf           rjmp    .-8         ; 0x3230 <main+0x2c>
CCP = CCP_IOREG_gc;
3238:   88 ed           ldi r24, 0xD8   ; 216
323a:   84 bf           out 0x34, r24   ; 52
CLK.CTRL = CLK_SCLKSEL_RC32M_gc;
323c:   91 e0           ldi r25, 0x01   ; 1
323e:   90 93 40 00     sts 0x0040, r25

Using the information from this file, you can modify your C code to this:

__asm__ __volatile__("ldi r24, 0xD8");
__asm__ __volatile__("out 0x34, r24");      // CCP = CCP_IOREG_gc;
__asm__ __volatile__("ldi r24, 0x02");
__asm__ __volatile__("sts 0x0050, r24");    // OSC.CTRL = OSC_RC32MEN_bm;
__asm__ __volatile__("lds r24, 0x0051");
__asm__ __volatile__("sbrs r24, 1");        
__asm__ __volatile__("rjmp .-8");           // while(!(OSC.STATUS & OSC_RC32MRDY_bm));
__asm__ __volatile__("ldi r24, 0xD8");
__asm__ __volatile__("out 0x34, r24");      // CCP = CCP_IOREG_gc;
__asm__ __volatile__("ldi   r25, 0x01");
__asm__ __volatile__("sts   0x0040, r25");  // CLK.CTRL = CLK_SCLKSEL_RC32M_gc;

This inline assembly was tested working against an ATXMEGA32A4U with no optimizations enabled. Alternatively, you could add an assembly file to your project and create a function in assembler, but this requires no knowledge of assembly to implement.

If you are interested in the avr instruction set, more information can be found here.