Recientemente estuve experimentando con la protección de código en un PIC12F509 y noté que las direcciones de memoria del programa bajo 0x40 se dejaron legibles. Confirmé que esto era normal cuando miraba la hoja de datos.
Entonces, si un programa es pequeño y solo se extiende a 0x39, será completamente legible incluso si la protección del código está activada.
Así que decidí experimentar con compensar el inicio del código a 0x40 para que estuviera protegido con CP activado.
Estoy usando el ensamblador con MPLAB X, así que para hacer esto cambié el vector de reinicio en el código de 0x000 a 0x040. Luego hice clic derecho en el proyecto y seleccioné las propiedades del proyecto. En PICkit3, especificé manualmente 0x040 como inicio de la memoria del programa.
Los archivos del ensamblador se compilan correctamente sin errores y el programa comienza en 0x040 cuando el microcontrolador se lee con el CP apagado en MPLAB IPE. Pero el código no se ejecuta.
El código funciona bien cuando el vector de restablecimiento es 0x000 y el inicio de la memoria del programa para el PICkit3 se selecciona automáticamente en 0x000 en las propiedades del proyecto.
¿Hay algo que estoy olvidando aquí? No puedo entender por qué el código no se ejecuta.
Aquí está el código, hay dos archivos: el archivo principal y la subrutina de bucle de retardo:
; 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
;***** CONFIGURATION
; int reset, no code protect, no watchdog, int RC clock
__CONFIG _MCLRE_OFF & _CP_OFF & _WDT_OFF & _IntRC_OSC
;***** VARIABLE DEFINITIONS
UDATA
cnt_8ms res 1 ; counter: increments every 8 ms
;***** RC CALIBRATION
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 *****************************************************
MAIN CODE
;***** Initialisation
start
; 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
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
wait1s_end
; 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
END
Y la subrutina de retardo:
#include <p12F509.inc>
GLOBAL delay10
;***** VARIABLE DEFINITIONS
UDATA
count res 1
count2 res 1
count3 res 1
;Subroutine
CODE
delay10
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
END
**** Actualización ****
Actualicé el vector de reinicio y creo que lo tengo funcionando correctamente.
;***** 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