2 \author Alexey Borisenko <abori021@uottawa.ca>
3 \brief Silicon Labs C2 Debug interface
21 //-----------------------------------------------------------------------------------
23 //-----------------------------------------------------------------------------------
24 unsigned char NUM_BYTES;
25 unsigned int FLASH_ADDR;
26 unsigned char *C2_PTR;
28 //! Handles a monitor command.
29 void slc2_handle_fn( uint8_t const app,
33 // define the spi app's app_t
34 app_t const slc2_app = {
46 "\tThis app handles Silicon Lab's C2 debugging protocol.\n"
49 //-----------------------------------------------------------------------------------
50 // FLASH Programming Routines (High Level)
51 //-----------------------------------------------------------------------------------
53 // These high-level routines perform the FLASH Programming Interface (FPI)
55 //-----------------------------------------------------------------------------------
57 //-----------------------------------------------------------------------------------
58 // - Initializes the C2 Interface for FLASH programming
64 C2_Reset(); // Reset the target device
65 delay_us(2); // Delay for at least 2us
66 C2_WriteAR(FPCTL); // Target the C2 FLASH Programming
67 // Control register (FPCTL) for C2 Data
69 C2_WriteDR(0x02); // Write the first key code to enable
70 // C2 FLASH programming
71 C2_WriteDR(0x01); // Write the second key code to enable
72 // C2 FLASH programming
73 delay_us(20000); // Delay for at least 20ms to ensure the
74 // target is ready for C2 FLASH programming
76 //-----------------------------------------------------------------------------------
78 //-----------------------------------------------------------------------------------
79 // - Reads the target Devcie ID register and Revision ID register
81 unsigned char C2_GetDevID()
83 C2_WriteAR(DEVICEID); // Select DeviceID regsiter for C2 Data
85 return C2_ReadDR(); // Read and return the DeviceID register
88 //-----------------------------------------------------------------------------------
90 //-----------------------------------------------------------------------------------
91 // - Reads the target Devcie ID register and Revision ID register
93 unsigned char C2_GetRevID()
95 C2_WriteAR(REVID); // Select DeviceID regsiter for C2 Data
97 return C2_ReadDR(); // Read and return the DeviceID register
100 //-----------------------------------------------------------------------------------
102 //-----------------------------------------------------------------------------------
103 // - Reads a block of FLASH memory starting at <FLASH_ADDR>
104 // - The size of the block is defined by <NUM_BYTES>
105 // - Stores the read data at the location targeted by the pointer <C2_PTR>
106 // - Assumes that FLASH accesses via C2 have been enabled prior to the function call
107 // - Function call returns a ‘1’ if successful; returns a ‘0’ if unsuccessful
111 unsigned char i; // Counter
112 unsigned char status; // FPI status information holder
113 C2_WriteAR(FPDAT); // Select the FLASH Programming Data register
114 // for C2 Data register accesses
115 C2_WriteDR(BLOCK_READ); // Send FLASH block read command
116 Poll_InBusy; // Wait for input acknowledge
117 // Check status before starting FLASH access sequence
118 Poll_OutReady; // Wait for status information
119 status = C2_ReadDR(); // Read FLASH programming interface status
120 if (status != COMMAND_OK)
121 return 0; // Exit and indicate error
122 C2_WriteDR(FLASH_ADDR >> 8); // Send address high byte to FPDAT
123 Poll_InBusy; // Wait for input acknowledge
124 C2_WriteDR(FLASH_ADDR & 0x00FF); // Send address low byte to FPDAT
125 Poll_InBusy; // Wait for input acknowledge
126 C2_WriteDR(NUM_BYTES); // Send block size
127 Poll_InBusy; // Wait for input acknowledge
128 // Check status before reading FLASH block
129 Poll_OutReady; // Wait for status information
130 status = C2_ReadDR(); // Read FLASH programming interface status
131 if (status != COMMAND_OK)
132 return 0; // Exit and indicate error
134 for (i=0; i<NUM_BYTES; i++)
136 Poll_OutReady; // Wait for data ready indicator
137 *C2_PTR++ = C2_ReadDR(); // Read data from the FPDAT register
139 return 1; // Exit and indicate success
141 //-----------------------------------------------------------------------------------
143 //-----------------------------------------------------------------------------------
144 // - Writes a block of FLASH memory starting at <FLASH_ADDR>
145 // - The size of the block is defined by <NUM_BYTES>
146 // - Writes the block stored at the location targetted by <C2_PTR>
147 // - Assumes that FLASH accesses via C2 have been enabled prior to the function call
148 // - Function call returns a ‘1’ if successful; returns a ‘0’ if unsuccessful
152 unsigned char i; // Counter
153 unsigned char status; // FPI status information holder
154 C2_WriteAR(FPDAT); // Select the FLASH Programming Data register
155 // for C2 Data register accesses
156 C2_WriteDR(BLOCK_WRITE); // Send FLASH block write command
157 Poll_InBusy; // Wait for input acknowledge
158 // Check status before starting FLASH access sequence
159 Poll_OutReady; // Wait for status information
160 status = C2_ReadDR(); // Read FLASH programming interface status
161 if (status != COMMAND_OK)
162 return 0; // Exit and indicate error
163 C2_WriteDR(FLASH_ADDR >> 8); // Send address high byte to FPDAT
164 Poll_InBusy; // Wait for input acknowledge
165 C2_WriteDR(FLASH_ADDR & 0x00FF); // Send address low byte to FPDAT
166 Poll_InBusy; // Wait for input acknowledge
167 C2_WriteDR(NUM_BYTES); // Send block size
168 Poll_InBusy; // Wait for input acknolwedge
170 // Check status before starting FLASH access sequence
171 Poll_OutReady; // Wait for status information
172 status = C2_ReadDR(); // Read FLASH programming interface status
173 if (status != COMMAND_OK)
174 return 0; // Exit and indicate error
175 C2_WriteDR(FLASH_ADDR >> 8); // Send address high byte to FPDAT
176 Poll_InBusy; // Wait for input acknowledge
177 C2_WriteDR(FLASH_ADDR & 0x00FF); // Send address low byte to FPDAT
178 Poll_InBusy; // Wait for input acknowledge
179 C2_WriteDR(NUM_BYTES); // Send block size
180 Poll_InBusy; // Wait for input acknolwedge
181 // Check status before writing FLASH block
182 Poll_OutReady; // Wait for status information
183 status = C2_ReadDR(); // Read FLASH programming interface status
184 if (status != COMMAND_OK)
185 return 0; // Exit and indicate error
187 for (i=0; i<NUM_BYTES; i++)
189 C2_WriteDR(*C2_PTR++); // Write data to the FPDAT register
190 Poll_InBusy; // Wait for input acknowledge
192 Poll_OutReady; // Wait for last FLASH write to complete
193 return 1; // Exit and indicate success
195 //-----------------------------------------------------------------------------------
197 //-----------------------------------------------------------------------------------
198 // - Erases a 512-byte FLASH page
199 // - Targets the FLASH page containing the address <FLASH_ADDR>
200 // - Assumes that FLASH accesses via C2 have been enabled prior to the function call
201 // - Function call returns a ‘1’ if successful; returns a ‘0’ if unsuccessful
205 unsigned char page; // Target FLASH page
206 unsigned char status; // FPI status information holder
208 page = (unsigned char)(FLASH_ADDR >> 9);
209 // <page> is the 512-byte sector containing
210 // the target <FLASH_ADDR>.
211 if (page >= NUM_PAGES - 1) // Check that target page is within range
212 // (NUM_PAGES minus 1 for reserved area)
213 return 0; // Indicate error if out of range
214 C2_WriteAR(FPDAT); // Select the FLASH Programming Data register
215 // for C2 Data register accesses
216 C2_WriteDR(PAGE_ERASE); // Send FLASH page erase command
217 Poll_InBusy; // Wait for input acknowledge
218 // Check status before starting FLASH access sequence
219 Poll_OutReady; // Wait for status information
220 status = C2_ReadDR(); // Read FLASH programming interface status
221 if (status != COMMAND_OK)
222 return 0; // Exit and indicate error
223 C2_WriteDR(page); // Send FLASH page number
224 Poll_InBusy; // Wait for input acknowledge
225 Poll_OutReady; // Wait for ready indicator
226 status = C2_ReadDR(); // Read FLASH programming interface status
227 if (status != COMMAND_OK)
228 return 0; // Exit and indicate error
229 C2_WriteDR(0x00); // Dummy write to initiate erase
230 Poll_InBusy; // Wait for input acknowledge
231 Poll_OutReady; // Wait for erase operation to complete
232 return 1; // Exit and indicate success
234 //-----------------------------------------------------------------------------------
236 //-----------------------------------------------------------------------------------
237 // - Erases the entire FLASH memory space
238 // - Assumes that FLASH accesses via C2 have been enabled prior to the function call
239 // - Function call returns a ‘1’ if successful; returns a ‘0’ if unsuccessful
241 char C2_DeviceErase()
243 unsigned char status; // FPI status information holder
244 C2_WriteAR(FPDAT); // Select the FLASH Programming Data register
245 // for C2 Data register accesses
246 C2_WriteDR(DEVICE_ERASE); // Send Device Erase command
247 Poll_InBusy; // Wait for input acknowledge
248 // Check status before starting FLASH access sequence
249 Poll_OutReady; // Wait for status information
250 status = C2_ReadDR(); // Read FLASH programming interface status
251 if (status != COMMAND_OK)
252 return 0; // Exit and indicate error
253 // Send a three-byte arming sequence to enable the device erase. If the sequence
254 // is not received correctly, the command will be ignored.
255 // Sequence: 0xDE, 0xAD, 0xA5.
257 C2_WriteDR(0xDE); // Arming sequence command 1
258 Poll_InBusy; // Wait for input acknowledge
259 C2_WriteDR(0xAD); // Arming sequence command 2
260 Poll_InBusy; // Wait for input acknowledge
261 C2_WriteDR(0xA5); // Arming sequence command 3
262 Poll_InBusy; // Wait for input acknowledge
263 Poll_OutReady; // Wait for erase operation to complete
264 return 1; // Exit and indicate success
266 //-----------------------------------------------------------------------------------
267 // Primitive C2 Command Routines
268 //-----------------------------------------------------------------------------------
270 // These routines perform the low-level C2 commands:
276 //-----------------------------------------------------------------------------------
278 //-----------------------------------------------------------------------------------
279 // - Performs a C2 Address register read
280 // - Returns the 8-bit register content
282 unsigned char C2_ReadAR()
284 unsigned char i; // Bit counter
285 unsigned char addr; // Address register read content
287 StrobeC2CK; // Strobe C2CK with C2D driver disabled
288 // INS field (10b, LSB first)
290 C2D_DriverOn; // Enable C2D driver (output)
294 C2D_DriverOff; // Disable C2D driver (input)
297 for (i=0; i<8; i++) // Shift in 8 bit ADDRESS field
305 StrobeC2CK; // Strobe C2CK with C2D driver disabled
307 return addr; // Return Address register read value
309 //-----------------------------------------------------------------------------------
311 //-----------------------------------------------------------------------------------
312 // - Performs a C2 Address register write (writes the <addr> input
313 // to Address register)
315 void C2_WriteAR(unsigned char addr)
317 unsigned char i; // Bit counter
319 StrobeC2CK; // Strobe C2CK with C2D driver disabled
320 // INS field (11b, LSB first)
322 C2D_DriverOn; // Enable C2D driver (output)
327 for(i=0; i<8; i++) // Shift out 8-bit ADDRESS field
337 C2D_DriverOff; // Disable C2D driver
338 StrobeC2CK; // Strobe C2CK with C2D driver disabled
341 //-----------------------------------------------------------------------------------
343 //-----------------------------------------------------------------------------------
344 // - Performs a C2 Data register read
345 // - Returns the 8-bit register content
347 unsigned char C2_ReadDR()
349 unsigned char i; // Bit counter
350 unsigned char dat; // Data register read content
352 StrobeC2CK; // Strobe C2CK with C2D driver disabled
353 // INS field (00b, LSB first)
355 C2D_DriverOn; // Enable C2D driver (output)
360 // LENGTH field (00b -> 1 byte)
366 C2D_DriverOff; // Disable C2D driver for input
371 while (!READC2D); // Strobe C2CK until target transmits a ‘1’
374 for (i=0; i<8; i++) // Shift in 8-bit DATA field
382 StrobeC2CK; // Strobe C2CK with C2D driver disabled
386 //-----------------------------------------------------------------------------------
388 //-----------------------------------------------------------------------------------
389 // - Performs a C2 Data register write (writes <dat> input to data register)
391 void C2_WriteDR(unsigned char dat)
393 unsigned char i; // Bit counter
395 StrobeC2CK; // Strobe C2CK with C2D driver disabled
396 // INS field (01b, LSB first)
398 C2D_DriverOn; // Enable C2D driver
402 // LENGTH field (00b -> 1 byte)
408 for (i=0; i<8; i++) // Shift out 8-bit DATA field
418 C2D_DriverOff; // Disable C2D driver for input
421 StrobeC2CK; // Strobe C2CK until target transmits a ‘1’
425 StrobeC2CK; // Strobe C2CK with C2D driver disabled
429 //-----------------------------------------------------------------------------------
431 //-----------------------------------------------------------------------------------
432 // - Performs a target device reset by pulling the C2CK pin low for >20us
436 CLRC2CK; // Put target device in reset state by pulling
437 delay_us(20); // C2CK low for >20us
438 SETC2CK; // Release target device from reset
443 //! Handles a monitor command.
444 void slc2_handle_fn( uint8_t const app,
449 unsigned char dev_id = 0;
450 unsigned char rev_id = 0;
457 FLASH_ADDR = (cmddata[1] << 8) + cmddata[0];
458 C2_PTR = cmddata; //cmddata + 2;
461 txdata(app, verb, 2);
469 FLASH_ADDR = (cmddata[1] << 8) + cmddata[0];
470 C2_PTR = cmddata + 2;
471 if(C2_BlockWrite()) {
485 dev_id = C2_GetDevID();
487 txdata(app, verb, 1);
491 rev_id = C2_GetRevID();
493 txdata(app, verb, 1);
497 FLASH_ADDR = (cmddata[1] << 8) + cmddata[0];
506 if(C2_DeviceErase()) {