OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [soc/] [sw/] [adv_jtag_bridge/] [adv_dbg_commands.c] - Diff between revs 12 and 21

Show entire file | Details | Blame | View Log

Rev 12 Rev 21
Line 1... Line 1...
/* adv_dbg_commands.c -- JTAG protocol bridge between GDB and Advanced debug module.
/* adv_dbg_commands.c -- JTAG protocol bridge between GDB and Advanced debug module.
   Copyright(C) Nathan Yawn, nyawn@opencores.net
   Copyright (C) 2008-2010 Nathan Yawn, nyawn@opencores.net
 
 
   This file contains functions which perform high-level transactions
   This file contains functions which perform high-level transactions
   on a JTAG chain and debug unit, such as setting a value in the TAP IR
   on a JTAG chain and debug unit, such as setting a value in the TAP IR
   or doing a burst write through the wishbone module of the debug unit.
   or doing a burst write through the wishbone module of the debug unit.
   It uses the protocol for the Advanced Debug Interface (adv_dbg_if).
   It uses the protocol for the Advanced Debug Interface (adv_dbg_if).
Line 24... Line 24...
 
 
 
 
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>  // for malloc()
#include <stdlib.h>  // for malloc()
#include <unistd.h>  // for exit()
#include <unistd.h>  // for exit()
//#include <pthread.h>  // for mutexes
#include <strings.h> // for bzero()
 
 
#include "chain_commands.h"
#include "chain_commands.h"
#include "adv_dbg_commands.h"     // hardware-specific defines for the debug module
#include "adv_dbg_commands.h"     // hardware-specific defines for the debug module
//#include "altera_virtual_jtag.h"  // hardware-specifg defines for the Altera Virtual JTAG interface
 
#include "cable_common.h"         // low-level JTAG IO routines
#include "cable_common.h"         // low-level JTAG IO routines
#include "errcodes.h"
#include "errcodes.h"
 
 
#define debug(...) //fprintf(stderr, __VA_ARGS__ )
#define debug(...) //fprintf(stderr, __VA_ARGS__ )
 
 
Line 121... Line 120...
    return err;
    return err;
 
 
  debug("selreg %ld\n", regidx);
  debug("selreg %ld\n", regidx);
 
 
  // If this reg is already selected, don't do a JTAG transaction
  // If this reg is already selected, don't do a JTAG transaction
  if((current_chain >= 0) && (current_reg_idx[current_chain] == regidx))
  if(current_reg_idx[current_chain] == regidx)
    return APP_ERR_NONE;
    return APP_ERR_NONE;
 
 
  switch(current_chain) {
  switch(current_chain) {
  case DC_WISHBONE:
  case DC_WISHBONE:
    index_len = DBG_WB_REG_SEL_LEN;
    index_len = DBG_WB_REG_SEL_LEN;
Line 343... Line 342...
  uint32_t in_data;
  uint32_t in_data;
  unsigned long addr;
  unsigned long addr;
  uint32_t err_data[2];
  uint32_t err_data[2];
  int bus_error_retries = 0;
  int bus_error_retries = 0;
  int err = APP_ERR_NONE;
  int err = APP_ERR_NONE;
 
  static char *output_scratchpad = NULL;
 
  static int output_scratchpad_size = 0;
 
 
    debug("Doing burst read, word size %d, word count %d, start address 0x%lX", word_size_bytes, word_count, start_address);
    debug("Doing burst read, word size %d, word count %d, start address 0x%lX", word_size_bytes, word_count, start_address);
 
 
    if(word_count <= 0) {
    if(word_count <= 0) {
      debug("Ignoring illegal read burst length (%d)\n", word_count);
      debug("Ignoring illegal read burst length (%d)\n", word_count);
Line 395... Line 396...
 
 
    // Send the BURST READ command, returns TAP to idle state
    // Send the BURST READ command, returns TAP to idle state
    if(err |= adbg_burst_command(opcode, addr, (word_count-i)))  // word_count-i in case of partial retry 
    if(err |= adbg_burst_command(opcode, addr, (word_count-i)))  // word_count-i in case of partial retry 
      return err;
      return err;
 
 
    // This is a kludge to word around oddities in the Xilinx BSCAN_* devices, and the
    // This is a kludge to work around oddities in the Xilinx BSCAN_* devices, and the
    // adv_dbg_if state machine.  The debug FSM needs 1 TCK between UPDATE_DR above, and
    // adv_dbg_if state machine.  The debug FSM needs 1 TCK between UPDATE_DR above, and
    // the CAPTURE_DR below, and the BSCAN_* won't provide it.  So, we force it, by putting the TAP
    // the CAPTURE_DR below, and the BSCAN_* won't provide it.  So, we force it, by putting the TAP
    // in BYPASS, which makes the debug_select line inactive, which is AND'ed with the TCK line (in the xilinx_internal_jtag module),
    // in BYPASS, which makes the debug_select line inactive, which is AND'ed with the TCK line (in the xilinx_internal_jtag module),
    // which forces it low.  Then we re-enable USER1/debug_select to make TCK high.  One TCK
    // which forces it low.  Then we re-enable USER1/debug_select to make TCK high.  One TCK
    // event, the hard way. 
    // event, the hard way. 
Line 412... Line 413...
    err |=  tap_set_shift_dr();
    err |=  tap_set_shift_dr();
 
 
    // We do not adjust for the DR length here.  BYPASS regs are loaded with 0,
    // We do not adjust for the DR length here.  BYPASS regs are loaded with 0,
    // and the debug unit waits for a '1' status bit before beginning to read data.
    // and the debug unit waits for a '1' status bit before beginning to read data.
 
 
 
#ifdef ADBG_OPT_HISPEED
 
       // Get 1 status bit, then word_size_bytes*8 bits
 
       status = 0;
 
       j = 0;
 
       while(!status) {  // Status indicates whether there is a word available to read.  Wait until it returns true.
 
         err |= jtag_read_write_bit(0, &status);
 
         j++;
 
         // If max count exceeded, retry
 
         if(j > MAX_READ_STATUS_WAIT) {
 
           printf("Burst read timed out.\n");
 
           if(!retry_do()) {
 
             printf("Retry count exceeded in burst read!\n");
 
             return err|APP_ERR_MAX_RETRY;
 
           }
 
           err = APP_ERR_NONE;  // on retry, errors cleared
 
           goto wb_burst_read_retry_full;
 
         }
 
       }
 
 
 
       // Check we have enough space for the (zero) output data
 
       if(output_scratchpad_size < (word_count*word_size_bytes))
 
         {
 
           free(output_scratchpad);
 
           output_scratchpad = (char *) malloc(word_count*word_size_bytes);
 
           if(output_scratchpad != NULL) {
 
             output_scratchpad_size = (word_count*word_size_bytes);
 
             bzero(output_scratchpad, output_scratchpad_size);
 
           }
 
           else {
 
             output_scratchpad_size = 0;
 
             return APP_ERR_MALLOC;
 
           }
 
         }
 
       //uint32_t outstream[64];
 
       //bzero((char *)outstream, 64*4);
 
 
 
       // Get the data in one shot
 
       err |= jtag_read_write_stream((uint32_t *)output_scratchpad, (uint32_t *)data, word_size_bits*word_count, 0, 0);
 
       for(i = 0; i < (word_count*word_size_bytes); i++)
 
         {
 
           crc_calc = adbg_compute_crc(crc_calc, ((uint8_t *)data)[i], 8);
 
         }
 
#else
 
 
   // Repeat for each word: wait until ready = 1, then read word_size_bits bits.
   // Repeat for each word: wait until ready = 1, then read word_size_bits bits.
   for(; i < word_count; i++)
   for(; i < word_count; i++)
     {
     {
       // Get 1 status bit, then word_size_bytes*8 bits
       // Get 1 status bit, then word_size_bytes*8 bits
       status = 0;
       status = 0;
Line 459... Line 504...
 
 
       if(word_size_bytes == 1) ((unsigned char *)data)[i] = in_data & 0xFF;
       if(word_size_bytes == 1) ((unsigned char *)data)[i] = in_data & 0xFF;
       else if(word_size_bytes == 2) ((unsigned short *)data)[i] = in_data & 0xFFFF;
       else if(word_size_bytes == 2) ((unsigned short *)data)[i] = in_data & 0xFFFF;
       else ((unsigned long *)data)[i] = in_data;
       else ((unsigned long *)data)[i] = in_data;
     }
     }
 
#endif
 
 
   // All bus data was read.  Read the data CRC from the debug module.
   // All bus data was read.  Read the data CRC from the debug module.
   err |= jtag_read_write_stream(&out_data, &crc_read, 32, 0, 1);
   err |= jtag_read_write_stream(&out_data, &crc_read, 32, 0, 1);
 
 
   err |= tap_exit_to_idle();  // Go from EXIT1 to IDLE
   err |= tap_exit_to_idle();  // Go from EXIT1 to IDLE
Line 476... Line 522...
     goto  wb_burst_read_retry_full;
     goto  wb_burst_read_retry_full;
   }
   }
   else debug("CRC OK!");
   else debug("CRC OK!");
 
 
 
 
 
 
   // Now, read the error register, and retry/recompute as necessary.
   // Now, read the error register, and retry/recompute as necessary.
   if(current_chain == DC_WISHBONE)
   if(current_chain == DC_WISHBONE)
     {
     {
       err |= adbg_ctrl_read(DBG_WB_REG_ERROR, err_data, 1);  // First, just get 1 bit...read address only if necessary,
       err |= adbg_ctrl_read(DBG_WB_REG_ERROR, err_data, 1);  // First, just get 1 bit...read address only if necessary,
       if(err_data[0] & 0x1) {  // Then we have a problem.
       if(err_data[0] & 0x1) {  // Then we have a problem.
Line 506... Line 551...
 
 
// Set up and execute a burst write to a contiguous set of addresses
// Set up and execute a burst write to a contiguous set of addresses
int adbg_wb_burst_write(void *data, int word_size_bytes, int word_count, unsigned long start_address)
int adbg_wb_burst_write(void *data, int word_size_bytes, int word_count, unsigned long start_address)
{
{
  unsigned char opcode;
  unsigned char opcode;
  uint8_t status;
 
  uint32_t datawords[2] = {0,0};
  uint32_t datawords[2] = {0,0};
  uint32_t statuswords[2] = {0,0};
 
  int i;
  int i;
  uint32_t crc_calc;
  uint32_t crc_calc;
  uint32_t crc_match;
  uint32_t crc_match;
  unsigned int word_size_bits;
  unsigned int word_size_bits;
  unsigned long addr;
  unsigned long addr;
  int bus_error_retries = 0;
  int bus_error_retries = 0;
  uint32_t err_data[2];
  uint32_t err_data[2];
  int loopct, successes;
  int loopct, successes;
  int first_status_loop;
#ifndef ADBG_OPT_HISPEED
 
  uint8_t status;
 
  uint32_t statuswords[2] = {0,0};
 
  int first_status_loop = 1;
 
#endif
  int err = APP_ERR_NONE;
  int err = APP_ERR_NONE;
 
 
    debug("Doing burst write, word size %d, word count %d, start address 0x%lx", word_size_bytes, word_count, start_address);
    debug("Doing burst write, word size %d, word count %d, start address 0x%lx\n", word_size_bytes, word_count, start_address);
    word_size_bits = word_size_bytes << 3;
    word_size_bits = word_size_bytes << 3;
 
 
    if(word_count <= 0) {
    if(word_count <= 0) {
      printf("Ignoring illegal burst write size (%d)\n", word_count);
      printf("Ignoring illegal burst write size (%d)\n", word_count);
      return 0;
      return 0;
Line 558... Line 605...
    default:
    default:
      printf("ERROR! Illegal debug chain selected while doing burst WRITE!\n");
      printf("ERROR! Illegal debug chain selected while doing burst WRITE!\n");
      return 1;
      return 1;
    }
    }
 
 
 
#ifndef ADBG_OPT_HISPEED
    // Compute which loop iteration in which to expect the first status bit
    // Compute which loop iteration in which to expect the first status bit
    first_status_loop = 1 + ((global_DR_prefix_bits + global_DR_postfix_bits)/(word_size_bits+1));
    first_status_loop = 1 + ((global_DR_prefix_bits + global_DR_postfix_bits)/(word_size_bits+1));
 
#endif
 
 
 wb_burst_write_retry_full:
 wb_burst_write_retry_full:
    i = 0;
    i = 0;
    addr = start_address;
    addr = start_address;
 wb_burst_write_retry_partial:
 wb_burst_write_retry_partial:
Line 574... Line 623...
    // Send burst command, return to idle state
    // Send burst command, return to idle state
    if(err |= adbg_burst_command(opcode, addr, (word_count-i)))  // word_count-i in case of partial retry
    if(err |= adbg_burst_command(opcode, addr, (word_count-i)))  // word_count-i in case of partial retry
      return err;
      return err;
 
 
   // Get us back to shift_dr mode to write a burst
   // Get us back to shift_dr mode to write a burst
   //err |= jtag_write_bit(TMS);  // select_dr_scan
 
   //err |= jtag_write_bit(0);           // capture_ir
 
   //err |= jtag_write_bit(0);           // shift_ir
 
   err |= tap_set_shift_dr();
   err |= tap_set_shift_dr();
 
 
   // Write a start bit (a 1) so it knows when to start counting
   // Write a start bit (a 1) so it knows when to start counting
   err |= jtag_write_bit(TDO);
   err |= jtag_write_bit(TDO);
 
 
 
#ifdef ADBG_OPT_HISPEED
 
   // If compiled for "hi-speed" mode, we don't read a status bit after every
 
   // word written.  This saves a lot of complication!
 
   // In this case, the loop below is used only for CRC calculation.
 
   err |= jtag_write_stream((uint32_t *) data, (word_count*word_size_bits), 0);  // Write data
 
#endif
 
 
   // Now, repeat...
   // Now, repeat...
   for(loopct = 0; i < word_count; i++,loopct++)  // loopct only used to check status... 
   for(loopct = 0; i < word_count; i++,loopct++)  // loopct only used to check status... 
     {
     {
       // Write word_size_bytes*8 bits, then get 1 status bit
       // Write word_size_bytes*8 bits, then get 1 status bit
       if(word_size_bytes == 4)       datawords[0] = ((unsigned long *)data)[i];
       if(word_size_bytes == 4)       datawords[0] = ((unsigned long *)data)[i];
       else if(word_size_bytes == 2) datawords[0] = ((unsigned short *)data)[i];
       else if(word_size_bytes == 2) datawords[0] = ((unsigned short *)data)[i];
       else                          datawords[0] = ((unsigned char *)data)[i];
       else                          datawords[0] = ((unsigned char *)data)[i];
 
 
       crc_calc = adbg_compute_crc(crc_calc, datawords[0], word_size_bits);
       crc_calc = adbg_compute_crc(crc_calc, datawords[0], word_size_bits);
 
 
 
#ifndef ADBG_OPT_HISPEED
       // This is an optimization
       // This is an optimization
       if((global_DR_prefix_bits + global_DR_postfix_bits) == 0) {
       if((global_DR_prefix_bits + global_DR_postfix_bits) == 0) {
 
         //#endif
         err |= jtag_write_stream(datawords, word_size_bits, 0);  // Write data
         err |= jtag_write_stream(datawords, word_size_bits, 0);  // Write data
 
         //#ifndef ADBG_OPT_HISPEED
         err |= jtag_read_write_bit(0, &status);  // Read status bit
         err |= jtag_read_write_bit(0, &status);  // Read status bit
         if(!status) {
         if(!status) {
           addr = start_address + (i*word_size_bytes);
           addr = start_address + (i*word_size_bytes);
           printf("Write before bus ready, retrying (idx %i, addr 0x%08lX).\n", i, addr);
           printf("Write before bus ready, retrying (idx %i, addr 0x%08lX).\n", i, addr);
           if(!retry_do()) { printf("Retry count exceeded!  Abort!\n\n"); exit(1);}
           if(!retry_do()) { printf("Retry count exceeded!  Abort!\n\n"); exit(1);}
Line 620... Line 676...
             // Don't bother going to TAP idle state, we're about to reset the TAP
             // Don't bother going to TAP idle state, we're about to reset the TAP
             goto wb_burst_write_retry_partial;
             goto wb_burst_write_retry_partial;
           }
           }
         }
         }
       }
       }
 
#endif
 
 
       if(err) {
       if(err) {
         printf("Error %s getting status bit, retrying.\n", get_err_string(err));
         printf("Error %s during burst write, retrying.\n", get_err_string(err));
         if(!retry_do()) {
         if(!retry_do()) {
           printf("Retry count exceeded!\n");
           printf("Retry count exceeded!\n");
           return err|APP_ERR_MAX_RETRY;
           return err|APP_ERR_MAX_RETRY;
         }
         }
         err = APP_ERR_NONE;
         err = APP_ERR_NONE;
Line 636... Line 693...
         }
         }
 
 
      debug("Wrote 0x%0lx", datawords[0]);
      debug("Wrote 0x%0lx", datawords[0]);
     }
     }
 
 
   // *** If this is a multi-device chain, at least one status bit will be lost.
   // *** If this is a multi-device chain (and we're not in hi-speed mode), at least one status bit will be lost.
   // *** If we want to check for it, we'd have to look while sending the CRC, and
   // *** If we want to check for it, we'd have to look while sending the CRC, and
   // *** maybe while burning bits to get the match bit.  So, for now, there is a
   // *** maybe while burning bits to get the match bit.  So, for now, there is a
   // *** hole here.
   // *** hole here.
 
 
   // Done sending data, Send the CRC we computed
   // Done sending data, Send the CRC we computed

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.