ATTINY1634 how do i use ccp_write_io to change the clock prescaler

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

how do i use this function?

i want to clear the 4 clock prescaler bits (CLKPS0 - CLKPS3)

 

ccp_write_io((void*) & CLKPR, 0);

 

i include <avr/cpufunc.h>

 

besides not knowing how to pass in what i want, i get undefined reference for that func

 

 

this seems to work... but is it the proper way....

CCP = 0xD8; 
CLKPR = 0;

 

ccp_write_io() looks nicer :)

 

 

thanks

mitch
    

Last Edited: Sat. Sep 11, 2021 - 07:01 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi mitchjs,

 

Here are some examples of use for this function with one of the newer AVRs:  avr128db48-getting-started-with-xoschf/main.c at master · microchip-pic-avr-examples/avr128db48-getting-started-with-xoschf · GitHub

 

You have to include avr/cpufunc.h to use the function.

 

In short:

ccp_write_io((uint8_t *) &<REGISTER>, <DATA>);

 

So in your case that would be:

ccp_write_io((uint8_t *) &CLKPR, 0);

 

 

Best regards,
Amund Aune
Applications Engineer @ Microchip Norway
(The postings on this site are my own and don’t necessarily represent Microchip’s positions, strategies, or opinions. For official Microchip Support, please visit https://microchipsupport.force.com/s/)

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


Do you really want to use ccp_write_io() anyway? It will involve a call to libattiny1614.a:

C:\Program Files (x86)\Atmel\Studio\7.0\packs\atmel\ATtiny_DFP\1.8.332\gcc\dev\attiny1614\avrxmega3>avr-nm libattiny1614.a | grep ccp
ccp_write.o:
00000000 T ccp_write_io

whereas if you use __PROTECTED_WRITE() that is in the xmega.h header:

 

 

then (a) you don't need to specially include cpufunc.h as the normal include of io.h also leads to the include of xmega.h anyway when you are programming an Xmega chip and (b) there is no CALL/RET overhead to the lib code as it's an inline Asm macro.

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


Neither ccp_write_io nor _PROTECTED_WRITE works.

tiny1634 is not xtiny.

 

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

My bad. I misread it as 1614 not 1634. Oops. blush

 

libattiny1614.a does contain ccp_write_io() but libattiny1634.a does not. So the former is an Xmega but the latter is not.

 

Rather curiously however:

C:\Program Files (x86)\Atmel\Studio\7.0\packs\atmel\ATtiny_DFP\1.8.332\include\avr>grep CCP * | grep _SFR_IO8
iotn10.h:#define CCP _SFR_IO8(0x3C)
iotn102.h:#define CCP     _SFR_IO8(0x3C)
iotn104.h:#define CCP     _SFR_IO8(0x3C)
iotn1634.h:#define CCP     _SFR_IO8(0x2F)
iotn20.h:#define CCP _SFR_IO8(0x3C)
iotn4.h:#define CCP _SFR_IO8(0x3C)
iotn40.h:#define CCP _SFR_IO8(0x3C)
iotn5.h:#define CCP _SFR_IO8(0x3C)
iotn828.h:#define CCP     _SFR_IO8(0x36)
iotn9.h:#define CCP _SFR_IO8(0x3C)

so 1634 is among models that have a "CCP"

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

Yes. As long as you have a CCP register, you should have a macro to manipulate it.
Will it be addressed someday, but should I report it to a support case?
Please someone.cheeky

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

The issue seems to be this:

C:\>avr-gcc -E -dM -mmcu=attiny1614 -B "C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.8.332\gcc\dev\attiny1614"  - < NUL | grep ARCH
#define __AVR_ARCH__ 103

C:\>avr-gcc -E -dM -mmcu=attiny1634 -B "C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.8.332\gcc\dev\attiny1634"  - < NUL | grep ARCH
#define __AVR_ARCH__ 35

while avr/io.h has this:

#if __AVR_ARCH__ >= 100
#  include <avr/xmega.h>
#endif

So the reason io.h is not including xmega.h in the 1634 case is it only considers AVR architectures 100+ to be "Xmega" (and hence have CCP) but 1634, unlike 1614, is only architecture 3.5 (__AVR_ARCH__  = 35).

 

Sadly it's not possible to use xmega.h by a direct #include because it relies on a symbol CCP_IOREG_gc which usually takes the form (in the header for an Xmega) of:

typedef enum CCP_enum
{
    CCP_SPM_gc = (0x9D<<0),  /* SPM Instruction Protection */
    CCP_IOREG_gc = (0xD8<<0),  /* IO Register Protection */
} CCP_t;

what might work is to paste that in as well as the include of xmega.h.

 

This:

#include <avr/io.h>
#include <avr/xmega.h>

typedef enum CCP_enum
{
    CCP_SPM_gc = (0x9D<<0),  /* SPM Instruction Protection */
    CCP_IOREG_gc = (0xD8<<0),  /* IO Register Protection */
} CCP_t;


int main(void)
{
    _PROTECTED_WRITE(CLKPR, 0);
}

generates this for 1634:

    _PROTECTED_WRITE(CLKPR, 0);
  88:	90 e0       	ldi	r25, 0x00	; 0
  8a:	88 ed       	ldi	r24, 0xD8	; 216
  8c:	8f bd       	out	0x2f, r24	; 47
  8e:	90 93 53 00 	sts	0x0053, r25	; 0x800053 <__TEXT_REGION_LENGTH__+0x7fc053>

which seems to be what is required.

 

If only the iotn1634.h file had that enum definition in it then it would be safe to just include xmega.h and use _PROTECTED_WRITE()

 

As ccp_write_io() requires library code that would be more complex to support.

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

i see i opened a little can of worms...

 

doing this directly:

CCP = 0xD8; 
CLKPR = 0;

 

seems to work....

 

and is sts right for this register? (if one used the xmega _protected_write() )

90 93 53 00 	sts	0x0053, r25	; 0x800053 <__TEXT_REGION_LENGTH__+0x7fc053>

i made my own protected write...

#define _ATINY1634_PROTECTED_WRITE(reg, value)				\
	__asm__ __volatile__("out %[ccp], %[ccp_ioreg]" "\n\t"	\
				"out %[ioreg], %[val]"			\
				:					\
				: [ccp] "I" (_SFR_IO_ADDR(CCP)),		\
				[ccp_ioreg] "d" ((uint8_t)0xD8),	\
				[ioreg] "I" (_SFR_IO_ADDR(reg)),	\
				[val] "r" ((uint8_t)value))

 

 

mitch

 

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

oh the code generated by my macro looks right

 

 

 26e:	90 e0       	ldi	r25, 0x00	; 0
 270:	88 ed       	ldi	r24, 0xD8	; 216
 272:	8f bd       	out	0x2f, r24	; 47
 274:	93 bf       	out	0x33, r25	; 51