Calibration, OSCCAL and OCDEN

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

Hi.

If I have understood the datasheet and previous posts here the microcontroller can't read OSCCAL during a debug session. (ATmega32, JTAG with mkII). I presume that the register can't be written to either?

In my case there is a calibration routine that use a 32kHz crystal on TIMER 2 in the beginning of the program. So this calibration routine should work just fine during normal mode but will fail during debugging.

So how should I make this work? If OSCCAL can not be written to I can not change the clock speed meaning my program can't communicate (7.2 MHz) during debug. To at least check that the calibration routine works I have thought about storing the calibrating byte in EEPROM just to check the value.

I hope there is something that I have misunderstood though. Can someone clarify this for me?

My favorites:
1. My oscilloscope, Yokogawa DLM2024.
2. My soldering iron, Weller WD2M, WMRP+WMRT.
3. JTAGICE3 debugger.

Last Edited: Wed. Aug 24, 2011 - 06:08 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Who said that you cannot read OSCCAL? Try it for yourself.

Obviously OSCCAL is meaningless in the Simulator.

You may be confused about reading the factory calibration from a running program.
Older AVRs like the Mega32 do not have the SIGRD bit in the SPMCSR register. They have four factory calibrations. Only the 1MHz calibration goes into OSCCAL.

New AVRs have a RSIG bit or a SIGRD bit. You can read both the Signature and the factory calibration values.

OTOH, the newer AVRs have a single 8MHz calibration. You do not need to use SIGRD because you can simply read OSCCAL.

David.

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

Yes, in simulator OSCCAL is pointless but I am using the emulator.

I have previously only used OSCCAL with the Atmega48/168 series. But with them debugging is made with debugWire. In Atmega32 it is JTAG.

During debugging of Atmega32 in AVR Studio (emulator) the OSCCAL can not be read by the MCU. Others have posted the same information. This must be because that the OCDEN is set. But OSCCAL can be WRITTEN by the MCU so there is actually no problem, it just me who thought that I should see the result. (That i see as perfectly normal).
It is funny that it is possible to both read and write to OSCCAL manually in pause mode but that must be solved by Studio by clearing OCDEN as soon as the program is paused.

Anyway, the calibration works fine so the problem is solved. If I want to see the resulting OSCCAL I just stop and look at the final write that the MCU do to it.

My favorites:
1. My oscilloscope, Yokogawa DLM2024.
2. My soldering iron, Weller WD2M, WMRP+WMRT.
3. JTAGICE3 debugger.

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

Just add a line:

volatile static uint8_t osccal_copy = OSCCAL;

This should mean that you have read the value, and can read it in your debug session.

You use the same trick for reading UDR or other weirdo registers. e.g. make a copy of what you write or read into a memory copy.

David.

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

Quote:
I presume that the register can't be written to either?

There are those r,w,rw or inaccessible at all - that varies depending on OCDEN setting. AVRStudio Help explains that.

Quote:
If OSCCAL can not be written to I can not change the clock speed meaning my program can't communicate (7.2 MHz) during debug.

OCD has it's limitations and some tricks cannot be done.

I suggest you should define three firmware versions, like:

    1.Release, 2.Debug_OCD,
    3.Debug_assert
and to run on RC at (1 & 3) and on quartz on (2). No hardware changes are needed to switch versions. Define your fusebits in .elf section, disable uploading flash in debugger and use programmer mode to upload flash+fusebits.

Mind USART cannot be halted by OCD in (2) so you will not have problems with sending and receiving a byte as long as the other end of USART does not insist on push/timeout of multibyte data when you halted target in between transfers. Just halt cpu after full frame of data is transmitted/received.

Never tried that but it seems pretty easy.

No RSTDISBL, no fun!

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

My original reply was purely from memory.

Your comments about OSCCAL being inaccessible made me debug a mega128 program via a JTAGICE-1 clone with Studio4.

At all stages, I can read and write OSCCAL.
The program writes strings to the USART. So I can see the effect of different OSCCAL values. It displays exactly the same under JTAG as without.

Of course this may be a bug with mega128 / the clone / not having an 'r' in the month.

If pushed, I could try different MCUs or debuggers.

David.

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

Unlike m16/32, m128 has extended IOs.

No RSTDISBL, no fun!

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

@Brutte,

I have seen some brief posts!

I presume that you are saying "try it with a mega16"

So I tried the same program with a mega16. It debugs the same. I think you will find that OSCCAL is always outside the OUT and SBI range.

I am quite happy to try any debug operation. Please can you suggest something that will illustrate your theory.

David.

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

Quote:
I think you will find that OSCCAL is always outside the OUT and SBI range.

m16 and m32 do not have extended IO space and because of that some IOs have some restrictions(are inacessible).
    on m16 OSCCAL==OCDR==0x31+0x20 on m128 OSCCAL==0x22+0x20 and OCDR=0x6F+0x20
david.prentice wrote:

Please can you suggest something that will illustrate your theory.

Can you give a hint about what "your theory" in this context means?

No RSTDISBL, no fun!

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

bengtr stated in his original post that he could not read or write OSCCAL when using a JTAG debugger.
Butte also claimed that it is not possible to read or write OSCCAL when debugging.

I stated that I thought it was perfectly accessible.
I later tried it in real life with a mega128. It was accessible.
Brutte claimed that the mega128 was a special case.
I also tried it with a mega16. It was accessible. i.e. the program could read and write the values.

Ah-ha. I see what you are saying. The mega16 shares the address for the OSCCAL and OCDR registers. This does mean that you have to proceed with care.

There is obviously some mechanism that can distinguish between the two physically different registers. Otherwise, no mega16 AVR could ever use the RC oscillator under JTAG.

David.

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

mega16 data wrote:
In some AVR devices, this register is shared with a standard I/O location. In this case, the OCDR Register can only be accessed if the OCDEN Fuse is programmed, and the debugger enables access to the OCDR Register. In all other cases, the standard I/O location is accessed.

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

I get it. "Your theory" is about the fact some resources are inaccessible while debugging.

OCDR/DWDR (should be) used for communication between application <--> debugger. On some AVRs these have separate locations, but on chips without external IO and where there are many peripherals, a shadowing is made on "least disturbing" IO locations.

When your OCDEN is programmed you can both read and write to/from 0x31+0x20 (on m16) as it is OCDR that is addressed.

What is more, each time you write to OCDR (like "out OCDR,temp"), your JTAG tool (JTAGICE MK1 dongle) passes the uint8_t which should be displayed in AS message window. Unfortunately AFAIK this feature does not work on Mk1 but ~works on Mk2.
Search for "DIDR/OCDR event".

If you want to know more about OCDR, then here is my unfinished post about its usage attempt in C:
https://www.avrfreaks.net/index.p...

Quote:
Otherwise, no mega16 AVR could ever use the RC oscillator under JTAG.

It is the register that is inaccessible, not the RC oscillator. I suppose OSCCAL is preloaded with calibration value, independent of OCDEN value.

So the question is:
Can you start m16 debugging session and spin up/down F_CPU by clicking in AS IO registers?
I would be really surprised to see that.
Set some PWM, tick "run timers in halt state" and blink some LED to observe..

No RSTDISBL, no fun!

Last Edited: Wed. Aug 24, 2011 - 02:17 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Can you start m16 debugging session and spin up/down F_CPU by clicking in AS IO registers?

I am 99.9% certain I've actually done that. I often wire up a couple of buttons to OSCCAL++ and OSCCAL-- followed by a printf() to the UART (idea is to try the buttons until something sensible appears) and what's more I almost always (while developing) run with a JTAGICEmkII attached to a mega16. So I think this does work - but I guess I'm going to have to try it again to refresh my memory (it was probably >5 years go I was last playing with this).

BTW I remember trying to use the OCDR mechanism at the time (not realising they were co-located) and I could never get OCDR (from a mega16) to work - this would have been Studio 4,12 or 4.13 I guess?

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

Here is the topic about OCDR event:
https://www.avrfreaks.net/index.p...
Now back to:

    m16, OCDEN programmed,
    writing to OSCCAL
ATMega16 datasheet describes what happens when in this situation you write to OCDR/OSCCAL. I tried that with Mk1 and I didn't notice any messaging in AS so my conclusion was:
"This feature will be added in the future release of AS17. Atmel".

I would be surprised if there was a method to distinguish both registers, but how to do it if not with OCDEN?

No RSTDISBL, no fun!

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

This is exactly what my test program was doing. i.e. stepping through a range of OSCCAL values while displaying text via the USART.

The mk1 clone obviously manages to distinguish between OCDEN and OSCCAL as appropriate. But with a few caveats. e.g. running to a breakpoint is fine.

Giving a pending JTAG command is not fine. I presume that the debugger keeps a copy of OSCCAL, and ensures that the AVR has this when running. When stopped, the debugger will communicate via OCDR. Bad news if they get confused.

I might try with a Dragon or mkII to see if things are different.

David.

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

Quote:
This is exactly what my test program was doing.

How did you know OSCCAL was written, if you were displaying text via USART then? At some moment the transmission became jammed/synchronized because RC frequency changed?

Could you please post a simple sequence of code so that I could reproduce that behavior (Mk1+m16)?

Quote:
The mk1 clone obviously manages to distinguish between OCDEN and OSCCAL as appropriate.

OCDR and OSCCAL :)

I wonder how is that made. OP suggests the OCDEN is used to switch between one and the other on-the-fly. Hard to believe as AFAIK there is no direct explicit access to fusebits during debugging session in AS.

OTOH the EEPROM fuse or OCDEN can be saved restored, but I thought it is before, not during session.

No RSTDISBL, no fun!

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

Quote:

How did you know OSCCAL was written, if you were displaying text via USART then? At some moment the transmission became jammed/synchronized because RC frequency changed?

The whole idea is that the int-RC is not great for UART so if you slowly sweep OSCCAL up or down (a for() loop or using buttons) there's generally about 10-15 values where a UART printed message comes through cleanly and ultimately you take the OSCCAL for the middle one and hard code it into OSCCAL for subsequent UART use. If OSCCAL++/OSCCAL-- wasn't writing the register this mechanism simply would not work. The very fact it switches between UART working and not shows the CPU frequency is being varied.

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

Quote:

ultimately you take the OSCCAL for the middle one and hard code it into OSCCAL for subsequent UART use.

LOL--there is a caveat there. If you have a totally "sweet" internal oscillator spot-on at 8MHz (or whatever), the "middle" value could be in the discontinuity and may ultimately be a "bad" value.

(See Figure nn-mm. Calibrated 8 MHz RC Oscillator Frequency vs. Osccal Value -- you see two crossings of the nominal value. So you could (will) get several "good" values when raming up, then some "bad" values, then another set of "good" values. You should be OK if you pick the middle of a set of good values, as opposed to splitting the difference between the highest and lowest "good" values found.

I ran into this when doing an "auto-cal" against a 32kHz crystal, and took a bigger step in the "right" direction when I was far from close as in an initial calibration. The code whipsawed and never settled; some units would land on the discontinuity and some might jump to either side.)

I try to tune to 7.3728MHz, which gets me away from the tricky area.

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

Quote:
The very fact it switches between UART working and not shows the CPU frequency is being varied.

Hope we are still talking about OCDEN==programmed situation. If so, then we have 16784-th bug in Atmel's datasheet and OCDR is inaccessible in m16.

The example with USART given shows modification of the IO accessed by CPU itself, not OCD. That is enough for OP purpose if we confirm it works with OCDEN programmed, and during debugging session.

However, can somebody give an example of successful modification of OSCCAL via OCD?

No RSTDISBL, no fun!

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

// Standard Input/Output functions
#include 
#include 

void main(void)
{
    char factory, oscdef;
    long oscillator = 8000000L;
    char *name = "8.00MHz";
#if defined(_CHIP_ATMEGA128_)
    UCSR0A = 0x00;
    UCSR0B = 0x18;
    UCSR0C = 0x06;
    UBRR0H = 0x00;
    UBRR0L = 0x33;
#define UBRRL UBRR0L
#else
    UCSRA = 0x00;
    UCSRB = 0x18;
    UCSRC = 0x86;
    UBRRH = 0x00;
    UBRRL = 0x33;               // 0x33;
#endif
    factory = OSCCAL;
    oscdef = factory * (oscillator / 8000000.0);        //simplistic good guess

    while (1) {
        char step, i, cnt;
        for (cnt = 32, step = oscdef - 16; cnt--; step = (step + 1)) {
            OSCCAL = factory;   //so legible printf()
            UBRRL = 8000000L / 16 / 9600 - 1;
            printf("\r\n8MHz CAL=#02X [#02X] ", factory, step);
            delay_ms(100);      //in case we have interrupt transmission
            OSCCAL = step;      //do string at this calibration:
            UBRRL = oscillator / (16L * 9600) - 1;
            printf("#s [%02X]:ABCDEFGHIJKLMNOPQRSTUVWXYZ", name, step);
            for (i = 0; i < 10; i++) {
                PORTB ^= (1 << 0);      //always nice to flash an LED
                delay_ms(100);
            }
        }

    };
}

You can run this code on a mega16 in a Studio4 debug session. Do not try two JTAG commands at once!

It runs with or without OCDEN fuse if you are not in a debug session.

@theusch,

I am well aware of the risk of a discontinuity. This is why a 'human' is involved. You look at 12 good strings on the terminal and choose a 'middle' value.

If you automate the calibration, as in AVR053, you do a couple of checks to make sure you have not got something 'on the edge'.

Yes. I just set the 'oscillator' variable to 7372800 and you can choose a suitable OSCCAL value.

David.

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

Quote:
It runs with or without OCDEN fuse if you are not in a debug session.

I have just tried:

ISR(TIMER1_COMPA_vect){
	OCDR++;	
}

plus initialization, AS4.18b692 + JTAGICEMk1 clone.
tested on:

    m16, rev. J m162, rev. H
(both chips share OSCCAL and OCDR)

I confirm this code modifies OSCCAL and RC frequency, independent of OCDEN fuse setting. Same when free running and during debugging session.

I do not have m32, but it seems OP is not going to have any troubles with RC calibration. Even while debugging.

Anybody has an idea how to write to OCDR on these chips to force IDR event?

No RSTDISBL, no fun!

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

I have never written to OCDR in my life. I assume that C-SPY or Studio will perform any necessary black magic.

I just run to breakpoints, inspect Watch variables, registers etc.

David.

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

Quote:
I have never written to OCDR in my life.

As clawson wrote:
m16, rev. P, p.227 wrote:
In some AVR devices, this register is shared with a standard I/O location. In this case, the OCDR Register can only be accessed if the OCDEN fuse is programmed, and the debugger enables access to the OCDR Register. In all other cases, the standard I/O location is accessed.

I did try to Mk1 write m128 OCDR (separate OSCCAL and OCDR) but also without success. That is, I think my JTAGICE Mk1 clone does not want to enable access to OCDR and I didn't see the options in AS to enable that.

As described in the link given:,

dr.mike wrote:
JTAGICEII & AVRStudio 4.18

So,
david.prentice wrote:
I might try with a Dragon or mkII to see if things are different.

Please do.

AS 4.18 Mk2 User's Guide, options wrote:
-Enable I/O Debug Register (IDR) in run mode:

When checked, this option allow parts which share the same I/O location for IDR and OSCCAL to output IDR events. IDR events are generated when the application writes to the IDR register.

Note: IDR is also known as OCDR, and is not available on debugWIRE OCD

IMHO your RC calibration code is not going to work with a dongle which enables access to OCDR on shared OCDR/OSCCAL. But as OP does not use OCDR functionality it seems, that is not a problem if s/he ticks the right option.

No RSTDISBL, no fun!

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

Sure enough, when debugging the program with a Dragon, you cannot see OSCCAL in the I/O View. (always=0)

I added this line so that I could see the Watch window

           osccal_copy = OSCCAL;

In practical terms, the program runs ok. You can step, run to breakpoints, examine Watches etc.

As I said earlier, I have never used OCDR. Nor do I envisage ever wanting to.
Can you suggest some worthwhile use of OCDR?

I presume that a mkII will behave the same as a Dragon.

Incidentally, this program shows how regular ascii text will display quite well, even with an iffy baud rate. The reason being that printable test is only seven bits, and the low bits are sent first. If you use the parity bit, you will catch the false bits. Likewise all UARTs will catch Framing errors.

All the same, choosing the middle setting of 18 apparently 'perfect' strings is a pretty good calibration.

David.

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

Quote:
In practical terms, the program runs ok.

I was asking about "Enable I/O Debug Register (IDR) in run mode" option for Dragon and Mk2. Does it work as expected? That is, if you set this option, no OSCCAL access on m16 is possible? And when disabled, you do write to OSCCAL on m16?

Quote:
Can you suggest some worthwhile use of OCDR?

I have already posted the link(or two). I must tell you functionality described below does not work currently as it should, because of.. yes, proprietary AS. But I think that perhaps some day it could be fixed (under GDB or Eclipse of course)..

Anyway, some microcontrollers (like ARMs for example) have an additional USART (I mean additional, except for those that are used in application) for TX in debug mode only. And application running in debug mode can send data through it. Like:

debug_print("Initializing IP stack");

for example. And this message is displayed on terminal to see what the software is doing right now, without halting the process(you could also use a regular USART for this, but you need to have a spare one).

Atmel's OCDR is "a kind of" clever pretending we have additional USART for printing messages to Message window of Debugger Software. It does not require additional hardware - all this is made through JTAG dongle.

You write the code as usual, filling it with debug_print("Ala ma kota") kind of message strings and it is tagged with a distinct 8-bit serial number (lets suppose 0x74 for this message). The string is not placed in flash itself, but only in a section of elf file (so it does not consume on-board resources). You can tear that messages out from elf to some txt file if you like.

Now, when a cpu hits this line of code, it simply executes:

Quote:

out OCDR,temp

where "temp" contains 0x74. This forces an "IDR dirty" event in debugger dongle and it reports 0x74 to debugger software which simply searches the section of elf file for the string tagged with 0x74. When it finds the string, it displays:

>>"Ala ma kota"

on terminal.

Simple as that, but AFAIK does not work, neither on mk1 nor on any other dongle. AS does not support the debugging strings so it displays
"IDR dirty event, OCDR=0x74" currently. At least that is what other Freaks with mk2 report.

No RSTDISBL, no fun!

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

Quote:

Simple as that,

That would require the PC side debugger to be modified to know to look up string 0x74 in the .elf? How do you plan to modify AVR Studio's internal debugger code?

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

Quote:
That would require the PC side debugger to be modified to know to look up string 0x74 in the .elf? How do you plan to modify AVR Studio's internal debugger code?

david wanted to know what OCDR is for and my answer is only an explanation.

I will answer your question in here:

https://www.avrfreaks.net/index.p...

No RSTDISBL, no fun!

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

I guess the intended use of OCDR is a bit simpler. It's a bit like putting the old LED flash thing dotted around your code to see which bits are executing and which aren't. With that you are probably limtied to 8 marker LEDs, with OCDR you have 256 (or is it just 128 - I'm never clear if it's 7 or 8 bit?) such marker points. I guess you could use it for something like code coverage checking?

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

Quote:
with OCDR you have 256 (or is it just 128 - I'm never clear if it's 7 or 8 bit?)

It seems it is 256. The _BV(7) is read out as "1" if dongle didn't report previous value yet.

Quote:
I guess you could use it for something like code coverage checking?

OCDR is too slow for that I am afraid. It is a general question about tracing.

IMHO it is much easier to do:

lds temp,TRACE_BYTE_123
dec temp
sts TRACE_BYTE_123,temp
brbs SREG_Z,jump_to_break

and to dump all TRACE_BYTE_XXX data when some asm("break") is hit to know how many times the code executed a specific sequence(if ever). Influence on timing is negligible (6 clks).

I do not know about some off-the-shelf profilers/coverage analyzers for GNU AVRs that would automatically append __attribute__(()) to appropriate functions or displayed warning when some TRACE_BYTE_YYY==0.

All debugging ideas fall into making it the least intrusive possible. OCDR meets that requirement at no cost (if ever made operational)!

No RSTDISBL, no fun!