Skip to content

Instantly share code, notes, and snippets.

@MarsTechHAN
Last active October 21, 2024 15:23
Show Gist options
  • Save MarsTechHAN/caf6bdf7b8356d9e55dd9aa929739b96 to your computer and use it in GitHub Desktop.
Save MarsTechHAN/caf6bdf7b8356d9e55dd9aa929739b96 to your computer and use it in GitHub Desktop.
Program Gowin from ESP32
import struct
import sys
if __name__ == '__main__':
fs = open(sys.argv[1], 'rb')
with open('fs.c', 'w+') as f:
print('const unsigned char fs_bitstream[] __attribute__((aligned(128))) ={', file=f)
counter = 0
while 1:
counter = counter + 1
fs_byte = fs.read(2)
if not fs_byte:
break
struct.unpack('>H', fs_byte)
print(', '.join([str(i) for i in fs_byte]) + ', ',end='', file=f)
if counter % 8 == 0:
print(file=f)
print(file=f)
print('};', file=f)
#include "fs.c" //fs_bitstream
#define TMS_SET digitalWrite(TMS_PIN, HIGH)
#define TMS_RESET digitalWrite(TMS_PIN, LOW)
#define TCK_SET digitalWrite(TCK_PIN, HIGH)
#define TCK_RESET digitalWrite(TCK_PIN, LOW)
#define TDI_SET digitalWrite(TDI_PIN, HIGH)
#define TDI_RESET digitalWrite(TDI_PIN, LOW)
#define TDO_VALUE digitalRead(TDO_PIN)
const uint8_t TCK_PIN = 22;
const uint8_t TDI_PIN = 19;
const uint8_t TDO_PIN = 23;
const uint8_t TMS_PIN = 33;
const uint8_t DELAY_LEN = 3;
const uint32_t BUFFER_SIZE = 0xff;
const uint32_t ID_GW1N9 = 0x1100581B;
typedef enum{
TAP_RESET,
TAP_IDLE,
TAP_DRSELECT,
TAP_DRCAPTURE,
TAP_DRSHIFT,
TAP_DREXIT1,
TAP_DRPAUSE,
TAP_DREXIT2,
TAP_DRUPDATE,
TAP_IRSELECT,
TAP_IRCAPTURE,
TAP_IRSHIFT,
TAP_IREXIT1,
TAP_IRPAUSE,
TAP_IREXIT2,
TAP_IRUPDATE,
TAP_UNKNOWN
} TAP_TypeDef;
typedef enum{
ISC_NOOP = 0x02,
ISC_ERASE = 0x05,
ERASE_DONE = 0x09,
READ_ID_CODE = 0x11,
ISC_ENABLE = 0x15,
FAST_PROGRAM = 0x17,
STATUS_CODE = 0x41,
JTAG_EF_PROGRAM = 0x71,
JTAG_EF_READ = 0x73,
JTAG_EF_ERASE = 0x75,
ISC_DISABLE = 0x3A,
REPROGRAM = 0x3C,
Bypass = 0xFF
} GWFPGA_Inst_Def;
typedef enum{
STATUS_CRC_ERROR = (1<<0),
STATUS_BAD_COMMAND = (1<<1),
STATUS_ID_VERIFY_FAILED = (1<<2),
STATUS_TIMEOUT = (1<<3),
STATUS_MEMORY_ERASE = (1<<5),
STATUS_PREAMBLE = (1<<6),
STATUS_SYSTEM_EDIT_MODE = (1<<7),
STATUS_PRG_SPIFLASH_DIRECT = (1<<8),
STATUS_NON_JTAG_CNF_ACTIVE = (1<<10),
STATUS_BYPASS = (1<<11),
STATUS_GOWIN_VLD = (1<<12),
STATUS_DONE_FINAL = (1<<13),
STATUS_SECURITY_FINAL = (1<<14),
STATUS_READY = (1<<15),
STATUS_POR = (1<<16),
STATUS_FLASH_LOCK = (1<<17)
} GWFPGA_StatusReg_Def;
void JTAG_Io_Init(){
pinMode(TCK_PIN, OUTPUT);
pinMode(TDI_PIN, OUTPUT);
pinMode(TMS_PIN, OUTPUT);
pinMode(TDO_PIN, INPUT);
}
void JTAG_TapMove_OneClock(uint8_t tms_value)
{
if(tms_value){
TMS_SET;
}else{
TMS_RESET;
}
TCK_RESET;
TCK_SET;
}
void JTAG_MoveTap(TAP_TypeDef TAP_From, TAP_TypeDef TAP_To)
{
if ((TAP_From == TAP_UNKNOWN) && (TAP_To==TAP_IDLE) )
{
JTAG_TapMove_OneClock(1);
JTAG_TapMove_OneClock(1);
JTAG_TapMove_OneClock(1);
JTAG_TapMove_OneClock(1);
JTAG_TapMove_OneClock(1);
JTAG_TapMove_OneClock(1);
JTAG_TapMove_OneClock(1);
JTAG_TapMove_OneClock(1);
JTAG_TapMove_OneClock(0);
JTAG_TapMove_OneClock(0);
}
else if ((TAP_From == TAP_IDLE) && (TAP_To==TAP_IDLE) )
{
JTAG_TapMove_OneClock(0);
JTAG_TapMove_OneClock(0);
JTAG_TapMove_OneClock(0);
}
else if ((TAP_From == TAP_IDLE) && (TAP_To==TAP_IRSHIFT) )
{
JTAG_TapMove_OneClock(1);
JTAG_TapMove_OneClock(1);
JTAG_TapMove_OneClock(0);
JTAG_TapMove_OneClock(0);
}
else if ((TAP_From == TAP_IDLE) && (TAP_To==TAP_DRSHIFT) )
{
JTAG_TapMove_OneClock(1);
JTAG_TapMove_OneClock(0);
JTAG_TapMove_OneClock(0);
}
else if ((TAP_From == TAP_IREXIT1) && (TAP_To==TAP_IDLE) )
{
JTAG_TapMove_OneClock(1);
JTAG_TapMove_OneClock(0);
JTAG_TapMove_OneClock(0);
}
else if ((TAP_From == TAP_DREXIT1) && (TAP_To==TAP_IDLE) )
{
JTAG_TapMove_OneClock(1);
JTAG_TapMove_OneClock(0);
JTAG_TapMove_OneClock(0);
}
else
{
Serial.printf("error tap walking.");
}
}
uint8_t JTAG_Write(uint8_t din, uint8_t dout, uint8_t tms, bool LSB)
{
uint8_t tmp = 0;
uint8_t dout_new = 0;
if (LSB==false)
{
uint8_t _tmp_din=0;
uint8_t sign = 1;
for (uint8_t i=0;i<=7;i++)
{
_tmp_din |=((din&(sign<<i))>>i)<<(7-i);
}
din = _tmp_din;
}
TMS_RESET;
for (uint8_t i=0; i<8; i++) // LSB
{
if (i == 7){
if((tms & 1) == 1)
TMS_SET;
}
tmp = din>>i ;
if((1&tmp) == 0)
TDI_RESET;
else
TDI_SET;
TCK_RESET;
TCK_SET;
dout_new <<= 1;
dout_new |= (TDO_VALUE & 1);
}
return dout_new;
}
void JTAG_WriteInst(uint8_t inst)
{
JTAG_MoveTap(TAP_IDLE, TAP_IRSHIFT);
JTAG_Write(inst, 0x0, 0x1,true);
JTAG_MoveTap(TAP_IREXIT1, TAP_IDLE);
JTAG_MoveTap(TAP_IDLE, TAP_IDLE);
JTAG_MoveTap(TAP_IDLE, TAP_IDLE);
JTAG_MoveTap(TAP_IDLE, TAP_IDLE);
}
void JTAG_RunTest(uint8_t cycles)
{
for (uint8_t i=0; i<cycles; i++)
{
JTAG_TapMove_OneClock(0);
}
}
uint32_t JTAG_ReadCode()
{
uint32_t out=0;
JTAG_WriteInst(READ_ID_CODE);
JTAG_MoveTap(TAP_IDLE, TAP_DRSHIFT);
TMS_RESET;
for (uint8_t i=0; i<32; i++)
{
if (i == 31) TMS_SET;
TCK_RESET;
TCK_SET;
out |= (TDO_VALUE) ? (1 << i) : 0;
};
JTAG_MoveTap(TAP_DREXIT1, TAP_IDLE);
return out;
}
uint32_t JTAG_ReadStatus()
{
uint32_t out=0;
JTAG_WriteInst(STATUS_CODE);
JTAG_MoveTap(TAP_IDLE, TAP_DRSHIFT);
TMS_RESET;
for (uint8_t i=0; i<32; i++)
{
if (i == 31) TMS_SET;
TCK_RESET;
TCK_SET;
out |= (TDO_VALUE) ? (1 << i) : 0;
};
JTAG_MoveTap(TAP_DREXIT1, TAP_IDLE);
return out;
}
void displayReadReg(uint32_t dev)
{
Serial.printf("STATUS_REG: %08x\n", dev);
if (dev & STATUS_CRC_ERROR)
Serial.printf("\tCRC Error\n");
if (dev & STATUS_BAD_COMMAND)
Serial.printf("\tBad Command\n");
if (dev & STATUS_ID_VERIFY_FAILED)
Serial.printf("\tID Verify Failed\n");
if (dev & STATUS_TIMEOUT)
Serial.printf("\tTimeout\n");
if (dev & STATUS_MEMORY_ERASE)
Serial.printf("\tMemory Erase\n");
if (dev & STATUS_PREAMBLE)
Serial.printf("\tPreamble\n");
if (dev & STATUS_SYSTEM_EDIT_MODE)
Serial.printf("\tSystem Edit Mode\n");
if (dev & STATUS_PRG_SPIFLASH_DIRECT)
Serial.printf("\tProgram spi flash directly\n");
if (dev & STATUS_NON_JTAG_CNF_ACTIVE)
Serial.printf("\tNon-jtag is active\n");
if (dev & STATUS_BYPASS)
Serial.printf("\tBypass\n");
if (dev & STATUS_GOWIN_VLD)
Serial.printf("\tGowin VLD\n");
if (dev & STATUS_DONE_FINAL)
Serial.printf("\tDone Final\n");
if (dev & STATUS_SECURITY_FINAL)
Serial.printf("\tSecurity Final\n");
if (dev & STATUS_READY)
Serial.printf("\tReady\n");
if (dev & STATUS_POR)
Serial.printf("\tPOR\n");
if (dev & STATUS_FLASH_LOCK)
Serial.printf("\tFlash Lock\n");
}
void setup() {
Serial.begin(115200);
Serial.println("Starting JTAG Chain...");
uint32_t debug_timming = millis();
JTAG_Io_Init();
Serial.println("---------------------------");
Serial.println("Reading IDCODE...");
uint32_t ID_CODE = JTAG_ReadCode();
Serial.printf("IDCODE: 0x%X\n", ID_CODE);
Serial.println("---------------------------");
Serial.println("Reading Status Reg...");
uint32_t STATUS_REG = JTAG_ReadStatus();
displayReadReg(STATUS_REG);
Serial.println("---------------------------");
Serial.println("Starting Writing to SRAM...");
JTAG_WriteInst(ISC_ENABLE);
JTAG_WriteInst(ISC_ERASE);
JTAG_WriteInst(ISC_NOOP);
uint32_t erase_time = millis();
while(millis() - erase_time < 4){ //TN653
TCK_RESET;
TCK_SET;
}
JTAG_WriteInst(ERASE_DONE);
JTAG_WriteInst(ISC_NOOP);
JTAG_WriteInst(ISC_DISABLE);
JTAG_WriteInst(ISC_NOOP);
erase_time = millis();
while(millis() - erase_time < 4){
TCK_RESET;
TCK_SET;
}
JTAG_WriteInst(ISC_ENABLE);
JTAG_WriteInst(FAST_PROGRAM);
JTAG_MoveTap(TAP_IDLE, TAP_DRSHIFT);
uint8_t tx_end = 0;
for (uint32_t i=0; i < sizeof(fs_bitstream); i+=1) {
if (i == sizeof(fs_bitstream) - 1)
tx_end = 1; // to move in EXIT1_DR
JTAG_Write(fs_bitstream[i], 0x00, tx_end, 0x00);
}
JTAG_MoveTap(TAP_DREXIT1, TAP_IDLE);
JTAG_WriteInst(ISC_DISABLE);
JTAG_WriteInst(ISC_NOOP);
Serial.println("SRAM Prog Finish...");
Serial.println("---------------------------");
Serial.println("Waiting for DONE...");
while(!(JTAG_ReadStatus() & STATUS_DONE_FINAL))
delay(1);
Serial.println("Done!");
Serial.println("---------------------------");
Serial.printf("Total Time: %ums", (millis() - debug_timming));
}
void loop() {
}
#From @ciniml https://gist.github.com/ciniml/e02f4cc9b00f30d950cd2a787a1ea8d3
import sys
input_path = sys.argv[1]
output_path = sys.argv[1].replace('.fs', '.bin')
with open(input_path, 'r') as input_file:
with open(output_path, 'wb') as output_file:
for line in iter(input_file.readline, ''): #type: str
line = line.strip()
if line.startswith('//'):
continue
buffer = bytearray(1)
for byte_index in range(0, len(line), 8):
value = 0
for bit_index in range(8):
bit = line[byte_index + bit_index]
value = (value << 1) | (1 if bit == '1' else 0)
buffer[0] = value
output_file.write(buffer)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment