-
Notifications
You must be signed in to change notification settings - Fork 130
Add unlock IDCODE support using indirect API #231
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the contribution! Left some comments when you have a chance to take a look.
callback_override = ctypes.CFUNCTYPE(None, ctypes.c_void_p) | ||
function = ctypes.cast(function_ptr, callback_override) | ||
function(self.unlock_idcode_cb) | ||
return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return |
NIT: No need for the return
at the very end.
import ctypes | ||
|
||
# Global variable to store the ID code | ||
global_id_code = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A global won't play well with multiple instances (e.g. if someone is debugging two chips at the same time). It looks like we need it for the callback in the dialog. Could we pass a partial function instead? That would allow us to prepopulate the id_code
:
import functools
def set_unloock_idcode(self, id_code):
partial = functools.partial(unlock_idcode_hook_dialog, id_code)
unlock_idcode_cb = enums.JLinkFunctions.UNLOCK_IDCODE_HOOK_PROTOTYPE(partial)
global_id_code = None | ||
|
||
|
||
def set_unlock_idcode(self, id_code): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we rename the self -> jlink
like in unlock_kinetis
?
global_id_code = id_code | ||
|
||
self._dll.JLINK_GetpFunc.restype = ctypes.c_void_p | ||
self.unlock_idcode_cb = enums.JLinkFunctions.UNLOCK_IDCODE_HOOK_PROTOTYPE(unlock_idcode_hook_dialog) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have to bind the callback to the passed instance? It looks like we pass the value to the SET_HOOK_DIALOG
function.
This PR adds support for unlock
IDCODE
which is one of J-Link indirect API functions. A number of Renesas devices can restrict debug access using a hexadecimal code known as anIDCODE
. When a device is locked, the J-Link driver will provide a dialog to enter anIDCODE
when connecting to the device:With this PR, a user can set the
IDCODE
which will automatically unlock the device when connecting. There will be no dialog prompt.Usage Example:
When
jlink.set_unlock_idcode()
is omitted, the user will get the default J-Link dialog prompt.This was validated on a Renesas S3A7 device using Windows 11 x64 with J-Link V8.12f and an Intel macOS Sequoia with J-Link V8.14.
I tried to follow the contribution guidelines as best I could. I am all ears if you would like something changed. I ended up using a global string to store the
IDCODE
due to the hook callback. I didn't know how else to handle it.Development was performed in Windows. I noticed a few issues with testing:
setuptools
must be 71.1.0 or older. Otherwise I seecoverage
must be 4.5.2 or newer to show actual coverage. With current version 4.4.1, coverage isn't detected correctly. For example,pylink\unlockers\unlock_idcode.py
is 36%. 4.5.2 is 96%.