Can't disable clock divider in ATtiny816

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

The clock (20MHz) is divided by 6 by default. I would like to disable the divider so that CLK_PER will also be 20MHz.

As far as I could understand from the datasheet the following two lines should do the trick:

CCP = CCP_IOREG_gc;
CLKCTRL.MCLKCTRLB &= ~CLKCTRL_PEN_bm;

However this does nothing. What have I missed?

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

In many of those operations (watchdog, for example), things have to be done within a specific and quite brief time window. You might not be doing it fast enough. Sometimes, folks resort to a function with inline assembly code to meet the constraints.

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

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

See the _PROTECTED_WRITE macro from avr-libc (part of xmega.h I believe)

:: Morten

 

(yes, I work for Atmel, yes, I do this in my spare time, now stop sending PMs)

 

The postings on this site are my own and do not represent Microchip’s positions, strategies, or opinions.

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

See the latest ATtiny816 datasheet pages 61-62 paragraph 10.3.2 and page 43 paragraph 8.5.6 - 8.5.7.1 for more info on CCP - Configuration  Change Protocol and Protected I/O Registers.

 

If using AS7, I suggest that you create an Atmel Start application for the ATtiny816, deselect Prescaler Enable in CLKCTRL, then look at the following include and source files;  clkctrl.c , ccp.h , protected_io.h , protected_io.S

 

if you go this route you will end up with something like this in your .lss

00000052 <CLKCTRL_init>:
 *       on calling convention. The memory model is not visible to the
 *       preprocessor, so it must be defined in the Assembler preprocessor directives.
 */
static inline void ccp_write_io(void *addr, uint8_t value)
{
	protected_write_io(addr, CCP_IOREG_gc, value);
  52:	40 e1       	ldi	r20, 0x10	; 16
  54:	68 ed       	ldi	r22, 0xD8	; 216
  56:	81 e6       	ldi	r24, 0x61	; 97
  58:	90 e0       	ldi	r25, 0x00	; 0
  5a:	26 d0       	rcall	.+76     	; 0xa8 <protected_write_io>
	//		 | 0 << CLKCTRL_CLKOUT_bp /* System clock out: disabled */);

000000a8 <protected_write_io>:
#if defined(__GNUC__)

#ifdef RAMPZ
	out     _SFR_IO_ADDR(RAMPZ), r1         // Clear bits 23:16 of Z
#endif
	movw    r30, r24                // Load addr into Z
  a8:	fc 01       	movw	r30, r24
	out     CCP, r22                // Start CCP handshake
  aa:	64 bf       	out	0x34, r22	; 52
	st      Z, r20                  // Write value to I/O register
  ac:	40 83       	st	Z, r20
	ret                             // Return to caller
  ae:	08 95       	ret

 

 

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

Last Edited: Tue. Jan 9, 2018 - 12:55 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

this is auto code generated by CodeVisionAVR, maybe useful

 

register unsigned char n;

// Disable the system clock divisor, so that the system
// and peripheral clocks will be the highest possible
#pragma optsize-
n = 0 << CLKCTRL_PEN_bp;
CPU_CCP = 0xD8; // Enable configuration change protection
CLKCTRL.MCLKCTRLB = n; // Ensure that the register is written in 4 cycles
#pragma optsize_default

 

Majid

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

I looked into the generated assembly code:

 

    CPU_CCP = CCP_IOREG_gc;
00000023  LDI R24,0xD8		Load immediate 
00000024  OUT 0x34,R24		Out to I/O location 
	CLKCTRL.MCLKCTRLB &= ~CLKCTRL_PEN_bm;
00000025  LDI R30,0x60		Load immediate 
00000026  LDI R31,0x00		Load immediate 
00000027  LDD R24,Z+1		Load indirect with displacement 
00000028  ANDI R24,0xFE		Logical AND with immediate 
00000029  STD Z+1,R24		Store indirect with displacement 
0000002A  RET 		Subroutine return 

That's way too much, so I've simply changed the 2nd command as I don't care about the divider values and got this:

	CPU_CCP = CCP_IOREG_gc;
00000023  LDI R24,0xD8		Load immediate 
00000024  OUT 0x34,R24		Out to I/O location 
	CLKCTRL.MCLKCTRLB = 0;
00000025  STS 0x0061,R1		Store direct to data space 
00000027  RET 		Subroutine return 

This works fine.

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

slow_rider wrote:
I don't care about the divider values and got this: CPU_CCP = CCP_IOREG_gc; 00000023 LDI R24,0xD8 Load immediate 00000024 OUT 0x34,R24 Out to I/O location CLKCTRL.MCLKCTRLB = 0; 00000025 STS 0x0061,R1 Store direct to data space 00000027 RET Subroutine return This works fine.

 

but in your code R1 value is unspecified, you need to clear it

 

consider compiled ASM of #5 :

 

	LDI  R17,LOW(0)
	LDI  R30,LOW(216)
	OUT  0x34,R30
	STS  97,R17

 

Majid

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

but in your code R1 value is unspecified, you need to clear it

Uh, no.  R1 is __zero_reg__.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

Yeah, don't you just love to write

zero = 1

when programming in assembler mixed with C? (Well I usually write zero_reg). wink

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

slow_rider wrote:

 

	CPU_CCP = CCP_IOREG_gc;
00000023  LDI R24,0xD8		Load immediate
00000024  OUT 0x34,R24		Out to I/O location
	CLKCTRL.MCLKCTRLB = 0;
00000025  STS 0x0061,R1		Store direct to data space
00000027  RET 		Subroutine return 

This works fine.

Yes it does.  Could you please mark your post, #6, as the solution.

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

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

Oki,
İ got it!

Majid