1; 2; 3; Copyright (c) 2013 Roy Rankin 4; 5; This file is part of the gpsim regression tests 6; 7; This library is free software; you can redistribute it and/or 8; modify it under the terms of the GNU Lesser General Public 9; License as published by the Free Software Foundation; either 10; version 2.1 of the License, or (at your option) any later version. 11; 12; This library is distributed in the hope that it will be useful, 13; but WITHOUT ANY WARRANTY; without even the implied warranty of 14; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15; Lesser General Public License for more details. 16; 17; You should have received a copy of the GNU Lesser General Public 18; License along with this library; if not, see 19; <http://www.gnu.org/licenses/lgpl-2.1.html>. 20 21 22 ;; The purpose of this program is to test gpsim's ability to 23 ;; simulate a pic 16F1788. 24 ;; Specifically, basic port operation, eerom, interrupts, 25 ;; a2d, dac, SR latch, capacitor sense, and enhanced instructions 26 27 28 list p=16f1788 ; list directive to define processor 29 include <p16f1788.inc> ; processor specific variable definitions 30 include <coff.inc> ; Grab some useful macros 31 32 __CONFIG _CONFIG1, _CP_OFF & _WDTE_ON & _FOSC_INTOSC & _PWRTE_ON & _BOREN_OFF & _MCLRE_ON & _CLKOUTEN_OFF 33 __CONFIG _CONFIG2, _STVREN_ON ; & _WRT_BOOT 34 35;------------------------------------------------------------------------ 36; gpsim command 37.command macro x 38 .direct "C", x 39 endm 40 41TSEN EQU H'0005' 42TSRNG EQU H'0004' 43 44;---------------------------------------------------------------------- 45GPR_DATA UDATA_SHR 46cmif_cnt RES 1 47tmr0_cnt RES 1 48tmr1_cnt RES 1 49eerom_cnt RES 1 50adr_cnt RES 1 51data_cnt RES 1 52inte_cnt RES 1 53iocaf_val RES 1 54 55 GLOBAL iocaf_val 56 57;---------------------------------------------------------------------- 58; ********************* RESET VECTOR LOCATION ******************** 59;---------------------------------------------------------------------- 60RESET_VECTOR CODE 0x000 ; processor reset vector 61 movlp high start ; load upper byte of 'start' label 62 goto start ; go to beginning of program 63 64 65 .sim "module library libgpsim_modules" 66 ; Use a pullup resistor as a voltage source 67 .sim "module load pullup V1" 68 .sim "V1.resistance = 10000.0" 69 .sim "V1.capacitance = 20e-12" 70 .sim "V1.voltage=1.0" 71 72 .sim "node n1" 73 .sim "attach n1 porta0 porta3" 74 .sim "node n2" 75 .sim "attach n2 porta1 porta4" 76 .sim "node n3" 77 .sim "attach n3 porta2 porta5" 78 .sim "node n4" 79 .sim "attach n4 portb0 V1.pin" 80 .sim "node n5" 81 .sim "attach n5 porta6 porta7" 82 .sim "node n6" 83 .sim "attach n6 portb1 portb7" 84 85 .sim "p16f1788.xpos = 72" 86 .sim "p16f1788.ypos = 72" 87 88 .sim "V1.xpos = 260" 89 .sim "V1.ypos = 120" 90 91 92;------------------------------------------------------------------------ 93; 94; Interrupt Vector 95; 96;------------------------------------------------------------------------ 97 98INT_VECTOR CODE 0x004 ; interrupt vector location 99 ; many of the core registers now saved and restored automatically 100 101; movwf w_temp 102; swapf STATUS,W 103 clrf BSR ; set bank 0 104; movwf status_temp 105 106 btfsc PIR2,EEIF 107 goto ee_int 108 109 btfsc INTCON,T0IF 110 goto tmr0_int 111 112 btfsc INTCON,IOCIF 113 goto inte_int 114 115 .assert "'***FAILED p16f1788 unexpected interrupt'" 116 nop 117 118 119; Interrupt from TMR0 120tmr0_int 121 incf tmr0_cnt,F 122 bcf INTCON,T0IF 123 goto exit_int 124 125; Interrupt from eerom 126ee_int 127 incf eerom_cnt,F 128 bcf PIR2,EEIF 129 goto exit_int 130 131; Interrupt from INT pin 132inte_int 133 incf inte_cnt,F 134 BANKSEL IOCAF 135 movf IOCAF,W 136 movwf iocaf_val 137 xorlw 0xff 138 andwf IOCAF, F 139 goto exit_int 140 141exit_int: 142 143 retfie 144 145 146;---------------------------------------------------------------------- 147; ******************* MAIN CODE START LOCATION ****************** 148;---------------------------------------------------------------------- 149MAIN CODE 150start 151 ;set clock to 16 Mhz 152 BANKSEL OSCCON 153 bsf OSCCON,6 154 155 call test_pir_pie_bits 156 157 BANKSEL FVRCON 158 ; Enable Core Temp, high range, FVR AD 2.048v 159 movlw (1<<TSEN)|(1<<TSRNG)|(1<<FVREN)|(1<<ADFVR1) 160 movwf FVRCON 161 BANKSEL STKPTR 162 movf STKPTR,W 163; ; 164 ; test pins in analog mode return 0 on register read 165 BANKSEL TRISA 166 clrf STATUS 167 clrf TRISA 168 .assert "trisa == 0x00, '*** FAILED 16f1788 TRISA not clear '" 169 nop 170 BANKSEL PORTA 171 movlw 0xff 172 movwf PORTA 173 .assert "porta == 0xe8, '*** FAILED 16f1788 analog bits read 0'" 174 nop 175 movf PORTA,W 176 177; 178; test PORTA works as expected 179; 180 clrf PORTA 181 BANKSEL ANSELA 182 clrf ANSELA ; set port to digital 183 bcf ANSELB,0 184 BANKSEL TRISA 185 movlw 0x38 186 movwf TRISA ;PORTA 0,1,2 output 3,4,5 input 187 188 clrf BSR ; bank 0 189 .assert "porta == 0x00, 'PORTA = 0x00'" 190 nop 191 movlw 0x07 192 movwf PORTA ; drive 0,1,2 bits high 193 bsf PORTC,7 194 .assert "porta == 0x3f, 'PORTA = 0x3f'" 195 nop 196 BANKSEL LATA 197 movf LATA,W 198 BANKSEL TRISA 199 movlw 0x07 200 movwf TRISA ; PORTA 3, 4, 5 output 0,1,2 input 201 BANKSEL PORTA 202 .assert "porta == 0x00, 'PORTA = 0x00'" 203 nop 204 movlw 0x38 205 movwf PORTA ; drive output bits high 206 .assert "porta == 0x3f, 'PORTA = 0x3f'" 207 nop 208 209 call test_eerom 210 call test_int 211 call read_config_data 212 call test_a2d 213 call test_dac 214 call test_a2d_ref 215 call write_prog 216 217 .assert "'*** PASSED 16f1788 Functionality'" 218 nop 219 reset 220 goto $ 221 222; 223; Test A/D Vref-pin and differential input 224; 225test_a2d_ref: 226 BANKSEL ANSELA 227 bsf ANSELA,2 228 bsf ANSELA,1 229 BANKSEL TRISA 230 bsf TRISA,5 231 BANKSEL DAC1CON0 232 ; Pin a2 is both DAC1 output and ADC Vref-pin 233 movlw (1<<DAC1EN)|(1<<DACOE1) 234 movwf DAC1CON0 235 movlw 0x10 ; Ladder 16/256 * 5V = 0.3125 V 236 movwf DAC1CON1 237 BANKSEL ADCON0 238 movlw (1<<ADFM)|(7 << 4) | (1<<ADNREF) ; 2's comp, Frc, Vref-pin 239 movwf ADCON1 240 movlw 0xf ; V- = Vref-pin 241 movwf ADCON2 242 movlw (1<<ADON)|(0xc<<2) ; V+ = AN12 243 movwf ADCON0 244 ; DAC output (1V - 0.3125) /(5-0.3125) 245 call a2dConvert 246 .assert "adresh == 0x02 && (adresl==0x59), '*** FAILED 16f1788 AN12=1V V-=Vref-pin'" 247 nop 248 249 ; Test Vdd = 5.00 as Vsource+ = 2.500 DAC4 (5 bit) 250 BANKSEL DAC4CON0 251 movlw (1<<DACEN)|(1<<DAC4OE1) 252 movwf DAC4CON0 253 movlw 0x10 ; ladder 16/32 254 movwf DAC4CON1 255 BANKSEL ADCON0 256 movlw (1<<ADFM)|(7 << 4) | (1<<ADNREF) ; 2's comp, Frc, Vref-pin 257 movwf ADCON1 258 movlw 0x1 ; V- = AN1 (2.5 V) 259 movwf ADCON2 260 movlw (1<<ADON)|(0xc<<2) ; V+ = AN12 261 movwf ADCON0 262 call a2dConvert 263 .assert "adresh == 0xfa && (adresl==0xe5), '*** FAILED 16f1788 V+=AN12=1V V-=AN1=2.5V 2's comp'" 264 nop 265 BANKSEL ADCON0 266 movlw (7 << 4) | (1<<ADNREF) ; sign-mag, Frc, Vref-pin 267 movwf ADCON1 268 movlw 0x1 ; V- = AN1 269 movwf ADCON2 270 movlw (1<<ADON)|(0xc<<2)|(1<<ADRMD) ; V+ = AN12 271 movwf ADCON0 272 call a2dConvert 273 .assert "adresh == 0x51 && (adresl==0x81), '*** FAILED 16f1788 V+=AN12=1V V-=AN1=2.5V sign-mag 10bit'" 274 nop 275 BANKSEL DAC4CON0 276 clrf DAC4CON0 277 BANKSEL DAC1CON0 278 clrf DAC1CON0 279 return 280 281 282test_pir_pie_bits: 283 BANKSEL PIR1 284 movlw 0xff 285 movwf PIR1 286 .assert "pir1 == 0xcf, '*** FAILED 16f1788 PIR1 write test'" 287 nop 288 clrf PIR1 289 movwf PIR2 290 .assert "pir2 == 0xff, '*** FAILED 16f1788 PIR2 write test'" 291 nop 292 clrf PIR2 293 movwf PIR3 294 .assert "pir3 == 0x10, '*** FAILED 16f1788 PIR3 write test'" 295 nop 296 clrf PIR3 297 298 BANKSEL PIE1 299 movwf PIE1 300 .assert "pie1 == 0xff, '*** FAILED 16f1788 PIE1 write test'" 301 nop 302 clrf PIE1 303 movwf PIE2 304 .assert "pie2 == 0xff, '*** FAILED 16f1788 PIE2 write test'" 305 nop 306 clrf PIE2 307 movwf PIE3 308 .assert "pie3 == 0x10, '*** FAILED 16f1788 PIE3 write test'" 309 nop 310 clrf PIE3 311 return 312test_dac: 313 BANKSEL ADCON1 314 movlw (1<<ADFM)| 0x70 ;A2D 2's comp, Frc, Vdd ref+, Vss ref- 315 movwf ADCON1 316 BANKSEL TRISC ; 317 bsf TRISC,0 ;Set RC0 to input 318 BANKSEL ANSELC ; 319 bsf ANSELC,0 ;Set RC0 to analog 320 BANKSEL ADCON0 ; 321 movlw (0x1e<<2)|(1<<ADON) ;Select A2D input from DAC1 and ADC on 322 movwf ADCON0 323 ; DAC output should be Vsource- (0) 324 call a2dConvert 325 .assert "(adresh==0x00) && (adresl==0x00), '*** FAILED 16f1788 DAC default'" 326 nop 327 ; test DAC enabled Vout = 5V * (128/256) = 2.5 328 BANKSEL DAC1CON0 329 movlw 0x80 330 movwf DAC1CON1 331 movlw (1<<DACEN) 332 movwf DAC1CON0 333 BANKSEL ADCON0 334 call a2dConvert 335 .assert "(adresh==0x08) && (adresl==0x00), '*** FAILED 16f1788 DAC enabled 1/2'" 336 nop 337 ; Test FVR = 4.096 as Vsource+ = 2.048 338 BANKSEL FVRCON 339 movlw (1<<FVREN)|(1<<CDAFVR1)|(1<<CDAFVR0) 340 movwf FVRCON 341 movlw (1<<DACEN) | (1<<DACPSS1) 342 movwf DAC1CON0 343 BANKSEL ADCON0 344 call a2dConvert 345 .assert "(adresh==0x06) && (adresl==0x8d), '*** FAILED 16f1788 DAC enabled 1/2 FVR '" 346 nop 347 banksel TRISB 348 bsf TRISB,7 349 clrf TRISE 350 351 ; Test Vdd = 5.00 as Vsource+ = 2.500 DAC4 (5 bit) 352 BANKSEL DAC4CON0 353 movlw (1<<DACEN)|(1<<DAC4OE1) | (1<<DAC4OE2) 354 movwf DAC4CON0 355 movlw 0x10 ; ladder 16/32 356 movwf DAC4CON1 357 BANKSEL ADCON0 358 movlw (0x18<<2)|(1<<ADON) ;Select A2D input from DAC4 and ADC on 359 movwf ADCON0 360 call a2dConvert 361 .assert "(adresh==0x08) && (adresl==0x00), '*** FAILED 16f1788 DAC4 enabled 1/2 Vdd '" 362 nop 363 364 365 ; Read DAC4 from output pin. (will be slightly lower than 2.500 V) 366 BANKSEL ADCON0 367 movlw (0x0a<<2)|(1<<ADON) ;Select A2D input from DAC4 output pin 368 movwf ADCON0 369 call a2dConvert 370 .assert "(adresh==0x07) && (adresl==0xfd), '*** FAILED 16f1788 DAC4 output pin'" 371 nop 372 373 374 BANKSEL DAC4CON0 375 clrf DAC4CON0 376 377 return 378 379test_eerom: 380 ; 381 ; test can write and read to all 128 eeprom locations 382 ; using intterupts 383 clrf adr_cnt 384 clrf data_cnt 385; setup interrupts 386 bsf INTCON,PEIE 387 bsf INTCON,GIE 388 BANKSEL PIE1 389 bsf PIE2,EEIE 390 BANKSEL PIR1 391; 392; write to EEPROM starting at EEPROM address 0 393; value of address as data using interrupts to 394; determine write complete. 395; read and verify data 396 397l1: 398 movf adr_cnt,W 399 clrf eerom_cnt 400 BANKSEL EEADRL 401 movwf EEADRL 402 movf data_cnt,W 403 movwf EEDATL 404 bcf EECON1, CFGS ;Deselect Configuration space 405 bcf EECON1, EEPGD ;Point to DATA memory 406 bsf EECON1, WREN ;Enable writes 407 408 409 bcf INTCON,GIE ;Disable interrupts while enabling write 410 411 movlw 0x55 ;Magic sequence to enable eeprom write 412 movwf EECON2 413 movlw 0xaa 414 movwf EECON2 415 416 bsf EECON1,WR ;Begin eeprom write 417 418 bsf INTCON,GIE ;Re-enable interrupts 419 bcf EECON1, WREN ;Disable writes 420 421 422 ;; clrf BSR ; Bank 0 423 movf eerom_cnt,W 424 skpnz 425 goto $-2 426; 427; read what we just wrote 428; 429 430 movf adr_cnt,W 431 432 BANKSEL EEADRL 433 movwf EEADRL 434 bcf EECON1, CFGS ;Deselect Config space 435 bcf EECON1, EEPGD ;Point to DATA memory 436 437 bsf EECON1,RD ; start read operation 438 movf EEDATL,W ; Read data 439 BANKSEL PIR1 440 441 xorwf data_cnt,W ; did we read what we wrote ? 442 skpz 443 goto eefail 444 445 incf adr_cnt,W 446 andlw 0x7f 447 movwf adr_cnt 448 movwf data_cnt 449 450 skpz 451 goto l1 452 453 return 454 455test_a2d 456 banksel ANSELC 457 clrf ANSELC 458 BANKSEL ADCON1 459 movlw 0x70 ;Sign-magnatude, Frc, Vdd ref+, Vss ref- 460 movwf ADCON1 461 movlw 0x0f ;negative input is negative reference 462 movwf ADCON2 463 BANKSEL TRISC ; 464 bsf TRISC,0 ;Set RC0 to input 465 BANKSEL ANSELC ; 466 bsf ANSELC,0 ;Set RC0 to analog 467 BANKSEL ADCON0 ; 468 movlw (0xc << 2)|(1<<ADON) ;12bit, Select channel AN12 and ADC on 469 movwf ADCON0 470 call a2dConvert 471 .assert "adresh == 0x33 && (adresl==0x30), '*** FAILED 16f1788 AN12=1V'" 472 nop 473 ; measure Core Temperature (v= 2.733 for 30C) 474 bsf ADCON1,ADFM ; 2's compliment (right justified) 475 movlw (0x1d << 2) | (1<<ADON) ; Core Temp channel and AD on 476 movwf ADCON0 477 call a2dConvert 478 .assert "(adresh==0x08) && (adresl==0xbf), '*** FAILED 16f1788 ADC Core Temp'" 479 nop 480 481 ; measure FVR (2.048) 482 movlw (0x1f << 2) | (1<<ADON) ; FVR channel and AD on 483 movwf ADCON0 484 call a2dConvert 485 .assert "(adresh==0x06) && (adresl==0x8d), '*** FAILED 16f1788 ADC FVR'" 486 nop 487 488 ; measure FVR using FVR Reference 489 movlw 0xf3 ; use FVR reference 490 movwf ADCON1 491 movlw (0x1f << 2) | (1<<ADON) ; FVR channel and AD on 492 movwf ADCON0 493 call a2dConvert 494 .assert "(adresh==0x0f) && (adresl==0xff), '*** FAILED 16f1788 ADC FVR with FVR Ref'" 495 nop 496 497 return 498 499; 500; Start A2D conversion and wait for results 501; 502a2dConvert 503 bsf ADCON0,GO 504 btfsc ADCON0,GO 505 goto $-1 506 movf ADRESH,W 507 return 508 509 510eefail: 511 .assert "'***FAILED 16f1788 eerom write/read error'" 512 nop 513 514test_tmr0: 515 return 516 517 518 519 520 521 522test_int: 523 BANKSEL TRISA 524 bsf TRISA,2 525 bcf TRISA,5 526 BANKSEL PORTA 527 clrf PORTA 528 BANKSEL IOCAP 529 bsf IOCAP,2 ; set interrupt on + edge of porta2 530 531 BANKSEL OPTION_REG 532 bsf OPTION_REG,INTEDG 533 BANKSEL INTCON 534 movlw 0x7f 535 movwf INTCON 536 .assert "intcon == 0x7e, '*** FAILED 16f1788 INT test - INTCON:IOCIF read only'" 537 nop 538 BANKSEL IOCAF 539 movlw 0xff 540 movwf IOCAF 541 .assert "iocaf == 0xff, '*** FAILED 16f1788 INT test - IOCAF writable bits'" 542 nop 543 clrf IOCAF 544 movwf IOCBF 545 .assert "iocbf == 0xff, '*** FAILED 16f1788 INT test - IOCBF writable bits'" 546 nop 547 clrf IOCBF 548 movwf IOCCF 549 .assert "ioccf == 0xff, '*** FAILED 16f1788 INT test - IOCCF writable bits'" 550 nop 551 clrf IOCCF 552 movwf IOCEF 553 .assert "iocef == 0x08, '*** FAILED 16f1788 INT test - IOCEF writable bits'" 554 nop 555 clrf IOCEF 556 clrf INTCON 557 bsf INTCON,GIE ;Global interrupts 558 bsf INTCON,IOCIE 559 560 BANKSEL PORTA 561 562 clrf inte_cnt 563 bsf PORTA,5 ; make a rising edge 564 nop 565 movf inte_cnt,w 566 .assert "W == 0x01, '*** FAILED 16f1788 INT test - No int on rising edge'" 567 nop 568 .assert "iocaf_val == 0x04, '*** FAILED 16f1788 IOCAF bit 2 not set'" 569 nop 570 clrf inte_cnt 571 bcf PORTA,5 ; make a falling edge 572 nop 573 movf inte_cnt,w 574 .assert "W == 0x00, '*** FAILED 16f1788 INT test - Unexpected int on falling edge'" 575 nop 576 577 578; Setup - edge interrupt 579 BANKSEL IOCAP 580 clrf IOCAP 581 bsf IOCAN,2 582 movlw 0xff 583 clrf IOCAF 584 BANKSEL INTCON 585 bcf INTCON,IOCIF ;Clear flag 586 587 clrf inte_cnt 588 bsf PORTA,5 ; make a rising edge 589 nop 590 movf inte_cnt,w 591 .assert "W == 0x00, '*** FAILED 16f1788 INT test - Unexpected int on rising edge'" 592 nop 593 clrf inte_cnt 594 bcf PORTA,5 ; make a falling edge 595 nop 596 movf inte_cnt,w 597 .assert "W == 0x01, '*** FAILED 16f1788 INT test - No int on falling edge'" 598 nop 599 .assert "iocaf_val == 0x04, '*** FAILED 16f1788 IOCAF bit 2 not set'" 600 nop 601 602 603 return 604 605; read STKPTR, TOSL and cause underflow 606rrr: 607 nop 608 BANKSEL STKPTR 609 movf STKPTR,W 610 movf TOSL,W 611 ; clrf TOSL 612 call rrr2 613 return 614 615; use STKPTR to cause stack underflow 616rrr2: 617 BANKSEL STKPTR 618 movlw 0x1f 619 movwf STKPTR ;; cause stack underflow 620 return 621 622; overflow stack with recursive call 623rrr3: 624 call rrr3 625 return 626 627 628; 629; Test reading and writing Configuration data via eeprom interface 630read_config_data: 631 ;Read DeviceID at address 0x06 from config data 632 BANKSEL EEADRL ; Select correct Bank 633 movlw 0x06 ; 634 movwf EEADRL ; Store LSB of address 635 clrf EEADRH ; Clear MSB of address 636 bsf EECON1,CFGS ; Select Configuration Space 637 bcf INTCON,GIE ; Disable interrupts 638 bsf EECON1,RD ; Initiate read 639 nop 640 nop 641 bsf INTCON,GIE ; Restore interrupts 642 .assert "eedath == 0x30 && eedatl == 0x2b, '*** FAILED 16f1788 Device ID'" 643 nop 644 645 ; test write which is in EEDATAH and EEDATAL to userID1 646 BANKSEL PIR2 647 clrf PIR2 648 BANKSEL EECON1 649 movlw 0x01 ; 650 movwf EEADRL ; Store LSB of address 651 bsf EECON1, WREN ;Enable writes 652 bcf INTCON,GIE ; disable interupts 653 movlw 0x55 ;Magic sequence to enable eeprom write 654 movwf EECON2 655 movlw 0xaa 656 movwf EECON2 657 bsf EECON1,WR 658 nop 659 nop 660 bsf INTCON,GIE 661 bcf EECON1, WREN ;Enable writes 662 BANKSEL PIR2 663 btfss PIR2,EEIF 664 goto $-1 665 .assert "UserID2 == 0x302b, '*** FAILED 16f1788 write to UserID2'" 666 nop 667 return 668 669clear_prog: 670; This row erase routine assumes the following: 671; 1. A valid address within the erase block is loaded in ADDRH:ADDRL 672; 2. ADDRH and ADDRL are located in shared data memory 0x70 - 0x7F 673 bcf INTCON,GIE ; Disable ints so required sequences will execute properly 674 BANKSEL EEADRL 675 movlw 0 676 movwf EEADRL 677 movlw 3 678 movwf EEADRH 679 bsf EECON1,EEPGD ; Point to program memory 680 bcf EECON1,CFGS ; Not configuration space 681 bsf EECON1,FREE ; Specify an erase operation 682 bsf EECON1,WREN ; Enable writes 683 movlw 0x55 ; Start of required sequence to initiate erase 684 movwf EECON2 685 movlw 0xAA ; 686 movwf EECON2 687 bsf EECON1,WR ; Set WR bit to begin erase 688 nop 689 nop 690 bcf EECON1,WREN ; Disable writes 691 bsf INTCON,GIE ; Enable interrupts 692 btfsc EECON1,WR 693 goto $-2 694 return 695 696write_prog: 697 698 bcf INTCON,GIE ; Disable ints so required sequences will execute properly 699 BANKSEL EEADRH ; Bank 3 700 movlw 0x03 701 movwf EEADRH ; 702 movlw 0x00 703 movwf EEADRL ; 704 movlw 0x00 705 movwf FSR0L ; 706 movlw 0x20 ; Program memory 707 movwf FSR0H ; 708 bsf EECON1,EEPGD ; Point to program memory 709 bcf EECON1,CFGS ; Not configuration space 710 bsf EECON1,WREN ; Enable writes 711 bsf EECON1,LWLO ; Only Load Write Latches 712LOOP 713 moviw FSR0++ ; Load first data byte into lower 714 movwf EEDATL ; 715 moviw FSR0++ ; Load second data byte into upper 716 movwf EEDATH ; 717 movf EEADRL,W ; Check if lower bits of address are '000' 718 xorlw 0x07 ; Check if we're on the last of 8 addresses 719 andlw 0x07 ; 720 btfsc STATUS,Z ; Exit if last of eight words, 721 goto START_WRITE ; 722 movlw 0x55 ; Start of required write sequence: 723 movwf EECON2 724 movlw 0xAA 725 movwf EECON2 726 bsf EECON1,WR ; Set WR bit to begin write 727 nop 728 nop 729 incf EEADRL,F ; Still loading latches Increment address 730 goto LOOP ; Write next latches 731START_WRITE 732 bcf EECON1,LWLO ; No more loading latches - Actually start Flash program 733 ; memory write 734 movlw 0x55 ; Start of required write sequence: 735 movwf EECON2 736 movlw 0xAA ; 737 movwf EECON2 738 bsf EECON1,WR ; Set WR bit to begin write 739 nop 740 nop 741 bcf EECON1,WREN ; Disable writes 742 bsf INTCON,GIE ; Enable interrupts 743 return 744 745 org 0x200 746rrDATA 747 dw 0x01, 0x02, 0x03 748 end 749