bootloader usb hid para microcontroladores pic18f4550 e pic18f2550.docx
TRANSCRIPT
/* Bootloader USB HID para microcontroladores PIC18F4550 e PIC18F2550 Clock: 48MHz ( ? MHz + PLL ativado ) Compilador: MikroC PRO PIC Autor: Tiago Blog: microcontrolandos.blogspot.com.br*/ #include <Built_in.h> /* Comandos */enum Cmd { cmdNONE, cmdINFO, cmdSTART, cmdWRITE, cmdERASE }; enum McuType { PIC16 = 1, PIC18, PIC18FJ, PIC24, DSPIC = 10, PIC32 = 20 }; enum Cmd CmdCode = cmdNONE; const STX = 0x0F; /* Calcula o endereço inicial do bootloader */const unsigned long BOOTLOADER_SIZE = 7432;const unsigned long BOOTLOADER_START = (( __FLASH_SIZE - BOOTLOADER_SIZE) / _FLASH_ERASE) * _FLASH_ERASE;const unsigned char RESET_VECTOR_SIZE = 4; /* Fornece informações sobre o MCU */typedef struct{ char McuType; //Tipo unsigned long FlashSize; //Tamanho da Flash unsigned EraseBlock; //Numero de blocos para apagar unsigned WriteBlock; //Numeros de blocos de escrita unsigned long BootStart; //Endereço inicial do bootloader unsigned EepromSize; //Tamanho da Eeprom char Device[19]; //Nome do microcontrolador}BootInfo; /* Cria a variavel com as informações */const BootInfo mcuBootInfo = { PIC18, __FLASH_SIZE, _FLASH_ERASE, _FLASH_WRITE_LATCH, BOOTLOADER_START, 256, "PIC18F4550" }; unsigned Address = 0;unsigned EraseBlockSize at Address; /* Endereço da USB RAM */unsigned char HidReadBuff[64] absolute 0x500;unsigned char HidWriteBuff[64] absolute 0x540;unsigned char Reserve4thBankForUSB[256] absolute 0x400;
char flags = 0;sbit WriteData at flags.B0; /* Envia uma resposta ao PC */void Ack( char cmd ){ HidWriteBuff[0] = STX; //Start HidWriteBuff[1] = cmd; //Comando while( !HID_Write( &HidWriteBuff, 64) ); //envia 64 bytes para o PC} /* Verifica um comando recebido */void CheckCmd(){ if( CmdCode == cmdNONE ) { if( HidReadBuff[0] != STX ) return; CmdCode = HIDReadBuff[1]; //Comando Hi(Address) = HidReadBuff[2]; //Address Lo(Address) = HidReadBuff[3]; //Address }} /* Aguarda a conexão com o software */char EnterBootloader(){unsigned timer = 7000; //Tempo que permanece esperando a conexão while( timer-- ) { USB_Polling_Proc(); if( HID_Read() ) //Byte(s) recebido(s) { CheckCmd(); //verifica o comando recebido /* Foi requisitado para enviar as inoformações ao PC */ if( CmdCode == cmdINFO ) { //Carrega a variavel 'mcuBootInfo' em 'HidWriteBuff' *(BootInfo*)( &HidWriteBuff+2) = mcuBootInfo; Ack( cmdINFO ); //Envia a resposta CmdCode = cmdNONE; return 1; //OK } } Delay_ms(1); } return 0; //Tempo esgotado} /* Inicia a comunicação com o software */
void StartBootloader(){ while(1) { USB_Polling_Proc(); if( HID_Read() ) { CheckCmd(); if( CmdCode == cmdWRITE ) //Escrever na Flash { if( !WriteData ) { WriteData = 1; } else { if( Address < BOOTLOADER_START ) Flash_Write_32( Address, &HidReadBuff[4] ); } Ack( cmdWRITE ); CmdCode = cmdNONE; } else if( CmdCode == cmdERASE ) //Apagar Flash { unsigned EraseBlocks; unsigned long blockAddress; for( EraseBlocks = 0; EraseBlocks < EraseBlockSize; EraseBlocks++ ) { blockAddress = EraseBlocks * _FLASH_ERASE; if( blockAddress < BOOTLOADER_START ) Flash_Erase_64( blockAddress ); } Ack( cmdERASE ); CmdCode = cmdNONE; } else if( CmdCode == cmdSTART ) //Encerra a rotina { Ack( cmdSTART ); return; } } }} void StartProgram(){ asm sleep;} void main(){
/* configura o inicio do codigo e define o endereço das funções */ OrgAll( BOOTLOADER_START - RESET_VECTOR_SIZE ); FuncOrg( main, BOOTLOADER_START ); FuncOrg( StartProgram, BOOTLOADER_START - RESET_VECTOR_SIZE ); if ( Reserve4thBankForUSB ); HID_Enable( &HidReadBuff, &HidWriteBuff ); //Habilita a comunicação USB if( EnterBootloader() ) //Aguarda a conexão...Conectou!!! StartBootloader(); Hid_Disable(); //Desabilita a USB Delay_ms( 10 ); StartProgram(); //Inicia o programa do usuário}