1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332
|
;; The purpose of this program is to test gpsim's ability to
;; simulate interrupts on the midrange core (specifically the 'f84).
list p=16f84 ; list directive to define processor
include <p16f84.inc> ; processor specific variable definitions
include <coff.inc> ; Grab some useful macros
;; Suppress warnings of using 'option' instruction.
errorlevel -224
__CONFIG _WDT_OFF
GPR_DATA UDATA
temp RES 1
temp1 RES 1
temp2 RES 1
temp3 RES 1
temp4 RES 1
temp5 RES 1
adr_cnt RES 1
data_cnt RES 1
failures RES 1
w_temp RES 1
status_temp RES 1
GLOBAL temp,temp1,temp2,temp3,temp4,temp5
GLOBAL start
;----------------------------------------------------------------------
; ********************* RESET VECTOR LOCATION ********************
;----------------------------------------------------------------------
RESET_VECTOR CODE 0x000 ; processor reset vector
movlw high start ; load upper byte of 'start' label
movwf PCLATH ; initialize PCLATH
goto start ; go to beginning of program
;------------------------------------------------------------------------
;
; Interrupt Vector
;
;------------------------------------------------------------------------
INT_VECTOR CODE 0x004 ; interrupt vector location
movwf w_temp
swapf STATUS,W
movwf status_temp
check_rbi:
btfsc INTCON,RBIF
btfss INTCON,RBIE
goto check_int
bsf temp5,1 ;Set a flag to indicate rb4-7 int occured
bcf INTCON,RBIF
check_int:
btfsc INTCON,INTF
btfss INTCON,INTE
goto check_t0
bsf temp5,0 ;Set a flag to indicate rb0 int occured
bcf INTCON,INTF
check_t0:
btfsc INTCON,T0IF
btfss INTCON,T0IE
goto exit_int
;; tmr0 has rolled over
bcf INTCON,T0IF ; Clear the pending interrupt
bsf temp1,0 ; Set a flag to indicate rollover
exit_int:
swapf status_temp,w
movwf STATUS
swapf w_temp,f
swapf w_temp,w
retfie
;----------------------------------------------------------------------
; ******************* MAIN CODE START LOCATION ******************
;----------------------------------------------------------------------
MAIN CODE
start
;; Assume no failures
clrf failures
;;
;; tmr0 test
;;
;; The following block of code tests tmr0 together with interrupts.
;; Each prescale value (0-7) is loaded into the timer. The software
;; waits until the interrupt due to tmr0 rollover occurs before
;; loading the new prescale value.
bsf INTCON,T0IE ;Enable TMR0 overflow interrupts
bsf INTCON,GIE ;Global interrupts
clrf temp1 ;Software flag used to monitor when the
;interrupt has been serviced.
clrw
test_tmr0:
option ;Assign new prescale value
btfss temp1,0 ;Wait for the interrupt to occur and
goto $-1 ;get serviced
clrf temp1 ;Clear flag for the next time
bsf STATUS,RP0
incf (OPTION_REG^0x80),W
bcf STATUS,RP0
andlw 0x7 ;Check the prescaler
skpz
goto test_tmr0
bcf INTCON,T0IE ;Disable tmr0 interrupts
;; Now check tmr0 with an external clock source
;;
;; It assumes that port b bit 0 is the stimulus.
;; This requires that the following gpsim commands be invoked:
;; gpsim> node new_test_node
;; gpsim> attach new_test_node porta4 portb0
bsf STATUS,RP0
bcf (TRISB ^ 0x80),0 ;portb bit 0 is an output
bcf STATUS,RP0
;; assign the prescaler to the wdt so that tmr0 counts every edge
;; select the clock source to be tocki
;; and capture low to high transitions (tose = 0)
movlw (1<<T0CS) | (1<<PSA)
; movlw (1<<T0CS) | (1<<PSA) | (1<<T0SE)
option
movlw 0xff
movwf temp2
movwf temp3
movwf temp4
bcf INTCON,T0IF ;not necessary..., but clear pending int.
bsf INTCON,T0IE ;Re-enable tmr0 interrupts
tmr0_l1:
bcf temp1,0 ;Interrupt flag
clrz
bcf PORTB,0
btfsc temp1,0
decf temp2,f ;Falling edge caused the interrupt
bcf temp1,0
bsf PORTB,0
btfsc temp1,0
decf temp3,f ;Rising edge caused the interrupt
;; if either temp2 or temp3 decremented to zero, then z will be set
skpz
goto tmr0_l1
incfsz temp4,f
goto test_inte
;; Now let's test external clocking with the falling edge
movlw (1<<T0CS) | (1<<PSA) | (1<<T0SE)
option
goto tmr0_l1
;; tmr0 test is done.
;;
;; inte test
;;
;; The following block of code tests the interrupt on
;; change for port b bit 0. It assumes that port a bit 4
;; is the stimulus. This requires that the following
;; gpsim commands be invoked:
;; gpsim> node new_test_node
;; gpsim> attach new_test_node porta4 portb0
;;
;; Also, recall that porta bit 4 is an open collector
;; output (it can't drive high). So to generate the
;; the logic highs, the portb weak pull-up resistors
;; need to be enabled.
test_inte:
bsf STATUS,RP0
bcf (TRISA ^ 0x80),4 ;Make porta bit 4 an output
bsf (TRISB ^ 0x80),0 ;and portb bit 0 an input
bcf (OPTION_REG^0x80),NOT_RBPU ;Enable the portb weak pull-ups
bsf (OPTION_REG^0x80),INTEDG ;Interrupt on rising edge
bcf STATUS,RP0
movlw 0xff
movwf temp1
movwf temp2
movwf temp3
movwf temp4
bcf PORTA,4
bcf INTCON,RBIF
bsf INTCON,INTE
;;
;; This routine toggles porta bit 4 with the hope of generating
;; an interrupt on portb bit 0.
;; temp1 counts the number of times an interrupt has occurred
;; temp2 counts the number of times the interrupt was due to
;; a rising edge.
inte_edgecount:
bcf temp5,0 ;Interrupt flag
clrz
bcf PORTA,4 ;Falling edge
btfsc temp5,0
decf temp2,f ;Falling edge caused the interrupt
bcf temp5,0
bsf PORTA,4 ;Rising edge
btfsc temp5,0
decf temp3,f ;Rising edge caused the interrupt
;; if either temp2 or temp3 decremented to zero, then z will be set
skpz
goto inte_edgecount
incfsz temp4,f
goto test_rbif
;; Now let's test the falling edge
bcf INTCON,INTE ;Disable inte interrupt
bcf PORTA,4
bcf INTCON,INTF
bsf STATUS,RP0
bcf (OPTION_REG^0x80),INTEDG ;Interrupt on falling edge
bcf STATUS,RP0
bsf INTCON,INTE
goto inte_edgecount
;;
;; test_rbif
;;
;; This next block tests the interrupt on change feature of
;; port b's I/O pins 4-7
;;
test_rbif
bcf INTCON,INTE ;Disable the rb0 interrupt
bsf STATUS,RP0
bsf (TRISA ^ 0x80),4 ;Porta bit 4 is now an input
bcf STATUS,RP0
clrf temp5 ;Interrupt flag
clrf temp1
movlw 0x10
movwf temp2
rbif_l1:
bcf INTCON,RBIE
movf temp2,w
tris PORTB
clrf PORTB
movf PORTB,W
clrf temp5 ;Interrupt flag
bcf INTCON,RBIF
bsf INTCON,RBIE
swapf temp2,w
movwf PORTB
btfsc temp5,1
iorwf temp1,f
.assert "(temp5 & 2) == 2"
clrc
rlf temp2,f
skpc
goto rbif_l1
done:
.assert "\"*** PASSED MidRange core interrupt test\""
goto $
failed:
.assert "\"*** FAILED MidRange core interrupt test\""
goto $
end
|