Skip to content

Instantly share code, notes, and snippets.

@f-steff
Created December 3, 2021 12:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save f-steff/10eafce95f5d45852bdfe98a23144f8f to your computer and use it in GitHub Desktop.
Save f-steff/10eafce95f5d45852bdfe98a23144f8f to your computer and use it in GitHub Desktop.
UrJTAG with IRMCK343 on Raspberry Pi

URJTAG for IRMCK343 on Raspberry Pi

Step by step configuration to setup a blank RPi, and get OTP reading working. OTP writing unfortunately does not work.

Getting started

  1. I used an RPi3 - any RPi would do.
  2. Installet RaspberryOS Lite on SD card- Change hostname and enable SSH by pressing CTRL-Shift-X in RPI Imager
  3. Configure Wifi by createing wpa_supplicant.conf using https://codepen.io/LilTrublMakr/full/yRGPrv/, then copy it to the SD card.
  4. SSH into the RPi over Wifi (See IP on console output - I got 10.0.1.83) using pi/raspberry
  5. Use passwd to change password.
  6. Manual configuration: sudo raspi-config
  7. reboot
  8. Install all the tools listed below

Install essintial dev-tools

$ sudo apt-get update && sudo apt-get upgrade
$ sudo apt-get install git git-core autoconf build-essential libtool
$ sudo apt-get install libreadline-gplv2-dev libncursesw5-dev libssl-dev libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev

Setup python for development

$ sudo apt-get  install python-dev python3-distutils python3-pip
$ sudo pip install pathlib
$ sudo pip install hexrec

URJTAG get and make

$ git clone git://git.code.sf.net/p/urjtag/git urjtag
$ cd urjtag/urjtag/
$ sudo apt-get install autopoint bison flex python2.7-dev python3-dev
$ ./autogen.sh 
$ ./configure
$ make
$ sudo make install
$ sudo ldconfig

Test UrJTAG by first configuring the GPIO's and then execute the jtag command as below.

Ensure GPIO's are exported and the the GPIO that controlls the high Vpp voltage for OTP programming is off.

$ ls /sys/class/gpio
$ echo 8 > /sys/class/gpio/export
$ echo 18 > /sys/class/gpio/export
$ echo 23 > /sys/class/gpio/export
$ echo 24 > /sys/class/gpio/export
$ echo 25 > /sys/class/gpio/export
$ echo out > /sys/class/gpio/gpio8/direction
$ echo 0 > /sys/class/gpio/gpio8/value

Quick test of GPIO

$ cat /sys/class/gpio/gpio14/direction
in
$ cat /sys/class/gpio/gpio14/value
0
$ echo out >/sys/class/gpio/gpio14/direction
$ cat /sys/class/gpio/gpio14/direction
out
$ cat /sys/class/gpio/gpio14/value
0
$ echo 1 > /sys/class/gpio/gpio14/value
$ echo 0 > /sys/class/gpio/gpio14/value
$ echo in >/sys/class/gpio/gpio14/direction

UrJTAG irmck343 test

Unfortunately the irmck343 does not respond properly to a device scan, so the device file have to be included manually. However the device then have a READID register that can be read.

$ sudo jtag
jtag> cable gpio tms=18 tdi=23 tdo=24 tck=25
jtag> detect
IR length: 8
Chain length: 1
Device Id: not supported (bit 0 was not a 1)
jtag> include /home/pi/urjtag/urjtag/data/infineon/IRMCF343/irmck343
jtag> instruction READID
jtag> shift ir
jtag> shift DR
jtag> dr
01000010 (0x42)

UrJTAG startup scripted

For unknown reasons, Urjtag requires the GPIO's to be exported at startup, and then sometimes after use they are unexported. To fix this, I wrapped the startup in a script:

 $ ./start.sh                       
 UrJTAG 2021.03 #3d3a9b45
 Copyright (C) 2002, 2003 ETC s.r.o.
 Copyright (C) 2007, 2008, 2009 Kolja Waschk and the respective authors
 
 UrJTAG is free software, covered by the GNU General Public License, and you are
 welcome to change it and/or distribute copies of it under certain conditions.
 There is absolutely no warranty for UrJTAG.
 
 warning: UrJTAG may damage your hardware!
 Type "quit" to exit, "help" for help.

To be even more lazy, I wrapped the cable setup etc. in an include file:

 jtag> include ./start
 Initializing GPIO JTAG Chain
 IR length: 8
 Chain length: 1
 Device Id: not supported (bit 0 was not a 1)
 01000010 (0x42)

Finally I created an include file to test reading from the OTP, which can be executed by using include ./test_read

Unfortunately I quickly found out that I needed a bus-driver to do anything usefull (like easy reading from the OTP, and controlling the Vpp and TCK while programming), and that required understanding a lot of things in urjtag in order to create a custom TAP driver. Python to the rescue...

URJTAG from python

Also here, for unknown reasons, Urjtag requires the GPIO's to be exported before use. However, this time I fixed in in the python file, sp simply execute ./test.py to get started. Complete readout of the otp in the irmck343 is implemented (although it's not possible to determen if the read operation was properly unlocked, or if the read data is scrambled.

A test mode to try to write back to the irmck343 is also implemented, but it does not to work. At least these reasons for this are plausable, but the exact reason is still unknown:

  • The timing requirements of the TCK sufficient the hacked way I did it.
  • The timing of the Vpp voltage may not be sufficient the hacked way I did it.
  • The exact application of Vpp may be entirely wrong, but unfortunately it's not properly documented.

A proper TAP/bus-driver may be needed to be implemented in Urjtag for better control of TCK and Vpp signals. The test mode output looks like this (Chip detection isn't done, so if the irmck343 isn't powered, all data are zero!):

$ cd ~/urjtag/urjtag
$ sudo ./test.py
Executing test.py
READID: 0x42  (Should be 0x42)

Otp unlocked!

Reading 10 bytes from otp

irmck343_read_otp_to_memory executed in 0.004762172698974609 seconds

Read: 0x0000: 0x02
Read: 0x0001: 0x4C
Read: 0x0002: 0xEC
Read: 0x0003: 0x7C
Read: 0x0004: 0x00
Read: 0x0005: 0x7D
Read: 0x0006: 0x01
Read: 0x0007: 0x7E
Read: 0x0008: 0x01
Read: 0x0009: 0x7F
Reading done

Modify one value.
Memory: 0x0000: 0x02 - Zeroed!

Attempt Burn with modified data!!
Burn: 0x0000: 0x00
Burn: 0x0001: 0x4C
Burn: 0x0002: 0xEC
Burn: 0x0003: 0x7C
Burn: 0x0004: 0x00
Burn: 0x0005: 0x7D
Burn: 0x0006: 0x01
Burn: 0x0007: 0x7E
Burn: 0x0008: 0x01
Burn: 0x0009: 0x7F
Burn done!!

READID: 0x00  (Should be 0x42)

Otp unlocked!

Reading 10 bytes from otp

irmck343_read_otp_to_memory executed in 0.0030870437622070312 seconds

Re-Read: 0x0000: 0x02
Re-Read: 0x0001: 0x4C
Re-Read: 0x0002: 0xEC
Re-Read: 0x0003: 0x7C
Re-Read: 0x0004: 0x00
Re-Read: 0x0005: 0x7D
Re-Read: 0x0006: 0x01
Re-Read: 0x0007: 0x7E
Re-Read: 0x0008: 0x01
Re-Read: 0x0009: 0x7F
Reading done

Links

Create folders and copy files from this gist to the Raspberry Pi (using scp):

  • copy PARTS to /home/pi/urjtag/urjtag/data/infineon/
  • copy irmck343 to /home/pi/urjtag/urjtag/data/infineon/IRMCF343/
  • copy STEPPINGS to /home/pi/urjtag/urjtag/data/infineon/IRMCF343/
  • copy start to /home/pi/urjtag/urjtag/
  • copy start.sh to /home/pi/urjtag/urjtag/

Make sure the scripts are executeable:

$ cd ~/urjtag/urjtag
$ chmod u+x start.sh
$ chmod u+x test.py

Happy hacking! Flemming fsteff@gmail.com, December 2021.

#
# $Id$
#
# JTAG declarations for International Rectifier/Infineon IRMCF343
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
#
# Written by Flemming Steffensen <fsteff@gmail.com>, 2021.
#
#
# Register list
register IR 8 # Instruction register
register DR 16 # Data Register
# Indirect registers
register OTP_Setup 8 # The OTP programmming configuration register
register OTP_Timer 8 # Number of TCK clocks X 64 to write one byte of data.
register OTP_Address 16 # The current address of OTP that data will be burned to.
register OTP_Data 8 # The data byte that will be burned to OTO
register Test_Mode 16 # Defines what mode the test interface is in (OTP Burn-in)
register OTP_Counter 16 # The OTP burned bytes counter
instruction length 8
instruction READID 00000000 OTP_Data # 0x00 Read JTAG TAP controller ID
# Write values
instruction wOTPSETUP 01010000 OTP_Setup # 0x50 Write contents of DR to OTP_Setup[7:0]
instruction wADDRESS 01010001 OTP_Address # 0x51 Write contents of DR to OTP_Address[15:0]
instruction wDATA 01010010 OTP_Data # 0x52 Write contents of DR to OTP_Data[7:0]
instruction wTIMER 01010100 OTP_Timer # 0x54 Write contents of DR to OTP_Timer[7:0]
# Read values
instruction rOTPSETUP 01100000 OTP_Setup # 0x60 Read OTP_Setup[7:0] to DR
instruction rADDRESS 01100001 OTP_Address # 0x61 Read OTP_JTAG_Address[15:0] to DR
instruction rDATA 01100010 OTP_Data # 0x62 Read OTP_Data[7:0] to DR
instruction rTIMER 01100011 OTP_Timer # 0x63 Read OTP_Wr_Timer[7:0] to DR
instruction rWR_COUNTER 01100110 OTP_Counter # 0x64 Read OTP_Wr_Counter[15:0] to DR
instruction wTESTMODE 01110000 Test_Mode # 0x70 Write contents of DR Test_Modes[15:0]
# Set options
instruction sAUTOINCR_BURN 01110001 IR # 0x71 Enable auto-increment burn mode for OTP programming (see below)
instruction sAUTOINCR_READ 01110010 IR # 0x72 Enable auto-increment read mode for OTP verification
# Select modes
instruction ENTERTEST 11110101 IR # 0xF5 Enter the ‘test mode’ for OTP memory access
instruction EXITTEST 11110110 IR # 0xF6 Exit the ‘test mode’ and return to standard 8051 JTAG interface
# endian little
#
# $Id$
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
#
# Written by Flemming Steffensen <fsteff@gmail.com>, 2021.
#
# Documentation:
# [1] International Rectifier, "IRMCx300 Software Developer's Guide.pdf"
# , "User Guide #0610 V1.2"
#
# bits 27-12 of the Device Identification Register
0000000000000000 irmck343 IRMCK343 # see section 6 [1] Unfortunately no identity is defined.
cable gpio tms=18 tdi=23 tdo=24 tck=25
detect
include /home/pi/urjtag/urjtag/data/infineon/IRMCF343/irmck343
instruction READID
shift ir
shift DR
dr
#!/bin/bash
# Cleanup (as some of these gpio's sometimes dissapear)
echo 8 > /sys/class/gpio/unexport
echo 18 > /sys/class/gpio/unexport
echo 23 > /sys/class/gpio/unexport
echo 24 > /sys/class/gpio/unexport
echo 25 > /sys/class/gpio/unexport
# Setup pins (again?)
echo 8 > /sys/class/gpio/export
echo 18 > /sys/class/gpio/export
echo 23 > /sys/class/gpio/export
echo 24 > /sys/class/gpio/export
echo 25 > /sys/class/gpio/export
# Ensure High voltage pin is low! Sleeps are required!
sleep 0.2
echo out > /sys/class/gpio/gpio8/direction
sleep 0.2
echo 0 > /sys/class/gpio/gpio8/value
# Execute UrJTAG
jtag
#
# $Id: STEPPINGS
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
#
#
# bits 31-28 of the Device Identification Register
0000 irmck343 0
#!/usr/bin/env python3
from pathlib import Path
import struct
import hexrec.records as hr
import urjtag
import time
import RPi.GPIO as GPIO # Need to use sysfs handle to satisfy urjtag and RPi.GPIO for direct control.
sleep_us = lambda x: time.sleep(x/1000000.0) # This is faster than calling clibs's usleep() from python.
# JTAG gpio pins.
tms = 18
tdi = 23
tdo = 24
tck = 25
vpp = 8 # Special 6.75 volt OTP programming voltage.
# urjtag.loglevel( urjtag.URJ_LOG_LEVEL_ALL )
urjtag.loglevel( urjtag.URJ_LOG_LEVEL_WARNING )
# urjtag.loglevel( urjtag.URJ_LOG_LEVEL_SILENT )
# Global
urc = urjtag.chain()
memory = hr.Memory() #
def print_execution_time(func):
'''Decorator that reports the execution time.'''
def wrap(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f'{func.__name__} executed in {end-start} seconds\n')
return result
return wrap
def jtag_define_part_irmck343():
urc.addpart(8) # Instruction length for the IR instructions.
# Registers
urc.add_register("IR", 8)
urc.add_register("DR", 16)
urc.add_register("OTP_Setup", 8)
urc.add_register("OTP_Timer", 8)
urc.add_register("OTP_Address", 16)
urc.add_register("OTP_Data", 8)
urc.add_register("Test_Mode", 16)
urc.add_register("OTP_Counter", 16)
# Instructions
urc.add_instruction("READID", "00000000", "OTP_Data" ) # 0x00 Read JTAG TAP controller ID
urc.add_instruction("wOTPSETUP", "01010000", "OTP_Setup" ) # 0x50 Write contents of DR to OTP_Setup[7:0]
urc.add_instruction("rOTPSETUP", "01100000", "OTP_Setup" ) # 0x60 Read OTP_Setup[7:0] to DR
urc.add_instruction("wADDRESS", "01010001", "OTP_Address") # 0x51 Write contents of DR to OTP_Address[15:0]
urc.add_instruction("rADDRESS", "01100001", "OTP_Address") # 0x61 Read OTP_JTAG_Address[15:0] to DR
urc.add_instruction("wDATA", "01010010", "OTP_Data" ) # 0x52 Write contents of DR to OTP_Data[7:0]
urc.add_instruction("rDATA", "01100010", "OTP_Data" ) # 0x62 Read OTP_Data[7:0] to DR
urc.add_instruction("wTIMER", "01010100", "OTP_Timer" ) # 0x54 Write contents of DR to OTP_Timer[7:0]
urc.add_instruction("rTIMER", "01100011", "OTP_Timer" ) # 0x63 Read OTP_Wr_Timer[7:0] to DR
urc.add_instruction("rWR_COUNTER", "01100110", "OTP_Counter") # 0x64 Read OTP_Wr_Counter[15:0] to DR
urc.add_instruction("wTESTMODE", "01110000", "Test_Mode" ) # 0x70 Write contents of DR Test_Modes[15:0]
urc.add_instruction("sAUTOINCR_BURN", "01110001", "OTP_Data" ) # 0x71 Enable auto-increment burn mode for OTP programming (see below)
urc.add_instruction("sAUTOINCR_READ", "01110010", "OTP_Data" ) # 0x72 Enable auto-increment read mode for OTP verification
urc.add_instruction("ENTERTEST", "11110101", "IR" ) # 0xF5 Enter the ‘test mode’ for OTP memory access
urc.add_instruction("EXITTEST", "11110110", "IR" ) # 0xF6 Exit the ‘test mode’ and return to standard 8051 JTAG interface
def jtag_irmck343_readid():
urc.set_instruction("READID")
urc.shift_ir()
urc.shift_dr()
return urc.get_dr_out()
def jtag_irmck343_set_otp_setup(val):
# Val bit pattern:
# 000xxxxx : Number of addresses to avance in auto-increment modes. (# to advance = 2^ OTP_Setup[7:5] )
# xxx0xxxx : Skip OTP_Addr[5:4]:0000 in auto-increment mode
# xxxx0xxx : OTP Output Enable Bit. 1: Enables OTP memory read access
# xxxxx000 : Program Test Mode. 000 = Read OTP. 010 = 1x Normal Programming. 011 = 4x Accelerated Programming
urc.set_instruction("wOTPSETUP") # Write 0x50 to IR then val to DR - Set OTP_Setup to val
urc.set_dr_in(val)
urc.shift_ir()
urc.shift_dr()
def jtag_irmck343_otp_read_mode():
jtag_irmck343_set_otp_setup(0x00) # Read mode.
def jtag_irmck343_otp_program_mode():
jtag_irmck343_set_otp_setup(0x0a) # Normal programming mode.
def jtag_irmck343_set_timer():
urc.set_instruction("wTIMER") # Write 0x54 to IR then 0x07 to DR - Set OTP_Wr_Timer to 0x07
urc.set_dr_in(0x07) # Hardcoded value, to match the extended DR used for programming.
urc.shift_ir()
urc.shift_dr()
def jtag_irmck343_set_address(address):
urc.set_instruction("wADDRESS") # Write 0x51 to IR then 0xFFFF to DR - Set OTP_Address to 0xFFFF
urc.set_dr_in(address)
urc.shift_ir()
urc.shift_dr()
def jtag_irmck343_use_tck():
urc.set_instruction("wTESTMODE") # Write 0x70 to IR then 0x0002 to DR - Set TCK to main system clock
urc.set_dr_in(0x0002)
urc.shift_ir()
urc.shift_dr()
def jtag_irmck343_set_auto_write_increment():
urc.set_instruction("sAUTOINCR_BURN") # Write 0x71 to IR - Enable auto-increment OTP write
urc.shift_ir()
def jtag_irmck343_set_auto_read_increment():
urc.set_instruction("sAUTOINCR_READ") # Write 0x72 to IR - Italic steps disable OTP read protection
urc.shift_ir()
urc.shift_dr()
def jtag_irmck343_entertest():
urc.set_instruction("ENTERTEST") # Write 0xF5 to IR - Enter test mode
urc.shift_ir()
def jtag_irmck343_exittest():
urc.set_instruction("EXITTEST") # Write 0xF6 to IR - Exit test mode
urc.shift_ir()
def jtag_irmck343_read_data():
# Unsure if this function actually works!
urc.set_instruction("rDATA") # Write 0x62 to IR - Read current address
urc.shift_ir()
urc.shift_dr()
return urc.get_dr_out()
def jtag_irmck343_read_increment_data():
urc.shift_dr()
return urc.get_dr_out()
def jtag_irmck343_write_increment_data(data):
urc.set_dr_in(data)
urc.shift_dr()
# sleep_us is too impricise for this timing. :-(
# !!!!!64x!!!!!!!
# Page 46: Number of TCK clocks X 64 to write one byte of data
for a in range((64 * 7)+1): # Then Toggle TCK - number of pulses according to Wr_Timer * 64
GPIO.output(tck, 1)
GPIO.output(tck, 0)
GPIO.output(tck, 0)
GPIO.output(tck, 0)
GPIO.output(tck, 0)
def gpio_pin_export(pin):
try:
sysfs_handle = open('/sys/class/gpio/export', 'w', 2)
sysfs_handle.write(str(pin))
# print(f"GPIO {pin} EXPORTED")
except:
print(f" Error: Can't open gpio {pin} for export. Something went wrong. Are you root?")
exit(1)
def gpio_pin_direction(pin, direction='in'):
if direction != 'in':
direction = 'out'
try:
sysfs_handle = open(f'/sys/class/gpio/gpio{pin}/direction', 'w')
sysfs_handle.write("out")
# print(f'GPIO pin {pin} set as {direction}put')
except:
print(f" Error: Can't open gpio {pin} for direction change. Something went wrong. Are you root?")
exit(1)
def gpio_pin_state(pin, state=0):
if state != 0:
state = 1
try:
sysfs_handle = open(f'/sys/class/gpio/gpio{pin}/value', 'w')
sysfs_handle.write(str(state))
# print(f'GPIO pin {pin} set to {state}')
except:
print(f" Error: Can't open gpio {pin} to change state. Something went wrong. Are you root?")
exit(1)
def gpio_sysfs_defaults(*pins):
for pin in pins:
gpio_pin_export(pin)
gpio_pin_direction(pin, 'in') # Default to safe inputs.
def gpio_rpi_defaults(*pins):
GPIO.setmode(GPIO.BCM) # Use pin names, such as GPIO8
GPIO.setwarnings(False)
for pin in pins:
GPIO.setup(pin, GPIO.OUT)
GPIO.output(pin, 0) # Must be written to early, to speed up access to the pin later.
def irmck343_unlock_otp():
# Unlock OTP and disable data scrambling.
jtag_irmck343_otp_read_mode() # Cmd 0x50
jtag_irmck343_set_address(0xffff) # Cmd 0x51
jtag_irmck343_set_auto_read_increment() # Cmd 0x72 - This and the following read will disable data scrampling during read.
data = jtag_irmck343_read_increment_data()
# print(f'protection: 0x{data:02X} ???')
# The value of address 0xFFFF must be 0xFF to descramble correctly,
# ...but the actual value read appear to be un-readable when directly addressed.
# When read out using incremental reading, the value is available!
print(f"Otp unlocked!\n")
@print_execution_time
def irmck343_read_otp_to_memory(start_address, byte_count):
# Read OTP into memory
jtag_irmck343_set_address(start_address) # Cmd 0x51
jtag_irmck343_set_auto_read_increment() # Cmd 0x72
for x in range(byte_count):
data = jtag_irmck343_read_increment_data()
# print(f'READ: 0x{data:02X}')
memory.append(struct.pack('>B', data))
# We got to start somewhere.
if __name__ == '__main__':
print(f'Executing {Path(__file__).name}')
# Set up GPIOs.
gpio_sysfs_defaults(tms, tdi, tdo, tck) # So urjtag cable() won't fail.
gpio_rpi_defaults(vpp, tck) # Used to overrule urjtag
# Define JTAG cable
urc.cable("gpio", "tms="+str(tms), "tdi="+str(tdi), "tdo="+str(tdo), "tck="+str(tck))
# The IRMCK343 does not have an idcode to detect return be zero.
jtag_define_part_irmck343() # The chip will be the first part (0) of the chain.
test_with_bytes = 10 # If read_bytes equals this value, burn testing is performed.
read_bytes = 10 # test
# read_bytes = 2**16 # 64k
# =Read================
urc.reset()
id = jtag_irmck343_readid() # Cmd 0x00
print(f'READID: 0x{id:02X} (Should be 0x42)\n')
jtag_irmck343_entertest() # Cmd 0xF5
jtag_irmck343_use_tck() # Cmd 0x70
irmck343_unlock_otp()
print(f'Reading {read_bytes} bytes from otp\n')
irmck343_read_otp_to_memory(0, read_bytes)
# Save to file.
file_name = "Read_OTP.bin"
if read_bytes != test_with_bytes:
# Only save if not testing.
print(f'Saving {file_name}...')
hr.save_memory(file_name, memory)
else:
for idx, val in enumerate(memory):
print(f'Read: 0x{idx:04X}: 0x{val:02X}')
print('Reading done')
jtag_irmck343_exittest()
if read_bytes != test_with_bytes:
exit(0)
# Only continues if 10 bytes are read. This is to limit the amout of data
# used to test burning.
# =Modify================
# Zero first value in memory that is not already zero.
print(f"\nModify one value.")
zeroed = False
for idx, val in enumerate(memory):
if not zeroed and val != 0:
print(f'Memory: 0x{idx:04X}: 0x{val:02X} - Zeroed!')
memory.write(idx, struct.pack('>B', 0))
zeroed = True
# =Burn================
# BURN DOES NOT WORK!!!
# Program as if no reading had been done.
print(f'\nAttempt Burn with modified data!!')
jtag_irmck343_entertest()
jtag_irmck343_use_tck()
jtag_irmck343_set_timer()
# This may be the wrong way to apply Vpp. Datasheet is very bad on this point.
GPIO.output(vpp, 1) # Enable Vpp high voltage
sleep_us(500) # Wait to ensure Vpp is steady.
jtag_irmck343_otp_program_mode()
jtag_irmck343_set_address(0x0000)
jtag_irmck343_set_auto_write_increment()
for idx, val in enumerate(memory):
print(f'Burn: 0x{idx:04X}: 0x{val:02X}')
jtag_irmck343_write_increment_data(val)
GPIO.output(vpp, 0) # Disable Vpp high voltage
print(f'Burn done!!\n')
jtag_irmck343_exittest() # Cmd 0xF6
# =Clear memory ================
memory.clear(0, len(memory))
# =Re-Read ================
# Re-Read usually works, but sometimes all read bytes (not id etc) are the last burned value.
# Read ID usualy does not work here - don't know why!
urc.reset()
id = jtag_irmck343_readid() # Cmd 0x00
print(f'READID: 0x{id:02X} (Should be 0x42)\n')
jtag_irmck343_entertest() # Cmd 0xF5
jtag_irmck343_use_tck() # Cmd 0x70
irmck343_unlock_otp()
print(f'Reading {read_bytes} bytes from otp\n')
irmck343_read_otp_to_memory(0, read_bytes)
jtag_irmck343_exittest()
for idx, val in enumerate(memory):
print(f'Re-Read: 0x{idx:04X}: 0x{val:02X}')
print('Reading done')
exit(0)
reset
instruction READID
shift IR
shift DR
DR # Returns: 01000010 (0x42)
instruction ENTERTEST # Write 0xF5 to IR - Enter test mode
shift IR
instruction wTESTMODE # Write 0x70 to IR then 0x0002 to DR - Set TCK to main system clock
dr 0x0002 # Writes: 0000000000000010 (0x0002)
shift IR
shift DR
DR # Returns 0000000001110000 (0x0070)
instruction wOTPSETUP # Write 0x50 to IR then 0x00 to DR - Set OTP_Setup to 0x00
dr 0x00 # Writes 00000000 (0x00)
#dr 00001000 # Writes 00001000 (0x08)
shift IR
shift DR
#DR # Returns 01010000 (0x50) <-- 0x08 <-- Instruction #
DR # Returns 01010000 (0x50) <-- 0x00 ???
instruction wADDRESS # Write 0x51 to IR then 0xFFFF to DR - Set OTP_Address to 0xFFFF
dr 0xFFFF # Writes: 1111111111111111 (0xFFFF)
shift IR
shift DR
DR # Returns 0000000001010001 (0x0051) <-- Instruction #
instruction sAUTOINCR_READ # Write 0x72 to IR - Italic steps disable OTP read protection
shift IR
shift DR # Read DR - Dummy read
DR # Returns 11111111 (0xFF)
instruction wADDRESS # Write 0x51 to IR then 0x0000 to DR - Set OTP_Address to 0x0000
DR 0x0000 # Writes 0000000000000000 (0x0000)
shift IR
shift DR
DR # Returns 0000000001010001 (0x0051) <-- Instruction #
instruction sAUTOINCR_READ # Write 0x72 to IR - Enable auto-increment OTP read
shift IR
shift DR # Read DR - Dummy read
DR
shift DR # Read DR - Read OTP address 0x0000
DR
shift DR # Read DR - Read OTP address 0x0001
DR
shift DR # Read DR - Read OTP address 0x0002
DR
shift DR # Read DR - Read OTP address 0x0003
DR
shift DR # Read DR - Read OTP address 0x0004
DR
shift DR # Read DR - Read OTP address 0x0005
DR
shift DR # Read DR - Read OTP address 0x0006
DR
shift DR # Read DR - Read OTP address 0x0007
DR
shift DR # Read DR - Read OTP address 0x0008
DR
instruction EXITTEST # Write 0xF6 to IR - Exit test mode
shift IR
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment