예제 #1
0
파일: ch341a.c 프로젝트: Trel725/chavrprog
/* write buffer(*buf) to SPI flash */
int32_t ch341SpiWrite(uint8_t *buf, uint32_t add, uint32_t len)
{
    uint8_t out[WRITE_PAYLOAD_LENGTH];
    uint8_t in[CH341_PACKET_LENGTH];
    uint32_t tmp, pkg_count;
    struct libusb_transfer *xferBulkIn, *xferBulkOut;
    uint32_t idx = 0;
    uint32_t ret;
    int32_t old_counter;
    struct timeval tv = {0, 100};

    if (devHandle == NULL) return -1;
    memset(out, 0xff, WRITE_PAYLOAD_LENGTH);
    xferBulkIn  = libusb_alloc_transfer(0);
    xferBulkOut = libusb_alloc_transfer(0);

    while (len > 0) {
        out[0] = 0x06; // Write enable
        ret = ch341SpiStream(out, in, 1);
        ch341SpiCs(out, true);
        idx = CH341_PACKET_LENGTH;
        out[idx++] = CH341A_CMD_SPI_STREAM;
        out[idx++] = 0x40; // byte swapped command for Flash Page Write
        tmp = add;
        for (int i = 0; i < 3; ++i) { // starting address of next write
            out[idx++] = swapByte((tmp >> 16) & 0xFF);
            tmp <<= 8;
        }
        tmp = 0;
        pkg_count = 1;
        while ((idx < WRITE_PAYLOAD_LENGTH) && (len > tmp)) {
            if (idx % CH341_PACKET_LENGTH == 0) {
                out[idx++] = CH341A_CMD_SPI_STREAM;
                pkg_count ++;
            } else {
                out[idx++] = swapByte(*buf++);
                tmp++;
                if (((add + tmp) & 0xFF) == 0) // cross page boundary
                    break;
            }
        }
        len -= tmp;
        add += tmp;
        bulkin_count = 0;
        libusb_fill_bulk_transfer(xferBulkIn, devHandle, BULK_READ_ENDPOINT, in,
                CH341_PACKET_LENGTH, cbBulkIn, NULL, DEFAULT_TIMEOUT);
        libusb_submit_transfer(xferBulkIn);
        libusb_fill_bulk_transfer(xferBulkOut, devHandle, BULK_WRITE_ENDPOINT, out,
                idx, cbBulkOut, NULL, DEFAULT_TIMEOUT);
        libusb_submit_transfer(xferBulkOut);
        old_counter = bulkin_count;
        ret = 0;
        while (bulkin_count < pkg_count) {
            libusb_handle_events_timeout(NULL, &tv);
            if (bulkin_count == -1) { // encountered error
                ret = -1;
                break;
            }
            if (old_counter != bulkin_count) { // new package came
                if (bulkin_count != pkg_count)
                    libusb_submit_transfer(xferBulkIn);  // resubmit bulk in request
                old_counter = bulkin_count;
            }
        }
        if (ret < 0) break;
        ch341SpiCs(out, false);
        ret = usbTransfer(__func__, BULK_WRITE_ENDPOINT, out, 3);
        if (ret < 0) break;
        out[0] = 0x04; // Write disable
        ret = ch341SpiStream(out, in, 1);
        do {
            ret = ch341ReadStatus();
            if (ret != 0)
                libusb_handle_events_timeout(NULL, &tv);
        } while(ret != 0);
        if (force_stop == 1) { // user hit ctrl+C
            force_stop = 0;
            if (len > 0)
                fprintf(stderr, "User hit Ctrl+C, writing unfinished.\n");
            break;
        }
    }
    libusb_free_transfer(xferBulkIn);
    libusb_free_transfer(xferBulkOut);
    return ret;
}
예제 #2
0
int main(int argc, char* argv[])
{
    int32_t ret;
    uint8_t *buf;
    FILE *fp;
    char *filename;
    int cap;
    int length = 0;
    char op = 0;
    uint32_t speed = CH341A_STM_I2C_20K;
    int8_t c;

    const char usage[] =
        "\nUsage:\n"\
        " -h, --help             display this message\n"\
	" -v,--verbose		print verbose info\n"\
        " -i, --info             read the chip ID info\n"\
        " -e, --erase            erase the entire chip\n"\
        " -l, --length <bytes>   manually set length\n"\
        " -w, --write <filename> write chip with data from filename\n"\
        " -r, --read <filename>  read chip and save data to filename\n"\
        " -t, --turbo            increase the i2c bus speed (-tt to use much faster speed)\n"\
	" -d, --double           double the spi bus speed\n";
    const struct option options[] = {
        {"help",    no_argument,        0, 'h'},
        {"erase",   no_argument,        0, 'e'},
  	{"verbose",   no_argument,        0, 'v'},
	{"write",   required_argument,  0, 'w'},
        {"length",   required_argument,  0, 'l'},
        {"read",    required_argument,  0, 'r'},
	{"turbo",   no_argument,  0, 't'},
	{"double",  no_argument,  0, 'd'},
        {0, 0, 0, 0}};

        int32_t optidx = 0;

        while ((c = getopt_long(argc, argv, "hiew:r:l:td:v", options, &optidx)) != -1){
            switch (c) {
                case 'i':
                case 'e':
                    if (!op)
                        op = c;
                    else
                        op = 'x';
                    break;
		case 'v':
			verbose = 1;
		        break;
                case 'w':
                case 'r':
                    if (!op) {
                        op = c;
                        filename = (char*) malloc(strlen(optarg) + 1);
                        strcpy(filename, optarg);
                    } else
                        op = 'x';
                    break;
		case 'l':
		    length = atoi(optarg);
		    break;
		case 't':
		    if ((speed & 3) < 3) {
		        speed++;
		    }
		    break;
		case 'd':
		    speed |= CH341A_STM_SPI_DBL;
		    break;
                default:
                    printf("%s\n", usage);
                    return 0;
            }
    }
    if (op == 0) {
        fprintf(stderr, "%s\n", usage);
        return 0;
    }
    if (op == 'x') {
        fprintf(stderr, "Conflicting options, only one option at a time.\n");
        return -1;
    }
    ret = ch341Configure(CH341A_USB_VENDOR, CH341A_USB_PRODUCT);
    if (ret < 0)
        return -1;
    ret = ch341SetStream(speed);
    if (ret < 0) goto out;
    ret = ch341SpiCapacity();
    if (ret < 0) goto out;
    cap = 1 << ret;
    printf("Chip capacity is %d\n", cap);

    if (length != 0){
	cap = length;
    }
    if (op == 'i') goto out;
    if (op == 'e') {
        uint8_t timeout = 0;
        ret = ch341EraseChip();
        if (ret < 0) goto out;
        do {
            sleep(1);
            ret = ch341ReadStatus();
            if (ret < 0) goto out;
            printf(".");
            fflush(stdout);
            timeout++;
            if (timeout == 100) break;
        } while(ret != 0);
        if (timeout == 100)
            fprintf(stderr, "Chip erase timeout.\n");
        else
            printf("Chip erase done!\n");
    }
    if ((op == 'r') || (op == 'w')) {
        buf = (uint8_t *)malloc(cap);
        if (!buf) {
            fprintf(stderr, "Malloc failed for read buffer.\n");
            goto out;
        }
    }
    if (op == 'r') {
        ret = ch341SpiRead(buf, 0, cap);
        if (ret < 0)
            goto out;
        fp = fopen(filename, "wb");
        if (!fp) {
            fprintf(stderr, "Couldn't open file %s for writing.\n", filename);
            goto out;
        }
        fwrite(buf, 1, cap, fp);
        if (ferror(fp))
            fprintf(stderr, "Error writing file [%s]\n", filename);
        fclose(fp);
    }
    if (op == 'w') {
        fp = fopen(filename, "rb");
        if (!fp) {
            fprintf(stderr, "Couldn't open file %s for reading.\n", filename);
            goto out;
        }
        ret = fread(buf, 1, cap, fp);
        if (ferror(fp)) {
            fprintf(stderr, "Error reading file [%s]\n", filename);
            if (fp)
                fclose(fp);
            goto out;
        }
        fprintf(stderr, "File Size is [%d]\n", ret);
        fclose(fp);
        ret = ch341SpiWrite(buf, 0, ret);
    }
out:
    ch341Release();
    return 0;
}