PIC 12F509 OSCCAL calibration - I just don't get it?!

Thread Starter

stormBytes

Joined Jan 26, 2010
43
Hey Folks,

So basically, I'm following Gooligum's Tutorial series on PIC , a fine work I might add, and working with the PIC 12F509 emulated through Real Pic Simulator. I'm confused about the whole OSCCAL thing.

Here's my code:

Rich (BB code):
 ;    File Name:                      L1-Turn_on_LED.asm                                                                     ;        Date:                           08-12-2010                                                                                                                 ;    Version:                        0.1           ;        Architechture:           Baseline PIC                                                               ;    Micro:                  12F509                                    
  ;     Description:            This code turns on an LED light  
  ;     Pin Assignment:         GP01 output, END         
  ;     **************************************************************************** 
        list            p=12F509                ; Specifies PIC to be used                                              #include        <p12f509.inc>   ; Processor-specific header file  
  
  ;     Config Bits:  
        __CONFIG        _MCLRE_ON & _CP_OFF & _WDT_OFF & _IntRC_OSC 
  ;     **************************************************************************** 
  
  ;     Reset Vector: 
  RESET CODE    0x3FF                   ; IntRC cal value stored at 0x3FF as 'MOVLW k'                                                                  ; where 'k' is a literal value.                         movlw   OSCCAL                  ; Move cal value in W to OSCCAL register 
  
  ;     Main Program *************************************************************** 
  start CODE 
                movlw   b'111101'               tris    GPIO                              ; Set GP1 as Output 
                movlw   b'000010'               movwf   GPIO                     ; Set GP1 to Output HIGH 
                goto    $                               ; Infinite loop 
        End
As I understand from reading the tutorial (baseline, lesson-01), Microchip inserts a default calibration value at 0x3FF, wrapped in a 'movlw' instruction.

In my code,

Rich (BB code):
RESET        CODE    0x3FF

tells the processor to execute the instruction ("movlw k") situated at 0x3FF, which copies the OSCCAL to W. Seeing as 0x3FF is the last memory address, Gooligum says that the "pointer" wraps back around to the first memory address (0x000h).

For some reason, in my simulation software (Real Pic Simulator) I get an "Out of Code" error generated from this line. I don't understand why this is happening. Even if (in simulation) the 0x3FF memory address is empty, the program should still wrap around to 0x000h and proceed, no?

I'm a total newbie so I ask that anyone kind enough to respond please consider that. I don't know much of the tech-jargon.

Help!
 

eblc1388

Joined Nov 28, 2008
1,542
For some reason, in my simulation software (Real Pic Simulator) I get an "Out of Code" error generated from this line. I don't understand why this is happening. Even if (in simulation) the 0x3FF memory address is empty, the program should still wrap around to 0x000h and proceed, no?
You are right, the program execution SHOULD wrap around to 0x0000 so in my opinion this is likely an "unimplemented" feature of the Simulator rather than a bug/problem.

It is common for most simulators to leave some features as unimplemented.

Have you checked with the designer about this, through the product webpage "Contact" link? Maybe it will be implemented in the next upgrade.
 

Markd77

Joined Sep 7, 2009
2,806
I'm not really familiar with the CODE thing, but there doesn't seem to be anything that says the main code starts at 0x000.
Maybe if you change the line to:
start CODE 0x000

If you put the retlw instruction after the RESET code, maybe that will simulate OK.
 

Thread Starter

stormBytes

Joined Jan 26, 2010
43
Actually I removed the "code" directive - it was freezing things up!

The main issue is that I don't get why it's not wrapping to the top of the program code. In Gooligum's sample code he's not pointing to 0x3FF but to 0x000
 

AlexR

Joined Jan 16, 2008
732
In the PIC12F509 the last memory address (0x03FF) always contians the instruction movlw XX where XX is the calibration factor for that chip. Pointing the rest vector to 0X03FF picks up the calibration factor and places it in the W register. The PC (program counter) then rolls over to 0x0000 and at that location you must have an instruction to save the calibration factor into the OSCCAL register.
So your program should read
Rich (BB code):
  ;    File Name:                   L1-Turn_on_LED.asm                            
  ;    Date:                        08-12-2010 
  ;    Version:                     0.1           
  ;    Architechture:               Baseline PIC
  ;    Micro:                          12F509                                    
  ;     Description:            This code turns on an LED light  
  ;     Pin Assignment:         GP01 output, END         
  ;     **************************************************************************** 
        list            p=12F509                ; Specifies PIC to be used                                              
#include        <p12f509.inc>   ; Processor-specific header file  
  
  ;     Config Bits:  
        __CONFIG        _MCLRE_ON & _CP_OFF & _WDT_OFF & _IntRC_OSC 
  ;     **************************************************************************** 
  
  ;     Reset Vector: 
  RESET CODE    0x3FF                                               ; Move cal value in W to OSCCAL register 
  
  ;     Main Program *************************************************************** 
  start CODE     0x0000
                movwf   OSCCAL                                        ; update register with factory cal value 
                movlw   b'111101'               tris    GPIO        ; Set GP1 as Output 
                movlw   b'000010'               movwf   GPIO        ; Set GP1 to Output HIGH 
                goto    $                               ; Infinite loop 
        End
 

eblc1388

Joined Nov 28, 2008
1,542
Pointing the rest vector to 0X03FF picks up the calibration factor and places it in the W register.
For 12F509, this reset address is hard coded into the PIC PC and the instruction at 0x03FF will be executed after reset regardless of whether user has pointed the reset vector to it or not, nor you can change this behavior.

i.e. one don't have to explicitly add codes in a program for this to happen.

So for all practical purposes the user code START or RESET address can be considered to be 0x0000, with the W then containing a value which user can simply ignore or placed into OSCCAL for frequency adjustment.
 

Thread Starter

stormBytes

Joined Jan 26, 2010
43
For 12F509, this reset address is hard coded into the PIC PC and the instruction at 0x03FF will be executed after reset regardless of whether user has pointed the reset vector to it or not, nor you can change this behavior.

i.e. one don't have to explicitly add codes in a program for this to happen.

So for all practical purposes the user code START or RESET address can be considered to be 0x0000, with the W then containing a value which user can simply ignore or placed into OSCCAL for frequency adjustment.
I was reading the reply just above yours and found you beat me to it! I had gotten a response to my question on Microchip forums with exactly this point; the PIC picks up the OSCCAL from 0x3FF right after reset, so effectively 0x000h is the 'effective Reset vector'. I don't understand why it's called a "reset vector". Maybe that's just a definition issue I'm missing.

Wouldn't it be better off called a reset "address" ? Vector seems to 'point somewhere' and well... It's not being pointed anywhere. It's already there :)
 

Thread Starter

stormBytes

Joined Jan 26, 2010
43
Wow very cool! Where did you get this? I mean.. not the obvious! I downloaded the datasheet. That's what pretty much every tutorial says to start with. Gooligum's a terrific resource. I actually paid to get a hard copy!

I'll be fiddling around with the code/tuts and posting more questions on here, seeing how terrific and helpful the crowd is.

That 20-page doc (ommits the 16F505/06) beats the 100+ page datasheet for the basics!
 

DonQ

Joined May 6, 2009
321
A slightly different way of looking at it that might give some insight.

At reset, the processor unconditionally starts executing code at address 3FF. One thing you could do here is to place a vector to the start location of your code: address 'whatever'. Then, at address 'whatever', you could start executing any code you wanted.

One good thing to do would be to load the working register with a value, followed by loading the OSCAL register with the working register.

This is probably a good thing to do at the beginning of every program so there is a shortcut.

You can have the instruction at 3FF, instead of a jump to the start of your code, load the working register immediately. Since the 'normal' jump at this address has been replaced with this non-jump instruction, the program execution 'falls through' (wrap around, whatever you want to call it) to program location zero. Here you could have whatever code you want, but since you will have to move the value to the OSCAL register eventually, you might as well do it here.

Now you can place a vector to the start of your code, or just continue coding in subsequent addresses. Problem is, interrupt vectors are nearby, so usually, you do a jump to something past your interrupt vectors.

Other processors may have different values instead of 3FF based on their total memory size, but the principle is the same.
 

eblc1388

Joined Nov 28, 2008
1,542
The main reason of placing the OSCCAL value at the top of memory really come down to one simple reason, instead of just being a shortcut.

It is to make the OSCCAL value chip specific, i.e. associated to the physical chip. It takes different values for chip of the same type and this value is measured/determined *after* the chip is made.

Because of the support offered by the hardware programmer, which automatically *stores* the value located at the top memory address before a chip erase or programming operation, the same value will be written back to the chip at the same address regardless of where user's program ends. This happens without user intervention thus making the value 'sticks' to the same chip.
 
Top