Actual implementation of cable driver for JIM, basic TAP state machine, and a skeleton for "some_cpu" with working IDCODE detection.

git-svn-id: https://urjtag.svn.sourceforge.net/svnroot/urjtag/trunk@932 b68d4a1b-bc3d-0410-92ed-d4ac073336b7
master
Kolja Waschk 17 years ago
parent 2b6e82c897
commit 3a1ec19c8c

@ -2,7 +2,9 @@
* ChangeLog: whitespace cosmetics
* Makefile.am, configure.ac, jim/tap.c, jim/Makefile.am, jim/README.jim,
tap/cable/jim.c, tap/cable.c, tap/Makefile.am: JTAG target sim skeleton
tap/cable/jim.c, tap/cable.c, tap/Makefile.am, jim/some_cpu.c,
include/jim.h, include/jim/some_cpu.h: JTAG target simulator "JIM"
and a "jim" cable driver to "connect" to it; detection already works.
2008-01-18 Arnim Laeuger <arniml@users.sourceforge.net>

@ -0,0 +1,102 @@
/*
* $Id: jim.h $
*
* Copyright (C) 2008 Kolja Waschk <kawk>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* Documentation used while writing this code:
*
* http://www.inaccessnetworks.com/projects/ianjtag/jtag-intro/jtag-intro.html
* "A Brief Introduction to the JTAG Boundary Scan Interface", Nick Patavalis
*
* http://www.xjtag.com/support-jtag/jtag-technical-guide.php
* "JTAG - A technical overview", XJTAG Ltd.
*
*/
#ifndef JIM_H
#define JIM_H 1
#include <stdint.h>
typedef enum
{
RESET = 0,
SELECT_DR = 0+1,
CAPTURE_DR = 0+2,
SHIFT_DR = 0+3,
EXIT1_DR = 0+4,
PAUSE_DR = 0+5,
EXIT2_DR = 0+6,
UPDATE_DR = 0+7,
IDLE = 8,
SELECT_IR = 8+1,
CAPTURE_IR = 8+2,
SHIFT_IR = 8+3,
EXIT1_IR = 8+4,
PAUSE_IR = 8+5,
EXIT2_IR = 8+6,
UPDATE_IR = 8+7,
}
tap_state_t;
typedef struct
{
uint32_t *reg;
int len;
} shift_reg_t;
typedef struct jim_device
{
struct jim_device *prev;
tap_state_t tap_state;
void (*tck_rise)(struct jim_device *dev, int tms, int tdi);
void (*tck_fall)(struct jim_device *dev);
void (*dev_free)(struct jim_device *dev);
int num_sregs;
int current_dr;
shift_reg_t *sreg;
int tdo;
int tdo_buffer;
}
jim_device_t;
typedef struct jim_state
{
int trst;
jim_device_t *last_device_in_chain;
}
jim_state_t;
void jim_set_trst(jim_state_t *s, int trst);
int jim_get_trst(jim_state_t *s);
int jim_get_tdo(jim_state_t *s);
void jim_tck_rise(jim_state_t *s, int tms, int tdi);
void jim_tck_fall(jim_state_t *s);
jim_device_t *jim_alloc_device(int num_sregs, const int reg_size[]);
jim_state_t *jim_init(void);
void jim_free(jim_state_t *s);
void jim_print_sreg(shift_reg_t *r);
void jim_print_tap_state(jim_device_t *dev);
#endif

@ -0,0 +1,29 @@
/*
* $Id: tap.c $
*
* Copyright (C) 2008 Kolja Waschk <kawk>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <jim.h>
void some_cpu_tck_rise(jim_device_t *dev);
jim_device_t *some_cpu(void);

@ -26,4 +26,5 @@ include $(top_srcdir)/Makefile.rules
noinst_LIBRARIES = libjim.a
libjim_a_SOURCES = \
tap.c
tap.c \
some_cpu.c

@ -0,0 +1,73 @@
/*
* $Id: tap.c $
*
* Copyright (C) 2008 Kolja Waschk <kawk>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdio.h>
#include <jim.h>
void some_cpu_tck_rise(jim_device_t *dev, int tms, int tdi)
{
// jim_print_tap_state(dev);
switch(dev->tap_state)
{
case RESET:
dev->sreg[0].reg[0] = 0x1; /* IDCODE instruction 0001 */
dev->sreg[1].reg[0] = 0x87654321; /* Load IDR (fake) */
dev->current_dr = 1; /* IDR */
break;
case UPDATE_IR:
switch(dev->sreg[0].reg[0])
{
case 0x1: /* IDCODE */
dev->sreg[1].reg[0] = 0x87654321; /* Load IDR (fake) */
dev->current_dr = 1; /* IDR */
break;
case 0xF: /* BYPASS */
default:
dev->current_dr = 0; /* BYPASS */
break;
}
break;
default:
break;
}
}
jim_device_t *some_cpu(void)
{
jim_device_t *dev;
const int reg_size[2] = { 4 /* IR */, 32 /* IDR */ };
dev = jim_alloc_device(2, reg_size);
if(dev)
{
dev->tck_rise = some_cpu_tck_rise;
}
return dev;
}

@ -0,0 +1,288 @@
/*
* $Id: tap.c $
*
* Copyright (C) 2008 Kolja Waschk <kawk>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <jim.h>
#include <jim/some_cpu.h>
const tap_state_t next_tap_state[16][2] =
{
/* RESET */ { IDLE, RESET },
/* SELECT_DR */ { CAPTURE_DR, SELECT_IR },
/* CAPTURE_DR */ { SHIFT_DR, EXIT1_DR },
/* SHIFT_DR */ { SHIFT_DR, EXIT1_DR },
/* EXIT1_DR */ { PAUSE_DR, UPDATE_DR },
/* PAUSE_DR */ { PAUSE_DR, EXIT2_DR },
/* EXIT2_DR */ { SHIFT_DR, UPDATE_DR },
/* UPDATE_DR */ { IDLE, SELECT_DR },
/* IDLE */ { IDLE, SELECT_DR },
/* SELECT_IR */ { CAPTURE_IR, RESET },
/* CAPTURE_IR */ { SHIFT_IR, EXIT1_IR },
/* SHIFT_IR */ { SHIFT_IR, EXIT1_IR },
/* EXIT1_IR */ { PAUSE_IR, UPDATE_IR },
/* PAUSE_IR */ { EXIT2_IR, EXIT2_IR },
/* EXIT2_IR */ { SHIFT_IR, UPDATE_IR },
/* UPDATE_IR */ { IDLE, SELECT_DR }
};
void jim_print_sreg(shift_reg_t *r)
{
printf("%08X", r->reg[0]);
}
void jim_print_tap_state(jim_device_t *dev)
{
printf(" tck rise, state=");
switch(dev->tap_state & 7)
{
case 0: printf((dev->tap_state==RESET) ? "RESET":"IDLE" ); break;
case 1: printf("SELECT"); break;
case 2: printf("CAPTURE"); break;
case 3: printf("SHIFT"); break;
case 4: printf("EXIT1"); break;
case 5: printf("PAUSE"); break;
case 6: printf("EXIT2"); break;
default: printf("UPDATE"); break;
};
if(dev->tap_state & 7)
{
if(dev->tap_state & 8)
{
printf("_IR="); jim_print_sreg(&dev->sreg[0]);
}
else
{
printf("_DR");
if(dev->current_dr != 0)
{
printf("=");
jim_print_sreg(&dev->sreg[dev->current_dr]);
}
};
};
printf("\n");
}
void jim_set_trst(jim_state_t *s, int trst)
{
s->trst = trst;
}
int jim_get_trst(jim_state_t *s)
{
return s->trst;
}
int jim_get_tdo(jim_state_t *s)
{
if(s->last_device_in_chain == NULL) return 0;
return s->last_device_in_chain -> tdo;
}
void jim_tck_rise(jim_state_t *s, int tms, int tdi)
{
jim_device_t *dev;
for(dev = s->last_device_in_chain; dev; dev = dev->prev)
{
int dev_tdi;
int i, n;
shift_reg_t *sr;
uint32_t *reg;
dev_tdi = (dev->prev != NULL) ? dev->prev->tdo : tdi;
if(dev->tck_rise != NULL) dev->tck_rise(dev, tms, dev_tdi);
if(dev->tap_state & 8)
{
sr = &(dev->sreg[0]);
}
else
{
if(dev->current_dr == 0)
{
sr = NULL; /* BYPASS */
}
else
{
sr = &(dev->sreg[dev->current_dr]);
}
}
if(sr == NULL) /* BYPASS */
{
dev->tdo_buffer = dev_tdi;
}
else
{
reg = sr->reg;
if(dev->tap_state == SHIFT_IR || dev->tap_state == SHIFT_DR)
{
/* Start with LSW of shift register at index 0 */
n = (sr->len-1) / 32;
for(i=0; i < (sr->len-1)/32; i++)
{
reg[i] >>= 1;
if(reg[i+1] & 1) reg[i] |= 0x8000;
};
/* End with MSW at index i */
reg[i] >>=1;
if(dev_tdi != 0)
{
n = (sr->len & 31);
if(n == 0) n = 32;
reg[i] |= (1 << (n-1));
}
}
dev->tdo_buffer = reg[0] & 1;
}
dev->tap_state = next_tap_state[dev->tap_state][tms];
}
}
void jim_tck_fall(jim_state_t *s)
{
jim_device_t *dev;
for(dev = s->last_device_in_chain; dev; dev = dev->prev)
{
dev->tdo = dev->tdo_buffer;
if(dev->tck_fall != NULL) dev->tck_fall(dev);
}
}
jim_device_t *jim_alloc_device(int num_sregs, const int reg_size[])
{
int i, r;
jim_device_t *dev = (jim_device_t *)malloc(sizeof(jim_device_t));
if(dev == NULL)
{
printf("Out of memory\n");
return NULL;
}
dev->sreg =
(shift_reg_t *)malloc(num_sregs * sizeof(shift_reg_t));
if(dev->sreg == NULL)
{
free(dev);
printf("Out of memory\n");
return NULL;
}
for(r=0,i=0;i<num_sregs;i++)
{
dev->sreg[i].len = reg_size[i];
dev->sreg[i].reg =
(uint32_t*)calloc(((reg_size[i]+31)/32), sizeof(uint32_t));
if(dev->sreg[i].reg == NULL) r++;
}
if(r>0)
{
printf("Out of memory\n");
for(i=0;i<num_sregs;i++) if(dev->sreg[i].reg!=NULL) free(dev->sreg[i].reg);
free(dev->sreg);
free(dev);
return NULL;
}
dev->num_sregs = num_sregs;
dev->current_dr = 0;
dev->tck_rise = NULL;
dev->tck_fall = NULL;
dev->dev_free = NULL;
dev->tap_state = RESET;
dev->tdo = dev->tdo_buffer = 1;
return dev;
}
jim_state_t *jim_init(void)
{
jim_state_t *s;
s = (jim_state_t *)malloc(sizeof(jim_state_t));
if(s == NULL)
{
printf("Out of memory!\n");
return NULL;
};
s->trst = 0;
s->last_device_in_chain = some_cpu();
if(s->last_device_in_chain != NULL)
{
s->last_device_in_chain->prev = NULL;
}
else
{
printf("Out of memory!\n");
return NULL;
}
return s;
}
void jim_free(jim_state_t *s)
{
jim_device_t *dev, *pre;
if(s == NULL) return;
for(dev = s->last_device_in_chain; dev; dev=pre)
{
int i;
if(dev->dev_free != NULL) dev->dev_free(dev);
for(i=0;i<dev->num_sregs;i++)
{
free(dev->sreg[i].reg);
}
free(dev->sreg);
pre = dev->prev;
free(dev);
}
s->last_device_in_chain = NULL;
free(s);
}

@ -35,6 +35,15 @@
#include <cmd.h>
#include <jim.h>
/* private parameters of this cable driver */
typedef struct
{
jim_state_t *s;
}
jim_cable_params_t;
int
jim_cable_connect( char *params[], cable_t *cable )
{
@ -43,7 +52,31 @@ jim_cable_connect( char *params[], cable_t *cable )
return 1;
}
printf( _("JTAG target simulator JIM - work in progress!\n"));
cable->chain = NULL;
cable->params = (jim_cable_params_t *)malloc(sizeof(jim_cable_params_t));
if(cable->params != NULL)
{
jim_state_t *s;
s = jim_init();
if(s == NULL)
{
free(cable->params);
cable->params = NULL;
}
else
{
((jim_cable_params_t *)(cable->params))->s = s;
}
}
if(cable->params == NULL)
{
printf(_("Initialization failed.\n"));
return 1;
};
return 0;
}
@ -58,6 +91,11 @@ jim_cable_disconnect( cable_t *cable )
void
jim_cable_free( cable_t *cable )
{
if(cable->params != NULL)
{
jim_free( ((jim_cable_params_t*)(cable->params))->s );
free( cable->params );
};
free( cable );
}
@ -69,31 +107,45 @@ jim_cable_done( cable_t *cable )
static int
jim_cable_init( cable_t *cable )
{
printf( _("JTAG target simulator JIM - work in progress!\n"));
return 0;
}
static void
jim_cable_clock( cable_t *cable, int tms, int tdi, int n )
{
int i;
jim_cable_params_t *jcp = (jim_cable_params_t*)(cable->params);
for(i = 0; i < n; i++)
{
jim_tck_rise( jcp->s, tms, tdi );
jim_tck_fall( jcp->s );
}
}
static int
jim_cable_get_tdo( cable_t *cable )
{
return 0;
jim_cable_params_t *jcp = (jim_cable_params_t*)(cable->params);
return jim_get_tdo( jcp->s );
}
static int
jim_cable_get_trst( cable_t *cable )
{
return 0;
jim_cable_params_t *jcp = (jim_cable_params_t*)(cable->params);
return jim_get_trst( jcp->s );
}
static int
jim_cable_set_trst( cable_t *cable, int trst )
{
return jim_cable_get_trst( cable );
jim_cable_params_t *jcp = (jim_cable_params_t*)(cable->params);
jim_set_trst( jcp->s, trst );
return jim_get_trst( jcp->s );
}
static void

Loading…
Cancel
Save