I recently was experimenting with code protection on a PIC12F509 and noticed the program memory addresses under 0x40 were left readable. I confirmed this was normal when I looked at the datasheet.

So if a program is small and just extends to 0x39 it will be fully readable even if code protection is on.

So I decided to experiment with offsetting the start of the code to 0x40 so it would be protected with CP on.

I am using assembler with MPLAB X so to do this I changed the reset vector in the code from 0x000 to 0x040. Then I right clicked the project and selected project properties. Under PICkit3 I manually specified 0x040 as the start of program memory.

The assembler files compile fine without errors and the program begins at 0x040 when the microcontroller is read with CP off in MPLAB IPE. But the code doesn't run.

The code runs fine when the reset vector is 0x000 and the start of program memory for the PICkit3 is automatically selected at 0x000 in project properties.

Is there something I'm forgetting here? I can't figure out why the code won't run.

Here is the code there are two files the main file and delay loop subroutine:

;   Reaction Timer game.                                                *
;                                                                       *
;   Demonstrates use of Timer0 to time real-world events                *
;                                                                       *
;   User must attempt to press button within 200 ms of "start" LED      *
;   lighting.  If and only if successful, "success" LED is lit.         *
;                                                                       *
;       Starts with both LEDs unlit.                                    *
;       2 sec delay before lighting "start"                             *
;       Waits up to 1 sec for button press                              *
;       (only) on button press, lights "success"                        *
;       1 sec delay before repeating from start                         *
;                                                                       *

list        p=12F509   
#include    <p12F509.inc>

EXTERN  delay10       ; W x 10 ms delay

            ; int reset, no code protect, no watchdog, int RC clock

cnt_8ms res 1                   ; counter: increments every 8 ms

RCCAL   CODE    0x3FF           ; processor reset vector
    res 1                   ; holds internal RC cal value, as a movlw k

;***** RESET VECTOR *****************************************************
RESET   CODE    0x040           ; effective reset vector
    movwf   OSCCAL          ; apply internal RC factory calibration 
    pagesel start
    goto    start           ; jump to main code

;***** Subroutine vectors
delay10r                         ; delay W x 10 ms
    pagesel delay10
    goto    delay10       

;***** MAIN PROGRAM *****************************************************

;***** Initialisation
    ; configure port
    movlw   b'111001'       ; configure GP1 and GP2 (only) as outputs
    tris    GPIO
    ; configure timer
    movlw   b'11010100'     ; configure Timer0:
            ; --0-----          timer mode (T0CS = 0)
            ; ----0---          prescaler assigned to Timer0 (PSA = 0)
            ; -----100          prescale = 32 (PS = 100)            
    option                  ;   -> increment every 32 us

;***** Main loop
    ; turn off both LEDs
    clrf    GPIO   

    ; delay 2 sec
    movlw   .200            ; 200 x 10 ms = 2 sec
    pagesel delay10r
    call    delay10r
    pagesel $           

    ; indicate start
    bsf     GPIO,2          ; turn on start LED     

    ; wait up to 1 sec for button press
    banksel cnt_8ms         ; clear timer (8 ms counter)
    clrf    cnt_8ms         ; repeat for 1 sec:
wait1s  clrf    TMR0            ;   clear Timer0        
w_tmr0                          ;   repeat for 8 ms:
    btfss   GPIO,3          ;     if button pressed (GP3 low)
    goto    wait1s_end      ;       finish delay loop immediately 
    movf    TMR0,w        
    xorlw   .250            ;   (250 ticks x 32 us/tick = 8 ms)
    btfss   STATUS,Z        
    goto    w_tmr0
    incf    cnt_8ms,f       ;   increment 8 ms counter
    movlw   .125            ; (125 x 8 ms = 1 sec) 
    xorwf   cnt_8ms,w
    btfss   STATUS,Z
    goto    wait1s

    ; indicate success if elapsed time < 200 ms       
    movlw   .25             ; if time < 200 ms (25 x 8 ms)
    subwf   cnt_8ms,w
    btfss   STATUS,C
    bsf     GPIO,1          ;   turn on success LED

    ; delay 1 sec
    movlw   .100            ; 100 x 10 ms = 1 sec
    pagesel delay10r
    call    delay10r
    pagesel $        

    ; repeat forever
    goto    main_loop            

And the delay subroutine:

#include    <p12F509.inc>      

GLOBAL  delay10

count   res 1
count2  res 1
count3  res 1

banksel count3  ; Select proper bank for variables
movwf   count3  ; Move number Of 10ms loops 10ms * X from W to count3
dly movlw   .252
movwf   count
movlw   .13
movwf   count2
dly2    decfsz  count,f
goto    dly2
decfsz  count2,f
goto    dly2
decfsz  count3,f
goto    dly
retlw   0   ; Return from subroutine with 0 in W register

**** Update ****

I updated the reset vector and I believe I have it working properly.

;***** RESET VECTOR *****************************************************
RESET   CODE    0x000
goto    0x040
RESET2  CODE    0x040   ; apply internal RC factory calibration 
movwf   OSCCAL
pagesel start
goto    start           ; jump to main code
  • 1
    \$\begingroup\$ I know this doesn't answer your question, but it would have been easier to leave the reset vector alone and just put a single GOTO there to your code section. \$\endgroup\$ Oct 9, 2015 at 6:36

1 Answer 1


You have placed somethiung that you call the reset vector at a different location, but the chip doesn't care: its hardware still starts executing at 0 after a reset. So to implement what you want you'd better take Krankshaft's suggestion: put a jump at 0 to the code that you want to be read-protected. Mayeb you can put a few uninteresting subroutines (like a delay) between 0 and 40.

  • \$\begingroup\$ I rewrote the reset vector portion of the code above is something like this what you were referring to? When the chip is read I see some hex values at 0x000 some blank space then some more hex at 0x040. The code works but what's to stop MPLAB from putting the delay10 code module at 0x000? \$\endgroup\$
    – Krankshaft
    Oct 9, 2015 at 9:22
  • \$\begingroup\$ Pad the space between the reset vector and your protected code with a "fake" function if required. Just fill it with an instruction that is a nop or even fixed data (perhaps your own signature :). \$\endgroup\$
    – David
    Oct 9, 2015 at 12:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.