Ivo van Poorten
/
SiLabs_C2
Basis for the C2 protocol from Silicon Labs.
main.cpp
- Committer:
- Ivop
- Date:
- 2014-05-26
- Revision:
- 14:c24f608a8adb
- Parent:
- 13:45aaa8847c2b
- Child:
- 15:0ccb0277d98e
File content as of revision 14:c24f608a8adb:
/* * SiLabs C2 Protocol on mbed pins p5/p6 * * Copyright (c) 2014, Ivo van Poorten <ivopvp@gmail.com> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "mbed.h" #include <stdarg.h> #include <stdio.h> #include <stdint.h> DigitalOut c2ck(p5); DigitalInOut c2d(p6); static uint8_t buffer[256]; static struct devices { char *name; int devid; } devices[] = { { "F30x", 0x04 }, { "F31x", 0x08 }, { "F32x", 0x09 }, { "F326/7", 0x0d }, { "F33x", 0x0a }, { "F336/7", 0x14 }, { "F34x", 0x0f }, { "F35x", 0x0b }, { "F36x", 0x12 }, { "F38x", 0x28 }, { "F39x/F37x", 0x2b }, { "F41x", 0x0c }, { "F50x/F51x", 0x1c }, { "F52xA/F53xA", 0x11 }, { "F54x", 0x21 }, { "F55x/F56x/F57x", 0x22 }, { "F58x/F59x", 0x20 }, { "F70x/F71x", 0x1e }, { "F80x/F81x/F82x/F83x", 0x23 }, { "F90x/F91x", 0x1f }, { "F92x/F93x", 0x16 }, { "F96x", 0x2a }, { "F99x", 0x25 }, { "T60x", 0x10 }, { "T606", 0x1b }, { "T61x", 0x13 }, { "T62x/T32x", 0x18 }, { "T622/T623/T326/T327", 0x19 }, { "T63x", 0x17 }, { NULL, 0 } }; #define C2_MASK_FLBUSY 0x80 #define C2_MASK_INBUSY 0x02 #define C2_MASK_OUTREADY 0x01 // Programming INterface (PI) Commands #define C2_PI_CMD_GET_VERSION 0x01 #define C2_PI_CMD_GET_DERIVATIVE 0x02 #define C2_PI_CMD_DEVICE_ERASE 0x03 #define C2_PI_CMD_BLOCK_READ 0x06 // FLASH (max. 64K bytes, bankswapping not supported) #define C2_PI_CMD_BLOCK_WRITE 0x07 // FLASH #define C2_PI_CMD_PAGE_ERASE 0x08 #define C2_PI_CMD_DIRECT_READ 0x09 // SFR (Special FUnction Registers, 256 bytes(?)) #define C2_PI_CMD_DIRECT_WRITE 0x0a // SFR #define C2_PI_CMD_INDIRECT_READ 0x0b // RAM (Internal, 256 bytes) #define C2_PI_CMD_INDIRECT_WRITE 0x0c // RAM #define C2_PI_CMD_XRAM_READ 0x0e // RAM (External, 2K or 4K bytes) #define C2_PI_CMD_XRAM_WRITE 0x0f // RAM // PI Status Values #define C2_PI_STATUS_COMMAND_INVALID 0x00 #define C2_PI_STATUS_NO_CONNECT 0x01 #define C2_PI_STATUS_FAILED 0x02 #define C2_PI_STATUS_TIMEOUT 0x04 #define C2_PI_STATUS_BAD_DATA 0x05 #define C2_PI_STATUS_OK 0x0d // C2 Registers #define C2_REG_DEVID 0 #define C2_REG_REVID 1 #define C2_REG_FPCTL 2 static int C2_REG_FPDAT = 0xb4; // or 0xad static int page_size = 512; // not seen 4096 yet static void fatal(char *f, ...) { va_list ap; va_start(ap,f); printf("\r\nFATAL: "); vprintf(f, ap); va_end(ap); exit(1); } static void c2ck_reset(void) { c2ck = 0; wait_us(25); c2ck = 1; wait_us(2); } static void c2ck_strobe(void) { c2ck = 0; wait_us(1); c2ck = 1; wait_us(1); } // Remember, ALL fields are sent LSB first(!) #define START do{ c2ck_strobe(); }while(0) #define STOP START #define INS(a,b) do{ c2d = a; c2ck_strobe(); c2d = b; c2ck_strobe(); }while(0) #define LENGTH(a,b) INS(a,b) #define WAIT do{\ while(t-- && !c2d) { \ c2ck_strobe(); \ wait_us(1); \ } if (!t) return -1; \ } while(0) #define READV do{\ for (i=0; i<8; i++) { \ v >>= 1; \ c2ck_strobe(); \ if (c2d) v |= 0x80; \ } } while(0) #define WRITEV do{\ for (i=0; i<8; i++) { \ c2d = v & 1; \ c2ck_strobe(); \ v >>= 1; \ } } while(0) static int c2_read_dr(void) { int t = 20, i, v = 0; START; c2d.output(); INS(0,0); LENGTH(0,0); c2d.input(); WAIT; READV; STOP; return v; } static int c2_write_dr(int v) { int t = 20, i; START; c2d.output(); INS(1,0); LENGTH(0,0); WRITEV; c2d.input(); WAIT; STOP; return 0; } static int c2_read_ar(void) { int i, v = 0; START; c2d.output(); INS(0,1); c2d.input(); READV; STOP; return v; } static void c2_write_ar(int v) { int i; START; c2d.output(); INS(1,1); WRITEV; c2d.input(); STOP; } static int poll_status(int mask) { int t = 20; do { if (!(c2_read_ar() & mask)) return 0; wait_us(1); } while(--t); return -1; } static void c2_enable_pi(void) { c2ck_reset(); c2_write_ar(C2_REG_FPCTL); if ((c2_write_dr(0x02)+c2_write_dr(0x04)+c2_write_dr(0x01))<0) fatal("cannot enable PI"); wait_us(21); } static void c2_read_mem(int type, uint16_t address, uint8_t size, uint8_t *buf) { int ret, i, ram_or_sfr = (type == C2_PI_CMD_DIRECT_READ) || (type == C2_PI_CMD_INDIRECT_READ); c2_write_ar(C2_REG_FPDAT); c2_write_dr(type); if (poll_status(C2_MASK_INBUSY) < 0 || poll_status(C2_MASK_OUTREADY) < 0) fatal("read_mem: cannot set FPDAT"); ret = c2_read_dr(); if (ret != C2_PI_STATUS_OK) fatal("read_mem: status not OK after setting FPDAT (status %02X)", ret); if (ram_or_sfr) { c2_write_dr((address >> 8)&0xff); if (poll_status(C2_MASK_INBUSY) < 0) fatal("read_mem: cannot write msb of address"); } c2_write_dr(address & 0xff); if (poll_status(C2_MASK_INBUSY) < 0) fatal("read_mem: cannot write lsb of address"); c2_write_dr(size); if (poll_status(C2_MASK_INBUSY) < 0) fatal("read_mem: cannot set block length"); if (poll_status(C2_MASK_OUTREADY) < 0) fatal("read_mem: no data ready"); for (i=0; i<=size; i++) buf[i] = c2_read_dr(); } int main() { int i, c, devid, revid; c2d.input(); c2ck = 1; // printf("\033[H\033[J"); printf("\r\nSiLabs C2 Protocol\r\n\r\n"); printf("Connect C2GND to GND, C2CK (clock) to p5 and C2D (data) to p6\r\n\r\n"); printf("Press any key to continue\r\n"); getc(stdin); c2_write_ar(C2_REG_DEVID); devid = c2_read_dr(); if (devid <= 0) fatal("unable to read devid\r\n"); c2_write_ar(C2_REG_REVID); revid = c2_read_dr(); if (revid < 0) fatal("unable to read revid\r\n"); for (i=0; devices[i].name; i++) { if (devices[i].devid == devid) break; } if (!i) fatal("unknown device: %02X:%02X\r\n", devid, revid); switch(devid) { case 0x0f: case 0x28: case 0x18: case 0x19: C2_REG_FPDAT = 0xad; default: break; } printf("\r\nDevice found: %s (%02X:%02X)", devices[i].name, devid, revid); printf("\r\nFPDAT Address: 0x%02X", C2_REG_FPDAT); printf("\r\nPage Size: %i\n\r", page_size); printf("\r\nEnabling Programming Interface\r\n"); c2_enable_pi(); printf("Reading page 0\r\n"); c2_read_mem(C2_PI_CMD_DIRECT_READ, 0x0000, 0xff, buffer); printf("Looks like all went well!!!"); }