Ivo van Poorten
/
SiLabs_C2
Basis for the C2 protocol from Silicon Labs.
Embed:
(wiki syntax)
Show/hide line numbers
main.cpp
00001 /* 00002 * SiLabs C2 Protocol on mbed pins p5/p6 00003 * 00004 * Copyright (c) 2014, Ivo van Poorten <ivopvp@gmail.com> 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions 00009 * are met: 00010 * 1. Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * 2. Redistributions in binary form must reproduce the above copyright 00013 * notice, this list of conditions and the following disclaimer in the 00014 * documentation and/or other materials provided with the distribution. 00015 * 00016 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 00017 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00018 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00019 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 00020 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 00021 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00022 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00023 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00024 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00025 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 */ 00027 00028 #include "mbed.h" 00029 #include <stdarg.h> 00030 #include <stdio.h> 00031 #include <stdint.h> 00032 00033 DigitalOut c2ck(p5); 00034 DigitalInOut c2d(p6); 00035 00036 static uint8_t buffer[256]; 00037 00038 static struct devices { 00039 char *name; 00040 int devid; 00041 } devices[] = { 00042 { "F30x", 0x04 }, { "F31x", 0x08 }, 00043 { "F32x", 0x09 }, { "F326/7", 0x0d }, 00044 { "F33x", 0x0a }, { "F336/7", 0x14 }, 00045 { "F34x", 0x0f }, { "F35x", 0x0b }, 00046 { "F36x", 0x12 }, { "F38x", 0x28 }, 00047 { "F39x/F37x", 0x2b }, { "F41x", 0x0c }, 00048 { "F50x/F51x", 0x1c }, { "F52xA/F53xA", 0x11 }, 00049 { "F54x", 0x21 }, { "F55x/F56x/F57x", 0x22 }, 00050 { "F58x/F59x", 0x20 }, { "F70x/F71x", 0x1e }, 00051 { "F80x/F81x/F82x/F83x", 0x23 }, { "F90x/F91x", 0x1f }, 00052 { "F92x/F93x", 0x16 }, { "F96x", 0x2a }, 00053 { "F99x", 0x25 }, { "T60x", 0x10 }, 00054 { "T606", 0x1b }, { "T61x", 0x13 }, 00055 { "T62x/T32x", 0x18 }, { "T622/T623/T326/T327", 0x19 }, 00056 { "T63x", 0x17 }, { NULL, 0 } 00057 }; 00058 00059 #define C2_MASK_FLBUSY 0x80 00060 #define C2_MASK_INBUSY 0x02 00061 #define C2_MASK_OUTREADY 0x01 00062 00063 // Programming Interface (PI) Commands 00064 00065 #define C2_PI_CMD_GET_VERSION 0x01 00066 #define C2_PI_CMD_GET_DERIVATIVE 0x02 00067 00068 #define C2_PI_CMD_DEVICE_ERASE 0x03 00069 00070 #define C2_PI_CMD_BLOCK_READ 0x06 // FLASH (max. 64K bytes, bankswapping not supported) 00071 #define C2_PI_CMD_BLOCK_WRITE 0x07 // FLASH 00072 00073 #define C2_PI_CMD_PAGE_ERASE 0x08 00074 00075 #define C2_PI_CMD_DIRECT_READ 0x09 // SFR (Special FUnction Registers, 256 bytes(?)) 00076 #define C2_PI_CMD_DIRECT_WRITE 0x0a // SFR 00077 00078 #define C2_PI_CMD_INDIRECT_READ 0x0b // RAM (Internal, 256 bytes) 00079 #define C2_PI_CMD_INDIRECT_WRITE 0x0c // RAM 00080 00081 #define C2_PI_CMD_XRAM_READ 0x0e // RAM (External, 2K or 4K bytes) 00082 #define C2_PI_CMD_XRAM_WRITE 0x0f // RAM 00083 00084 // PI Status Values 00085 #define C2_PI_STATUS_COMMAND_INVALID 0x00 00086 #define C2_PI_STATUS_NO_CONNECT 0x01 00087 #define C2_PI_STATUS_FAILED 0x02 00088 #define C2_PI_STATUS_PAGE_LOCKED 0x03 // "security" feature 00089 #define C2_PI_STATUS_TIMEOUT 0x04 00090 #define C2_PI_STATUS_BAD_DATA 0x05 00091 #define C2_PI_STATUS_OK 0x0d 00092 00093 // C2 Registers 00094 #define C2_REG_DEVID 0 00095 #define C2_REG_REVID 1 00096 #define C2_REG_FPCTL 2 00097 static int C2_REG_FPDAT = 0xb4; // or 0xad 00098 static int page_size = 512; 00099 00100 static void fatal(char *f, ...) { 00101 va_list ap; 00102 va_start(ap,f); 00103 printf("\r\nFATAL: "); 00104 vprintf(f, ap); 00105 va_end(ap); 00106 exit(1); 00107 } 00108 00109 static void c2ck_reset(void) { 00110 c2d.input(); 00111 c2ck = 0; 00112 wait_us(25); 00113 c2ck = 1; 00114 wait_us(3); 00115 } 00116 00117 static void c2ck_strobe(void) { 00118 c2ck = 0; 00119 wait_us(1); 00120 c2ck = 1; 00121 wait_us(1); 00122 } 00123 00124 // Remember, ALL fields are sent LSB first(!) 00125 00126 #define START do{ c2ck_strobe(); }while(0) 00127 #define STOP START 00128 #define INS(a,b) do{ c2d = a; c2ck_strobe(); c2d = b; c2ck_strobe(); }while(0) 00129 #define LENGTH(a,b) INS(a,b) 00130 #define WAIT c2ck_strobe(); do{\ 00131 while(!c2d && t--) { \ 00132 c2ck_strobe(); \ 00133 wait_us(1); \ 00134 } if (!t) return -1; \ 00135 } while(0) 00136 #define READV do{\ 00137 for (i=0; i<8; i++) { \ 00138 v >>= 1; \ 00139 c2ck_strobe(); \ 00140 if (c2d) v |= 0x80; \ 00141 } } while(0) 00142 #define WRITEV do{\ 00143 for (i=0; i<8; i++) { \ 00144 c2d = v & 1; \ 00145 c2ck_strobe(); \ 00146 v >>= 1; \ 00147 } } while(0) 00148 00149 static int c2_read_dr(void) { 00150 int t = 20, i, v = 0; 00151 00152 START; 00153 c2d.output(); 00154 INS(0,0); 00155 LENGTH(0,0); 00156 c2d.input(); 00157 WAIT; 00158 READV; 00159 STOP; 00160 00161 return v; 00162 } 00163 00164 static int c2_write_dr(int v) { 00165 int t = 20, i; 00166 00167 START; 00168 c2d.output(); 00169 INS(1,0); 00170 LENGTH(0,0); 00171 WRITEV; 00172 c2d.input(); 00173 WAIT; 00174 STOP; 00175 00176 return 0; 00177 } 00178 00179 static int c2_read_ar(void) { 00180 int i, v = 0; 00181 00182 START; 00183 c2d.output(); 00184 INS(0,1); 00185 c2d.input(); 00186 READV; 00187 STOP; 00188 00189 return v; 00190 } 00191 00192 static void c2_write_ar(int v) { 00193 int i; 00194 00195 START; 00196 c2d.output(); 00197 INS(1,1); 00198 WRITEV; 00199 c2d.input(); 00200 STOP; 00201 } 00202 00203 static int poll_status(int mask) { 00204 int t = 20, s; 00205 do { 00206 s = c2_read_ar(); 00207 if (mask == C2_MASK_INBUSY) { 00208 if (!(s & mask)) return 0; 00209 } else { 00210 if (s & mask) return 0; 00211 } 00212 wait_us(1); 00213 } while(--t); 00214 return -1; 00215 } 00216 00217 static void c2_enable_pi(void) { 00218 c2ck_reset(); 00219 wait_ms(2); 00220 c2_write_ar(C2_REG_FPCTL); 00221 if ((c2_write_dr(0x02))<0) 00222 fatal("cannot enable PI (wr2)"); 00223 if ((c2_write_dr(0x04))<0) 00224 fatal("cannot enable PI (wr4)"); 00225 if ((c2_write_dr(0x01))<0) 00226 fatal("cannot enable PI (wr1)"); 00227 wait_ms(25); 00228 } 00229 00230 static int c2_read_mem(int type, int address, int size, uint8_t *buf) { 00231 int ret, i, ram_or_sfr = (type == C2_PI_CMD_DIRECT_READ) || (type == C2_PI_CMD_INDIRECT_READ); 00232 00233 c2_write_ar(C2_REG_FPDAT); 00234 c2_write_dr(type); 00235 00236 if (poll_status(C2_MASK_INBUSY) < 0) 00237 fatal("read_mem: cannot set FPDAT, no input ACK"); 00238 if (poll_status(C2_MASK_OUTREADY) < 0) 00239 fatal("read_mem: cannot set FPDAT, no output ready"); 00240 00241 ret = c2_read_dr(); 00242 if (ret != C2_PI_STATUS_OK) 00243 fatal("read_mem: status not OK after setting FPDAT (status %02X)", ret); 00244 00245 if (!ram_or_sfr) { 00246 c2_write_dr((address >> 8)&0xff); 00247 if (poll_status(C2_MASK_INBUSY) < 0) 00248 fatal("read_mem: cannot write msb of address"); 00249 } 00250 00251 c2_write_dr(address & 0xff); 00252 if (poll_status(C2_MASK_INBUSY) < 0) 00253 fatal("read_mem: cannot write lsb of address"); 00254 00255 c2_write_dr(size&0xff); 00256 if (poll_status(C2_MASK_INBUSY) < 0) 00257 fatal("read_mem: cannot set block length"); 00258 if (poll_status(C2_MASK_OUTREADY) < 0) 00259 fatal("read_mem: no data ready"); 00260 00261 ret = c2_read_dr(); 00262 if (ret != C2_PI_STATUS_OK) 00263 return ret; 00264 00265 for (i=0; i<size; i++) { 00266 if (poll_status(C2_MASK_OUTREADY) < 0) 00267 fatal("read_mem: no data ready during retrieval of block"); 00268 buf[i] = c2_read_dr(); 00269 } 00270 00271 return C2_PI_STATUS_OK; 00272 } 00273 00274 int main() { 00275 int i, c, devid, revid, ret; 00276 00277 c2d.input(); 00278 c2ck = 1; 00279 00280 // printf("\033[H\033[J"); 00281 printf("\r\nSiLabs C2 Protocol\r\n\r\n"); 00282 printf("Connect C2GND to GND, C2CK (clock) to p5 and C2D (data) to p6\r\n\r\n"); 00283 printf("Press any key to continue\r\n"); 00284 00285 getc(stdin); 00286 00287 c2_write_ar(C2_REG_DEVID); 00288 devid = c2_read_dr(); 00289 if (devid <= 0) fatal("unable to read devid\r\n"); 00290 00291 c2_write_ar(C2_REG_REVID); 00292 revid = c2_read_dr(); 00293 if (revid < 0) fatal("unable to read revid\r\n"); 00294 00295 for (i=0; devices[i].name; i++) { 00296 if (devices[i].devid == devid) break; 00297 } 00298 00299 if (!i) fatal("unknown device: %02X:%02X\r\n", devid, revid); 00300 00301 switch(devid) { 00302 case 0x0f: case 0x28: case 0x18: case 0x19: C2_REG_FPDAT = 0xad; 00303 default: break; 00304 } 00305 00306 printf("\r\nDevice found: %s (%02X:%02X)", devices[i].name, devid, revid); 00307 printf("\r\nFPDAT Address: 0x%02X", C2_REG_FPDAT); 00308 printf("\r\nPage Size: %i\n\r", page_size); 00309 00310 printf("\r\nEnabling Programming Interface\r\n"); 00311 c2_enable_pi(); 00312 00313 for (c=0; c<256; c++) { 00314 printf("\r\nReading page %i\r\n", c); 00315 ret = c2_read_mem(C2_PI_CMD_BLOCK_READ, c<<8, 0x100, buffer); 00316 if (ret == C2_PI_STATUS_OK) { 00317 for (i=0; i<0x100; i++) { 00318 printf("%02x ", buffer[i]); 00319 if (i%16 == 15) printf("\r\n"); 00320 } 00321 } else { 00322 if (ret == C2_PI_STATUS_PAGE_LOCKED) 00323 printf("page is locked, "); 00324 printf("read failed\r\n"); 00325 } 00326 } 00327 }
Generated on Tue Jul 12 2022 21:31:13 by 1.7.2