PIC18F2550 Programmer using Arduno

Post Reply
User avatar
SemiconductorCat
Major
Major
Posts: 455
Joined: Mon Aug 22, 2011 8:42 pm
Location: currently in hyperspace

PIC18F2550 Programmer using Arduno

Post by SemiconductorCat » Sat Oct 13, 2012 10:38 am

Some people thinks that programmers have magical firmware or software, but they are wrong,Almost all 99% of their
interfaces are open specifications.

Here is a project on programming PIC18F2550 with an arduno board: .
https://sites.google.com/site/thehighsp ... ino-pic18f

And here is the microchip's 18FXXX programming specification.
http://ww1.microchip.com/downloads/en/D ... 39622L.pdf


The windows/linux program is still a command based version. You could go and read the code. I do encourage reading
other's code. It was open source and I'll be free to put it in here.

Code: Select all

/*
Copyright (C) 2012  kirill Kulakov

    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 3 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, see <http://www.gnu.org/licenses/>.

*/

#include "rs232.h"
#include "HEX.h"

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

#define DEVICE_DELAY 150

void main(){

	printf("Arduino as A PIC18f2550 programmer - Version 0.2 - http://goo.gl/fyd9mn\n");

	if(_main()){
		printf("Error! can not continue\n");
		printf("Make sure you have uploaded the sketch to the Arduino,\nconnected the chip correctly and using a valid HEX file\n");
	}
	else {
		printf("The chip was programmed successfully!\n");
		
	}
	
	system("pause");
}


int _main(){

	HEX thehex;
	char buf[4096],key;
	int n;
	unsigned int address=0,i,j;
	int comPort=-1;

	//reading the hex file
	printf("Enter location of hex file: ");
	scanf("%4096[^\n]",buf);
	if( (thehex = readHex(buf)) == NULL ){
		printf("Can not open the file\n");
		return 1;
	}

	printf("---------------------------\n");
	printf("Connecting to the Arduino...");

	for(i=0;i<16;i++){
		if(!OpenComport(i, 9600)){
			for(j=0;j<10;j++){
				SendBuf(2,(unsigned char *)"DX",strlen("DX"));
				n = PollComport(2, (unsigned char *)buf, 4095);
				Sleep(DEVICE_DELAY);
				if( *buf == 'T' || *buf == 'F' ){
					comPort = i;
					break;
				}
				
			}
			CloseComport(2);
			if( comPort != -1 )
				break;		
		}
	}

	if( comPort == -1 ){
		printf("Cannot connect to the programmer");
		return 1;
	}

	OpenComport(comPort, 9600);

	printf("Success!\nConnecting to the chip...");

	//wait for 18f2550

	do{
	if( SendBuf(comPort,(unsigned char *)"DX",strlen("DX")) == -1 ) return 1;
	n = PollComport(comPort, (unsigned char *)buf, 4095);
	Sleep(DEVICE_DELAY);
	}while( n == 0 || *buf != 'T' );
	
	printf("Success!\n");

	printf("Erasing the chip...");

	//chip reset
	if( SendBuf(comPort,(unsigned char *)"EX",strlen("EX")) == -1 ) return 1;

	printf("Success!\n");

	Sleep(DEVICE_DELAY);

	

	printf("Programming fuse bits...");


	for(i=0;i<0xf;i++){
		if(fuseChanged(thehex,i)){
			sprintf(buf,"C%X%02XX",i,getfuse(thehex,i));
			SendBuf(comPort,(unsigned char *)buf,strlen(buf));
			Sleep(DEVICE_DELAY);
		}
	}
	
	printf("Success!\n");
	
	printf("Programming flash memory...");

	//memory write

	while( address < 0x8000 ){

		for(i=0;i<0x20;i++){
			if( getData(thehex,address+i) != 0xff ){
				sprintf(buf,"W");
				sprintf(buf+strlen(buf),"%04X",address);
				for(i=0;i<0x20;i++)
					sprintf(buf+strlen(buf),"%02X",getData(thehex,address+i));
				sprintf(buf+strlen(buf),"X\n");
				SendBuf(comPort,(unsigned char *)buf,strlen(buf));
				Sleep(DEVICE_DELAY);
				break;
			}
		}

		address += 0x20;

	}

	printf("Success!\n");
  
	CloseComport(2);

	printf("---------------------------\n");

	return 0;

}
^- this file includes "rs232.h" and rs232.c functions were used. I have no idea to post them in here.You could find
them on their original repository. See bottom links reference.

And this is what arduno does. Many people think it's arduno "C". But it's wrong. it's not "C" , but it's a "C" like language.
Neither it's extension ends with ".C" but with ".ino". But it's easier to go through the code and understand.
Happy code digging.

Code: Select all

// I wrote it according to the following datasheet:
// http://ww1.microchip.com/downloads/en/DeviceDoc/39622L.pdf

//pin out config
#define PGC 6
#define PGD 5
//#define EN 7 //PGM & MCLR
#define PGM 8
#define MCLR 7

#define P15 1
#define P12 1

String inputString = "";
boolean stringComplete = false;

unsigned long temp;

byte buffer[32];
byte address[3];

void setup(){
  Serial.begin(9600);
  pinMode(PGC,OUTPUT);
  pinMode(PGD,OUTPUT);
  pinMode(PGM,OUTPUT);
  pinMode(MCLR,OUTPUT);
  
 inputString.reserve(200);
 
}


void loop(){ 

  //turn on the chip (disable programming mode & diable reset)
  digitalWrite(PGM,LOW);
  digitalWrite(MCLR,HIGH);
  
} 



//////THE MAIN CODE///////////
//////////////////////////////
//////////////////////////////
void serialEvent() {
   
  while (Serial.available()) {

    char inChar = (char)Serial.read(); 
    
    if (inChar == 'X') { //buffering till X
      stringComplete = true;
      break;
    } 
    
    inputString += inChar;
    
  }
  
  
  if (stringComplete && inputString.charAt(0) == 'W'){ //WRITE
    
    if(inputString.length() != 69) {
      //Serial.println("Input is wrong, should be: W<address - 4 digit><32bytes>X"); 
      nullString();
      goto endofthisif;
      }
    
    address[2] = 0;
    address[1] = char2byte(inputString.charAt(2),inputString.charAt(1));
    address[0] = char2byte(inputString.charAt(4),inputString.charAt(3));
    
    nullBuffer(); // set everything FF
    
    for(int i=0;i<32;i++){
      buffer[i] = char2byte(inputString.charAt(2*i+6),inputString.charAt(2*i+5));
      } 
    
    nullString();
    
    // print address
    //Serial.print("Programming 32bytes,starting at:");
    //Serial.print("0x00");
    //if(address[1]<0x10) Serial.print("0"); Serial.print(address[1],HEX);
    //if(address[0]<0x10) Serial.print("0"); Serial.println(address[0],HEX);
    
    //for(int i=0;i<32;i++) { Serial.print(buffer[i],HEX); }
      
    //Serial.println("");
    
    ///Write
    
    digitalWrite(PGM,HIGH);
    digitalWrite(MCLR,HIGH);
    
    delay(1);

    programBuffer(address[2],address[1],address[0]);
    
    digitalWrite(PGM,LOW);
    digitalWrite(MCLR,LOW);
    
    //Serial.println("Programming complety");    
    }
  
  endofthisif:;
  
  
  
  
  if (stringComplete && inputString.charAt(0) == 'E'){ //Erase all
     digitalWrite(PGM,HIGH);
     digitalWrite(MCLR,HIGH);
     delay(1);
     
     ////erase 
     erase_all();
     
    digitalWrite(PGM,LOW);
    digitalWrite(MCLR,LOW);
     
     //Serial.println("Erase complety");
     
     nullString();
    }
    
    
    
    
    
    
    if (stringComplete && inputString.charAt(0) == 'R'){ //READ
      
      
      
         address[2] = char2byte(inputString.charAt(2),inputString.charAt(1));
         address[1] = char2byte(inputString.charAt(4),inputString.charAt(3));
         address[0] = char2byte(inputString.charAt(6),inputString.charAt(5));
         
         //read
         
    
    temp=0;

    temp = ((long)address[2])<<(16); //doesn't work with out (long)
    temp |= ((long)address[1])<<(8);
    temp |= (long)address[0];
    
    Serial.print(temp,HEX); Serial.print(":");  
    
    digitalWrite(PGM,HIGH);
    digitalWrite(MCLR,HIGH);
    delay(1);
    
    for(int i=0;i<32;i++){
        address[2] = byte( (temp&0xFF0000)>>16 );
        address[1] = byte( (temp&0xFF00)>>8 );
        address[0] = byte( temp&0xFF );
        Serial.print(readFlash(address[2],address[1],address[0]),HEX);
        Serial.print(" ");
        temp++;
       }
    
    Serial.println("");
    
    digitalWrite(PGM,LOW);
    digitalWrite(MCLR,LOW);
    
    nullString();
     
    }
    
    
    if (stringComplete && inputString.charAt(0) == 'C'){ //config
    
     digitalWrite(PGM,HIGH);
     digitalWrite(MCLR,HIGH);
     delay(1);
    
    configWrite( char2byte(inputString.charAt(1),'0'),char2byte(inputString.charAt(3),inputString.charAt(2)) );
    
    digitalWrite(PGM,LOW);
    digitalWrite(MCLR,LOW);
    nullString();
    
    }
    
    if (stringComplete && inputString.charAt(0) == 'D'){ //config
    
    if( checkIf_pic18f2550() ){
      delay(100); Serial.print("T");
    } else {
      delay(100); Serial.print("F");
    }
    
    
    digitalWrite(PGM,LOW);
    digitalWrite(MCLR,LOW);
    nullString();
    
    }
    
    //clear string incase the first CHAR isn't E,R,W
    if(inputString.charAt(0) != 'E' && inputString.charAt(0) != 'R' && inputString.charAt(0) != 'W' && inputString.charAt(0) != 'C' && inputString.charAt(0) != 'D') nullString();
  
}




byte readFlash(byte usb,byte msb,byte lsb){
  
  byte value=0;
  
  send4bitcommand(B0000);
  send16bit( 0x0e00 | usb ); //
  send4bitcommand(B0000);
  send16bit(0x6ef8);
  
  send4bitcommand(B0000);
  send16bit( 0x0e00 | msb ); //
  send4bitcommand(B0000);
  send16bit(0x6ef7);
  
  send4bitcommand(B0000);
  send16bit( 0x0e00 | lsb ); //
  send4bitcommand(B0000);
  send16bit(0x6ef6); 
  
  send4bitcommand(B1000); //
  
  pinMode(PGD,INPUT); digitalWrite(PGD,LOW);
  
  for(byte i=0;i<8;i++){ //read
     digitalWrite(PGC,HIGH);
     digitalWrite(PGC,LOW);
    }
    
    
for(byte i=0;i<8;i++){ //shift out
     digitalWrite(PGC,HIGH); 
     digitalWrite(PGC,LOW);
     if(digitalRead(PGD) == HIGH) value += 1<<i; //sample PGD
    } 
    
  return value;
 
  }


void send4bitcommand(byte data){
  pinMode(PGD,OUTPUT);
  for(byte i=0;i<4;i++){
    if( (1<<i) & data ) digitalWrite(PGD,HIGH); else digitalWrite(PGD,LOW); 
     digitalWrite(PGC,HIGH);
     digitalWrite(PGC,LOW);
    }

}

void send16bit(unsigned int data){
  pinMode(PGD,OUTPUT);
  for(byte i=0;i<16;i++){
    if( (1<<i) & data ) digitalWrite(PGD,HIGH); else digitalWrite(PGD,LOW); 
     digitalWrite(PGC,HIGH);
     digitalWrite(PGC,LOW);
    }

}


void erase_all(){ //for some reason the chip stops respone, just reconnect voltage
  
  send4bitcommand(B0000);
  send16bit(0x0e3c); //
  send4bitcommand(B0000);
  send16bit(0x6ef8);
  
  send4bitcommand(B0000);
  send16bit(0x0e00); //
  send4bitcommand(B0000);
  send16bit(0x6ef7);
  
  send4bitcommand(B0000);
  send16bit(0x0e05); //
  send4bitcommand(B0000);
  send16bit(0x6ef6);
  
  send4bitcommand(B1100);
  send16bit(0x3F3F);
  
  
  send4bitcommand(B0000);
  send16bit(0x0e3c); //
  send4bitcommand(B0000);
  send16bit(0x6ef8);
  
  send4bitcommand(B0000);
  send16bit(0x0e00); //
  send4bitcommand(B0000);
  send16bit(0x6ef7);
  
  send4bitcommand(B0000);
  send16bit(0x0e04); //
  send4bitcommand(B0000);
  send16bit(0x6ef6);
  
  send4bitcommand(B1100);
  send16bit(0x8F8F);
  
  send4bitcommand(B0000); //
  send16bit(0x0000); //
  
  delay(2);
  
  send4bitcommand(B0000); //
  send16bit(0x0000); //
  
  delay(2);
  
  digitalWrite(PGD,LOW);
  
  delay(2);
  
  digitalWrite(PGD,HIGH);
  
}


void configWrite(byte address,byte data){
  
  
  send4bitcommand(B0000);
  send16bit( 0x8ea6 );
  send4bitcommand(B0000);
  send16bit( 0x8ca6 );  
  
  send4bitcommand(B0000);
  send16bit( 0x0e30 ); //
  send4bitcommand(B0000);
  send16bit(0x6ef8);
  
  send4bitcommand(B0000);
  send16bit( 0x0e00 ); //
  send4bitcommand(B0000);
  send16bit(0x6ef7);
  
  send4bitcommand(B0000);
  send16bit( 0x0e00 | address ); //
  send4bitcommand(B0000);
  send16bit(0x6ef6); 
  
  //Serial.println("programming");
  
  send4bitcommand(B1111);
  if(address&0x01) send16bit( 0x0000 | data<<8 ); // if even MSB ignored, LSB read 
  else send16bit( 0x0000 | data ); // if odd MSB read, LSB ignored
  
  digitalWrite(PGC,HIGH);
  digitalWrite(PGC,LOW);
  
  digitalWrite(PGC,HIGH);
  digitalWrite(PGC,LOW);
  
  digitalWrite(PGC,HIGH);
  digitalWrite(PGC,LOW);  

  digitalWrite(PGC,HIGH);
  delay(1);
  digitalWrite(PGC,LOW);
  delayMicroseconds(100);
  
  send16bit(0x0000); 
  }
  
void programBuffer(byte usb,byte msb,byte lsb){ 
  
  if( (lsb&0x0F) | ((lsb&0xF0)>>4)%2){
   //Serial.println("Error: First digit (refere as HEX) have to be 0, and the second digit have to be even.");
   //Serial.println("valid examples: 0x000000 , 0x000060, 0x006320, 0x0063E0"); 
   //Serial.println("INvalid examples: 0x000004 , 0x000014, 0x006328, 0x0063EA");
   //Serial.println("0,2,4,6,8,A,C,E are even");
   return;
  }
  
  //step 1
  send4bitcommand(B0000);
  send16bit(0x8ea6); 
  send4bitcommand(B0000);
  send16bit(0x9ca6);
  
  //step 2
  send4bitcommand(B0000);
  send16bit( 0x0e00 | usb ); //
  send4bitcommand(B0000);
  send16bit(0x6ef8);
  
  send4bitcommand(B0000);
  send16bit( 0x0e00 | msb ); //
  send4bitcommand(B0000);
  send16bit(0x6ef7);
  
  send4bitcommand(B0000);
  send16bit( 0x0e00 | lsb ); //
  send4bitcommand(B0000);
  send16bit(0x6ef6);

  //step 3
  for(byte i=0;i<15;i++){
    send4bitcommand(B1101);
    send16bit( buffer[(2*i)+1]<<8 | buffer[(i*2)] );    
    } 
  
  //step 4
  send4bitcommand(B1111);
  send16bit( buffer[31]<<8 | buffer[30] );  
  
  //nop
  digitalWrite(PGC,HIGH);
  digitalWrite(PGC,LOW);
  
  digitalWrite(PGC,HIGH);
  digitalWrite(PGC,LOW);
  
  digitalWrite(PGC,HIGH);
  digitalWrite(PGC,LOW);  

  digitalWrite(PGC,HIGH);
  delay(1);
  digitalWrite(PGC,LOW);
  delayMicroseconds(100);
  
  send16bit(0x0000); 
  
  //done
  
  }


/////////////////////////////
//nothing special underhere:

void nullString(){
  inputString = "";
  stringComplete = false; 
  }
  
void nullBuffer(){
  for(byte i=0;i<32;i++) buffer[i] = 0xFF;
  }
  
byte char2byte(char lsb,char msb){
  
  byte result=0;
  
  switch(lsb){
    case '0': result = 0; break;
    case '1': result = 1; break;
    case '2': result = 2; break;
    case '3': result = 3; break;
    case '4': result = 4; break;
    case '5': result = 5; break;
    case '6': result = 6; break;
    case '7': result = 7; break;
    case '8': result = 8; break;
    case '9': result = 9; break;
    case 'A': result = 0xA; break;
    case 'B': result = 0xB; break;
    case 'C': result = 0xC; break;
    case 'D': result = 0xD; break;
    case 'E': result = 0xE; break;
    case 'F': result = 0xF; break;
  }
  
switch(msb){
    case '0': result |= 0<<4; break;
    case '1': result |= 1<<4; break;
    case '2': result |= 2<<4; break;
    case '3': result |= 3<<4; break;
    case '4': result |= 4<<4; break;
    case '5': result |= 5<<4; break;
    case '6': result |= 6<<4; break;
    case '7': result |= 7<<4; break;
    case '8': result |= 8<<4; break;
    case '9': result |= 9<<4; break;
    case 'A': result |= 0xA<<4; break;
    case 'B': result |= 0xB<<4; break;
    case 'C': result |= 0xC<<4; break;
    case 'D': result |= 0xD<<4; break;
    case 'E': result |= 0xE<<4; break;
    case 'F': result |= 0xF<<4; break;
  }
  
  return result;
  
}

int checkIf_pic18f2550(){
  
  digitalWrite(PGM,HIGH);
  digitalWrite(MCLR,HIGH);
  delay(1);
  
  if( readFlash(0x3f,0xff,0xff) == 0x12 )
    return 1;
  else
    return 0;
}




Reference links:
* main project : https://sites.google.com/site/thehighsp ... ino-pic18f
* microchip programming specification: http://ww1.microchip.com/downloads/en/D ... 39622L.pdf
* code repository : https://bitbucket.org/kirill578/arduino ... ?at=master



Happy Reading the Code.
Post Reply

Return to “Arduino”