Você está na página 1de 7

PIC: Bootloader USB HID

Quando se está trabalhando com microcontroladores PIC é muito


chato ter que ficar retirando o PIC da protoboard para ficar
regravando o firmware enquanto efetua seus testes. Utilizando
PIC's com suporte a USB facilita muito essa tarefa.

Após instalar um bootloader no PIC, é possivel carregar um novo


firmware através da porta USB.

EXPLICAÇÃO DO BOOTLOADER

www.francarie.net
http://microcontrolandos.blogspot.com.br Página 1
O Bootloader deve ser a primeira coisa a ser executada no PIC. Por
isso o vetor BOOTLOADER RESET VECTOR apontará para o início
do código do bootloader.

Ao conectá-lo ao PC, durante 7 segundos ficará na espera do


usuário clicar no botao CONECTAR no software. Caso estoure este
tempo, ele iniciará o programa do usuário. Depois de conectado
ele estará pronto pra receber o novo firmware.

Depois de gravado, ele iniciará o programa do usuário, apontando


para o vetor APPLICATION RESET VECTOR. Nesse vetor foi gravado
o endereço inicial do firmware.

O bootloader ocupa o final da memória. Então os programas a ser


gravado no PIC, não devem ultrapassar essa área.
www.francarie.net
http://microcontrolandos.blogspot.com.br Página 2
O código foi compilado para um cristal de 20Mhz. Mas é possível
utilizar outros valores de cristais configurando o fusível PLL
Prescaler Selection.

Veja que para poder utilizar o bootloader, antes tem que gravá-lo
utilizando um gravador convencional.

Pode ser possível utilizá-lo para outros dispositivos PIC18. Fiz


somente o teste com o PIC18F4550.

CÓDIGO DO BOOTLOADER
MikroC PRO PIC

1. //PIC18F4550 ou PIC182550
2. //CLOCK 48MHz ( HS + PLL )
3.
4. #include <Built_in.h>
5.
6. //Comandos
7. enum Cmd { cmdNONE, cmdINFO, cmdSTART, cmdWRITE, cmdERASE };
8.
9. enum McuType { PIC16 = 1, PIC18, PIC18FJ, PIC24, DSPIC = 10,
PIC32 = 20 };
10.
11. enum Cmd CmdCode = cmdNONE;
12.
13. const STX = 0x0F;
14.
15. //Calcula o endereço inicial do bootloader
16. const unsigned long BOOTLOADER_SIZE = 7432;
17. const unsigned long BOOTLOADER_START = (( __FLASH_SIZE -
BOOTLOADER_SIZE) / _FLASH_ERASE) * _FLASH_ERASE;
18. const unsigned char RESET_VECTOR_SIZE = 4;
19.
20. //fornece informações sobre o MCU
21. typedef struct
22. {
23. char McuType; //Tipo
24. unsigned long FlashSize; //Tamanho da Flash
25. unsigned EraseBlock; //Numero de blocos para apagar

www.francarie.net
http://microcontrolandos.blogspot.com.br Página 3
26. unsigned WriteBlock; //Numeros de blocos de escrita
27. unsigned long BootStart; //Endereço inicial do bootloader
28. unsigned EepromSize; //Tamanho da Eeprom
29. char Device[19]; //Nome do microcontrolador
30. }BootInfo;
31.
32. //Cria a variavel com as informações
33. const BootInfo mcuBootInfo = { PIC18,
34. __FLASH_SIZE,
35. _FLASH_ERASE,
36. _FLASH_WRITE_LATCH,
37. BOOTLOADER_START,
38. 256,
39. "PIC18F4550"
40. };
41.
42. unsigned Address = 0;
43. unsigned EraseBlockSize at Address;
44.
45. //Endereço da USB RAM
46. unsigned char HidReadBuff[64] absolute 0x500;
47. unsigned char HidWriteBuff[64] absolute 0x540;
48. unsigned char Reserve4thBankForUSB[256] absolute 0x400;
49.
50. char flags = 0;
51. sbit WriteData at flags.B0;
52.
53. //configura o inicio do codigo e define o endereço das funções
54. #define ConfigMem() OrgAll(BOOTLOADER_START-
RESET_VECTOR_SIZE); \
55. FuncOrg(main, BOOTLOADER_START); \
56. FuncOrg(StartProgram, BOOTLOADER_START-
RESET_VECTOR_SIZE);\
57. if (Reserve4thBankForUSB) ;
58.
59. //Envia uma resposta ao PC
60. void Ack( char cmd )
61. {
62. HidWriteBuff[0] = STX; //Start
63. HidWriteBuff[1] = cmd; //Comando
64. while( !HID_Write(&HidWriteBuff, 64) ); //envia 64 bytes
para o PC
65. }
66.
67. //Verifica um comando recebido
68. void CheckCmd()
69. {
70. if( CmdCode == cmdNONE )

www.francarie.net
http://microcontrolandos.blogspot.com.br Página 4
71. {
72. if( HidReadBuff[0] != STX ) //Start?
73. return;
74.
75. CmdCode = HIDReadBuff[1]; //Comando
76. Hi(Address) = HidReadBuff[2]; //Address
77. Lo(Address) = HidReadBuff[3]; //Address
78. }
79. }
80.
81. char EnterBootloader()
82. {
83. unsigned timer = 7000; //Tempo que permanece esperando a
conexão
84. while( timer-- )
85. {
86. USB_Polling_Proc();
87.
88. if( HID_Read() ) //Algum byte recebido?
89. {
90. CheckCmd(); //verifica o comando recebido
91.
92. //Foi requisitado para enviar as inoformações ao PC
93. if( CmdCode == cmdINFO )
94. {
95. //Carrega a variavel "mcuBootInfo" em
"HidWriteBuff"
96. *(BootInfo*)(&HidWriteBuff+2) = mcuBootInfo;
97. Ack( cmdINFO ); //Envia a resposta
98. CmdCode = cmdNONE;
99. return 1; //OK
100. }
101. }
102.
103. Delay_ms(1);
104. }
105.
106. return 0;
107. }
108.
109. void StartBootloader()
110. {
111. while(1)
112. {
113. USB_Polling_Proc();
114.
115. if( HID_Read() )

www.francarie.net
http://microcontrolandos.blogspot.com.br Página 5
116. {
117. CheckCmd();
118.
119. if( CmdCode == cmdWRITE ) //Comando Escrever na Flash
120. {
121. if( WriteData == 0 )
122. {
123. WriteData = 1;
124. }
125. else
126. {
127. if( Address < BOOTLOADER_START )
128. Flash_Write_32( Address,
&HidReadBuff[4] );
129. }
130. Ack( cmdWRITE );
131. CmdCode = cmdNONE;
132. }
133.
134. else if( CmdCode == cmdERASE ) //comando Apagar Flash
135. {
136. unsigned EraseBlocks;
137. unsigned long blockAddress;
138. for( EraseBlocks = 0; EraseBlocks < EraseBlockSize;
EraseBlocks++ )
139. {
140. blockAddress = EraseBlocks * _FLASH_ERASE;
141. if( blockAddress < BOOTLOADER_START )
142. Flash_Erase_64( blockAddress );
143. }
144. Ack( cmdERASE );
145. CmdCode = cmdNONE;
146. }
147.
148. else if( CmdCode == cmdSTART ) //Inicia o programa do
usuario
149. {
150. Ack( cmdSTART );
151. return;
152. }
153. }
154. }
155. }
156.
157. //25276, 0x62BC
158. void StartProgram()
159. {
160. asm sleep;

www.francarie.net
http://microcontrolandos.blogspot.com.br Página 6
161. }
162.
163. //25280, 0x62C0
164. void main()
165. {
166. ConfigMem();
167.
168. //Habilita a comunicação USB
169. HID_Enable( &HidReadBuff, &HidWriteBuff );
170.
171. if( EnterBootloader() ) //aguarda a conexão...Conectou?
172. {
173. StartBootloader();
174. }
175.
176. Hid_Disable(); //desabilita a USB
177. Delay_ms(10);
178. StartProgram(); //Inicia o programa do usuário
179. }

www.francarie.net
http://microcontrolandos.blogspot.com.br Página 7

Você também pode gostar