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-d4ac073336b7master
parent
2b6e82c897
commit
3a1ec19c8c
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue