ULINK driver: Remove typedefs in OpenULINK firmware: Use typedefs from stdint.h ...
[openocd.git] / src / jtag / drivers / OpenULINK / src / jtag.c
index cf126ed274344859986e98155e0391630adb8fbe..3c2fea297c483f0393038bc8c10135dad7edee5c 100644 (file)
 
 #include <stdbool.h>
 
-/** Delay value for SCAN operations with less than maximum TCK frequency */
-u8 delay_scan = 0;
+/** Delay value for SCAN_IN operations with less than maximum TCK frequency */
+uint8_t delay_scan_in = 0;
 
-/** Delay value for CLOCK_TCK operations */
-u8 delay_tck = 0;
+/** Delay value for SCAN_OUT operations with less than maximum TCK frequency */
+uint8_t delay_scan_out = 0;
+
+/** Delay value for SCAN_IO operations with less than maximum TCK frequency */
+uint8_t delay_scan_io = 0;
+
+/** Delay value for CLOCK_TCK operations with less than maximum frequency */
+uint8_t delay_tck = 0;
 
 /** Delay value for CLOCK_TMS operations with less than maximum frequency */
-u8 delay_tms = 0;
+uint8_t delay_tms = 0;
 
 /**
  * Perform JTAG SCAN-IN operation at maximum TCK frequency.
@@ -41,16 +47,18 @@ u8 delay_tms = 0;
  * Dummy data is shifted into the JTAG chain via TDI, TDO data is sampled and
  * stored in the EP2 IN buffer.
  *
+ * Maximum achievable TCK frequency is 182 kHz for ULINK clocked at 24 MHz.
+ *
  * @param out_offset offset in OUT2BUF where payload data starts
  */
-void jtag_scan_in(u8 out_offset, u8 in_offset)
+void jtag_scan_in(uint8_t out_offset, uint8_t in_offset)
 {
-  u8 scan_size_bytes, bits_last_byte;
-  u8 tms_count_start, tms_count_end;
-  u8 tms_sequence_start, tms_sequence_end;
-  u8 tdo_data, i, j;
+  uint8_t scan_size_bytes, bits_last_byte;
+  uint8_t tms_count_start, tms_count_end;
+  uint8_t tms_sequence_start, tms_sequence_end;
+  uint8_t tdo_data, i, j;
 
-  u8 outb_buffer;
+  uint8_t outb_buffer;
 
   /* Get parameters from OUT2BUF */
   scan_size_bytes = OUT2BUF[out_offset];
@@ -72,8 +80,8 @@ void jtag_scan_in(u8 out_offset, u8 in_offset)
 
     for (j = 0; j < 8; j++) {
       OUTB = outb_buffer; /* TCK changes here */
-      OUTB = (outb_buffer | PIN_TCK);
       tdo_data = tdo_data >> 1;
+      OUTB = (outb_buffer | PIN_TCK);
 
       if (GET_TDO()) {
         tdo_data |= 0x80;
@@ -96,8 +104,8 @@ void jtag_scan_in(u8 out_offset, u8 in_offset)
     }
 
     OUTB = outb_buffer; /* TCK change here */
-    OUTB = (outb_buffer | PIN_TCK);
     tdo_data = tdo_data >> 1;
+    OUTB = (outb_buffer | PIN_TCK);
 
     if (GET_TDO()) {
       tdo_data |= 0x80;
@@ -114,6 +122,93 @@ void jtag_scan_in(u8 out_offset, u8 in_offset)
   }
 }
 
+/**
+ * Perform JTAG SCAN-IN operation at variable TCK frequency.
+ *
+ * Dummy data is shifted into the JTAG chain via TDI, TDO data is sampled and
+ * stored in the EP2 IN buffer.
+ *
+ * Maximum achievable TCK frequency is 113 kHz for ULINK clocked at 24 MHz.
+ *
+ * @param out_offset offset in OUT2BUF where payload data starts
+ */
+void jtag_slow_scan_in(uint8_t out_offset, uint8_t in_offset)
+{
+  uint8_t scan_size_bytes, bits_last_byte;
+  uint8_t tms_count_start, tms_count_end;
+  uint8_t tms_sequence_start, tms_sequence_end;
+  uint8_t tdo_data, i, j, k;
+
+  uint8_t outb_buffer;
+
+  /* Get parameters from OUT2BUF */
+  scan_size_bytes = OUT2BUF[out_offset];
+  bits_last_byte = OUT2BUF[out_offset + 1];
+  tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
+  tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
+  tms_sequence_start = OUT2BUF[out_offset + 3];
+  tms_sequence_end = OUT2BUF[out_offset + 4];
+
+  if (tms_count_start > 0) {
+    jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
+  }
+
+  outb_buffer = OUTB & ~(PIN_TDI | PIN_TCK | PIN_TMS);
+
+  /* Shift all bytes except the last byte */
+  for (i = 0; i < scan_size_bytes - 1; i++) {
+    tdo_data = 0;
+
+    for (j = 0; j < 8; j++) {
+      OUTB = outb_buffer; /* TCK changes here */
+      for (k = 0; k < delay_scan_in; k++);
+      tdo_data = tdo_data >> 1;
+
+      OUTB = (outb_buffer | PIN_TCK);
+      for (k = 0; k < delay_scan_in; k++);
+
+      if (GET_TDO()) {
+        tdo_data |= 0x80;
+      }
+    }
+
+    /* Copy TDO data to IN2BUF */
+    IN2BUF[i + in_offset] = tdo_data;
+  }
+
+  tdo_data = 0;
+
+  /* Shift the last byte */
+  for (j = 0; j < bits_last_byte; j++) {
+    /* Assert TMS signal if requested and this is the last bit */
+    if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
+      outb_buffer |= PIN_TMS;
+      tms_count_end--;
+      tms_sequence_end = tms_sequence_end >> 1;
+    }
+
+    OUTB = outb_buffer; /* TCK change here */
+    for (k = 0; k < delay_scan_in; k++);
+    tdo_data = tdo_data >> 1;
+
+    OUTB = (outb_buffer | PIN_TCK);
+    for (k = 0; k < delay_scan_in; k++);
+
+    if (GET_TDO()) {
+      tdo_data |= 0x80;
+    }
+  }
+  tdo_data = tdo_data >> (8 - bits_last_byte);
+
+  /* Copy TDO data to IN2BUF */
+  IN2BUF[i + in_offset] = tdo_data;
+
+  /* Move to correct end state */
+  if (tms_count_end > 0) {
+    jtag_slow_clock_tms(tms_count_end, tms_sequence_end);
+  }
+}
+
 /**
  * Perform JTAG SCAN-OUT operation at maximum TCK frequency.
  *
@@ -121,16 +216,18 @@ void jtag_scan_in(u8 out_offset, u8 in_offset)
  * data is not sampled.
  * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state.
  *
+ * Maximum achievable TCK frequency is 142 kHz for ULINK clocked at 24 MHz.
+ *
  * @param out_offset offset in OUT2BUF where payload data starts
  */
-void jtag_scan_out(u8 out_offset)
+void jtag_scan_out(uint8_t out_offset)
 {
-  u8 scan_size_bytes, bits_last_byte;
-  u8 tms_count_start, tms_count_end;
-  u8 tms_sequence_start, tms_sequence_end;
-  u8 tdi_data, i, j;
+  uint8_t scan_size_bytes, bits_last_byte;
+  uint8_t tms_count_start, tms_count_end;
+  uint8_t tms_sequence_start, tms_sequence_end;
+  uint8_t tdi_data, i, j;
 
-  u8 outb_buffer;
+  uint8_t outb_buffer;
 
   /* Get parameters from OUT2BUF */
   scan_size_bytes = OUT2BUF[out_offset];
@@ -193,6 +290,93 @@ void jtag_scan_out(u8 out_offset)
   }
 }
 
+/**
+ * Perform JTAG SCAN-OUT operation at maximum TCK frequency.
+ *
+ * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
+ * data is not sampled.
+ * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state.
+ *
+ * Maximum achievable TCK frequency is 97 kHz for ULINK clocked at 24 MHz.
+ *
+ * @param out_offset offset in OUT2BUF where payload data starts
+ */
+void jtag_slow_scan_out(uint8_t out_offset)
+{
+  uint8_t scan_size_bytes, bits_last_byte;
+  uint8_t tms_count_start, tms_count_end;
+  uint8_t tms_sequence_start, tms_sequence_end;
+  uint8_t tdi_data, i, j, k;
+
+  uint8_t outb_buffer;
+
+  /* Get parameters from OUT2BUF */
+  scan_size_bytes = OUT2BUF[out_offset];
+  bits_last_byte = OUT2BUF[out_offset + 1];
+  tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
+  tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
+  tms_sequence_start = OUT2BUF[out_offset + 3];
+  tms_sequence_end = OUT2BUF[out_offset + 4];
+
+  if (tms_count_start > 0) {
+    jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
+  }
+
+  outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS);
+
+  /* Shift all bytes except the last byte */
+  for (i = 0; i < scan_size_bytes - 1; i++) {
+    tdi_data = OUT2BUF[i + out_offset + 5];
+
+    for (j = 0; j < 8; j++) {
+      if (tdi_data & 0x01) {
+        outb_buffer |= PIN_TDI;
+      }
+      else {
+        outb_buffer &= ~PIN_TDI;
+      }
+
+      OUTB = outb_buffer; /* TDI and TCK change here */
+      for (k = 0; k < delay_scan_out; k++);
+      tdi_data = tdi_data >> 1;
+
+      OUTB = (outb_buffer | PIN_TCK);
+      for (k = 0; k < delay_scan_out; k++);
+    }
+  }
+
+  tdi_data = OUT2BUF[i + out_offset + 5];
+
+  /* Shift the last byte */
+  for (j = 0; j < bits_last_byte; j++) {
+    if (tdi_data & 0x01) {
+      outb_buffer |= PIN_TDI;
+    }
+    else {
+      outb_buffer &= ~PIN_TDI;
+    }
+
+    /* Assert TMS signal if requested and this is the last bit */
+    if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
+      outb_buffer |= PIN_TMS;
+      tms_count_end--;
+      tms_sequence_end = tms_sequence_end >> 1;
+    }
+
+    OUTB = outb_buffer; /* TDI and TCK change here */
+    for (k = 0; k < delay_scan_out; k++);
+    tdi_data = tdi_data >> 1;
+
+    OUTB = (outb_buffer | PIN_TCK);
+    for (k = 0; k < delay_scan_out; k++);
+  }
+
+  /* Move to correct end state */
+  if (tms_count_end > 0) {
+    jtag_slow_clock_tms(tms_count_end, tms_sequence_end);
+  }
+}
+
 /**
  * Perform bidirectional JTAG SCAN operation at maximum TCK frequency.
  *
@@ -200,16 +384,18 @@ void jtag_scan_out(u8 out_offset)
  * data is sampled and stored in the EP2 IN buffer.
  * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state.
  *
+ * Maximum achievable TCK frequency is 100 kHz for ULINK clocked at 24 MHz.
+ *
  * @param out_offset offset in OUT2BUF where payload data starts
  */
-void jtag_scan_io(u8 out_offset, u8 in_offset)
+void jtag_scan_io(uint8_t out_offset, uint8_t in_offset)
 {
-  u8 scan_size_bytes, bits_last_byte;
-  u8 tms_count_start, tms_count_end;
-  u8 tms_sequence_start, tms_sequence_end;
-  u8 tdi_data, tdo_data, i, j;
+  uint8_t scan_size_bytes, bits_last_byte;
+  uint8_t tms_count_start, tms_count_end;
+  uint8_t tms_sequence_start, tms_sequence_end;
+  uint8_t tdi_data, tdo_data, i, j;
 
-  u8 outb_buffer;
+  uint8_t outb_buffer;
 
   /* Get parameters from OUT2BUF */
   scan_size_bytes = OUT2BUF[out_offset];
@@ -291,38 +477,164 @@ void jtag_scan_io(u8 out_offset, u8 in_offset)
   }
 }
 
+/**
+ * Perform bidirectional JTAG SCAN operation at maximum TCK frequency.
+ *
+ * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
+ * data is sampled and stored in the EP2 IN buffer.
+ * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state.
+ *
+ * Maximum achievable TCK frequency is 78 kHz for ULINK clocked at 24 MHz.
+ *
+ * @param out_offset offset in OUT2BUF where payload data starts
+ */
+void jtag_slow_scan_io(uint8_t out_offset, uint8_t in_offset)
+{
+  uint8_t scan_size_bytes, bits_last_byte;
+  uint8_t tms_count_start, tms_count_end;
+  uint8_t tms_sequence_start, tms_sequence_end;
+  uint8_t tdi_data, tdo_data, i, j, k;
+
+  uint8_t outb_buffer;
+
+  /* Get parameters from OUT2BUF */
+  scan_size_bytes = OUT2BUF[out_offset];
+  bits_last_byte = OUT2BUF[out_offset + 1];
+  tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
+  tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
+  tms_sequence_start = OUT2BUF[out_offset + 3];
+  tms_sequence_end = OUT2BUF[out_offset + 4];
+
+  if (tms_count_start > 0) {
+    jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
+  }
+
+  outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS);
+
+  /* Shift all bytes except the last byte */
+  for (i = 0; i < scan_size_bytes - 1; i++) {
+    tdi_data = OUT2BUF[i + out_offset + 5];
+    tdo_data = 0;
+
+    for (j = 0; j < 8; j++) {
+      if (tdi_data & 0x01) {
+        outb_buffer |= PIN_TDI;
+      }
+      else {
+        outb_buffer &= ~PIN_TDI;
+      }
+
+      OUTB = outb_buffer; /* TDI and TCK change here */
+      for (k = 0; k < delay_scan_io; k++);
+      tdi_data = tdi_data >> 1;
+
+      OUTB = (outb_buffer | PIN_TCK);
+      for (k = 0; k < delay_scan_io; k++);
+      tdo_data = tdo_data >> 1;
+
+      if (GET_TDO()) {
+        tdo_data |= 0x80;
+      }
+    }
+
+    /* Copy TDO data to IN2BUF */
+    IN2BUF[i + in_offset] = tdo_data;
+  }
+
+  tdi_data = OUT2BUF[i + out_offset + 5];
+  tdo_data = 0;
+
+  /* Shift the last byte */
+  for (j = 0; j < bits_last_byte; j++) {
+    if (tdi_data & 0x01) {
+      outb_buffer |= PIN_TDI;
+    }
+    else {
+      outb_buffer &= ~PIN_TDI;
+    }
+
+    /* Assert TMS signal if requested and this is the last bit */
+    if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
+      outb_buffer |= PIN_TMS;
+      tms_count_end--;
+      tms_sequence_end = tms_sequence_end >> 1;
+    }
+
+    OUTB = outb_buffer; /* TDI and TCK change here */
+    for (k = 0; k < delay_scan_io; k++);
+    tdi_data = tdi_data >> 1;
+
+    OUTB = (outb_buffer | PIN_TCK);
+    for (k = 0; k < delay_scan_io; k++);
+    tdo_data = tdo_data >> 1;
+
+    if (GET_TDO()) {
+      tdo_data |= 0x80;
+    }
+  }
+  tdo_data = tdo_data >> (8 - bits_last_byte);
+
+  /* Copy TDO data to IN2BUF */
+  IN2BUF[i + in_offset] = tdo_data;
+
+  /* Move to correct end state */
+  if (tms_count_end > 0) {
+    jtag_slow_clock_tms(tms_count_end, tms_sequence_end);
+  }
+}
+
 /**
  * Generate TCK clock cycles.
  *
+ * Maximum achievable TCK frequency is 375 kHz for ULINK clocked at 24 MHz.
+ *
  * @param count number of TCK clock cyclces to generate.
  */
-void jtag_clock_tck(u16 count)
+void jtag_clock_tck(uint16_t count)
 {
-  u16 i;
-  u8 j;
+  uint16_t i;
+  uint8_t outb_buffer = OUTB & ~(PIN_TCK);
 
   for ( i = 0; i < count; i++ ) {
-    SET_TCK_LOW();
-    for(j = 0; j < delay_tck; j++);
+    OUTB = outb_buffer;
+    OUTB = outb_buffer | PIN_TCK;
+  }
+}
 
-    SET_TCK_HIGH();
-    for(j = 0; j < delay_tck; j++);
+/**
+ * Generate TCK clock cycles at variable frequency.
+ *
+ * Maximum achieveable TCK frequency is 166.6 kHz for ULINK clocked at 24 MHz.
+ *
+ * @param count number of TCK clock cyclces to generate.
+ */
+void jtag_slow_clock_tck(uint16_t count)
+{
+  uint16_t i;
+  uint8_t j;
+  uint8_t outb_buffer = OUTB & ~(PIN_TCK);
+
+  for ( i = 0; i < count; i++ ) {
+    OUTB = outb_buffer;
+    for (j = 0; j < delay_tck; j++);
+    OUTB = outb_buffer | PIN_TCK;
+    for (j = 0; j < delay_tck; j++);
   }
 }
 
 /**
- * Perform TAP-FSM state transitions at maximum TCK frequency.
+ * Perform TAP FSM state transitions at maximum TCK frequency.
+ *
+ * Maximum achievable TCK frequency is 176 kHz for ULINK clocked at 24 MHz.
  *
  * @param count the number of state transitions to perform.
  * @param sequence the TMS pin levels for each state transition, starting with
  *  the least-significant bit.
  */
-void jtag_clock_tms(u8 count, u8 sequence)
+void jtag_clock_tms(uint8_t count, uint8_t sequence)
 {
-  volatile u8 outb_buffer;
-  u8 i;
-
-  outb_buffer = OUTB & ~(PIN_TCK);
+  uint8_t outb_buffer = OUTB & ~(PIN_TCK);
+  uint8_t i;
 
   for ( i = 0; i < count; i++ ) {
     /* Set TMS pin according to sequence parameter */
@@ -342,13 +654,32 @@ void jtag_clock_tms(u8 count, u8 sequence)
 /**
  * Perform TAP-FSM state transitions at less than maximum TCK frequency.
  *
+ * Maximum achievable TCK frequency is 117 kHz for ULINK clocked at 24 MHz.
+ *
  * @param count the number of state transitions to perform.
  * @param sequence the TMS pin levels for each state transition, starting with
  *  the least-significant bit.
  */
-void jtag_slow_clock_tms(u8 count, u8 sequence)
+void jtag_slow_clock_tms(uint8_t count, uint8_t sequence)
 {
+  uint8_t outb_buffer = OUTB & ~(PIN_TCK);
+  uint8_t i, j;
 
+  for (i = 0; i < count; i++) {
+    /* Set TMS pin according to sequence parameter */
+    if ( sequence & 0x1 ) {
+      outb_buffer |= PIN_TMS;
+    }
+    else {
+      outb_buffer &= ~PIN_TMS;
+    }
+
+    OUTB = outb_buffer;
+    for (j = 0; j < delay_tms; j++);
+    sequence = sequence >> 1;
+    OUTB = outb_buffer | PIN_TCK;
+    for (j = 0; j < delay_tms; j++);
+  }
 }
 
 /**
@@ -358,9 +689,9 @@ void jtag_slow_clock_tms(u8 count, u8 sequence)
  *  of the JTAG input signals and the least-significant byte cotains the state
  *  of the JTAG output signals.
  */
-u16 jtag_get_signals(void)
+uint16_t jtag_get_signals(void)
 {
-  u8 input_signal_state, output_signal_state;
+  uint8_t input_signal_state, output_signal_state;
 
   input_signal_state = 0;
   output_signal_state = 0;
@@ -384,7 +715,7 @@ u16 jtag_get_signals(void)
   /* Get states of output pins */
   output_signal_state = PINSB & MASK_PORTB_DIRECTION_OUT;
 
-  return ((u16)input_signal_state << 8) | ((u16)output_signal_state);
+  return ((uint16_t)input_signal_state << 8) | ((uint16_t)output_signal_state);
 }
 
 /**
@@ -393,7 +724,7 @@ u16 jtag_get_signals(void)
  * @param low signals which should be de-asserted.
  * @param high signals which should be asserted.
  */
-void jtag_set_signals(u8 low, u8 high)
+void jtag_set_signals(uint8_t low, uint8_t high)
 {
   OUTB &= ~(low & MASK_PORTB_DIRECTION_OUT);
   OUTB |= (high & MASK_PORTB_DIRECTION_OUT);
@@ -402,13 +733,18 @@ void jtag_set_signals(u8 low, u8 high)
 /**
  * Configure TCK delay parameters.
  *
- * @param scan number of delay cycles in shift operations.
+ * @param scan_in number of delay cycles in scan_in operations.
+ * @param scan_out number of delay cycles in scan_out operations.
+ * @param scan_io number of delay cycles in scan_io operations.
  * @param tck number of delay cycles in clock_tck operations.
  * @param tms number of delay cycles in clock_tms operations.
  */
-void jtag_configure_tck_delay(u8 scan, u8 tck, u8 tms)
+void jtag_configure_tck_delay(uint8_t scan_in, uint8_t scan_out,
+    uint8_t scan_io, uint8_t tck, uint8_t tms)
 {
-  delay_scan = scan;
+  delay_scan_in = scan_in;
+  delay_scan_out = scan_out;
+  delay_scan_io = scan_io;
   delay_tck = tck;
   delay_tms = tms;
 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)