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

Discussion in 'Embedded Systems and Microcontrollers' started by stormBytes, Aug 13, 2010.

  1. stormBytes

    Thread Starter Active Member

    Jan 26, 2010
    41
    1
    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:

    Code ( (Unknown Language)):
    1.  ;    File Name:                      L1-Turn_on_LED.asm                                                                     ;        Date:                           08-12-2010                                                                                                                 ;    Version:                        0.1           ;        Architechture:           Baseline PIC                                                               ;    Micro:                  12F509                                    
    2.   ;     Description:            This code turns on an LED light  
    3.   ;     Pin Assignment:         GP01 output, END        
    4.   ;     ****************************************************************************
    5.         list            p=12F509                ; Specifies PIC to be used                                              #include        <p12f509.inc>   ; Processor-specific header file  
    6.  
    7.   ;     Config Bits:  
    8.         __CONFIG        _MCLRE_ON & _CP_OFF & _WDT_OFF & _IntRC_OSC
    9.   ;     ****************************************************************************
    10.  
    11.   ;     Reset Vector:
    12.   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
    13.  
    14.   ;     Main Program ***************************************************************
    15.   start CODE
    16.                 movlw   b'111101'               tris    GPIO                              ; Set GP1 as Output
    17.                 movlw   b'000010'               movwf   GPIO                     ; Set GP1 to Output HIGH
    18.                 goto    $                               ; Infinite loop
    19.         End  
    20.  
    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,

    Code ( (Unknown Language)):
    1. 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!
     
  2. eblc1388

    Senior Member

    Nov 28, 2008
    1,542
    102
    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.
     
  3. stormBytes

    Thread Starter Active Member

    Jan 26, 2010
    41
    1
    Hopefully I'll have the actual mcus here by month's end. Then I'll be able to skip the emulation altogether.
     
  4. stormBytes

    Thread Starter Active Member

    Jan 26, 2010
    41
    1
    Weird.. in the sample code Gooligum has it as:

    Code ( (Unknown Language)):
    1.  
    2. RESET        CODE    0x000
    3.  
     
  5. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    Does it work if you put ORG 0x000 before start?
     
  6. stormBytes

    Thread Starter Active Member

    Jan 26, 2010
    41
    1
    Code 0x0000 works fine, what I don't understand is WHY it needs to be 0's when the cal value is stored at 0x3ff.
     
  7. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    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.
     
  8. stormBytes

    Thread Starter Active Member

    Jan 26, 2010
    41
    1
    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
     
  9. AlexR

    Well-Known Member

    Jan 16, 2008
    735
    54
    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
    Code ( (Unknown Language)):
    1.   ;    File Name:                   L1-Turn_on_LED.asm                            
    2.   ;    Date:                        08-12-2010
    3.   ;    Version:                     0.1          
    4.   ;    Architechture:               Baseline PIC
    5.   ;    Micro:                          12F509                                    
    6.   ;     Description:            This code turns on an LED light  
    7.   ;     Pin Assignment:         GP01 output, END        
    8.   ;     ****************************************************************************
    9.         list            p=12F509                ; Specifies PIC to be used                                              
    10. #include        <p12f509.inc>   ; Processor-specific header file  
    11.  
    12.   ;     Config Bits:  
    13.         __CONFIG        _MCLRE_ON & _CP_OFF & _WDT_OFF & _IntRC_OSC
    14.   ;     ****************************************************************************
    15.  
    16.   ;     Reset Vector:
    17.   RESET CODE    0x3FF                                               ; Move cal value in W to OSCCAL register
    18.  
    19.   ;     Main Program ***************************************************************
    20.   start CODE     0x0000
    21.                 movwf   OSCCAL                                        ; update register with factory cal value
    22.                 movlw   b'111101'               tris    GPIO        ; Set GP1 as Output
    23.                 movlw   b'000010'               movwf   GPIO        ; Set GP1 to Output HIGH
    24.                 goto    $                               ; Infinite loop
    25.         End
     
    stormBytes likes this.
  10. eblc1388

    Senior Member

    Nov 28, 2008
    1,542
    102
    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.
     
    stormBytes likes this.
  11. stormBytes

    Thread Starter Active Member

    Jan 26, 2010
    41
    1
    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 :)
     
  12. stormBytes

    Thread Starter Active Member

    Jan 26, 2010
    41
    1
    Another question -

    Datasheet Excerpt

    This is right out of the datasheet. I'm trying to understand how you know that the PIC starts off by picking up the OSCCAL value stored at 0x3FF ?
     
  13. eblc1388

    Senior Member

    Nov 28, 2008
    1,542
    102
    Datasheet section 4.7.1 - Memory Organization >> Program Counter >> Effects of Reset.
     
    stormBytes likes this.
  14. stormBytes

    Thread Starter Active Member

    Jan 26, 2010
    41
    1
    Awesome! Thanks so much!

    Navigating the datasheet is in itself a feat!
     
  15. AlexR

    Well-Known Member

    Jan 16, 2008
    735
    54
    Take a look at the memory map on page 2 of the document below. The reset vector in the PIC12F509 is shown at 0x03FF.
    The data sheet is not very well written but what I think they mean is that on reset after picking up the osccal value at 0x03FF the program rolls around to 0x0000 making it the effective location that the program starts from after a reset.

    http://ww1.microchip.com/downloads/en/DeviceDoc/41227E.pdf
     
    stormBytes likes this.
  16. stormBytes

    Thread Starter Active Member

    Jan 26, 2010
    41
    1
    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!
     
  17. DonQ

    Active Member

    May 6, 2009
    320
    11
    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.
     
  18. eblc1388

    Senior Member

    Nov 28, 2008
    1,542
    102
    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.
     
  19. stormBytes

    Thread Starter Active Member

    Jan 26, 2010
    41
    1
    Having worked with an actual PIC 12F509 all works great! Thanks for the helpful insight. I think I get it now :)
     
Loading...