Basis for the C2 protocol from Silicon Labs.

Dependencies:   mbed

Committer:
Ivop
Date:
Sun May 25 17:27:52 2014 +0000
Revision:
8:af5d402396fb
Parent:
7:65a72aad87b8
Child:
9:6a689843a88e
defines for various programming interface (PI) commands

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 8:af5d402396fb 59 #define C2_PI_CMD_GET_VERSION 0x01
Ivop 8:af5d402396fb 60 #define C2_PI_CMD_GET_DERIVATIVE 0x02
Ivop 8:af5d402396fb 61
Ivop 8:af5d402396fb 62 #define C2_PI_CMD_DEVICE_ERASE 0x03
Ivop 8:af5d402396fb 63
Ivop 8:af5d402396fb 64 #define C2_PI_CMD_BLOCK_READ 0x06 // FLASH (max. 64K bytes, bankswapping not supported)
Ivop 8:af5d402396fb 65 #define C2_PI_CMD_BLOCK_WRITE 0x07 // FLASH
Ivop 8:af5d402396fb 66
Ivop 8:af5d402396fb 67 #define C2_PI_CMD_PAGE_ERASE 0x08
Ivop 8:af5d402396fb 68
Ivop 8:af5d402396fb 69 #define C2_PI_CMD_DIRECT_READ 0x09 // SFR (Special FUnction Registers, 256 bytes(?))
Ivop 8:af5d402396fb 70 #define C2_PI_CMD_DIRECT_WRITE 0x0a // SFR
Ivop 8:af5d402396fb 71
Ivop 8:af5d402396fb 72 #define C2_PI_CMD_INDIRECT_READ 0x0b // RAM (Internal, 256 bytes)
Ivop 8:af5d402396fb 73 #define C2_PI_CMD_INDIRECT_WRITE 0x0c // RAM
Ivop 8:af5d402396fb 74
Ivop 8:af5d402396fb 75 #define C2_PI_CMD_XRAM_READ 0x0e // RAM (External, 2K or 4K bytes)
Ivop 8:af5d402396fb 76 #define C2_PI_CMD_XRAM_WRITE 0x0f // RAM
Ivop 8:af5d402396fb 77
Ivop 4:a9e3ee5741be 78 #define C2_DEVID 0
Ivop 4:a9e3ee5741be 79 #define C2_REVID 1
Ivop 4:a9e3ee5741be 80 #define C2_FPCTL 2
Ivop 4:a9e3ee5741be 81 static int C2_FPDAT = 0xb4; // or 0xad
Ivop 4:a9e3ee5741be 82 static int page_size = 512; // not seen 4096 yet
Ivop 4:a9e3ee5741be 83
Ivop 7:65a72aad87b8 84 static void fatal(char *f, ...) {
Ivop 7:65a72aad87b8 85 va_list ap;
Ivop 7:65a72aad87b8 86 va_start(ap,f);
Ivop 7:65a72aad87b8 87 printf("\n\rFATAL: ");
Ivop 7:65a72aad87b8 88 vprintf(f, ap);
Ivop 7:65a72aad87b8 89 va_end(ap);
Ivop 7:65a72aad87b8 90 exit(1);
Ivop 7:65a72aad87b8 91 }
Ivop 7:65a72aad87b8 92
Ivop 1:7a82f806fe92 93 static void c2ck_reset(void) {
Ivop 1:7a82f806fe92 94 c2ck = 0;
Ivop 1:7a82f806fe92 95 wait_us(25);
Ivop 1:7a82f806fe92 96 c2ck = 1;
Ivop 1:7a82f806fe92 97 wait_us(1);
Ivop 1:7a82f806fe92 98 }
Ivop 1:7a82f806fe92 99
Ivop 1:7a82f806fe92 100 static void c2ck_strobe(void) {
Ivop 1:7a82f806fe92 101 c2ck = 0;
Ivop 1:7a82f806fe92 102 wait_us(1);
Ivop 1:7a82f806fe92 103 c2ck = 1;
Ivop 1:7a82f806fe92 104 wait_us(1);
Ivop 1:7a82f806fe92 105 }
Ivop 1:7a82f806fe92 106
Ivop 1:7a82f806fe92 107 // Four basic C2 Instructions
Ivop 1:7a82f806fe92 108 //
Ivop 1:7a82f806fe92 109 // 00b Data Read
Ivop 1:7a82f806fe92 110 // 01b Data Write
Ivop 1:7a82f806fe92 111 // 10b Address Read
Ivop 1:7a82f806fe92 112 // 11b Address Write
Ivop 2:9092d0d1558b 113 //
Ivop 2:9092d0d1558b 114 // Remember, ALL fields are sent LSB first(!)
Ivop 1:7a82f806fe92 115
Ivop 2:9092d0d1558b 116 #define START do{ c2ck_strobe(); }while(0)
Ivop 2:9092d0d1558b 117 #define STOP START
Ivop 2:9092d0d1558b 118 #define INS(a,b) do{ c2d = a; c2ck_strobe(); c2d = b; c2ck_strobe(); }while(0)
Ivop 2:9092d0d1558b 119 #define LENGTH(a,b) INS(a,b)
Ivop 2:9092d0d1558b 120 #define WAIT do{\
Ivop 2:9092d0d1558b 121 while(t-- && !c2d) { \
Ivop 2:9092d0d1558b 122 c2ck_strobe(); \
Ivop 2:9092d0d1558b 123 wait_us(1); \
Ivop 2:9092d0d1558b 124 } if (!t) return -1; \
Ivop 2:9092d0d1558b 125 } while(0)
Ivop 4:a9e3ee5741be 126 #define READV do{\
Ivop 4:a9e3ee5741be 127 for (i=0; i<8; i++) { \
Ivop 4:a9e3ee5741be 128 v >>= 1; \
Ivop 4:a9e3ee5741be 129 c2ck_strobe(); \
Ivop 4:a9e3ee5741be 130 if (c2d) v |= 0x80; \
Ivop 4:a9e3ee5741be 131 } } while(0)
Ivop 4:a9e3ee5741be 132 #define WRITEV do{\
Ivop 4:a9e3ee5741be 133 for(i=0; i<8; i++) { \
Ivop 4:a9e3ee5741be 134 c2d = v & 1; \
Ivop 4:a9e3ee5741be 135 c2ck_strobe(); \
Ivop 4:a9e3ee5741be 136 v >>= 1; \
Ivop 4:a9e3ee5741be 137 } } while(0)
Ivop 2:9092d0d1558b 138
Ivop 2:9092d0d1558b 139 static int c2_read_dr(void) {
Ivop 4:a9e3ee5741be 140 int t = 20, i, v = 0;
Ivop 2:9092d0d1558b 141
Ivop 2:9092d0d1558b 142 START;
Ivop 2:9092d0d1558b 143 c2d.output();
Ivop 2:9092d0d1558b 144 INS(0,0);
Ivop 2:9092d0d1558b 145 LENGTH(0,0);
Ivop 2:9092d0d1558b 146 c2d.input();
Ivop 2:9092d0d1558b 147 WAIT;
Ivop 4:a9e3ee5741be 148 READV;
Ivop 2:9092d0d1558b 149 STOP;
Ivop 2:9092d0d1558b 150
Ivop 4:a9e3ee5741be 151 return v;
Ivop 2:9092d0d1558b 152 }
Ivop 2:9092d0d1558b 153
Ivop 4:a9e3ee5741be 154 static int c2_write_dr(int v) {
Ivop 2:9092d0d1558b 155 int t = 20, i;
Ivop 2:9092d0d1558b 156
Ivop 2:9092d0d1558b 157 START;
Ivop 2:9092d0d1558b 158 c2d.output();
Ivop 2:9092d0d1558b 159 INS(1,0);
Ivop 2:9092d0d1558b 160 LENGTH(0,0);
Ivop 4:a9e3ee5741be 161 WRITEV;
Ivop 2:9092d0d1558b 162 c2d.input();
Ivop 2:9092d0d1558b 163 WAIT;
Ivop 2:9092d0d1558b 164 STOP;
Ivop 2:9092d0d1558b 165
Ivop 2:9092d0d1558b 166 return 0;
Ivop 2:9092d0d1558b 167 }
Ivop 2:9092d0d1558b 168
Ivop 2:9092d0d1558b 169 static int c2_read_ar(void) {
Ivop 4:a9e3ee5741be 170 int i, v = 0;
Ivop 2:9092d0d1558b 171
Ivop 2:9092d0d1558b 172 START;
Ivop 2:9092d0d1558b 173 c2d.output();
Ivop 2:9092d0d1558b 174 INS(0,1);
Ivop 2:9092d0d1558b 175 c2d.input();
Ivop 4:a9e3ee5741be 176 READV;
Ivop 4:a9e3ee5741be 177 STOP;
Ivop 2:9092d0d1558b 178
Ivop 4:a9e3ee5741be 179 return v;
Ivop 2:9092d0d1558b 180 }
Ivop 2:9092d0d1558b 181
Ivop 4:a9e3ee5741be 182 static void c2_write_ar(int v) {
Ivop 2:9092d0d1558b 183 int i;
Ivop 2:9092d0d1558b 184
Ivop 2:9092d0d1558b 185 START;
Ivop 2:9092d0d1558b 186 c2d.output();
Ivop 2:9092d0d1558b 187 INS(1,1);
Ivop 4:a9e3ee5741be 188 WRITEV;
Ivop 2:9092d0d1558b 189 c2d.input();
Ivop 2:9092d0d1558b 190 STOP;
Ivop 2:9092d0d1558b 191 }
Ivop 1:7a82f806fe92 192
Ivop 6:deb670cb8105 193 static int poll_status(int mask) {
Ivop 6:deb670cb8105 194 int t = 20;
Ivop 6:deb670cb8105 195 do {
Ivop 6:deb670cb8105 196 if (!(c2_read_ar() & mask)) return 0;
Ivop 6:deb670cb8105 197 wait_us(1);
Ivop 6:deb670cb8105 198 } while(--t);
Ivop 6:deb670cb8105 199 return -1;
Ivop 6:deb670cb8105 200 }
Ivop 7:65a72aad87b8 201
Ivop 0:902f10e5d3e0 202 int main() {
Ivop 4:a9e3ee5741be 203 int i, c, devid, revid;
Ivop 1:7a82f806fe92 204
Ivop 1:7a82f806fe92 205 c2d.input();
Ivop 1:7a82f806fe92 206 c2ck = 1;
Ivop 1:7a82f806fe92 207
Ivop 8:af5d402396fb 208 // printf("\033[H\033[J");
Ivop 8:af5d402396fb 209 printf("\n\rSiLabs C2 Protocol\n\r\n\r");
Ivop 1:7a82f806fe92 210 printf("Connect C2CK (clock) to p5 and C2D (data) to p6\n\r\n\r");
Ivop 1:7a82f806fe92 211 printf("Press any key to continue\n\r");
Ivop 4:a9e3ee5741be 212
Ivop 4:a9e3ee5741be 213 getc(stdin);
Ivop 3:b30605f1c435 214
Ivop 5:53d4a67cd657 215 c2_write_ar(C2_DEVID);
Ivop 3:b30605f1c435 216 devid = c2_read_dr();
Ivop 5:53d4a67cd657 217 if (devid <= 0) fatal("unable to read devid\n\r");
Ivop 1:7a82f806fe92 218
Ivop 5:53d4a67cd657 219 c2_write_ar(C2_REVID);
Ivop 3:b30605f1c435 220 revid = c2_read_dr();
Ivop 3:b30605f1c435 221 if (revid < 0) fatal("unable to read revid\n\r");
Ivop 3:b30605f1c435 222
Ivop 4:a9e3ee5741be 223 for (i=0; devices[i].name; i++) {
Ivop 4:a9e3ee5741be 224 if (devices[i].devid == devid) break;
Ivop 4:a9e3ee5741be 225 }
Ivop 4:a9e3ee5741be 226
Ivop 7:65a72aad87b8 227 if (!i) fatal("unknown device: %02X:%02X\n\r", devid, revid);
Ivop 4:a9e3ee5741be 228
Ivop 4:a9e3ee5741be 229 switch(devid) {
Ivop 4:a9e3ee5741be 230 case 0x0f: case 0x28: case 0x18: case 0x19: C2_FPDAT = 0xad;
Ivop 4:a9e3ee5741be 231 default: break;
Ivop 4:a9e3ee5741be 232 }
Ivop 4:a9e3ee5741be 233
Ivop 4:a9e3ee5741be 234 printf("\n\rDevice found: %s (%02X:%02X)", devices[i].name, devid, revid);
Ivop 4:a9e3ee5741be 235 printf("\n\rFPDAT Address: 0x%02X", C2_FPDAT);
Ivop 4:a9e3ee5741be 236 printf("\n\rPage Size: %i\n\r", page_size);
Ivop 4:a9e3ee5741be 237 }