Create New Item
Item Type
File
Folder
Item Name
Search file in folder and subfolders...
Are you sure want to rename?
File Manager
/
PIC18F452
:
driver.c
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
/**********************************************************************/ /* */ /* File name: driver.c */ /* */ /* Since: 2002/12/03 */ /* */ /* Version: 1.02 */ /* */ /* Author: MONTAGNE Xavier [XM] {link xavier.montagne@wanadoo.fr} */ /* */ /* Purpose: Offer low level functions for basic PIC programming */ /* procedures. Have a look at the Microchip specifications */ /* for further details. */ /* */ /* Distribution: This file is part of PP18. */ /* PP18 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, or (at your option) */ /* any later version. */ /* */ /* PP18 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 PP18; see the file */ /* COPYING.txt. If not, write to the Free Software */ /* Foundation, 59 Temple Place - Suite 330, */ /* Boston, MA 02111-1307, USA. */ /* */ /* History: */ /* 2002/12/03 [XM] Create this file */ /* 2003/06/26 [XM] Added the Delay_Prog management. */ /* */ /**********************************************************************/ /*********************************************************************** * INCLUDES **********************************************************************/ #include "driver.h" /*********************************************************************** * DEFINES. **********************************************************************/ #define MOVLW 0x0E00 #define MOVWF 0x6E00 #define TBLPTRL_ad 0xF6 #define TBLPTRH_ad 0xF7 #define TBLPTRU_ad 0xF8 /* * As specified in PIC18C ICSP specification. */ #define NB_BIT_PER_INST 4 #define NB_BIT_PER_DATA 16 #define NB_BIT_PER_HALF_DATA 8 /*********************************************************************** * MACROS **********************************************************************/ #define WriteOpNOP() WriteOp(0x00) #define WriteOpTRNoChange() WriteOp(0x08) #define WriteOpTRPostInc() WriteOp(0x09) #define WriteOpTRPostDec() WriteOp(0x0a) #define WriteOpTRPreInc() WriteOp(0x0b) #define WriteOpTWNoChange() WriteOp(0x0c) #define WriteOpTWPostInc() WriteOp(0x0d) #define WriteOpTWPostDec() WriteOp(0x0e) #define WriteOpTWPreInc() WriteOp(0x0f) #ifdef LINUX #include <sys/io.h> #define pport_in(value, port_adr) value = inb(port_adr) #define pport_out(value, port_adr) outb(value, port_adr) #else #ifdef WITHOUT_PIC #include <stdlib.h> #include <stdio.h> #define pport_in(value, port_adr) value = (rand())%0xFF; #define pport_out(value, port_adr) #else #define pport_in(value, port_adr) __asm mov dx, port_adr ;\ __asm in al, dx ;\ __asm mov value, al #define pport_out(value, port_adr) __asm mov dx, port_adr ;\ __asm mov al, value ;\ __asm out dx, al #endif /* WITHOUT_PIC */ #endif /* LINUX */ /*********************************************************************** * Function prototypes. **********************************************************************/ static void WriteRB6_RB7(unsigned char); static void WriteRB6_RB7Delay(unsigned char val); static void WriteOp(unsigned char TBLWT); static void WriteOpDelay(unsigned char TBLWT); static void WriteData(unsigned short data); static void WriteDataAtTBLPTR(unsigned short data, ACTION action); static void ReadDataAtTBLPTR(unsigned char *data, ACTION action); static unsigned char ReadData(void); static void SetTBLPTR(unsigned int location); static void SelectBit(pr_Signal *ptr_bit, PIN_LABEL name); /*********************************************************************** * Global variables. **********************************************************************/ pr_ValSignal CLOCK = { PL_CLOCK, RB6_MASK, NON_INVERTED }; pr_ValSignal DATA_TO_PIC = { PL_DATA_TO_PIC, RB7_MASK, NON_INVERTED }; pr_ValSignal DATA_FROM_PIC = { PL_DATA_FROM_PIC, BUSY_MASK, INVERTED }; pr_ValSignal MCLR_VPP = { PL_VPP, MCLR_MASK, INVERTED }; pr_ValSignal VCC_ON = { PL_VCC, VCC_ON_MASK, INVERTED }; /***** Value in data parallele port register. *************************/ unsigned char data_bus; unsigned short LPT_adr_out = PPORT_OUT_ADR; unsigned short LPT_adr_in = PPORT_IN_ADR; unsigned int delay_IO = 400; unsigned int delay_Prog = 5; /*********************************************************************** * Stuck at 0 all of the signals (logical 0, not necessarily physical 0). * * @param void * @return void **********************************************************************/ void _InitHardware(void) { ClearBit(PL_CLOCK); ClearBit(PL_DATA_TO_PIC); ClearBit(PL_VPP); ClearBit(PL_VCC); } /*********************************************************************** * Set VCC_ON bit physicaly at 1. * * @param void * @return void **********************************************************************/ void _PowerOn(void) { unsigned int j; /* 10 ms delay */ /* LPT port transfer rate = 150 ko/s */ for (j = 0; j < 1500; j++) SetBit(PL_VCC); } /*********************************************************************** * Clear VCC_ON bit physicaly at 0. * * @param void * @return void **********************************************************************/ void _PowerOff(void) { ClearBit(PL_VCC); } /*********************************************************************** * Write a buffer into the memory of the PIC. * A programmable delay exists to avoid any transfert problem with * low speed communication PIC. Full speed is default speed. * * @param u_int adr IN Start address in the PIC address * @param u_short *block IN Buffer start address * @param u_int size IN Number of SHORT to write * @param u_int *try_done IN For compatibility with JW version * @param u_int word_programmed IN Number of SHORT programmed * @return void **********************************************************************/ void ProgramBlock(unsigned int adr, unsigned short *block, unsigned int size, unsigned int *try_done, unsigned int *word_programmed) { unsigned int i, j, word_prg; unsigned short value; for (j = 0; j < 1500; j++) SetBit(PL_VPP); /* Precharge phase */ SetTBLPTR(0x3C0006); WriteDataAtTBLPTR(0x00, NO_CHANGE); WriteOpNOP(); WriteData((unsigned short)(0x8EA6)); WriteOpNOP(); WriteData((unsigned short)(0x9CA6)); /* End fo Precharge phase */ word_prg = 0; SetTBLPTR(adr); for (i = 0; i < size; i = i + 1) { value = *block; for (j = 0; (j < 3) & (size > 1); j++) { WriteDataAtTBLPTR(value, POST_INC); i++; block++; word_prg++; value = *block; } WriteDataAtTBLPTR(value, PRE_INC); WriteOpDelay(0x00); for (j = 0; j < delay_IO; j++) SetBit(PL_CLOCK); ClearBit(PL_CLOCK); WriteData(0x0000); WriteDataAtTBLPTR(0x0000, POST_INC); block++; word_prg++; } *try_done = i; *word_programmed = word_prg; ClearBit(PL_VPP); } /*********************************************************************** * Write a buffer into the configuration field of the PIC. * A programmable delay exists to avoid any transfert problem with * low speed communication PIC. Full speed is default speed. * * @param u_int adr IN Start address in the PIC address * @param u_short *block IN Buffer start address * @param u_int size IN Number of SHORT to write * @param u_int *try_done IN For compatibility with JW version * @param u_int word_programmed IN Number of SHORT programmed * @return void **********************************************************************/ void ProgramBlockCfg(unsigned int adr, unsigned short *block, unsigned int size, unsigned int *try_done, unsigned int *word_programmed) { unsigned int i, j, word_prg; unsigned short value; for (j = 0; j < 1500; j++) SetBit(PL_VPP); /* Precharge phase */ SetTBLPTR(0x3C0006); WriteDataAtTBLPTR(0x00, NO_CHANGE); WriteOpNOP(); WriteData((unsigned short)(0x8EA6)); WriteOpNOP(); WriteData((unsigned short)(0x8CA6)); /* End of precharge phase */ word_prg = 0; SetTBLPTR(adr); for (i = 0; i < size; i = i + 1) { value = *block; for (j = 0; (j < 3) & (size > 1); j++) { WriteDataAtTBLPTR(value, POST_INC); i++; block++; word_prg++; value = *block; } WriteDataAtTBLPTR(value, PRE_INC); WriteOpDelay(0x00); for (j = 0; j < delay_IO; j++) SetBit(PL_CLOCK); ClearBit(PL_CLOCK); WriteData(0x0000); WriteDataAtTBLPTR(0x0000, POST_INC); block++; word_prg++; } *try_done = i; *word_programmed = word_prg; ClearBit(PL_VPP); } /*********************************************************************** * Read the memory of the PIC and store the result into a buffer. * A programmable delay exists to avoid any transfert problem with * low speed communication PIC. Full speed is default speed. * * @param u_int adr IN Start address in the PIC address * @param u_short *block IN Buffer address * @param u_int size IN Number of SHORT to write * @return void **********************************************************************/ void ReadBlock(unsigned int adr, unsigned short *block, unsigned int size) { unsigned int i, j; unsigned char result_H, result_L; unsigned short result; for (j = 0; j < 1500; j++) SetBit(PL_VPP); SetTBLPTR(adr); for (i = 0; i < size; i = i + 1) { ReadDataAtTBLPTR(&result_L, POST_INC); ReadDataAtTBLPTR(&result_H, POST_INC); result = (unsigned short)(result_L + (unsigned short)(result_H << 8)); *block = result; block++; for (j = 0; j < delay_IO; j++) ClearBit(PL_CLOCK); } ClearBit(PL_VPP); } /*********************************************************************** * Erase the entier memory of the PIC. * A programmable delay exists to avoid any transfert problem with * low speed communication PIC. Full speed is default speed. * * @param void * @return void **********************************************************************/ void BulkErase(void) { unsigned int j; for (j = 0; j < 1500; j++) SetBit(PL_VPP); SetTBLPTR(0x3C0004); WriteDataAtTBLPTR(0x83, NO_CHANGE); WriteOpNOP(); WriteData(0x0000); WriteOpNOP(); for (j = 0; j < 5000; j++) ClearBit(PL_CLOCK); WriteData(0x0000); ClearBit(PL_VPP); SetBit(PL_VPP); SetTBLPTR(0x3C0004); WriteDataAtTBLPTR(0x80, NO_CHANGE); WriteOpNOP(); WriteData(0x0000); WriteOpNOP(); for (j = 0; j < 5000; j++) ClearBit(PL_CLOCK); WriteData(0x0000); ClearBit(PL_VPP); return; } /*********************************************************************** * Update the TBLPTR. It's necessary to do so before programming the * PIC. This is the START address of the read/write sequences. * * @param u_int location IN Value of the TBLPTR register * @return void **********************************************************************/ static void SetTBLPTR(unsigned int location) { unsigned char TBLPTRL, TBLPTRH, TBLPTRU; TBLPTRL = (unsigned char)(location & 0xff); TBLPTRH = (unsigned char)((location >> 8) & 0xff); TBLPTRU = (unsigned char)((location >> 16) & 0xff); /* TBLPTRL */ WriteOpNOP(); WriteData((unsigned short)(MOVLW + TBLPTRL)); WriteOpNOP(); WriteData((unsigned short)(MOVWF + TBLPTRL_ad)); /* TBLPTRH */ WriteOpNOP(); WriteData((unsigned short)(MOVLW + TBLPTRH)); WriteOpNOP(); WriteData((unsigned short)(MOVWF + TBLPTRH_ad)); /* TBLPTRU */ WriteOpNOP(); WriteData((unsigned short)(MOVLW + TBLPTRU)); WriteOpNOP(); WriteData((unsigned short)(MOVWF + TBLPTRU_ad)); } /*********************************************************************** * Write any 16 bits word into the PIC memory at the address pointed by * TBLPTR. * * @param u_short data IN Data to write at TBLPTR * @param ACTION action IN Post-inc, pre-inc,... * @return void **********************************************************************/ static void WriteDataAtTBLPTR(unsigned short data, ACTION action) { switch (action) { case NO_CHANGE : WriteOpTWNoChange(); break; case POST_INC : WriteOpTWPostInc(); break; case POST_DEC : WriteOpTWPostDec(); break; case PRE_INC : WriteOpTWPreInc(); break; default : break; }; WriteData(data); } /*********************************************************************** * Read any 16 bits word into the PIC memory at the address pointed by * TBLPTR. * * @param u_short *data IN Data to read at TBLPTR * @param ACTION action IN Post-inc, pre-inc,... * @return void **********************************************************************/ static void ReadDataAtTBLPTR(unsigned char *data, ACTION action) { switch (action) { case NO_CHANGE : WriteOpTRNoChange(); break; case POST_INC : WriteOpTRPostInc(); break; case POST_DEC : WriteOpTRPostDec(); break; case PRE_INC : WriteOpTRPreInc(); break; default : break; }; *data = ReadData(); } /*********************************************************************** * Send any 8 bits command word to the PIC. The bits are sent one by * one to the PIC via the RB6 & RB7 pins. * * @param u_char CMD IN Command to send to the PIC * @return void **********************************************************************/ static void WriteOp(unsigned char CMD) { unsigned char i; for (i = 0; i < NB_BIT_PER_INST; i++) WriteRB6_RB7((unsigned char)((CMD >> i) & 1)); } /*********************************************************************** * Send any 8 bits command word to the PIC. The bits are sent one by * one to the PIC via the RB6 & RB7 pins. * Delay for special operation is added as specified in the Microchip * specification. * * @param u_char CMD IN Command to send to the PIC * @return void **********************************************************************/ static void WriteOpDelay(unsigned char CMD) { unsigned char i; for (i = 0; i < NB_BIT_PER_INST-1; i++) WriteRB6_RB7((unsigned char)((CMD >> i) & 1)); WriteRB6_RB7Delay((unsigned char)((CMD >> NB_BIT_PER_INST) & 1)); } /*********************************************************************** * Send any 16 bits data word to the PIC. The bits are sent one by * one to the PIC via the RB6 & RB7 pins. * * @param u_short data IN Data to send to the PIC * @return void **********************************************************************/ static void WriteData(unsigned short data) { unsigned char i; for (i = 0; i < NB_BIT_PER_DATA; i++) WriteRB6_RB7((unsigned char)((data >> i) & 1)); } /*********************************************************************** * Read a 16 bits data word from the PIC. The bits are read one by * one to the PIC via the RB6 & RB7 pins. * * @param void * @return u_short Data read from the PIC **********************************************************************/ static unsigned char ReadData(void) { unsigned char i, data, val; data = 0; for (i = 0; i < NB_BIT_PER_HALF_DATA; i++) WriteRB6_RB7((unsigned char)((data >> i) & 1)); SetBit(PL_DATA_TO_PIC); for (i = 0; i < NB_BIT_PER_HALF_DATA; i++) { val = ReadBit(PL_DATA_FROM_PIC); data |= (unsigned char)(((val) ? 1: 0) << i); } ClearBit(PL_DATA_TO_PIC); return (data); } /*********************************************************************** * Read one bit from the PIC. The bit is one of the 5 signals of the * programmer. * * @param PIN_LABEL name IN Signal name * @return u_char LPT data value masked by the signal **********************************************************************/ unsigned char ReadBit(PIN_LABEL name) { unsigned char data; unsigned int j; pr_Signal the_bit; SelectBit(&the_bit, name); for (j = 0; j < delay_Prog; j++) SetBit(PL_CLOCK); for (j = 0; j < delay_Prog; j++) ClearBit(PL_CLOCK); pport_in(data, LPT_adr_in); if (the_bit->status & INVERTED) data = (unsigned char)((~data) & the_bit->mask); else data = (unsigned char)(data & the_bit->mask); return (data); } /*********************************************************************** * Write one bit on one signal from the 5 signals of the programmer. * * @param u_char val IN Boolean value to set on the signal * @return void **********************************************************************/ static void WriteRB6_RB7(unsigned char val) { unsigned int j; for (j = 0; j < delay_Prog; j++) SetBit(PL_CLOCK); for (j = 0; j < delay_Prog; j++) (val & 1) ? SetBit(PL_DATA_TO_PIC) : ClearBit(PL_DATA_TO_PIC); for (j = 0; j < delay_Prog; j++) ClearBit(PL_CLOCK); for (j = 0; j < delay_Prog; j++) ClearBit(PL_DATA_TO_PIC); } /*********************************************************************** * Write one bit on one signal from the 5 signals of the programmer. * Special delay is added as specified by the Microchip specification. * * @param u_char val IN Boolean value to set on the signal * @return void **********************************************************************/ static void WriteRB6_RB7Delay(unsigned char val) { SetBit(PL_CLOCK); (val & 1) ? SetBit(PL_DATA_TO_PIC) : ClearBit(PL_DATA_TO_PIC); } /*********************************************************************** * Stuck the signal at 1 (logical 1, not physical 1). * * @param PIN_LABEL name IN Signal name * @return void **********************************************************************/ void SetBit(PIN_LABEL name) { pr_Signal the_bit; SelectBit(&the_bit, name); if (the_bit->status & INVERTED) data_bus &= (unsigned char)~the_bit->mask; else data_bus |= the_bit->mask; pport_out(data_bus, PPORT_OUT_ADR); } /*********************************************************************** * Stuck the signal at 0 (logical 0, not physical 0). * * @param PIN_LABEL name IN Signal name * @return void **********************************************************************/ void ClearBit(PIN_LABEL name) { pr_Signal the_bit; SelectBit(&the_bit, name); if (the_bit->status & INVERTED) data_bus |= the_bit->mask; else data_bus &= (unsigned char)~the_bit->mask; pport_out(data_bus, PPORT_OUT_ADR); } /*********************************************************************** * Setup a signal. * * @param PIN_LABEL name IN Signal name * @param u_char mask IN Mask value of the signal * @param u_char status IN INVERTED or NOT_INVERTED * @return void **********************************************************************/ void ConfigBit(PIN_LABEL name, unsigned char mask, unsigned char status) { pr_Signal the_bit; SelectBit(&the_bit, name); if (mask) the_bit->mask = mask; the_bit->status = status; } /*********************************************************************** * Select a signal. * * @param pr_Signal *ptr_bit IN Signal pointer * @param PIN_LABEL name IN Signal name * @return void **********************************************************************/ static void SelectBit(pr_Signal *ptr_bit, PIN_LABEL name) { switch (name) { case PL_DATA_TO_PIC: *ptr_bit = &DATA_TO_PIC; break; case PL_DATA_FROM_PIC: *ptr_bit = &DATA_FROM_PIC; break; case PL_CLOCK: *ptr_bit = &CLOCK; break; case PL_VPP: *ptr_bit = &MCLR_VPP; break; case PL_VCC: *ptr_bit = &VCC_ON; break; } } /*********************************************************************** * Get the mask value of a signal. * * @param PIN_LABEL name IN Signal name * @return void **********************************************************************/ unsigned char GetMask(PIN_LABEL name) { pr_Signal the_bit; SelectBit(&the_bit, name); return (the_bit->mask); } /*********************************************************************** * Get the Status value of a signal. * * @param PIN_LABEL name IN Signal name * @return void **********************************************************************/ unsigned char GetStatus(PIN_LABEL name) { pr_Signal the_bit; SelectBit(&the_bit, name); return (the_bit->status); } /* End of file */