## mega3208 - Prescaler always on?

14 posts / 0 new
Author
Message

I'm using a mega3208 and trying to understand the main clock, and prescaler activity.

I would like the main clock to run at 20Mhz, so my fuses are thus:

So, FREQSEL is 20Mhz and OSCLOCK is clear.

Then my startup code looks like this:

CLKCTRL.MCLKLOCK = 0; // Ensure clock-lock is clear.
CLKCTRL.MCLKCTRLB = 0; // Switch off the pre-scaler.
uart_init(0, 115200UL);

Then uart_init(...) like this: (F_PER is: #define F_PER 20000000)

void uart_init(uint8_t uart, uint32_t baud)
{
if(uart >= UART_MAX_UARTS) // sanity check.
{
return;
}

// First set up the ring buffers for this UART
ring_buffer_init(&uart_rx_rb[uart], &uart_rx_buffer[uart][0], UART_RX_BUFF_SIZE);
ring_buffer_init(&uart_tx_rb[uart], &uart_tx_buffer[uart][0], UART_TX_BUFF_SIZE);

// Now configure the registers for this uart
if(uart==0)
{
PORTA_DIRSET = (1<<0);	// TX on PA0
PORTA_DIRCLR = (1<<1);	// RX on PA1

PORTA_OUTSET = (1<<0); // set TX high.

// Baud
USART0_BAUD = ((64*F_PER) / (16*baud));

// RX Interrupt enable
USART0_CTRLA = USART_RXCIE_bm;

USART0_CTRLB = USART_RXEN_bm | USART_TXEN_bm;
}
}

And then I send 0x55 out of uart, and check it with my oscilloscope, thus:

Which is clearly 19200 bps, not 115200 bps.

But - that is exactly 1/6th of the desired rate, which is what the default clock prescaler is. But that should be off, as per my startup code.

No matter what I do with the PEN bit of MCLKCTRLB, the baudrate remains the same. It does not change either way.

What have I missed?

SpiderKenny
@spiderelectron
www.spider-e.com

Last Edited: Fri. Jul 20, 2018 - 09:52 AM

1/6th seems an "odd" division. Scalers usually work in binary multiples. I could understand 1/4 or 1/8 perhaps but not 1/6th ??

Ah yes, but the 3208 is a remarkable beast with fractional prescalers in various places. See 0x08 above.

SpiderKenny
@spiderelectron
www.spider-e.com

And the default prescaler is: 0x08 (which is 1/6th).

SpiderKenny
@spiderelectron
www.spider-e.com

I notice from reading the datasheet:

Yet I don't see CCB in your code ?

EDIT oh and what's more:

So the curious /6 is the power on default. So you simply aren't writing to this register!

Last Edited: Fri. Jul 20, 2018 - 10:07 AM

Am I not? What does this do then:

(As per my OP) :

CLKCTRL.MCLKLOCK = 0; // Ensure clock-lock is clear.
CLKCTRL.MCLKCTRLB = 0; // Switch off the pre-scaler.
uart_init(0, 115200UL);

SpiderKenny
@spiderelectron
www.spider-e.com

You do know what CCP is don't you? You can't just do:

CLKCTRL.MCLKCTRLB = 0; // Switch off the pre-scaler.

The write will be ignored because you have not enabled configuration change protection.

What's more CCP requires that you write the magic key value to the CCP register THEN you make the write to the register that is protected WITHIN FOUR MACHINE CYCLES. This may or may not be achievable in plain. I think most libraries provide some kind of hand crafted macro writing in inline Asm that does the CCP write then the SFR write in a guaranteed less than 4 cycles.

also...

Last Edited: Fri. Jul 20, 2018 - 10:18 AM

Ah right - sorry _ i get it now.]

I need to write to CCP first... d'oh!

I do know about CCP, I just missed the subtle clue int he doc.

Thanks!

SpiderKenny
@spiderelectron
www.spider-e.com

Not sure if you are using GCC but I just found something I never knew existed (I don't remember seeing this documented in the user manual):

D:\atmel_avr\avr8-gnu-toolchain\avr\include\avr>type xmega.h
/* Copyright (c) 2012 Joerg Wunsch

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.

* Neither the name of the copyright holders nor the names of
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. */

/* $Id$ */

/*
* This file is included by <avr/io.h> whenever compiling for an Xmega
* device.  It abstracts certain features common to the Xmega device
* families.
*/

#ifndef _AVR_XMEGA_H
#define _AVR_XMEGA_H

#ifdef __DOXYGEN__
/**
\def _PROTECTED_WRITE
\ingroup avr_io

Write value \c value to IO register \c reg that is protected through
the Xmega configuration change protection (CCP) mechanism.  This
implements the timed sequence that is required for CCP.

Example to modify the CPU clock:
\code
#include <avr/io.h>

_PROTECTED_WRITE(CLK_CTRL, CLK_SCLKSEL0_bm);
\endcode
*/
#define _PROTECTED_WRITE(reg, value)
#else  /* !__DOXYGEN__ */
#define _PROTECTED_WRITE(reg, value)                            \
__asm__ __volatile__("out %[ccp], %[ccp_ioreg]" "\n\t"        \
"sts %[ioreg], %[val]"                   \
:                                        \
[ccp_ioreg] "d" ((uint8_t)CCP_IOREG_gc),       \
[val] "r" ((uint8_t)value))
#endif /* DOXYGEN */

#endif /* _AVR_XMEGA_H */

So PROTECTED_WRITE() would seem to be the "official" way to handle this.

EDIT: Oh I see, xmega.h is included when you use <avr/io.h> if you are building for Xmega (and I assume that also mean XTiny):

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


but despite it having Doxygen I'm still not seeing where this is mentioned in the AVR-LibC manual??

Last Edited: Fri. Jul 20, 2018 - 10:26 AM

In Studio 7 the following code:

CPU_CCP = CCP_IOREG_gc;
CLKCTRL.MCLKCTRLB = 0;

Compiles as:

  d0:	88 ed       	ldi	r24, 0xD8	; 216
d2:	84 bf       	out	0x34, r24	; 52
d4:	10 92 61 00 	sts	0x0061, r1	; 0x800061 

So that fits into the 4-cycle limit.

**EDIT** But I'll use PROTECTED_WRITE anyway.

Thanks again.

SpiderKenny
@spiderelectron
www.spider-e.com

Last Edited: Fri. Jul 20, 2018 - 10:25 AM

I don't think I am Xmega or Xtiny, it's one of the new 0-Series.

SpiderKenny
@spiderelectron
www.spider-e.com

Yeah, they are effectively Xmega's in sheep's clothing. So things Xmega apply a lot more to them than anything to do with traditional Tiny or Mega AVRs. In fact the CCP thing is a case in point - it was added when Xmega were born and is characteristic of Xmega family chips. Also the very fact that the C compiler sees these as

__AVR_ARCH__ >= 100

shows that it, too, sees them as effectively Xmega.

The only people unable to admit this seems to Microchip's marketing/naming department.

It is a source of some confusion as people with "mega" experience are going to come to these thinking they are just like all previous mega when they are really a radically different design. In the old days mega UARTs had register with names like UCSRA but now you have USART0_CTRLA etc.

No existing "mega" ever had anything like this either...

Last Edited: Fri. Jul 20, 2018 - 11:02 AM

This is what I have done for the M4809 to run @20MHz. (sorry for the bad language used.... )

; Select 20 MHz internal oscillator
clr		temp
ldi		temp1, CPU_CCP_IOREG_gc
sts		CPU_CCP, temp1
sts		CLKCTRL_MCLKCTRLA, temp

; This disables the divisor and allows chip to run at full spped
clr		temp
ldi		temp1, CPU_CCP_IOREG_gc
sts		CPU_CCP, temp1
sts		CLKCTRL_MCLKCTRLB, temp		; Clear CLKCTRL_PEN_bm

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

You guys have been very helpful once again.

I should have guessed it would be CCP, and once it was pointed out it was obvious!

Guess I couldn't see the woods for the trees.

BTW, I'm loving the 0-Series, they are a great fit for my products. Especially having 3 UARTS and pin-swapping. What a great little device.

SpiderKenny
@spiderelectron
www.spider-e.com