; Bootloader pour PIC16F876 / 877 ; V1.3, 03/2003 ; (c) Julien Schmitt 2000 ; julien@jls-info.com ; CHANGELOG ; * V1.0 : initial release - aout 2000 ; * V1.1 : supporte les "record types" de fichier hex bizarres (cf. dernieres version de MPASM), passage du programme en GPL ;-) - avril 2002 ; * V1.2 : adaptation pour gpasm, calcul automatique de la vitesse en fonction de QUARTZ - fevrier 2003 ; * V1.3 : correction bug hex non valide - mars 2003 ; Copyright (C) Julien Schmitt ; This program is free software; you can redistribute it and/or ; modify it under the terms of the GNU General Public License ; as published by the Free Software Foundation; either version 2 ; of the License, or (at your option) any later version. ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; You should have received a copy of the GNU General Public License ; along with this program; if not, write to the Free Software ; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. LIST P=16F877 INCLUDE __CONFIG _BODEN_ON & _CP_OFF & _WRT_ENABLE_ON & _PWRTE_ON & _WDT_ON & _HS_OSC & _DEBUG_OFF & _CPD_OFF & _LVP_OFF ERRORLEVEL -302 QUARTZ equ d'4000000' ;en Hz BAUD_DIV equ LOW((QUARTZ / d'153600') - 1) CRIGHT equ 0A9h ;ASCII copyright symbol BSPACE equ 08h ;ASCII control H CR equ 0Dh ;ASCII carriage return LF equ 0Ah ;ASCII line feed ESPACE equ d'32' ;ASCII space EOF equ 0 CARRY equ 1 NOW equ 2 CBLOCK 20h TEMP1 TEMP2 TEMP3 TEMP4 CHAR HEX_L HEX_H DONNEE CHECKSUM NBDATA FLAGS NB_ECRITS_H NB_ECRITS_L ENDC CBLOCK 70h ;accessible depuis toutes les ADRESSE_H ;banques ADRESSE_L DONNEE_H DONNEE_L ENDC ORG 0000h movlw HIGH(DEMARRAGE) movwf PCLATH goto DEMARRAGE ORG 1C80h DEBUT ;**************************************************************************** ; TXCHAR : transmet le caractere W ;**************************************************************************** TXCHAR clrwdt btfss PIR1,TXIF goto TXCHAR movwf TXREG return ;**************************************************************************** ; TXSTR : transmet la chaine W ;**************************************************************************** TXSTR movwf TEMP1 movlw HIGH(MSG) movwf PCLATH movf TEMP1,W call MSG andlw 0FFH btfsc STATUS,Z return call TXCHAR incf TEMP1,W goto TXSTR ;**************************************************************************** ; TEMPO : 1 dans W, attente de 10 ms ;**************************************************************************** TEMPO movwf TEMP1 clrf TEMP3 tempo_2 movlw LOW(QUARTZ / d'153600') / 2 movwf TEMP2 tempo_1 clrwdt decfsz TEMP3,F goto tempo_1 decfsz TEMP2,F goto tempo_1 decfsz TEMP1,F goto tempo_2 return ;**************************************************************************** ; AFF_BARRE : affiche la barre de progression au boot ; retourne 00 si pas de caractere recu, FF sinon ;**************************************************************************** AFF_BARRE call PROMPT movlw d'15' ;affiche la barre de progression movwf TEMP1 affiche_barre_1 movlw ESPACE call TXCHAR decfsz TEMP1,F goto affiche_barre_1 movlw '<' call TXCHAR movlw d'16' movwf TEMP1 affiche_barre_2 movlw BSPACE call TXCHAR decfsz TEMP1,F goto affiche_barre_2 movlw d'15' movwf TEMP4 attente_barre movlw '#' call TXCHAR movlw d'20' call TEMPO btfsc PIR1,RCIF goto fin_barre decfsz TEMP4,F goto attente_barre retlw 00h fin_barre movf RCREG,W ;vidage de l'UART retlw 0FFh ;**************************************************************************** ; RETOUR_LIGNE : envoie un retour … la ligne ;**************************************************************************** RETOUR_LIGNE movlw CR call TXCHAR movlw LF call TXCHAR return ;**************************************************************************** ; PROMPT ;**************************************************************************** PROMPT call RETOUR_LIGNE movlw 00h ;prompt call TXSTR return ;**************************************************************************** ; HEX2BIN : conversion d'un octet ascii dans W en bin. retour dans DONNEE ; retour FF si OK, 00 si erreur ;**************************************************************************** HEX2BIN movwf TEMP1 movlw '0' subwf TEMP1,F btfss STATUS,C retlw 00h movlw '9'-'0'+1 subwf TEMP1,W btfss STATUS,C goto fin_hex_OK movlw 'A'-'0' subwf TEMP1,F btfss STATUS,C retlw 00h movlw 'F'-'A'+1 subwf TEMP1,W btfsc STATUS,C retlw 00h movlw 0Ah addwf TEMP1,F fin_hex_OK movf TEMP1,W movwf DONNEE retlw 0FFh ;**************************************************************************** ; HEXCONV : conversion d'un octet ascii dans HEX_H et HEX_L en bin. ; retour dans DONNEE ; retour FF si OK, 00 si erreur ;**************************************************************************** HEXCONV movf HEX_L,W call HEX2BIN andlw 0FFh btfsc STATUS,Z retlw 00h movf DONNEE,W movwf TEMP4 movf HEX_H,W call HEX2BIN andlw 0FFh btfsc STATUS,Z retlw 00h swapf DONNEE,W iorwf TEMP4,W movwf DONNEE retlw 0FFh ;**************************************************************************** ; TOUPPER Convertit W en majuscules ;**************************************************************************** TOUPPER movwf TEMP4 movlw 'z'+1 subwf TEMP4,W btfsc STATUS,C goto fin_toupper movlw 'a' subwf TEMP4,W btfss STATUS,C goto fin_toupper movlw 'a'-'A' subwf TEMP4,W return fin_toupper movf TEMP4,W return ;**************************************************************************** ; TXHEX == ecrit W en Hexadecimal ;**************************************************************************** TXHEX movwf TEMP3 swapf TEMP3,W call WRITEDIG movf TEMP3,W WRITEDIG andlw 0Fh addlw 0F6h btfsc STATUS,C addlw 07h addlw 3Ah goto TXCHAR ;**************************************************************************** ; INCREMENTE : INCREMENTE W en BCD, flags CARRY mis … jour : 1 debordement ;**************************************************************************** INCREMENTE movwf TEMP1 incf TEMP1,F movf TEMP1,W andlw 0Fh sublw 0Ah btfss STATUS,Z goto fin_incremente movf TEMP1,W andlw 0F0h addlw 10h movwf TEMP1 andlw 0F0h sublw 0A0h btfss STATUS,Z goto fin_incremente clrw bsf FLAGS,CARRY return fin_incremente bcf FLAGS,CARRY movf TEMP1,W return ;**************************************************************************** ; RECORD_TYPE : teste le type d'enregistrement de la ligne, et positionne ; les flags appropries ;**************************************************************************** RECORD_TYPE addlw 0FFh ; derniere ligne ? btfsc STATUS,Z goto derniere_ligne ; oui bsf FLAGS,NOW ; sinon, record bizarre --> NOWRITE addlw 01h return derniere_ligne bsf FLAGS,EOF addlw 01h return ;**************************************************************************** ; LIGNE_FIC : reception d'une ligne de fichier HEX ; renvoie 00 si erreur , FF sinon ;**************************************************************************** LIGNE_FIC clrf CHECKSUM movlw 03h movwf TEMP1 attente_entete clrwdt btfss PIR1,RCIF goto attente_entete movf RCREG,W sublw ':' btfsc STATUS,Z goto attente_nbre_data_1 decfsz TEMP1,F ;passer 2 fois si ce goto attente_entete ;n'est pas ":" a cause retlw 00h ;des eventuels CR/LF... attente_nbre_data_1 clrwdt btfss PIR1,RCIF goto attente_nbre_data_1 movf RCREG,W call TOUPPER movwf HEX_H attente_nbre_data_2 clrwdt btfss PIR1,RCIF goto attente_nbre_data_2 movf RCREG,W call TOUPPER movwf HEX_L call HEXCONV andlw 0FFh btfsc STATUS,Z retlw 00h movf DONNEE,W movwf NBDATA addwf CHECKSUM,F attente_adresse_1 clrwdt btfss PIR1,RCIF goto attente_adresse_1 movf RCREG,W call TOUPPER movwf HEX_H attente_adresse_2 clrwdt btfss PIR1,RCIF goto attente_adresse_2 movf RCREG,W call TOUPPER movwf HEX_L call HEXCONV andlw 0FFh btfsc STATUS,Z retlw 00h movf DONNEE,W movwf ADRESSE_H addwf CHECKSUM,F attente_adresse_3 clrwdt btfss PIR1,RCIF goto attente_adresse_3 movf RCREG,W call TOUPPER movwf HEX_H attente_adresse_4 clrwdt btfss PIR1,RCIF goto attente_adresse_4 movf RCREG,W call TOUPPER movwf HEX_L call HEXCONV andlw 0FFh btfsc STATUS,Z retlw 00h movf DONNEE,W movwf ADRESSE_L addwf CHECKSUM,F attente_info_ligne_1 clrwdt btfss PIR1,RCIF goto attente_info_ligne_1 movf RCREG,W call TOUPPER movwf HEX_H attente_info_ligne_2 clrwdt btfss PIR1,RCIF goto attente_info_ligne_2 movf RCREG,W call TOUPPER movwf HEX_L call HEXCONV andlw 0FFh btfsc STATUS,Z retlw 00h movf DONNEE,W btfss STATUS,Z call RECORD_TYPE addwf CHECKSUM,F movlw 20h ;initialisation du FSR movwf FSR incf NBDATA,W movwf TEMP3 lecture_datas decfsz TEMP3,F goto lecture_datas_1 goto lecture_checksum_1 lecture_datas_1 clrwdt btfss PIR1,RCIF goto lecture_datas_1 movf RCREG,W call TOUPPER movwf HEX_H lecture_datas_2 clrwdt btfss PIR1,RCIF goto lecture_datas_2 movf RCREG,W call TOUPPER movwf HEX_L call HEXCONV andlw 0FFh btfsc STATUS,Z retlw 00h movf DONNEE,W addwf CHECKSUM,F movwf INDF incf FSR,F goto lecture_datas lecture_checksum_1 clrwdt btfss PIR1,RCIF goto lecture_checksum_1 movf RCREG,W call TOUPPER movwf HEX_H lecture_checksum_2 clrwdt btfss PIR1,RCIF goto lecture_checksum_2 movf RCREG,W call TOUPPER movwf HEX_L call HEXCONV andlw 0FFh btfsc STATUS,Z retlw 00h movf CHECKSUM,W addwf DONNEE,W btfss STATUS,Z retlw 00h bcf STATUS,C rrf ADRESSE_H,F ;division de l'adresse par 2 rrf ADRESSE_L,F retlw 0FFh ;**************************************************************************** ; READFLASH : lis donnnee dans la FLASH … l'adresse ADRESSE retour dans HEX(H et L) ;**************************************************************************** READFLASH bsf STATUS,RP1 movf ADRESSE_H,W movwf EEADRH movf ADRESSE_L,W movwf EEADR bsf STATUS,RP0 bsf EECON1,EEPGD bsf EECON1,RD nop nop bcf STATUS,RP0 movf EEDATA,W movwf DONNEE_L movf EEDATH,W movwf DONNEE_H bcf STATUS,RP1 return ;**************************************************************************** ; WRITEFLASH : ecris donnnee pointee par FSR dans la FLASH … l'adresse ADRESSE ;**************************************************************************** WRITEFLASH clrwdt bsf STATUS,RP1 movf ADRESSE_H,W movwf EEADRH movf ADRESSE_L,W movwf EEADR movf INDF,W movwf EEDATA incf FSR,F movf INDF,W movwf EEDATH bsf STATUS,RP0 bsf EECON1,EEPGD bsf EECON1,WREN movlw 55h movwf EECON2 movlw 0AAh movwf EECON2 bsf EECON1,WR nop nop bcf EECON1,WREN clrwdt bcf STATUS,RP0 bcf STATUS,RP1 decf FSR,F return ;**************************************************************************** ; ECRIS_LIGNE : ecris la ligne recue ; renvoie 00 si OK , CC si ecriture interdite, FF si erreur FLASH ;**************************************************************************** ECRIS_LIGNE movlw 20h movwf FSR bcf STATUS,C rrf NBDATA,F ;NBDATA = NBDATA / 2 incf NBDATA,F mot_suivant decfsz NBDATA,F goto mot_suivant_ retlw 00h mot_suivant_ ;debut test si ecriture autorisee movf ADRESSE_H,F ; btfss STATUS,Z ;ADRESSE_H = 0 ? goto test_mem_haute ;non movf ADRESSE_L,W sublw 02h btfsc STATUS,C ;ADRESSE_L > 03h ? retlw 0CCh ;non goto fin_test_mem test_mem_haute movlw HIGH(DEBUT) subwf ADRESSE_H,W btfss STATUS,C ;ADRESSE_H < HIGH(DEBUT) ? goto fin_test_mem ;oui btfss STATUS,Z ;ADRESSE_H = HIGH(DEBUT) retlw 0CCh ;non donc ADRESSE > DEBUT movlw LOW(DEBUT) subwf ADRESSE_L,W btfss STATUS,C ;ADRESSE_L < LOW(DEBUT) ? goto fin_test_mem ;oui retlw 0CCh fin_test_mem ;fin test si ecriture autorisee call READFLASH movf DONNEE_L,W subwf INDF,W btfss STATUS,Z goto ecrit_mot ;teste si le mot … ecrire incf FSR,F ;est different movf DONNEE_H,W ;de celui qui y est deja subwf INDF,W ;pour economiser la FLASH btfsc STATUS,Z goto fin_mot decf FSR,F ecrit_mot call WRITEFLASH call READFLASH movf DONNEE_L,W subwf INDF,W btfss STATUS,Z retlw 0FFh ;teste si le PIC incf FSR,F ;a ete bien programme movf DONNEE_H,W subwf INDF,W btfss STATUS,Z retlw 0FFh movf NB_ECRITS_L,W call INCREMENTE movwf NB_ECRITS_L btfss FLAGS,CARRY goto fin_mot movf NB_ECRITS_H,W call INCREMENTE movwf NB_ECRITS_H fin_mot incf FSR,F incfsz ADRESSE_L,F goto mot_suivant incf ADRESSE_H,F goto mot_suivant ;**************************************************************************** ; Debut du programme ;**************************************************************************** DEMARRAGE clrwdt bsf STATUS,IRP ;page 3 pour adressage indirect bsf STATUS,RP0 bcf TRISC,0 bcf TRISB,6 bcf TRISB,7 bsf TXSTA,BRGH ;high speed bsf TXSTA,TXEN movlw BAUD_DIV movwf SPBRG ;vitesse 9600 Bauds bcf STATUS,RP0 bcf PORTC,0 bsf PORTB,6 bsf PORTB,7 bsf RCSTA,CREN bsf RCSTA,SPEN ;serial port enabled call RETOUR_LIGNE movlw 05h ;message d'acceuil call TXSTR call AFF_BARRE andlw 0FFh btfsc STATUS,Z goto fin_boot ;renvoi 0 : demarrage programme call RETOUR_LIGNE movlw 0C1h call TXSTR boucle call PROMPT ;renvoi FF : l'util. prend la main att_char clrwdt btfsc RCSTA,OERR ;overrun ? goto overrun btfss PIR1,RCIF goto att_char movf RCREG,W call TOUPPER movwf CHAR movlw 'Q' subwf CHAR,W btfsc STATUS,Z goto fin_boot_ movlw 'U' subwf CHAR,F btfsc STATUS,Z goto upload goto att_char overrun bcf RCSTA,CREN clrwdt bsf RCSTA,CREN goto att_char fin_boot_ movlw 'q' call TXCHAR fin_boot call RETOUR_LIGNE movlw 36h call TXSTR movlw d'10' call TEMPO clrf RCSTA bsf STATUS,RP0 clrf TXSTA clrf SPBRG bcf STATUS,RP0 clrf STATUS clrf PCLATH goto 03h upload movlw 'u' call TXCHAR call RETOUR_LIGNE movlw 4Ah ;attente fichier HEX call TXSTR call RETOUR_LIGNE bcf FLAGS,EOF bcf FLAGS,NOW clrf NB_ECRITS_H clrf NB_ECRITS_L upload_ligne call LIGNE_FIC andlw 0FFh btfsc STATUS,Z goto erreur_fichier btfsc FLAGS,NOW ; No write ? goto no_write call ECRIS_LIGNE andlw 0FFh btfss STATUS,Z goto erreur_programmation movlw '#' call TXCHAR btfss FLAGS,EOF ;derniere ligne ? goto upload_ligne ;non, on continue call RETOUR_LIGNE movf NB_ECRITS_H,W call TXHEX movf NB_ECRITS_L,W call TXHEX movlw 96h call TXSTR goto boucle no_write bcf FLAGS,NOW movlw '#' call TXCHAR goto upload_ligne ; on continue, sans avoir ecrit erreur_fichier movlw 61h call TXSTR goto boucle erreur_programmation sublw 0CCh btfss STATUS,Z goto erreur_flash call RETOUR_LIGNE movlw 0A7h goto erreur_adresse erreur_flash call RETOUR_LIGNE movlw 7Ah erreur_adresse call TXSTR movf ADRESSE_H,W call TXHEX movf ADRESSE_L,W call TXHEX movlw 'h' call TXCHAR goto boucle ORG 1F00h ;alignement ;**************************************************************************** ; MSG : table de messages ;**************************************************************************** MSG addwf PCL,F DT "PIC>",0 ;00h DT CR,LF,"Bootloader V1.3",CR,LF ;05h DT CRIGHT," ClubElek - INSA ",CR,LF DT "J.S. 2000",0 DT "Demarrage programme",0 ;36h DT "Attente fichier HEX...",0 ;4Ah DT "Fichier HEX non valide !",0 ;61h DT "Erreur de programmation en ",0 ;7Ah DT " mot(s) ecrit(s)",0 ;96h DT "Interdiction d'ecrire en ",0 ;A7h DT "Utilisation :",CR,LF ;C1h DT " * U : chargement",CR,LF DT " * Q : demarrage",0 END