Basis for the C2 protocol from Silicon Labs.

Dependencies:   mbed

Committer:
Ivop
Date:
Sun May 25 17:52:29 2014 +0000
Revision:
12:49ac91452d77
Parent:
11:2b19d52ea37c
Child:
13:45aaa8847c2b
enable_pi() function; usage: also connect the groud pin!

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 0:902f10e5d3e0 30
Ivop 0:902f10e5d3e0 31 DigitalOut c2ck(p5);
Ivop 0:902f10e5d3e0 32 DigitalInOut c2d(p6);
Ivop 0:902f10e5d3e0 33
Ivop 4:a9e3ee5741be 34 static struct devices {
Ivop 4:a9e3ee5741be 35 char *name;
Ivop 4:a9e3ee5741be 36 int devid;
Ivop 4:a9e3ee5741be 37 } devices[] = {
Ivop 8:af5d402396fb 38 { "F30x", 0x04 }, { "F31x", 0x08 },
Ivop 8:af5d402396fb 39 { "F32x", 0x09 }, { "F326/7", 0x0d },
Ivop 8:af5d402396fb 40 { "F33x", 0x0a }, { "F336/7", 0x14 },
Ivop 8:af5d402396fb 41 { "F34x", 0x0f }, { "F35x", 0x0b },
Ivop 8:af5d402396fb 42 { "F36x", 0x12 }, { "F38x", 0x28 },
Ivop 8:af5d402396fb 43 { "F39x/F37x", 0x2b }, { "F41x", 0x0c },
Ivop 8:af5d402396fb 44 { "F50x/F51x", 0x1c }, { "F52xA/F53xA", 0x11 },
Ivop 8:af5d402396fb 45 { "F54x", 0x21 }, { "F55x/F56x/F57x", 0x22 },
Ivop 8:af5d402396fb 46 { "F58x/F59x", 0x20 }, { "F70x/F71x", 0x1e },
Ivop 8:af5d402396fb 47 { "F80x/F81x/F82x/F83x", 0x23 }, { "F90x/F91x", 0x1f },
Ivop 8:af5d402396fb 48 { "F92x/F93x", 0x16 }, { "F96x", 0x2a },
Ivop 8:af5d402396fb 49 { "F99x", 0x25 }, { "T60x", 0x10 },
Ivop 8:af5d402396fb 50 { "T606", 0x1b }, { "T61x", 0x13 },
Ivop 8:af5d402396fb 51 { "T62x/T32x", 0x18 }, { "T622/T623/T326/T327", 0x19 },
Ivop 8:af5d402396fb 52 { "T63x", 0x17 }, { NULL, 0 }
Ivop 4:a9e3ee5741be 53 };
Ivop 4:a9e3ee5741be 54
Ivop 6:deb670cb8105 55 #define C2_MASK_FLBUSY 0x80
Ivop 6:deb670cb8105 56 #define C2_MASK_INBUSY 0x02
Ivop 6:deb670cb8105 57 #define C2_MASK_OUTREADY 0x01
Ivop 6:deb670cb8105 58
Ivop 9:6a689843a88e 59 // Programming INterface (PI) Commands
Ivop 9:6a689843a88e 60
Ivop 8:af5d402396fb 61 #define C2_PI_CMD_GET_VERSION 0x01
Ivop 8:af5d402396fb 62 #define C2_PI_CMD_GET_DERIVATIVE 0x02
Ivop 8:af5d402396fb 63
Ivop 8:af5d402396fb 64 #define C2_PI_CMD_DEVICE_ERASE 0x03
Ivop 8:af5d402396fb 65
Ivop 8:af5d402396fb 66 #define C2_PI_CMD_BLOCK_READ 0x06 // FLASH (max. 64K bytes, bankswapping not supported)
Ivop 8:af5d402396fb 67 #define C2_PI_CMD_BLOCK_WRITE 0x07 // FLASH
Ivop 8:af5d402396fb 68
Ivop 8:af5d402396fb 69 #define C2_PI_CMD_PAGE_ERASE 0x08
Ivop 8:af5d402396fb 70
Ivop 8:af5d402396fb 71 #define C2_PI_CMD_DIRECT_READ 0x09 // SFR (Special FUnction Registers, 256 bytes(?))
Ivop 8:af5d402396fb 72 #define C2_PI_CMD_DIRECT_WRITE 0x0a // SFR
Ivop 8:af5d402396fb 73
Ivop 8:af5d402396fb 74 #define C2_PI_CMD_INDIRECT_READ 0x0b // RAM (Internal, 256 bytes)
Ivop 8:af5d402396fb 75 #define C2_PI_CMD_INDIRECT_WRITE 0x0c // RAM
Ivop 8:af5d402396fb 76
Ivop 8:af5d402396fb 77 #define C2_PI_CMD_XRAM_READ 0x0e // RAM (External, 2K or 4K bytes)
Ivop 8:af5d402396fb 78 #define C2_PI_CMD_XRAM_WRITE 0x0f // RAM
Ivop 8:af5d402396fb 79
Ivop 9:6a689843a88e 80 // PI Status Values
Ivop 9:6a689843a88e 81
Ivop 9:6a689843a88e 82 #define C2_PI_STATUS_COMMAND_INVALID 0x00
Ivop 9:6a689843a88e 83 #define C2_PI_STATUS_NO_CONNECT 0x01
Ivop 9:6a689843a88e 84 #define C2_PI_STATUS_FAILED 0x02
Ivop 9:6a689843a88e 85 #define C2_PI_STATUS_TIMEOUT 0x04
Ivop 9:6a689843a88e 86 #define C2_PI_STATUS_BAD_DATA 0x05
Ivop 9:6a689843a88e 87 #define C2_PI_STATUS_OK 0x0d
Ivop 9:6a689843a88e 88
Ivop 9:6a689843a88e 89 // C2 Registers
Ivop 4:a9e3ee5741be 90 #define C2_DEVID 0
Ivop 4:a9e3ee5741be 91 #define C2_REVID 1
Ivop 4:a9e3ee5741be 92 #define C2_FPCTL 2
Ivop 4:a9e3ee5741be 93 static int C2_FPDAT = 0xb4; // or 0xad
Ivop 4:a9e3ee5741be 94 static int page_size = 512; // not seen 4096 yet
Ivop 4:a9e3ee5741be 95
Ivop 7:65a72aad87b8 96 static void fatal(char *f, ...) {
Ivop 7:65a72aad87b8 97 va_list ap;
Ivop 7:65a72aad87b8 98 va_start(ap,f);
Ivop 7:65a72aad87b8 99 printf("\n\rFATAL: ");
Ivop 7:65a72aad87b8 100 vprintf(f, ap);
Ivop 7:65a72aad87b8 101 va_end(ap);
Ivop 7:65a72aad87b8 102 exit(1);
Ivop 7:65a72aad87b8 103 }
Ivop 7:65a72aad87b8 104
Ivop 1:7a82f806fe92 105 static void c2ck_reset(void) {
Ivop 1:7a82f806fe92 106 c2ck = 0;
Ivop 1:7a82f806fe92 107 wait_us(25);
Ivop 1:7a82f806fe92 108 c2ck = 1;
Ivop 11:2b19d52ea37c 109 wait_us(2);
Ivop 1:7a82f806fe92 110 }
Ivop 1:7a82f806fe92 111
Ivop 1:7a82f806fe92 112 static void c2ck_strobe(void) {
Ivop 1:7a82f806fe92 113 c2ck = 0;
Ivop 1:7a82f806fe92 114 wait_us(1);
Ivop 1:7a82f806fe92 115 c2ck = 1;
Ivop 1:7a82f806fe92 116 wait_us(1);
Ivop 1:7a82f806fe92 117 }
Ivop 1:7a82f806fe92 118
Ivop 2:9092d0d1558b 119 // Remember, ALL fields are sent LSB first(!)
Ivop 1:7a82f806fe92 120
Ivop 2:9092d0d1558b 121 #define START do{ c2ck_strobe(); }while(0)
Ivop 2:9092d0d1558b 122 #define STOP START
Ivop 2:9092d0d1558b 123 #define INS(a,b) do{ c2d = a; c2ck_strobe(); c2d = b; c2ck_strobe(); }while(0)
Ivop 2:9092d0d1558b 124 #define LENGTH(a,b) INS(a,b)
Ivop 2:9092d0d1558b 125 #define WAIT do{\
Ivop 2:9092d0d1558b 126 while(t-- && !c2d) { \
Ivop 2:9092d0d1558b 127 c2ck_strobe(); \
Ivop 2:9092d0d1558b 128 wait_us(1); \
Ivop 2:9092d0d1558b 129 } if (!t) return -1; \
Ivop 2:9092d0d1558b 130 } while(0)
Ivop 4:a9e3ee5741be 131 #define READV do{\
Ivop 4:a9e3ee5741be 132 for (i=0; i<8; i++) { \
Ivop 4:a9e3ee5741be 133 v >>= 1; \
Ivop 4:a9e3ee5741be 134 c2ck_strobe(); \
Ivop 4:a9e3ee5741be 135 if (c2d) v |= 0x80; \
Ivop 4:a9e3ee5741be 136 } } while(0)
Ivop 4:a9e3ee5741be 137 #define WRITEV do{\
Ivop 11:2b19d52ea37c 138 for (i=0; i<8; i++) { \
Ivop 4:a9e3ee5741be 139 c2d = v & 1; \
Ivop 4:a9e3ee5741be 140 c2ck_strobe(); \
Ivop 4:a9e3ee5741be 141 v >>= 1; \
Ivop 4:a9e3ee5741be 142 } } while(0)
Ivop 2:9092d0d1558b 143
Ivop 2:9092d0d1558b 144 static int c2_read_dr(void) {
Ivop 4:a9e3ee5741be 145 int t = 20, i, v = 0;
Ivop 2:9092d0d1558b 146
Ivop 2:9092d0d1558b 147 START;
Ivop 2:9092d0d1558b 148 c2d.output();
Ivop 2:9092d0d1558b 149 INS(0,0);
Ivop 2:9092d0d1558b 150 LENGTH(0,0);
Ivop 2:9092d0d1558b 151 c2d.input();
Ivop 2:9092d0d1558b 152 WAIT;
Ivop 4:a9e3ee5741be 153 READV;
Ivop 2:9092d0d1558b 154 STOP;
Ivop 2:9092d0d1558b 155
Ivop 4:a9e3ee5741be 156 return v;
Ivop 2:9092d0d1558b 157 }
Ivop 2:9092d0d1558b 158
Ivop 4:a9e3ee5741be 159 static int c2_write_dr(int v) {
Ivop 2:9092d0d1558b 160 int t = 20, i;
Ivop 2:9092d0d1558b 161
Ivop 2:9092d0d1558b 162 START;
Ivop 2:9092d0d1558b 163 c2d.output();
Ivop 2:9092d0d1558b 164 INS(1,0);
Ivop 2:9092d0d1558b 165 LENGTH(0,0);
Ivop 4:a9e3ee5741be 166 WRITEV;
Ivop 2:9092d0d1558b 167 c2d.input();
Ivop 2:9092d0d1558b 168 WAIT;
Ivop 2:9092d0d1558b 169 STOP;
Ivop 2:9092d0d1558b 170
Ivop 2:9092d0d1558b 171 return 0;
Ivop 2:9092d0d1558b 172 }
Ivop 2:9092d0d1558b 173
Ivop 2:9092d0d1558b 174 static int c2_read_ar(void) {
Ivop 4:a9e3ee5741be 175 int i, v = 0;
Ivop 2:9092d0d1558b 176
Ivop 2:9092d0d1558b 177 START;
Ivop 2:9092d0d1558b 178 c2d.output();
Ivop 2:9092d0d1558b 179 INS(0,1);
Ivop 2:9092d0d1558b 180 c2d.input();
Ivop 4:a9e3ee5741be 181 READV;
Ivop 4:a9e3ee5741be 182 STOP;
Ivop 2:9092d0d1558b 183
Ivop 4:a9e3ee5741be 184 return v;
Ivop 2:9092d0d1558b 185 }
Ivop 2:9092d0d1558b 186
Ivop 4:a9e3ee5741be 187 static void c2_write_ar(int v) {
Ivop 2:9092d0d1558b 188 int i;
Ivop 2:9092d0d1558b 189
Ivop 2:9092d0d1558b 190 START;
Ivop 2:9092d0d1558b 191 c2d.output();
Ivop 2:9092d0d1558b 192 INS(1,1);
Ivop 4:a9e3ee5741be 193 WRITEV;
Ivop 2:9092d0d1558b 194 c2d.input();
Ivop 2:9092d0d1558b 195 STOP;
Ivop 2:9092d0d1558b 196 }
Ivop 1:7a82f806fe92 197
Ivop 6:deb670cb8105 198 static int poll_status(int mask) {
Ivop 6:deb670cb8105 199 int t = 20;
Ivop 6:deb670cb8105 200 do {
Ivop 6:deb670cb8105 201 if (!(c2_read_ar() & mask)) return 0;
Ivop 6:deb670cb8105 202 wait_us(1);
Ivop 6:deb670cb8105 203 } while(--t);
Ivop 6:deb670cb8105 204 return -1;
Ivop 6:deb670cb8105 205 }
Ivop 11:2b19d52ea37c 206
Ivop 12:49ac91452d77 207 static void c2_enable_pi(void) {
Ivop 12:49ac91452d77 208 c2ck_reset();
Ivop 12:49ac91452d77 209 c2_write_ar(C2_FPCTL);
Ivop 12:49ac91452d77 210 if ((c2_write_dr(0x02)+c2_write_dr(0x04)+c2_write_dr(0x02))<0)
Ivop 12:49ac91452d77 211 fatal("cannot enable PI");
Ivop 12:49ac91452d77 212 wait_us(21);
Ivop 12:49ac91452d77 213 }
Ivop 11:2b19d52ea37c 214
Ivop 0:902f10e5d3e0 215 int main() {
Ivop 4:a9e3ee5741be 216 int i, c, devid, revid;
Ivop 1:7a82f806fe92 217
Ivop 1:7a82f806fe92 218 c2d.input();
Ivop 1:7a82f806fe92 219 c2ck = 1;
Ivop 1:7a82f806fe92 220
Ivop 8:af5d402396fb 221 // printf("\033[H\033[J");
Ivop 8:af5d402396fb 222 printf("\n\rSiLabs C2 Protocol\n\r\n\r");
Ivop 12:49ac91452d77 223 printf("Connect C2GND to GND, C2CK (clock) to p5 and C2D (data) to p6\n\r\n\r");
Ivop 1:7a82f806fe92 224 printf("Press any key to continue\n\r");
Ivop 4:a9e3ee5741be 225
Ivop 4:a9e3ee5741be 226 getc(stdin);
Ivop 3:b30605f1c435 227
Ivop 5:53d4a67cd657 228 c2_write_ar(C2_DEVID);
Ivop 3:b30605f1c435 229 devid = c2_read_dr();
Ivop 5:53d4a67cd657 230 if (devid <= 0) fatal("unable to read devid\n\r");
Ivop 1:7a82f806fe92 231
Ivop 5:53d4a67cd657 232 c2_write_ar(C2_REVID);
Ivop 3:b30605f1c435 233 revid = c2_read_dr();
Ivop 3:b30605f1c435 234 if (revid < 0) fatal("unable to read revid\n\r");
Ivop 3:b30605f1c435 235
Ivop 4:a9e3ee5741be 236 for (i=0; devices[i].name; i++) {
Ivop 4:a9e3ee5741be 237 if (devices[i].devid == devid) break;
Ivop 4:a9e3ee5741be 238 }
Ivop 4:a9e3ee5741be 239
Ivop 7:65a72aad87b8 240 if (!i) fatal("unknown device: %02X:%02X\n\r", devid, revid);
Ivop 4:a9e3ee5741be 241
Ivop 4:a9e3ee5741be 242 switch(devid) {
Ivop 4:a9e3ee5741be 243 case 0x0f: case 0x28: case 0x18: case 0x19: C2_FPDAT = 0xad;
Ivop 4:a9e3ee5741be 244 default: break;
Ivop 4:a9e3ee5741be 245 }
Ivop 4:a9e3ee5741be 246
Ivop 4:a9e3ee5741be 247 printf("\n\rDevice found: %s (%02X:%02X)", devices[i].name, devid, revid);
Ivop 4:a9e3ee5741be 248 printf("\n\rFPDAT Address: 0x%02X", C2_FPDAT);
Ivop 4:a9e3ee5741be 249 printf("\n\rPage Size: %i\n\r", page_size);
Ivop 12:49ac91452d77 250
Ivop 12:49ac91452d77 251 printf("\n\rEnabling Programming Interface\n\r");
Ivop 12:49ac91452d77 252 c2_enable_pi();
Ivop 4:a9e3ee5741be 253 }