you may encounter a problem.
@end deffn
+@deffn Command {parport_toggling_time} [nanoseconds]
+Displays how many nanoseconds the hardware needs to toggle TCK;
+the parport driver uses this value to obey the
+@command{jtag_khz} configuration.
+When the optional @var{nanoseconds} parameter is given,
+that setting is changed before displaying the current value.
+
+The default setting should work reasonably well on commodity PC hardware.
+However, you may want to calibrate for your specific hardware.
+@quotation Tip
+To measure the toggling time with a logic analyzer or a digital storage
+oscilloscope, follow the procedure below:
+@example
+> parport_toggling_time 1000
+> jtag_khz 500
+@end example
+This sets the maximum JTAG clock speed of the hardware, but
+the actual speed probably deviates from the requested 500 kHz.
+Now, measure the time between the two closest spaced TCK transitions.
+You can use @command{runtest 1000} or something similar to generate a
+large set of samples.
+Update the setting to match your measurement:
+@example
+> parport_toggling_time <measured nanoseconds>
+@end example
+Now the clock speed will be a better match for @command{jtag_khz rate}
+commands given in OpenOCD scripts and event handlers.
+
+You can do something similar with many digital multimeters, but note
+that you'll probably need to run the clock continuously for several
+seconds before it decides what clock rate to show. Adjust the
+toggling time up or down until the measured clock rate is a good
+match for the jtag_khz rate you specified; be conservative.
+@end quotation
+@end deffn
+
@deffn {Config Command} {parport_write_on_exit} (on|off)
This will configure the parallel driver to write a known
cable-specific value to the parallel interface on exiting OpenOCD
static char* parport_cable = NULL;
static uint16_t parport_port;
static int parport_exit = 0;
+static uint32_t parport_toggling_time_ns = 1000;
+static int wait_states;
/* interface variables
*/
static void parport_write(int tck, int tms, int tdi)
{
- int i = jtag_get_speed() + 1;
+ int i = wait_states + 1;
if (tck)
dataport_value |= cable->TCK_MASK;
static int parport_speed(int speed)
{
+ wait_states = speed;
+ return ERROR_OK;
+}
+
+static int parport_khz(int khz, int* jtag_speed)
+{
+ if (khz == 0) {
+ LOG_DEBUG("RCLK not supported");
+ return ERROR_FAIL;
+ }
+
+ *jtag_speed = 499999 / (khz * parport_toggling_time_ns);
+ return ERROR_OK;
+}
+
+static int parport_speed_div(int speed, int* khz)
+{
+ uint32_t denominator = (speed + 1) * parport_toggling_time_ns;
+
+ *khz = (499999 + denominator) / denominator;
return ERROR_OK;
}
bitbang_interface = &parport_bitbang;
+ wait_states = jtag_get_speed();
+
return ERROR_OK;
}
return ERROR_OK;
}
+static int
+parport_handle_parport_toggling_time_command(struct command_context_s *cmd_ctx,
+ char *cmd, char **args, int argc)
+{
+ if (argc == 1) {
+ uint32_t ns;
+ int retval = parse_u32(args[0], &ns);
+
+ if (ERROR_OK != retval)
+ return retval;
+
+ if (ns == 0) {
+ LOG_ERROR("0 ns is not a valid parport toggling time");
+ return ERROR_FAIL;
+ }
+
+ parport_toggling_time_ns = ns;
+ wait_states = jtag_get_speed();
+ }
+
+ command_print(cmd_ctx, "parport toggling time = %" PRIu32 " ns",
+ parport_toggling_time_ns);
+
+ return ERROR_OK;
+}
+
static int parport_register_commands(struct command_context_s *cmd_ctx)
{
register_command(cmd_ctx, NULL, "parport_port",
"configure the parallel driver to write "
"a known value to the parallel interface");
+ register_command(cmd_ctx, NULL, "parport_toggling_time",
+ parport_handle_parport_toggling_time_command, COMMAND_ANY,
+ "time <ns> it takes for the hardware to toggle TCK");
+
return ERROR_OK;
}
jtag_interface_t parport_interface = {
- .name = "parport",
- .register_commands = &parport_register_commands,
- .init = &parport_init,
- .quit = &parport_quit,
- .speed = &parport_speed,
- .execute_queue = &bitbang_execute_queue,
- };
+ .name = "parport",
+ .register_commands = parport_register_commands,
+ .init = parport_init,
+ .quit = parport_quit,
+ .khz = parport_khz,
+ .speed_div = parport_speed_div,
+ .speed = parport_speed,
+ .execute_queue = bitbang_execute_queue,
+};