Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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