Created
November 21, 2022 04:51
-
-
Save tzechienchu/4700f74d4c33cdfcee7265ecd5b92274 to your computer and use it in GitHub Desktop.
ICE40 Programming C Code for Raspberry Pi
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* IceZProg -- Programmer and Debug Tool for the IcoZero Board | |
* | |
* Copyright (C) 2017 Clifford Wolf <clifford@clifford.at> | |
* | |
* Permission to use, copy, modify, and/or distribute this software for any | |
* purpose with or without fee is hereby granted, provided that the above | |
* copyright notice and this permission notice appear in all copies. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
* | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <stdint.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <errno.h> | |
#include <wiringPi.h> | |
#define CFG_SS 26 // PIN 32, GPIO.26 | |
#define CFG_SCK 27 // PIN 36, GPIO.27 | |
#define CFG_SI 22 // PIN 31, GPIO.22 | |
#define CFG_SO 23 // PIN 33, GPIO.23 | |
#define CFG_RST 25 // PIN 37, GPIO.25 | |
#define CFG_DONE 21 // PIN 29, GPIO.21 | |
void spi_begin() | |
{ | |
digitalWrite(CFG_SS, LOW); | |
// fprintf(stderr, "SPI_BEGIN\n"); | |
} | |
void spi_end() | |
{ | |
digitalWrite(CFG_SS, HIGH); | |
// fprintf(stderr, "SPI_END\n"); | |
} | |
void uwait_barrier_sync(int n) | |
{ | |
int k; | |
for (k = 0; k < n; k++) | |
asm volatile("" : : : "memory"); | |
__sync_synchronize(); | |
} | |
uint32_t spi_xfer(uint32_t data, int nbits) | |
{ | |
uint32_t rdata = 0; | |
int i; | |
for (i = nbits-1; i >= 0; i--) | |
{ | |
uwait_barrier_sync(10); | |
digitalWrite(CFG_SO, (data & (1 << i)) ? HIGH : LOW); | |
uwait_barrier_sync(10); | |
if (digitalRead(CFG_SI) == HIGH) | |
rdata |= 1 << i; | |
uwait_barrier_sync(10); | |
digitalWrite(CFG_SCK, HIGH); | |
uwait_barrier_sync(10); | |
digitalWrite(CFG_SCK, LOW); | |
} | |
// fprintf(stderr, "SPI:%d %02x %02x\n", nbits, data, rdata); | |
return rdata; | |
} | |
void flash_power_up() | |
{ | |
spi_begin(); | |
spi_xfer(0xAB, 8); | |
spi_end(); | |
} | |
void flash_read_id() | |
{ | |
int i; | |
spi_begin(); | |
spi_xfer(0x9F, 8); | |
printf("Flash ID:"); | |
for (i = 1; i < 21; i++) | |
printf(" %02X", spi_xfer(0, 8)); | |
printf("\n"); | |
spi_end(); | |
} | |
void flash_write_enable() | |
{ | |
spi_begin(); | |
spi_xfer(0x06, 8); | |
spi_end(); | |
} | |
void flash_erase_64kB(int addr) | |
{ | |
spi_begin(); | |
spi_xfer(0xd8, 8); | |
spi_xfer(addr, 24); | |
spi_end(); | |
} | |
void flash_write(int addr, char *data, int n) | |
{ | |
spi_begin(); | |
spi_xfer(0x02, 8); | |
spi_xfer(addr, 24); | |
while (n--) | |
spi_xfer(*(data++), 8); | |
spi_end(); | |
} | |
void flash_read(int addr, char *data, int n) | |
{ | |
spi_begin(); | |
spi_xfer(0x03, 8); | |
spi_xfer(addr, 24); | |
while (n--) | |
*(data++) = spi_xfer(0, 8); | |
spi_end(); | |
} | |
void flash_wait() | |
{ | |
while (1) | |
{ | |
spi_begin(); | |
spi_xfer(0x05, 8); | |
int status = spi_xfer(0, 8); | |
spi_end(); | |
if ((status & 0x01) == 0) | |
break; | |
// fprintf(stderr, "[wait]"); | |
usleep(1000); | |
} | |
// fprintf(stderr, "[ok]\n"); | |
} | |
void flash_wrsector(int addr, char *data, int size) | |
{ | |
int i; | |
restart: | |
printf("Writing 0x%06x .. 0x%06x:", addr, addr+size-1); | |
fflush(stdout); | |
printf(" [erasing]"); | |
fflush(stdout); | |
flash_write_enable(); | |
flash_erase_64kB(addr); | |
flash_wait(); | |
if (size == 0) { | |
printf("\n"); | |
fflush(stdout); | |
return; | |
} | |
printf(" [writing"); | |
fflush(stdout); | |
for (i = 0; i < size; i += 256) | |
{ | |
if (i % 4096 == 0) { | |
printf("."); | |
fflush(stdout); | |
} | |
flash_write_enable(); | |
flash_write(addr+i, data+i, size-i < 256 ? size-i : 256); | |
flash_wait(); | |
} | |
printf("] [readback"); | |
fflush(stdout); | |
for (i = 0; i < size; i += 256) | |
{ | |
if (i % 4096 == 0) { | |
printf("."); | |
fflush(stdout); | |
} | |
char buffer[256]; | |
flash_read(addr+i, buffer, size-i < 256 ? size-i : 256); | |
if (memcmp(buffer, data+i, size-i < 256 ? size-i : 256)) { | |
printf("ERROR\n"); | |
fflush(stdout); | |
goto restart; | |
} | |
} | |
printf("]\n"); | |
fflush(stdout); | |
} | |
int main(int argc, char **argv) | |
{ | |
if (argc != 2 || (argv[1][0] == '-' && argv[1][1]) || !argv[1][0]) { | |
printf("Usage: %s <binfile> ... program <binfile> to IceZero flash\n", argv[0]); | |
printf(" %s - ... program stdin to IceZero flash\n", argv[0]); | |
printf(" %s . ... erase first sector of IceZero flash\n", argv[0]); | |
printf(" %s .. ... just restart the FPGA\n", argv[0]); | |
return 1; | |
} | |
wiringPiSetup(); | |
pinMode(CFG_SS, OUTPUT); | |
pinMode(CFG_SCK, OUTPUT); | |
pinMode(CFG_SI, INPUT); | |
pinMode(CFG_SO, OUTPUT); | |
pinMode(CFG_RST, OUTPUT); | |
pinMode(CFG_DONE, INPUT); | |
digitalWrite(CFG_SS, HIGH); | |
digitalWrite(CFG_SCK, LOW); | |
digitalWrite(CFG_SO, LOW); | |
digitalWrite(CFG_RST, LOW); | |
if (strcmp(argv[1], "..")) | |
{ | |
flash_power_up(); | |
flash_read_id(); | |
} | |
if (!strcmp(argv[1], ".")) | |
{ | |
char buffer[1024]; | |
int i; | |
for (i = 0; i < (int)sizeof(buffer); i++) | |
buffer[i] = 0xff; | |
flash_wrsector(0, buffer, sizeof(buffer)); | |
} | |
else | |
if (strcmp(argv[1], "..")) | |
{ | |
int addr = 0, size = 0; | |
char buffer[64*1024]; | |
FILE *f = strcmp(argv[1], "-") ? fopen(argv[1], "rb") : stdin; | |
if (f == NULL) { | |
printf("Failed to open %s: %s\n", argv[1], strerror(errno)); | |
return 1; | |
} | |
do { | |
addr += size; | |
size = 0; | |
while (size < (int)sizeof(buffer)) { | |
int rc = fread(buffer+size, 1, sizeof(buffer)-size, f); | |
if (rc <= 0) break; | |
size += rc; | |
} | |
if (size > 0) | |
flash_wrsector(addr, buffer, size); | |
} while (size == sizeof(buffer)); | |
} | |
digitalWrite(CFG_RST, LOW); | |
usleep(2000); | |
digitalWrite(CFG_RST, HIGH); | |
usleep(500000); | |
if (digitalRead(CFG_DONE) != HIGH) { | |
printf("Warning: cdone is low\n"); | |
return 1; | |
} | |
printf("DONE.\n"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment