CLKPR is not set on higher optimization levels

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

OK, I have again run into issues setting my Clock prescaler.

I am using the ATMega324PB in a custom board and in the Xplained Pro board. I have a clock failure every time programming the Xplained Pro (and it's consistent across all Xplained, must be a bug in the board) and ALSO I have come across a documented die error where once the clock failure is detected only a power cycle (NOT a reset) will "fix" it. I am trying to work around this error, and also make code work for the custom boards, which do not have this issue.

So I am using the following C code:

if (XFDCSR & (1<<XFDIF)) // indicates clock failure
{
    CLKPR = (1<<CLKPCE);
    CLKPR = 0;
    return 1; // clock failure
}
else // external crystal
{
    CLKPR = (1<<CLKPCE);
    CLKPR = (1<<CLKPS0);
    return 0; // external crystal is good, F_CPU set to 8MHz
}

When I have Debug enabled (-O1), this works just fine to set the Clock Prescaler to 0 on failure and 2 when it uses the external oscillator.

When I switch to Release (-Os), it appropriately changes the clock to 8MHz on failure, but stays at 16MHz when it doesn't have an internal failure.

What's more, when I use the same techniques on the custom board (which don't have a failure) nothing ever seems to get set.

 

What is going on??

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

This is why there's an Asm macro for this. Read the libc manual. 

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

Yeah, I get it. It turns out, however, that my chip is not supported by that header file. That's what I get for seeing a latest and greatest thing and trying to use it.

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

dtreth@gmail.com wrote:
When I have Debug enabled (-O1), this works just fine to set the Clock Prescaler to 0 on failure and 2 when it uses the external oscillator. When I switch to Release (-Os), it appropriately changes the clock to 8MHz on failure, but stays at 16MHz when it doesn't have an internal failure. What's more, when I use the same techniques on the custom board (which don't have a failure) nothing ever seems to get set.

dtreth@gmail.com wrote:
It turns out, however, that my chip is not supported by that header file.

 

As PB might indeed have an "enhanced" clock section, I'd think that the gurus here would be able to help -- if you give enough info.

 

-- Show the generated code for -O1 and -Os.

-- (then the PB people and others that might like to poke at the datasheet and dev boards and similar could make educated guesses)

 

I read and re-read -- does the code always take the "failure" branch with -Os?  I'm not clear.  If it always takes that branch that would point to the if(), wouldn't it?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

OK so, how do I show the ASM generated from the C Code? I actually went into the header file and ripped out the enum and function defined for the 324PA and I am using that to great effect. It makes me very uneasy to do that, though. The problem appears to be that Atmel has yet to add the 324PB to ANY of their header files (it's not even in the io.h base file, some insane macro builds the header file name at the end, which ALSO means it's very difficult for me to check what CPU is defined in the project, but I have mostly worked around that....)

And yes, you seem to have understood my problem statement. I just don't know enough about C and the AVR-GCC to know how to actually figure out what the problem is based upon that. All those registers are made by macros that mark them volatile, so I would assume it'd be smart enough to, well, not be so smart.

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

dtreth@gmail.com wrote:
OK so, how do I show the ASM generated from the C Code?

 

Look at the .lss file in the Project's Output folder.

 

 

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

dtreth@gmail.com wrote:
The problem appears to be that Atmel has yet to add the 324PB to ANY of their header files (it's not even in the io.h base file, some insane macro builds the header file name at the end, which ALSO means it's very difficult for me to check what CPU is defined in the project, but I have mostly worked around that....)

Interesting assertion(s).

 

A recent Studio7 install shows:

...where I do Project..Properties..Device.

dtreth@gmail.com wrote:
(it's not even in the io.h base file, some insane macro builds the header file name at the end,

lol -- indded, I see that.  But the restoof your assertions:

dtreth@gmail.com wrote:
which ALSO means it's very difficult for me to check what CPU is defined in the project,

I showed one way above (the "right" way?), but in addition the Solution Explorer will show which header file(s) are being used under Dependencies:

 

 

I still want to see the code for your fragment at the two optimization levels.

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

???

OP use a 324PB not a 328PB

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

sparrow2 wrote:
OP use a 324PB not a 328PB

lol -- that's what I started with with my "experiments"...  redo ...

 

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

OK so, I actually CAN select the 324PB (you're searching for the 328, I have made that mistake before, but maybe you're showing me what you found with the 328PB[as an aside you might want to update your ASF because the 328PB IS defined in the headers]) but as you see in the io.h header file there is no macro for the chip directly. I could write a thing that sets a program-wide macro based upon the __AVR_DEV_LIB_NAME__ macro, but that seems brittle (for when they actually do add the 324PB to the headers). And I don't actually need to know by looking at it, I meant how to check programmatically (so I can use a source file for both the 328PA and the 324PB chips I have). You said you showed something "above" but I don't see it, unless you mean the chip select screen when you start up a new project.

OK so, the .lss files: I don't have them because I ripped that macro out of the avr/power.h header. If I have some time today I'll try to recreate it.

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

dtreth@gmail.com wrote:
unless you mean the chip select screen when you start up a new project.

Well, I guess it does show up when doing a new project.  But in my experiments above, I didn't start a new project.  I took an existing project, and did

theusch wrote:
Project..Properties..Device.

...which you can do at any time to change -- or >>SEE<< -- what device is being targeted.  Your complaint was that it was "very difficult".  IMO it isn't that "difficult" once you know where to look, and also the Dependencies gives you a very strong hint as it shows the particular chip-include file.

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

OK, so... I am unsure which part of "programmatically" isn't being properly communicated here....

At any rate,

if (XFDCSR & (1<<XFDIF)) // indicates clock failure
     9b4:	80 91 62 00 	lds	r24, 0x0062
     9b8:	81 ff       	sbrs	r24, 1
     9ba:	06 c0       	rjmp	.+12     	; 0x9c8 <main+0x14>
{
    CLKPR = (1<<CLKPCE);
     9bc:	e1 e6       	ldi	r30, 0x61	; 97
     9be:	f0 e0       	ldi	r31, 0x00	; 0
     9c0:	80 e8       	ldi	r24, 0x80	; 128
     9c2:	80 83       	st	Z, r24
    CLKPR = 0;
     9c4:	10 82       	st	Z, r1
     9c6:	06 c0       	rjmp	.+12     	; 0x9d4 <main+0x20>
return 1; // clock failure
}
else // external crystal
{
    CLKPR = (1<<CLKPCE);
     9c8:	e1 e6       	ldi	r30, 0x61	; 97
     9ca:	f0 e0       	ldi	r31, 0x00	; 0
     9cc:	80 e8       	ldi	r24, 0x80	; 128
     9ce:	80 83       	st	Z, r24
    CLKPR = (1<<CLKPS0);
     9d0:	81 e0       	ldi	r24, 0x01	; 1
     9d2:	80 83       	st	Z, r24

is from the -O1 build and

if (XFDCSR & (1<<XFDIF)) // indicates clock failure
     9be:	80 91 62 00 	lds	r24, 0x0062
     9c2:	81 ff       	sbrs	r24, 1
     9c4:	06 c0       	rjmp	.+12     	; 0x9d2 <main+0x1e>
{
    CLKPR = (1<<CLKPCE);
     9c6:	80 e8       	ldi	r24, 0x80	; 128
     9c8:	80 93 61 00 	sts	0x0061, r24
    CLKPR = 0;
     9cc:	10 92 61 00 	sts	0x0061, r1
     9d0:	06 c0       	rjmp	.+12     	; 0x9de <main+0x2a>
    return 1; // clock failure
}
else // external crystal
{
    CLKPR = (1<<CLKPCE);
     9d2:	80 e8       	ldi	r24, 0x80	; 128
     9d4:	80 93 61 00 	sts	0x0061, r24
    CLKPR = (1<<CLKPS0);
     9d8:	81 e0       	ldi	r24, 0x01	; 1
     9da:	80 93 61 00 	sts	0x0061, r24

for the -Os build, although I did both with DEBUG because I needed the c code symbols to tell where it was. I looked at the Release code and it seems to be the same as the debug when switched to -O2 excapt for the lines of C code in there for ease of reference.