Basis for the C2 protocol from Silicon Labs.

Dependencies:   mbed

Committer:
Ivop
Date:
Mon May 26 18:08:12 2014 +0000
Revision:
16:844edb89d863
Parent:
15:0ccb0277d98e
Child:
17:0c5581ae2471
misc fixes, looks like i just read 256 bytes of FLASH :)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Ivop 1:7a82f806fe92 1 /*
Ivop 1:7a82f806fe92 2 * SiLabs C2 Protocol on mbed pins p5/p6
Ivop 1:7a82f806fe92 3 *
Ivop 1:7a82f806fe92 4 * Copyright (c) 2014, Ivo van Poorten <ivopvp@gmail.com>
Ivop 1:7a82f806fe92 5 * All rights reserved.
Ivop 1:7a82f806fe92 6 *
Ivop 1:7a82f806fe92 7 * Redistribution and use in source and binary forms, with or without
Ivop 1:7a82f806fe92 8 * modification, are permitted provided that the following conditions
Ivop 1:7a82f806fe92 9 * are met:
Ivop 1:7a82f806fe92 10 * 1. Redistributions of source code must retain the above copyright
Ivop 1:7a82f806fe92 11 * notice, this list of conditions and the following disclaimer.
Ivop 1:7a82f806fe92 12 * 2. Redistributions in binary form must reproduce the above copyright
Ivop 1:7a82f806fe92 13 * notice, this list of conditions and the following disclaimer in the
Ivop 1:7a82f806fe92 14 * documentation and/or other materials provided with the distribution.
Ivop 1:7a82f806fe92 15 *
Ivop 1:7a82f806fe92 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
Ivop 1:7a82f806fe92 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
Ivop 1:7a82f806fe92 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
Ivop 1:7a82f806fe92 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
Ivop 1:7a82f806fe92 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
Ivop 1:7a82f806fe92 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Ivop 1:7a82f806fe92 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Ivop 1:7a82f806fe92 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Ivop 1:7a82f806fe92 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
Ivop 1:7a82f806fe92 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Ivop 1:7a82f806fe92 26 */
Ivop 1:7a82f806fe92 27
Ivop 0:902f10e5d3e0 28 #include "mbed.h"
Ivop 7:65a72aad87b8 29 #include <stdarg.h>
Ivop 14:c24f608a8adb 30 #include <stdio.h>
Ivop 14:c24f608a8adb 31 #include <stdint.h>
Ivop 0:902f10e5d3e0 32
Ivop 0:902f10e5d3e0 33 DigitalOut c2ck(p5);
Ivop 0:902f10e5d3e0 34 DigitalInOut c2d(p6);
Ivop 0:902f10e5d3e0 35
Ivop 14:c24f608a8adb 36 static uint8_t buffer[256];
Ivop 14:c24f608a8adb 37
Ivop 4:a9e3ee5741be 38 static struct devices {
Ivop 4:a9e3ee5741be 39 char *name;
Ivop 4:a9e3ee5741be 40 int devid;
Ivop 4:a9e3ee5741be 41 } devices[] = {
Ivop 8:af5d402396fb 42 { "F30x", 0x04 }, { "F31x", 0x08 },
Ivop 8:af5d402396fb 43 { "F32x", 0x09 }, { "F326/7", 0x0d },
Ivop 8:af5d402396fb 44 { "F33x", 0x0a }, { "F336/7", 0x14 },
Ivop 8:af5d402396fb 45 { "F34x", 0x0f }, { "F35x", 0x0b },
Ivop 8:af5d402396fb 46 { "F36x", 0x12 }, { "F38x", 0x28 },
Ivop 8:af5d402396fb 47 { "F39x/F37x", 0x2b }, { "F41x", 0x0c },
Ivop 8:af5d402396fb 48 { "F50x/F51x", 0x1c }, { "F52xA/F53xA", 0x11 },
Ivop 8:af5d402396fb 49 { "F54x", 0x21 }, { "F55x/F56x/F57x", 0x22 },
Ivop 8:af5d402396fb 50 { "F58x/F59x", 0x20 }, { "F70x/F71x", 0x1e },
Ivop 8:af5d402396fb 51 { "F80x/F81x/F82x/F83x", 0x23 }, { "F90x/F91x", 0x1f },
Ivop 8:af5d402396fb 52 { "F92x/F93x", 0x16 }, { "F96x", 0x2a },
Ivop 8:af5d402396fb 53 { "F99x", 0x25 }, { "T60x", 0x10 },
Ivop 8:af5d402396fb 54 { "T606", 0x1b }, { "T61x", 0x13 },
Ivop 8:af5d402396fb 55 { "T62x/T32x", 0x18 }, { "T622/T623/T326/T327", 0x19 },
Ivop 8:af5d402396fb 56 { "T63x", 0x17 }, { NULL, 0 }
Ivop 4:a9e3ee5741be 57 };
Ivop 4:a9e3ee5741be 58
Ivop 6:deb670cb8105 59 #define C2_MASK_FLBUSY 0x80
Ivop 6:deb670cb8105 60 #define C2_MASK_INBUSY 0x02
Ivop 6:deb670cb8105 61 #define C2_MASK_OUTREADY 0x01
Ivop 6:deb670cb8105 62
Ivop 9:6a689843a88e 63 // Programming INterface (PI) Commands
Ivop 9:6a689843a88e 64
Ivop 8:af5d402396fb 65 #define C2_PI_CMD_GET_VERSION 0x01
Ivop 8:af5d402396fb 66 #define C2_PI_CMD_GET_DERIVATIVE 0x02
Ivop 8:af5d402396fb 67
Ivop 8:af5d402396fb 68 #define C2_PI_CMD_DEVICE_ERASE 0x03
Ivop 8:af5d402396fb 69
Ivop 8:af5d402396fb 70 #define C2_PI_CMD_BLOCK_READ 0x06 // FLASH (max. 64K bytes, bankswapping not supported)
Ivop 8:af5d402396fb 71 #define C2_PI_CMD_BLOCK_WRITE 0x07 // FLASH
Ivop 8:af5d402396fb 72
Ivop 8:af5d402396fb 73 #define C2_PI_CMD_PAGE_ERASE 0x08
Ivop 8:af5d402396fb 74
Ivop 8:af5d402396fb 75 #define C2_PI_CMD_DIRECT_READ 0x09 // SFR (Special FUnction Registers, 256 bytes(?))
Ivop 8:af5d402396fb 76 #define C2_PI_CMD_DIRECT_WRITE 0x0a // SFR
Ivop 8:af5d402396fb 77
Ivop 8:af5d402396fb 78 #define C2_PI_CMD_INDIRECT_READ 0x0b // RAM (Internal, 256 bytes)
Ivop 8:af5d402396fb 79 #define C2_PI_CMD_INDIRECT_WRITE 0x0c // RAM
Ivop 8:af5d402396fb 80
Ivop 8:af5d402396fb 81 #define C2_PI_CMD_XRAM_READ 0x0e // RAM (External, 2K or 4K bytes)
Ivop 8:af5d402396fb 82 #define C2_PI_CMD_XRAM_WRITE 0x0f // RAM
Ivop 8:af5d402396fb 83
Ivop 9:6a689843a88e 84 // PI Status Values
Ivop 9:6a689843a88e 85 #define C2_PI_STATUS_COMMAND_INVALID 0x00
Ivop 9:6a689843a88e 86 #define C2_PI_STATUS_NO_CONNECT 0x01
Ivop 9:6a689843a88e 87 #define C2_PI_STATUS_FAILED 0x02
Ivop 9:6a689843a88e 88 #define C2_PI_STATUS_TIMEOUT 0x04
Ivop 9:6a689843a88e 89 #define C2_PI_STATUS_BAD_DATA 0x05
Ivop 9:6a689843a88e 90 #define C2_PI_STATUS_OK 0x0d
Ivop 9:6a689843a88e 91
Ivop 9:6a689843a88e 92 // C2 Registers
Ivop 13:45aaa8847c2b 93 #define C2_REG_DEVID 0
Ivop 13:45aaa8847c2b 94 #define C2_REG_REVID 1
Ivop 13:45aaa8847c2b 95 #define C2_REG_FPCTL 2
Ivop 13:45aaa8847c2b 96 static int C2_REG_FPDAT = 0xb4; // or 0xad
Ivop 4:a9e3ee5741be 97 static int page_size = 512; // not seen 4096 yet
Ivop 4:a9e3ee5741be 98
Ivop 7:65a72aad87b8 99 static void fatal(char *f, ...) {
Ivop 7:65a72aad87b8 100 va_list ap;
Ivop 7:65a72aad87b8 101 va_start(ap,f);
Ivop 14:c24f608a8adb 102 printf("\r\nFATAL: ");
Ivop 7:65a72aad87b8 103 vprintf(f, ap);
Ivop 7:65a72aad87b8 104 va_end(ap);
Ivop 7:65a72aad87b8 105 exit(1);
Ivop 7:65a72aad87b8 106 }
Ivop 7:65a72aad87b8 107
Ivop 1:7a82f806fe92 108 static void c2ck_reset(void) {
Ivop 1:7a82f806fe92 109 c2ck = 0;
Ivop 1:7a82f806fe92 110 wait_us(25);
Ivop 1:7a82f806fe92 111 c2ck = 1;
Ivop 16:844edb89d863 112 wait_us(3);
Ivop 1:7a82f806fe92 113 }
Ivop 1:7a82f806fe92 114
Ivop 1:7a82f806fe92 115 static void c2ck_strobe(void) {
Ivop 1:7a82f806fe92 116 c2ck = 0;
Ivop 1:7a82f806fe92 117 wait_us(1);
Ivop 1:7a82f806fe92 118 c2ck = 1;
Ivop 1:7a82f806fe92 119 wait_us(1);
Ivop 1:7a82f806fe92 120 }
Ivop 1:7a82f806fe92 121
Ivop 2:9092d0d1558b 122 // Remember, ALL fields are sent LSB first(!)
Ivop 1:7a82f806fe92 123
Ivop 2:9092d0d1558b 124 #define START do{ c2ck_strobe(); }while(0)
Ivop 2:9092d0d1558b 125 #define STOP START
Ivop 2:9092d0d1558b 126 #define INS(a,b) do{ c2d = a; c2ck_strobe(); c2d = b; c2ck_strobe(); }while(0)
Ivop 2:9092d0d1558b 127 #define LENGTH(a,b) INS(a,b)
Ivop 2:9092d0d1558b 128 #define WAIT do{\
Ivop 2:9092d0d1558b 129 while(t-- && !c2d) { \
Ivop 2:9092d0d1558b 130 c2ck_strobe(); \
Ivop 2:9092d0d1558b 131 wait_us(1); \
Ivop 2:9092d0d1558b 132 } if (!t) return -1; \
Ivop 2:9092d0d1558b 133 } while(0)
Ivop 4:a9e3ee5741be 134 #define READV do{\
Ivop 4:a9e3ee5741be 135 for (i=0; i<8; i++) { \
Ivop 4:a9e3ee5741be 136 v >>= 1; \
Ivop 4:a9e3ee5741be 137 c2ck_strobe(); \
Ivop 4:a9e3ee5741be 138 if (c2d) v |= 0x80; \
Ivop 4:a9e3ee5741be 139 } } while(0)
Ivop 4:a9e3ee5741be 140 #define WRITEV do{\
Ivop 11:2b19d52ea37c 141 for (i=0; i<8; i++) { \
Ivop 4:a9e3ee5741be 142 c2d = v & 1; \
Ivop 4:a9e3ee5741be 143 c2ck_strobe(); \
Ivop 4:a9e3ee5741be 144 v >>= 1; \
Ivop 4:a9e3ee5741be 145 } } while(0)
Ivop 2:9092d0d1558b 146
Ivop 2:9092d0d1558b 147 static int c2_read_dr(void) {
Ivop 4:a9e3ee5741be 148 int t = 20, i, v = 0;
Ivop 2:9092d0d1558b 149
Ivop 2:9092d0d1558b 150 START;
Ivop 2:9092d0d1558b 151 c2d.output();
Ivop 2:9092d0d1558b 152 INS(0,0);
Ivop 2:9092d0d1558b 153 LENGTH(0,0);
Ivop 2:9092d0d1558b 154 c2d.input();
Ivop 2:9092d0d1558b 155 WAIT;
Ivop 4:a9e3ee5741be 156 READV;
Ivop 2:9092d0d1558b 157 STOP;
Ivop 2:9092d0d1558b 158
Ivop 4:a9e3ee5741be 159 return v;
Ivop 2:9092d0d1558b 160 }
Ivop 2:9092d0d1558b 161
Ivop 4:a9e3ee5741be 162 static int c2_write_dr(int v) {
Ivop 2:9092d0d1558b 163 int t = 20, i;
Ivop 2:9092d0d1558b 164
Ivop 2:9092d0d1558b 165 START;
Ivop 2:9092d0d1558b 166 c2d.output();
Ivop 2:9092d0d1558b 167 INS(1,0);
Ivop 2:9092d0d1558b 168 LENGTH(0,0);
Ivop 4:a9e3ee5741be 169 WRITEV;
Ivop 2:9092d0d1558b 170 c2d.input();
Ivop 2:9092d0d1558b 171 WAIT;
Ivop 2:9092d0d1558b 172 STOP;
Ivop 2:9092d0d1558b 173
Ivop 2:9092d0d1558b 174 return 0;
Ivop 2:9092d0d1558b 175 }
Ivop 2:9092d0d1558b 176
Ivop 2:9092d0d1558b 177 static int c2_read_ar(void) {
Ivop 4:a9e3ee5741be 178 int i, v = 0;
Ivop 2:9092d0d1558b 179
Ivop 2:9092d0d1558b 180 START;
Ivop 2:9092d0d1558b 181 c2d.output();
Ivop 2:9092d0d1558b 182 INS(0,1);
Ivop 2:9092d0d1558b 183 c2d.input();
Ivop 4:a9e3ee5741be 184 READV;
Ivop 4:a9e3ee5741be 185 STOP;
Ivop 2:9092d0d1558b 186
Ivop 4:a9e3ee5741be 187 return v;
Ivop 2:9092d0d1558b 188 }
Ivop 2:9092d0d1558b 189
Ivop 4:a9e3ee5741be 190 static void c2_write_ar(int v) {
Ivop 2:9092d0d1558b 191 int i;
Ivop 2:9092d0d1558b 192
Ivop 2:9092d0d1558b 193 START;
Ivop 2:9092d0d1558b 194 c2d.output();
Ivop 2:9092d0d1558b 195 INS(1,1);
Ivop 4:a9e3ee5741be 196 WRITEV;
Ivop 2:9092d0d1558b 197 c2d.input();
Ivop 2:9092d0d1558b 198 STOP;
Ivop 2:9092d0d1558b 199 }
Ivop 1:7a82f806fe92 200
Ivop 6:deb670cb8105 201 static int poll_status(int mask) {
Ivop 16:844edb89d863 202 int t = 20, s;
Ivop 6:deb670cb8105 203 do {
Ivop 16:844edb89d863 204 s = c2_read_ar();
Ivop 16:844edb89d863 205 if (mask == C2_MASK_INBUSY) {
Ivop 16:844edb89d863 206 if (!(s & mask)) return 0;
Ivop 16:844edb89d863 207 } else {
Ivop 16:844edb89d863 208 if (s & mask) return 0;
Ivop 16:844edb89d863 209 }
Ivop 16:844edb89d863 210 printf("debug: wait 1us\r\n");
Ivop 6:deb670cb8105 211 wait_us(1);
Ivop 6:deb670cb8105 212 } while(--t);
Ivop 6:deb670cb8105 213 return -1;
Ivop 6:deb670cb8105 214 }
Ivop 11:2b19d52ea37c 215
Ivop 12:49ac91452d77 216 static void c2_enable_pi(void) {
Ivop 12:49ac91452d77 217 c2ck_reset();
Ivop 13:45aaa8847c2b 218 c2_write_ar(C2_REG_FPCTL);
Ivop 14:c24f608a8adb 219 if ((c2_write_dr(0x02)+c2_write_dr(0x04)+c2_write_dr(0x01))<0)
Ivop 12:49ac91452d77 220 fatal("cannot enable PI");
Ivop 15:0ccb0277d98e 221 wait_ms(21);
Ivop 12:49ac91452d77 222 }
Ivop 11:2b19d52ea37c 223
Ivop 14:c24f608a8adb 224 static void c2_read_mem(int type, uint16_t address, uint8_t size, uint8_t *buf) {
Ivop 14:c24f608a8adb 225 int ret, i, ram_or_sfr = (type == C2_PI_CMD_DIRECT_READ) || (type == C2_PI_CMD_INDIRECT_READ);
Ivop 14:c24f608a8adb 226
Ivop 14:c24f608a8adb 227 c2_write_ar(C2_REG_FPDAT);
Ivop 14:c24f608a8adb 228 c2_write_dr(type);
Ivop 14:c24f608a8adb 229
Ivop 16:844edb89d863 230 if (poll_status(C2_MASK_INBUSY) < 0)
Ivop 16:844edb89d863 231 fatal("read_mem: cannot set FPDAT, no input ACK");
Ivop 16:844edb89d863 232 if (poll_status(C2_MASK_OUTREADY) < 0)
Ivop 16:844edb89d863 233 fatal("read_mem: cannot set FPDAT, no output ready");
Ivop 14:c24f608a8adb 234
Ivop 14:c24f608a8adb 235 ret = c2_read_dr();
Ivop 14:c24f608a8adb 236 if (ret != C2_PI_STATUS_OK)
Ivop 14:c24f608a8adb 237 fatal("read_mem: status not OK after setting FPDAT (status %02X)", ret);
Ivop 14:c24f608a8adb 238
Ivop 16:844edb89d863 239 if (!ram_or_sfr) {
Ivop 14:c24f608a8adb 240 c2_write_dr((address >> 8)&0xff);
Ivop 14:c24f608a8adb 241 if (poll_status(C2_MASK_INBUSY) < 0)
Ivop 14:c24f608a8adb 242 fatal("read_mem: cannot write msb of address");
Ivop 14:c24f608a8adb 243 }
Ivop 14:c24f608a8adb 244
Ivop 14:c24f608a8adb 245 c2_write_dr(address & 0xff);
Ivop 14:c24f608a8adb 246 if (poll_status(C2_MASK_INBUSY) < 0)
Ivop 14:c24f608a8adb 247 fatal("read_mem: cannot write lsb of address");
Ivop 14:c24f608a8adb 248
Ivop 16:844edb89d863 249 c2_write_dr(size&0xff);
Ivop 14:c24f608a8adb 250 if (poll_status(C2_MASK_INBUSY) < 0)
Ivop 14:c24f608a8adb 251 fatal("read_mem: cannot set block length");
Ivop 14:c24f608a8adb 252 if (poll_status(C2_MASK_OUTREADY) < 0)
Ivop 16:844edb89d863 253 fatal("read_mem: no data ready (dr:%02X ar:%02X)", c2_read_dr(), c2_read_ar());
Ivop 14:c24f608a8adb 254
Ivop 16:844edb89d863 255 for (i=0; i<size; i++)
Ivop 14:c24f608a8adb 256 buf[i] = c2_read_dr();
Ivop 14:c24f608a8adb 257 }
Ivop 14:c24f608a8adb 258
Ivop 0:902f10e5d3e0 259 int main() {
Ivop 4:a9e3ee5741be 260 int i, c, devid, revid;
Ivop 1:7a82f806fe92 261
Ivop 1:7a82f806fe92 262 c2d.input();
Ivop 1:7a82f806fe92 263 c2ck = 1;
Ivop 1:7a82f806fe92 264
Ivop 8:af5d402396fb 265 // printf("\033[H\033[J");
Ivop 14:c24f608a8adb 266 printf("\r\nSiLabs C2 Protocol\r\n\r\n");
Ivop 14:c24f608a8adb 267 printf("Connect C2GND to GND, C2CK (clock) to p5 and C2D (data) to p6\r\n\r\n");
Ivop 14:c24f608a8adb 268 printf("Press any key to continue\r\n");
Ivop 4:a9e3ee5741be 269
Ivop 4:a9e3ee5741be 270 getc(stdin);
Ivop 3:b30605f1c435 271
Ivop 13:45aaa8847c2b 272 c2_write_ar(C2_REG_DEVID);
Ivop 3:b30605f1c435 273 devid = c2_read_dr();
Ivop 14:c24f608a8adb 274 if (devid <= 0) fatal("unable to read devid\r\n");
Ivop 1:7a82f806fe92 275
Ivop 13:45aaa8847c2b 276 c2_write_ar(C2_REG_REVID);
Ivop 3:b30605f1c435 277 revid = c2_read_dr();
Ivop 14:c24f608a8adb 278 if (revid < 0) fatal("unable to read revid\r\n");
Ivop 3:b30605f1c435 279
Ivop 4:a9e3ee5741be 280 for (i=0; devices[i].name; i++) {
Ivop 4:a9e3ee5741be 281 if (devices[i].devid == devid) break;
Ivop 4:a9e3ee5741be 282 }
Ivop 4:a9e3ee5741be 283
Ivop 14:c24f608a8adb 284 if (!i) fatal("unknown device: %02X:%02X\r\n", devid, revid);
Ivop 4:a9e3ee5741be 285
Ivop 4:a9e3ee5741be 286 switch(devid) {
Ivop 13:45aaa8847c2b 287 case 0x0f: case 0x28: case 0x18: case 0x19: C2_REG_FPDAT = 0xad;
Ivop 4:a9e3ee5741be 288 default: break;
Ivop 4:a9e3ee5741be 289 }
Ivop 4:a9e3ee5741be 290
Ivop 14:c24f608a8adb 291 printf("\r\nDevice found: %s (%02X:%02X)", devices[i].name, devid, revid);
Ivop 14:c24f608a8adb 292 printf("\r\nFPDAT Address: 0x%02X", C2_REG_FPDAT);
Ivop 14:c24f608a8adb 293 printf("\r\nPage Size: %i\n\r", page_size);
Ivop 12:49ac91452d77 294
Ivop 14:c24f608a8adb 295 printf("\r\nEnabling Programming Interface\r\n");
Ivop 12:49ac91452d77 296 c2_enable_pi();
Ivop 14:c24f608a8adb 297
Ivop 14:c24f608a8adb 298 printf("Reading page 0\r\n");
Ivop 16:844edb89d863 299 c2_read_mem(C2_PI_CMD_BLOCK_READ, 0x0000, 0x100, buffer);
Ivop 14:c24f608a8adb 300 printf("Looks like all went well!!!");
Ivop 4:a9e3ee5741be 301 }