3 \author Scott Livingston
5 \brief dsPIC33F programmer application for the GoodFET. Structure
6 and style is somewhat modeled after avr.c
17 //! Handle a PIC command; currently assumes dsPIC33F/PIC24H
18 void pic_handle_fn( uint8_t const app,
22 // define the pic app's app_t
23 app_t const pic_app = {
35 "\tThe PIC app adds support for programming/debugging\n"
36 "\tdsPIC33F based devices.\n"
41 // Initialize pins; do NOT begin transaction.
43 P5REN &= ~(PGC|PGD|MCLR);
44 DIR_PGD_WR; // Initially PGD in write mode
50 prep_timer(); // What better time than now?
54 //! Handle a PIC command; currently assumes dsPIC33F/PIC24H
55 void pic_handle_fn( uint8_t const app,
59 unsigned int nb; // Number of bytes
60 unsigned int highb, loww; // Used for ICSP commands
71 loww |= (*(cmddata+1)) << 8;
73 pic33f_six( highb, loww );
78 pic33f_sixlist( len ); // Reply to host is handled by pic33f_sixlist.
82 loww = pic33f_regout();
83 *cmddata = loww & 0xff;
84 *(cmddata+1) = loww >> 8;
105 debugstr( "Verb unimplemented in PIC application." );
113 void pic33f_trans8( unsigned char byte )
115 /* We only twiddle the PGD and PGC lines.
116 MCLR is assumed to be in the correct state. */
119 DIR_PGD_WR; // Write mode
136 DIR_PGD_RD; // Read mode
139 void pic33f_trans16( unsigned int word )
141 pic33f_trans8( word & 0xff );
142 pic33f_trans8( word >> 8 );
146 void pic33f_six( unsigned int highb, unsigned int loww )
148 /* dsPIC33F/PIC24H instructions have width 24 bits, so we use the
149 lower 8 bits of highb and (all 16 bits of) loww to form the
152 Shift in the instruction. Note that it does not execute until
153 the next 4 clock cycles (which also corresponds to a command
159 for (i = 0; i < 4; i++) {
165 pic33f_trans16( loww );
166 pic33f_trans8( highb );
171 unsigned int pic33f_regout()
174 unsigned int result = 0x0000;
178 // Shift in command (REGOUT: 0001b).
188 for (i = 0; i < 3; i++) {
195 // Pump clock for 8 cycles, and switch PGD direction to read.
196 for (i = 0; i < 7; i++) {
204 /* Now read VISI register (LSb first, as usual).
205 Note that when reading from attached device, data is valid (to
206 be read) on falling clock edges. */
207 for (i = 0; i < 16; i++) {
211 result |= READ_PGD << i;
215 /* One last tick apparently is needed here, at least by the
216 dsPIC33FJ128GP708 chip that I am working with. Note that this
217 is not in the flash programming specs. */
227 void pic33f_sixlist( unsigned int list_len )
230 unsigned int instr_loww;
232 // Bound to Rx buffer size.
233 if (list_len > CMDDATALEN)
234 list_len = CMDDATALEN;
236 // Run each instruction!
237 for (k = 0; k < list_len-2; k+=3) {
238 instr_loww = *(cmddata+k);
239 instr_loww |= (*(cmddata+k+1)) << 8;
240 pic33f_six( *(cmddata+k+2), instr_loww );
243 // Reply with total number of bytes used from Rx buffer.
244 txdata( PIC, PIC_SIXLIST33F, k );
248 unsigned int pic33f_getid()
255 // Read application ID.
256 pic33f_six( 0x04, 0x0200 ); // goto 0x200 (i.e. reset)
257 pic33f_six( 0x00, 0x0000 ); // nop
258 pic33f_six( 0x20, 0x0800 ); // mov #0x80, W0
259 pic33f_six( 0x88, 0x0190 ); // mov W0, TBLPAG
260 pic33f_six( 0x20, 0x7F00 ); // mov #0x7F0, W0
261 pic33f_six( 0x20, 0x7841 ); // mov #VISI, W1
262 pic33f_six( 0x00, 0x0000 ); // nop
263 pic33f_six( 0xBA, 0x0890 ); // TBLRDL [W0], [W1]
264 pic33f_six( 0x00, 0x0000 ); // nop
265 pic33f_six( 0x00, 0x0000 ); // nop
266 result = pic33f_regout();
267 *cmddata = result & 0xff;
271 pic33f_six( 0x20, 0x0FF0 ); // mov #0xFF, W0
272 pic33f_six( 0x88, 0x0190 ); // mov W0, TBLPAG
273 pic33f_six( 0xEB, 0x0000 ); // clr W0
274 pic33f_six( 0x00, 0x0000 ); // nop
275 pic33f_six( 0xBA, 0x08B0 ); // TBLRDL [W0++], [W1]
276 pic33f_six( 0x00, 0x0000 ); // nop
277 pic33f_six( 0x00, 0x0000 ); // nop
278 result = pic33f_regout();
279 *(cmddata+1) = result & 0xff;
280 *(cmddata+2) = result >> 8;
283 // Read hardware revision.
284 pic33f_six( 0xBA, 0x0890 ); // TBLRDL [W0++], [W1]
285 pic33f_six( 0x00, 0x0000 ); // nop
286 pic33f_six( 0x00, 0x0000 ); // nop
287 result = pic33f_regout();
288 *(cmddata+3) = result & 0xff;
289 *(cmddata+4) = result >> 8;
298 void pic33f_connect()
300 unsigned int key_low;
301 unsigned int key_high;
303 key_low = ICSP_KEY_LOW;
304 key_high = ICSP_KEY_HIGH;
319 pic33f_trans8( key_low & 0xff );
320 key_low = key_low >> 8;
321 pic33f_trans8( key_low & 0xff );
322 pic33f_trans8( key_high & 0xff );
323 key_high = key_high >> 8;
324 pic33f_trans8( key_high & 0xff );
327 SET_MCLR; // ...and pull MCLR pin back up.
328 delay_ms(25); // Now wait about 25 ms (required per spec!).
330 /* The first ICSP command must be a SIX, and further, 9 bits are
331 required before the instruction (to be executed), rather than
332 the typical 4 bits. Thus, to simplify code, I simply load a nop
333 here; hence 33 bits are shifted into the dsPIC33F/PIC24H. */
337 for (key_low = 0; key_low < 33; key_low++) {
348 void pic33f_disconnect()