Загрузка данных


#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <string.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>

/* Побитовый разворот одного байта (Bit Mirroring) */
unsigned char mirror_byte(unsigned char b) {
#if 0//def MY_CODE
    b = ((b & 0xF0) >> 4) | ((b & 0x0F) << 4);
    b = ((b & 0xCC) >> 2) | ((b & 0x33) << 2);
    b = ((b & 0xAA) >> 1) | ((b & 0x55) << 1);
#endif
    return b;
}

/* Функция для принудительного чтения статуса 0x3C прямо внутри процесса */
void read_embedded_status(int fd) {
    unsigned char cmd[] = {mirror_byte(0x3C), 0x00, 0x00, 0x00 };
    unsigned char buf[8] = {0};
    unsigned char id_code[] = {mirror_byte(0x16), 0x00, 0x00, 0x00 };

    if (write(fd, cmd, 4) != 4) {
        printf("[STATUS]: Failed to write status command\n");
        return;
    }
    usleep(2000);
    if (read(fd, buf, 8) == 8) {
        printf("[STATUS]: 0x%02X %02X %02X %02X %02X %02X %02X %02X\n",
               buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
    } else {
        printf("[STATUS]: Failed to read status bytes\n");
    }

    if (write(fd, id_code, 4) != 4) {
        printf("[ID_CODE]: Failed to write status command\n");
        return;
    }
    usleep(2000);
    memset(buf,0,sizeof(buf));
    if (read(fd, buf, 8) == 8) {
        printf("[ID_CODE]: 0x%02X %02X %02X %02X %02X %02X %02X %02X\n",
               buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
    } else {
        printf("[ID_CODE]: Failed to read idcode bytes\n");
    }
}

int main(int argc, char *argv[]) {
    if (argc < 3) {
        printf("Usage: %s <i2c-dev-path> <bitstream.bit>\n", argv[0]);
        return 1;
    }

    int fd = open(argv[1], O_RDWR);
    if (fd < 0) { perror("Failed to open I2C bus"); return 1; }

    if (ioctl(fd, I2C_SLAVE_FORCE, 0x40) < 0) { perror("Failed to set slave address"); return 1; }

    FILE *f_bit = fopen(argv[2], "rb");
    if (!f_bit) { perror("Failed to open bit file"); return 1; }

    printf("[USER_FLASH] Connected to 0x40. Starting direct execution...\n");

    printf("Start LSC_REFRESH\n");
    unsigned char lsc_refresh[] = {mirror_byte(0x79), 0x00, 0x00, 0x00};
    if (write(fd, lsc_refresh, 4) != 4) { perror("LSC refresh failed"); return 1; }

    read_embedded_status(fd);
    /* (Activation Key) */
    unsigned char act_key[] = { 0xA4, 0xC6, 0xF4, 0x8A };
    printf("Start ACTIVATION_KEY\n");
    if (write(fd, act_key, 4) != 4) { perror("Activation key failed"); return 1; }
    usleep(5000);
    read_embedded_status(fd);

    unsigned char lsc_programd[] = {mirror_byte(0x5E), 0x00, 0x00, 0x00};
    printf("Start PROGRAM DONE\n");
    if (write(fd, lsc_programd, 4) != 4) { perror("LSC programd failed"); return 1; }
    read_embedded_status(fd);

    unsigned char isc_disable[] = { mirror_byte(0x26), 0x00, 0x00, 0x00 };
    write(fd, isc_disable, 4);

    read_embedded_status(fd);

#if 0
    /* 2. Отправляем команду ISC_ENABLE (0xC6 0x00 0x00 0x00) с зеркалированием бит */
    unsigned char isc_enable[] = { mirror_byte(0xC6), 0x00, 0x00, 0x00 };
    if (write(fd, isc_enable, 4) != 4) { perror("ISC_ENABLE failed"); return 1; }
    usleep(10000);

    /* 3. Отправляем команду ISC_ERASE (0x0E 0x01 0x00 0x00) с зеркалированием бит */
    unsigned char isc_erase[] = { mirror_byte(0x0E), mirror_byte(0x01), 0x00, 0x00 };
    if (write(fd, isc_erase, 4) != 4) { perror("ISC_ERASE failed"); return 1; }
    printf("[USER_FLASH] Memory erasing... waiting 100ms\n");
    usleep(100000);
    
    // Смотрим статус сразу после очистки памяти ПЛИС
    read_embedded_status(fd, "AFTER_ERASE");

    /* 4. Отправляем команду начала записи LSC_BITSTREAM_BURST (0x7A 0x00 0x00 0x00) */
    unsigned char burst_cmd[] = { mirror_byte(0x7A), 0x00, 0x00, 0x00 };
    if (write(fd, burst_cmd, 4) != 4) { perror("Burst command failed"); return 1; }
    usleep(2000);

    /* 5. Читаем файл .bit, отрезаем текстовый заголовок Radiant (359 байт) и льем данные */
    //fseek(f_bit, 359, SEEK_SET);
    fseek(f_bit, 0, SEEK_SET);
    unsigned char block[4096];
    size_t read_bytes;
    size_t total_sent = 0;

    printf("[USER_FLASH] Streaming payload data directly into SCL/SDA wires...\n");
    while ((read_bytes = fread(block, 1, sizeof(block), f_bit)) > 0) {
        for (size_t i = 0; i < read_bytes; i++) {
            block[i] = mirror_byte(block[i]);
        }
        if (write(fd, block, read_bytes) != read_bytes) {
            perror("Write payload error");
            return 1;
        }
        total_sent += read_bytes;
    }
    printf("[USER_FLASH] Sent %zu bytes of bitstream.\n", total_sent);
    usleep(5000);

    read_embedded_status(fd, "BEFORE_ISC_DISABLE");
    
    /* 6. Добивка тактов заполнения (Padding) для очистки FIFO */
    unsigned char padding[1024];
    for(int i=0; i<1024; i++) padding[i] = 0xFF;
    write(fd, padding, 1024);

    /* 7. Команда финализации ISC_DISABLE (0x26 0x00 0x00 0x00) */
    unsigned char isc_disable[] = { mirror_byte(0x26), 0x00, 0x00, 0x00 };
    write(fd, isc_disable, 4);
    usleep(5000);

    /* 8. Мягкий перезапуск LSC_REFRESH (0x79 0x00 0x00 0x00) */
    unsigned char refresh[] = { mirror_byte(0x79), 0x00, 0x00, 0x00 };
    write(fd, refresh, 4);
    
    // Финальный статус после перезапуска
    read_embedded_status(fd, "FINAL_STAGE");

    printf("[USER_FLASH] Execution complete. Check the LED! Run i2ctransfer status now.\n");
    fclose(f_bit);
    close(fd);
    return 0;
#endif
}