initial push

This commit is contained in:
Bernd Mueller
2026-06-17 13:44:30 +02:00
commit adfd70813f
372 changed files with 146450 additions and 0 deletions

33
m683xx/bdm-load/Makefile Normal file
View File

@@ -0,0 +1,33 @@
#TARGET_ARCH = -bi586-pc-linux-gnulibc1
#CC = egcc
CFLAGS += -Wall -ggdb -O2
CFLAGS += -Wstrict-prototypes
CFLAGS += ${TARGET_ARCH}
#/* Select right place or libraries with configured m68k-coff support */
LDLIBS += -lbfd
#CFLAGS += -I ./gdblibs
#LOCLIBS += ./gdblibs/libbfd.a ./gdblibs/libiberty.a
#LDFLAGS += -lintl
LDLIBS += -liberty
LDFLAGS += ${TARGET_ARCH}
all : bdm-load bdm_test tpudb
dep:
$(CC) $(CFLAGS) $(CPPFLAGS) -w -E -M *.c $(MORE_C_FILES) > depend
depend:
@touch depend
clean :
rm -f *.o *.lo *~ *.a *.so *.so.* depend
bdm-load : bdm-load.o bdmlib.o bdmflash.o ${LOCLIBS}
bdm_test : bdm_test.o bdmlib.o ${LOCLIBS}
tpudb : tpudb.o bdmlib.o tpudis.o ${LOCLIBS}
-include depend

188
m683xx/bdm-load/README Normal file
View File

@@ -0,0 +1,188 @@
BDM-LOAD snapshot 2003-08-15
This is attempt to rewrite bdm-load utility for 683xx based
embedded systems.
This code is in experimental and rewrite phase, it works for me,
but there is no warranty that it is useful or safe for others.
Except "bdm-load" program, two test utilities are build.
It is "bdm_test" program. It was my first experiment with
interfacing BDM library with stand-alone program.
The second project is to write free TPU debugger, but this
code does not do anything useful yet.
INSTALL
To compile and install "bdm-load" you need:
- mc683xx target system with BDM interface
- GCC compiler for your Linux system.
- BDM driver - latest version is attached into "bdm-load" archive
- BFD object file handling library
- some time and experience with Linux system and make utility
To be able load other formats than S-record and IntelHEX, you
need to link with BFD library with m68kcoff and/or m68kelf
targets. I have system wide BFD with all targets I use.
I build my Linux binutils configured by next line in created
source tree subdirectory i586-linux
---System wide multi binutils configuration-----------------------
../configure \
--with-ld --exec-prefix=/usr --prefix=/usr \
--enable-shared --enable-commonbfdlib --verbose --with-mmap \
--enable-targets=i586-pc-linux-gnulibc1,i386-a.out-linux,i386-coff,\
m68k-linux-elf,m68k-coff,m68k-a.out-linux,h8300-hitachi-coff,\
sparc-linux-elf,i586-win-pe,tic30-ti-coff,tic30-ti-aout
------------------------------------------------------------------
You need not to rebuild your system wide BFD. You can statically link
with "libbfd.a", "libiberty.a" and "bfd.h" taken, for example,
from GDB build tree configured for m68k-coff. Configuration of GDB
is bellow
---GDB for m683xx with BDM configuration--------------------------
../configure --target=m68k-bdm-coff --enable-gdbtk --with-x --verbose \
--enable-targets=m68k-linux-elf,m68k-coff,m68k-a.out-linux
------------------------------------------------------------------
To compile statically copy three needed files to gdblibs subdirectory
and change next lines in "Makefile" to form
CFLAGS += -I ./gdblibs
#LDFLAGS += -lbfd -liberty
LOCLIBS += ./gdblibs/libbfd.a ./gdblibs/libiberty.a
Prebuild version of "bdm-load" is attached to archive under name
"bdm-load-i586-linux-static".
PROGRAMMERS NOTES
Sources of "bdm-load" are in next files
bdmlib.c,bdmlib.h library for communication with CPU32
through BDM
bdmflash.c,bdmflash.h flash write and erase algorithms and
flash areas write filter routines
bdm-load.c loader command line and interactive
interface
It is necessary to add new entries into array flash_alg_infos_def
in "bdmflash.c" file for every new flash programming algorithm.
Flash types should be sorted from smallest to biggest.
RUNNING BDM-LOAD
Command line interface
Usage bdm-load [OPTIONS] file1 ...
-h --help - this help information!
-i --init-file=FILE - object file to initialize processor
-r --reset - reset target CPU before other operations
-c --check - check flash setup (needed for auto)
-e --erase - erase flash
-b --blankck - blank check of flash
-l --load - download listed filenames
--go[=address] - run target CPU from entry address
-M --mbar=val - setup 68360 MBAR register
-s --script - do actions and return
-d --bdm-delay=d - sets BDM driver speed/delay
-D --bdm-device - sets BDM device file
-f --flash=TYPE@ADR - select flash
For flash TYPE@ADR can be
{<TYPE>|auto}[@{csboot|cs<x>|<start>{+<size>|-<end>}}]
Examples
auto@csboot amd29f400@0x800000-0x87ffff auto@0+0x80000
If auto type or cs address is used, check must be
specified to take effect.
Known flash types/algorithms :
amd29f010x2 amd29f040 amd29f400 amd29f800 at49f040x2 amd29f080x4
Possible commands in interactive mode :
- run
starts CPU32 execution at address taken from last downloaded
object file. If no file is loaded, it starts at address
fetched during last reset command.
- reset
resets CPU32 and if no entry address is defined, PC address is
remembered
- erase
sets erase request and starts erase procedure
-load [<object-file>]
sets load request and starts download of files from
object file list.
if <object-file> is specified, object file list is cleared
and specified file is added on-to list
- exit/quit
exit interactive mode and return to shell
- dump <address> <bytes>
dumps memory contents from specified address.
bytes specifies number of bytes to print.
- stat
shows CPU32 state, does not require CPU32 to stop
- check
checks flash memories at specified ranges,
if auto type or "cs" address is specified for some
flash, CS address is fetched and flash autodetection
is run
- autoset
same as check, but all flash types are revalidated
- stop
stops CPU32 and clears all reset, erase, load and run
requests
- make
make in current directory is called
The simplest way to initialize CPU32 chipselect subsystem
and other SIM parameters is to provide "cpu32init" file
in same directory as "bdm-load" is started from.
The "cpu32init" file is processed at every reset of target.
The syntax of the macro file is:
<cmd-letter> <num1> <num2> <num3>
The nums are either in hex (form 0x), in decimal (form 123) or in octal
(form 0234)
The meaning of the nums depends on the command letter:
w or W means: (write)
write to address (num1) contents (num2) length is (num3) bytes. Only
1, 2, 4 bytes are permitted.
z or Z means: (zap, zero)
fill memory area beginning at (num1) with byte value (num2) length
(num3) bytes.
c or C means: (copy)
copy memory area from (num1) to (num2) with length (num3) bytes.
m or M is new command to set 68360 MBAR register.
the MBAR register is set to value of (num3)
Empty lines and lines with a leading '#' are ignored. See GDB-BDM
patches for more information.
For more questions contact
Pavel Pisa <pisa@cmp.felk.cvut.cz>

903
m683xx/bdm-load/bdm-load.c Normal file
View File

@@ -0,0 +1,903 @@
/*
* Adapted from....
*
* Remote debugging interface for 683xx via Background Debug Mode
* needs a driver, which controls the BDM interface.
* written by G.Magin
* (C) 1995 Technische Universitaet Muenchen, Lehrstuhl fuer Prozessrechner
*
* D.Jeff Dionne
* (C) 1995, Dionne & Associates
*
* V0.2 Enhancements:
* Added command line arguments
* Rewritten flash programming functions for more flexability
*
* Andrew Dennison <adennison@swin.edu.au>
* December 1995
*
* Modified by Pavel Pisa pisa@cmp.felk.cvut.cz 2000
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* NOTE:
* This file is assumed to be runnable only on Linux/i386 because of
* HW-restrictions: the driver is currently only available on i386-Linux
* So byte-swapping and alignment is handled directly, violating the
* GNU-coding standards. However, the "dirty spots" are restricted in this
* file.
*
* If anybody wants to port to e.g. Sparc, byte-sex has to be handled in
* a more general way.
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <getopt.h>
#include <bfd.h>
#include "bdm.h"
#include "bdmlib.h"
#include "bdmflash.h"
/*
* Global Types
**************
*/
typedef caddr_t CORE_ADDR;
#define END_MACRO 0
#define BEGIN_MACRO 1
#define NO_SUFFIX_MACRO 2
#define DEBUG_MESSAGES
#define swap_l(x) (x>>24) | ((x>>8)&0xff00) | ((x<<8)&0xff0000) | ((x&0xff)<<24)
#define AUTO_ADR_CSBOOT ((caddr_t)-100)
#define AUTO_ADR_CSX ((caddr_t)-100+1)
typedef struct str_list_t{
char **items;
int count;
int alloccnt;
}str_list_t; /* to store list of filenames */
/*
* Global Variables
******************
*/
char hashmark = 0; /* flag set by "set hash" */
int bdm_autoreset = 0; /* automatic reset before load */
int bdm_ttcu = 0; /* time to come up for init by rom */
char *initname; /* need reimplement !!!!!!!!! */
char *bdm_dev_name; /* device name */
static char *entry_name=NULL;
int
mem_dump (char *buf)
{
caddr_t adr;
long len, l;
int i, ret;
u_char mem[16];
char *dump_fname = NULL;
FILE *dump_file = NULL;
i = sscanf (buf, " %li %li %as", &l, &len, &dump_fname);
if (i < 2)
{
printf ("use : dump address len [file]\n");
return -1;
}
if(dump_fname && *dump_fname)
{ dump_file=fopen(dump_fname,"wb");
if(dump_file==NULL)
{
printf ("mem_dump : file \"%s\" open for write error\n", dump_fname);
free(dump_fname);
return -1;
}
free(dump_fname);
}
adr = (caddr_t) l;
while (len)
{
l = len > 16 ? 16 : len;
ret = bdmlib_read_block (adr, l, mem);
if (ret != l)
{
printf ("error to read 0x%lx len 0x%lx ret %d\n",
(u_long) adr, l, ret);
if(dump_file!=NULL)
fclose(dump_file);
return -2;
}
printf ("%06lx:", (u_long) adr);
for (i = 0; i < l; i++)
printf (" %02x", mem[i]);
printf ("\n");
if(dump_file!=NULL)
fwrite(mem, l, 1, dump_file);
len -= l;
adr += l;
}
if(dump_file!=NULL)
fclose(dump_file);
return 0;
}
int
mem_modify (char *buf)
{
int ret;
char *p;
long addr;
long count=0;
long capacity=0;
u_char *data=NULL;
u_char val;
while(*buf&&!isblank(*buf)) buf++;
while(*buf&&isblank(*buf)) buf++;
if(!*buf)
{ usage_error:
if(data) free(data);
printf ("use : modify address byte1 byte2 ...\n");
return -1;
}
addr=strtol(buf,&p,0);
if(p==buf) goto usage_error;
buf=p;
capacity=128;
data=malloc(capacity);
while(*buf&&isblank(*buf)) buf++;
while(*buf){
val=strtol(buf,&p,0);
if(p==buf) goto usage_error;
buf=p;
if(count>=capacity){
capacity*=2;
data=realloc(data,capacity);
if(!data) goto usage_error;
}
data[count++]=val;
while(*buf&&isblank(*buf)) buf++;
}
ret=bdmlib_wrb_filt(bdmlib_bfilt, (caddr_t)addr, count, data);
//if(ret!=count)
printf("bdmlib_wrb_filt: addr=0x%08lx count=%ld return=%ld\n",
(long)addr,(long)count,(long)ret);
if(data) free(data);
return ret;
}
int
cpu_get_rpc(u_int32_t *val)
{
int ret;
u_int32_t rpc;
if ((ret = bdmlib_get_sys_reg (BDM_REG_RPC, &rpc)) < 0)
return ret;
*val=swap_l(rpc);
return 0;
}
int
cpu_stat (char *buf)
{
int ret;
u_int32_t rpc;
ret = bdmlib_getstatus ();
printf ("MCU ");
if (ret & BDM_TARGETRESET)
printf ("Reset ");
if (ret & BDM_TARGETSTOPPED)
printf ("Stopped ");
if (ret & BDM_TARGETPOWER)
printf ("NoPower ");
if (ret & BDM_TARGETNC)
printf ("NoConnect ");
printf ("\n");
if (ret & BDM_TARGETSTOPPED)
{
if ((ret = cpu_get_rpc (&rpc)) < 0)
return ret;
printf ("RPC=%x\n",rpc);
}
return 0;
}
int
flash_check_one (bdmlib_bfilt_t *filt, int autoset)
{
flash_alg_info_t const *alg;
caddr_t adr;
flash_d_t readid[2];
int ret;
alg = (flash_alg_info_t *) filt->info;
adr = filt->begin_adr;
if(filt->flags&BDMLIB_FILT_AUTO)
{
autoset|=2;
if(adr==filt->end_adr)
autoset|=4;
}
if ((autoset & 4)&&(adr>=AUTO_ADR_CSBOOT)&&(adr<=AUTO_ADR_CSBOOT+12))
{
u_int32_t csx_opt, csx_base, csx_size;
caddr_t cpu32csopt_adr;
cpu32csopt_adr=(caddr_t)0xfffa48+(adr-AUTO_ADR_CSBOOT)*4;
if (bdmlib_read_var (cpu32csopt_adr, BDM_SIZE_LONG, &csx_opt) >= 0)
{
static u_int32_t csx_sizes[]={1<<11,1<<13,1<<14,1<<16,
1<<17,1<<18,1<<19,1<<20};
csx_base = (csx_opt >> 8) & 0xfff800;
filt->begin_adr = (caddr_t) csx_base;
csx_size = csx_sizes[(csx_opt >> 16) & 0x7];
filt->end_adr = (caddr_t) (csx_base + csx_size - 1);
if(adr==AUTO_ADR_CSBOOT)
printf ("Flash addresses taken from CSBOOT\n");
else
printf ("Flash addresses taken from CS%d\n",
(int)(adr-AUTO_ADR_CSX));
printf ("Start %06lX End %06lX\n",
(long) filt->begin_adr, (long) filt->end_adr);
}
}
adr = filt->begin_adr;
ret = bdmflash_check_id (alg, adr, readid);
if((ret >= 0)&&(autoset&4)&&(filt->begin_adr==filt->end_adr))
filt->end_adr=filt->begin_adr+alg->addr_mask;
printf ("Flash@%06lX-%06lX ManID %08X DevID %08X\n",
(long) adr, (long) filt->end_adr,
(unsigned) readid[0], (unsigned) readid[1]);
if (ret >= 0)
{
printf ("Flash ID is OK\nUsed algorithm %s\n", alg->alg_name);
return 1;
}
if (!autoset & 2)
{
printf ("Flash parameters are incorrect !!!\n");
return -1;
}
alg = bdmflash_alg_probe (adr);
if (alg == NULL)
{
printf ("Flash parameters cannot be probed\n");
return -1;
}
ret = bdmflash_check_id (alg, adr, readid);
if (ret < 0)
{
printf ("Probed parameters are incorrect\n");
return -1;
}
filt->info = (void *) alg;
if(filt->begin_adr==filt->end_adr)
filt->end_adr=filt->begin_adr+alg->addr_mask;
printf ("Probed flash parameters\n");
printf ("Flash@%06lX-%06lX ManID %04X DevID %04X\n",
(long) filt->begin_adr, (long) filt->end_adr,
(unsigned) readid[0], (unsigned) readid[1]);
printf ("Used algorithm %s\n", alg->alg_name);
return 1;
}
int
flash_check(char *buf, int autoset)
{
int ret;
bdmlib_bfilt_t *filt = bdmlib_bfilt;
printf("\n");
while(filt)
{
if(filt->flags&BDMLIB_FILT_FLASH)
{
ret=flash_check_one(filt,autoset);
printf("\n");
if(ret<0)
return ret;
}
filt=filt->next;
}
return 0;
}
int
flash_erase(void)
{
int ret;
bdmlib_bfilt_t *filt = bdmlib_bfilt;
while(filt)
{
if(filt->flags&BDMLIB_FILT_FLASH)
{
ret=bdmflash_erase_filt (filt, (caddr_t) 0, 0);
if(ret<0)
return ret;
}
filt=filt->next;
}
return 0;
}
int
flash_blankck(void)
{
int ret,sum=0;
bdmlib_bfilt_t *filt = bdmlib_bfilt;
while(filt)
{
if(filt->flags&BDMLIB_FILT_FLASH)
{
ret=bdmflash_blankck_filt (filt, (caddr_t) 0, 0);
if(ret<0)
return ret;
sum+=ret;
}
filt=filt->next;
}
return sum;
}
/* bdmlib_propeller(stdout); */
int
flash_setup(char *buf)
{
char *p,*r;
int i;
caddr_t begin_adr=(caddr_t)(0);
caddr_t end_adr=(caddr_t)(0);
char alg_name[32];
flash_alg_info_t const *alg=NULL;
bdmlib_bfilt_t *filt;
while(*buf&&isblank(*buf)) buf++;
if((p=strchr(buf,'@'))!=NULL){/* '@' character in specification */
i=p-buf;
if(i>=sizeof(alg_name)-1)
i=sizeof(alg_name)-1;
strncpy(alg_name,buf,i);
alg_name[i]=0;
p++;
if(!strncmp(p,"csboot",6)){ /* take address from CSBOOT */
p+=6;
end_adr=begin_adr=AUTO_ADR_CSBOOT;
}else if(!strncmp(p,"cs",2)){
p+=2;
end_adr=begin_adr=AUTO_ADR_CSX+strtoul(p,&r,0);
if((p==r)||(begin_adr>AUTO_ADR_CSX+11)){
fprintf(stderr,"%s : bad chipselect format\n",buf);
return -1;
}
p=r;
}else{ /* take begin address after '@' */
end_adr=begin_adr=(caddr_t)strtoul(p,&r,0);
if(p==r){
fprintf(stderr,"%s : bad begin address format\n",buf);
return -1;
}
p=r;
if(*p=='+'){ /* take end address from size */
end_adr=begin_adr+strtoul(++p,&r,0)-1;
if(p==r){
fprintf(stderr,"%s : bad size format\n",buf);
return -1;
}
p=r;
} else if(*p=='-') { /* take absolute end address */
end_adr=(caddr_t)strtoul(++p,&r,0);
if(p==r){
fprintf(stderr,"%s : bad end address format\n",buf);
return -1;
}
p=r;
}
}
while(*buf&&isblank(*buf)) buf++;
if(*p){
fprintf(stderr,"%s : extra characters in specification %s\n",buf,p);
return -1;
}
}
else {
end_adr=begin_adr=AUTO_ADR_CSBOOT;
strncpy(alg_name,buf,sizeof(alg_name)-1);
}
if(strcmp(alg_name,"auto")){
int alg_indx=0;
do{
alg=flash_alg_infos[alg_indx++];
if(alg==NULL){
fprintf(stderr,"%s : unknown flash type or algorithm\n",alg_name);
return -1;
}
}while(strcmp(alg_name,alg->alg_name));
}
filt=(bdmlib_bfilt_t*)malloc(sizeof(bdmlib_bfilt_t));
if(filt==NULL){
fprintf(stderr,"No memory for flash_setup\n");
return -1;
}
filt->flags=BDMLIB_FILT_FLASH;
if(alg==NULL){
filt->flags|=BDMLIB_FILT_AUTO;
filt->info=flash_alg_infos[0];
} else filt->info=(void *)alg;
filt->begin_adr=begin_adr;
filt->end_adr=end_adr;
if(begin_adr==end_adr){
filt->flags|=BDMLIB_FILT_AUTO;
};
filt->filt_id=1;
filt->wrb_filt=&bdmflash_wrb_filt;
filt->next=bdmlib_bfilt;
bdmlib_bfilt=filt;
return 0;
}
int
str_list_add(str_list_t *list, char *str)
{
char **p;
int a;
if(list->count>=list->alloccnt)
{
a=list->alloccnt+5;
if(list->items==NULL)
p=(char**)malloc(sizeof(char *)*a);
else
p=(char**)realloc(list->items,sizeof(char *)*a);
if(p==NULL) return -1;
list->items=p;
list->alloccnt=a;
}
list->items[list->count++]=str;
return list->count;
}
void str_list_clear(str_list_t *list)
{
while(list->count--)
{
if(list->items[list->count]!=NULL)
free(list->items[list->count]);
}
list->alloccnt=list->count=0;
if(list->items!=NULL) free(list->items);
list->items=NULL;
}
/*
* Main Program
**************
*/
int
main (int argc, char *argv[])
{
int done;
int error;
int ret;
static int print_help = 0; /* Help */
static int reset = 0; /* Reset target */
static int check = 0; /* Check flash configuration */
static int erase = 0; /* Erase flash */
static int blankck = 0; /* Check, that flash is blank */
static int load = 0; /* Load files to flash */
static int run = 0; /* Run target from entry point */
static int script = 0; /* Batch mode */
static int bdm_delay = 0; /* Delay/speed for BDM driver */
static int set_mbar_fl = 0; /* Set MBAR requested */
static u_long mbar_val = 0;
static u_long entry_pt=0;
str_list_t files2load={0,}; /* List of filenames to load */
int cmd;
char buf[255];
char *p;
int i;
/* initialize global flash control variables */
initname = strdup ("ram_init.srec"); /* default init file for EFI332 */
/* initialize name of bdm device */
bdm_dev_name = strdup ("/dev/bdm");
/* start bdmlib debugging */
bdmlib_setdebug (0);
/* Parse arguments and options. Taken from GDB. */
{
int c;
/* When var field is 0, use flag field to record the equivalent
short option (or arbitrary numbers starting at 10 for those
with no equivalent). */
static struct option long_options[] =
{
{"help", no_argument, &print_help, 1},
{"h", no_argument, &print_help, 1},
{"flash", required_argument, 0, 'f'},
{"f", required_argument, 0, 'f'},
{"init-file", required_argument, 0, 'i'},
{"i", required_argument, 0, 'i'},
{"reset", no_argument, &reset, 1},
{"r", no_argument, &reset, 1},
{"check", no_argument, &check, 1},
{"c", no_argument, &check, 1},
{"erase", no_argument, &erase, 1},
{"e", no_argument, &erase, 1},
{"blankck", no_argument, &blankck, 1},
{"b", no_argument, &blankck, 1},
{"load", no_argument, &load, 1},
{"l", no_argument, &load, 1},
{"go", optional_argument, NULL, 'g'},
{"g", no_argument, &run, 1},
{"mbar", required_argument, NULL, 'M'},
{"M", required_argument, NULL, 'M'},
{"script", no_argument, &script, 1},
{"s", no_argument, &script, 1},
{"bdm-delay", required_argument, 0, 'd'},
{"d", required_argument, 0, 'd'},
{"bdm-device", required_argument, 0, 'D'},
{"D", required_argument, 0, 'D'},
{0, no_argument, 0, 0}
};
while (1)
{
int option_index;
c = getopt_long_only (argc, argv, "",
long_options, &option_index);
if (c == EOF)
break;
/* Long option that takes an argument. */
if (c == 0 && long_options[option_index].flag == 0)
c = long_options[option_index].val;
switch (c)
{
case 0:
/* Long option that just sets a flag. */
break;
case 'f':
/* Setup flash region */
if(flash_setup(optarg)<0)
exit(1);
break;
case 'g':
/* Run target from default or optional entry point */
run=1;
if (optarg) {
if (entry_name) free (entry_name);
entry_name = strdup (optarg);
}
break;
case 'M':
/* Set MBAR register */
mbar_val=strtoul(optarg,&p,0);
set_mbar_fl=1;
if(optarg==p){
fprintf(stderr,"%s: bad numeric format for MBAR\n",argv[0]);
exit(1);
}
break;
case 'D':
if (bdm_dev_name)
free (bdm_dev_name);
bdm_dev_name = strdup (optarg);
break;
case 'i':
/* Init File */
if(initname)
free(initname);
initname = strdup (optarg);
break;
case 'd':
/* BDM driver delay */
bdm_delay=strtol(optarg,&p,0);
if(optarg==p){
fprintf(stderr,"%s: bad numeric format for BDM delay\n",argv[0]);
exit(1);
}
break;
case '?':
fprintf(stderr,
"Use `%s --help' for a complete list of options.\n",
argv[0]);
exit (1);
}
}
}
if(print_help)
{
printf ("Usage bdm-load [OPTIONS] file1 ...\n"
"\t-h --help - this help information!\n"
"\t-i --init-file=FILE - object file to initialize processor\n"
"\t-r --reset - reset target CPU before other operations\n"
"\t-c --check - check flash setup (needed for auto)\n"
"\t-e --erase - erase flash\n"
"\t-b --blankck - blank check of flash\n"
"\t-l --load - download listed filenames\n"
"\t --go[=address] - run target CPU from entry address\n"
"\t-M --mbar=val - setup 68360 MBAR register\n"
"\t-s --script - do actions and return\n"
"\t-d --bdm-delay=d - sets BDM driver speed/delay\n"
"\t-D --bdm-device - sets BDM device file\n"
"\t-f --flash=TYPE@ADR - select flash\n"
"For flash TYPE@ADR can be\n"
" {<TYPE>|auto}[@{csboot|cs<x>|<start>{+<size>|-<end>}}]\n"
"Examples\n"
" auto@csboot amd29f400@0x800000-0x87ffff auto@0+0x80000\n"
"If auto type or cs address is used, check must be\n"
"specified to take effect.\n"
"Known flash types/algorithms :\n");
for(i=0;flash_alg_infos[i]!=NULL;i++)
printf(" %s",flash_alg_infos[i]->alg_name);
printf("\n\n");
exit (0);
}
while(optind<argc)
str_list_add(&files2load,strdup(argv[optind++]));
#ifdef DEBUG_MESSAGES
printf ("Init file is: %s\n", initname);
for(i=0;i<files2load.count;i++){
printf ("Object file : %s\n", files2load.items[i]);
}
printf ("Actions to do%s%s%s%s%s\n", (reset) ? " Reset" : "",
(check) ? " Check" : "", (erase) ? " Erase" : "",
(blankck) ? " Blankck" : "", (load) ? " Load" : "");
#endif
/* Connect to target */
if((ret=bdmlib_open (bdm_dev_name)) != BDM_NO_ERROR) {
printf("%s: Open \"%s\" reports %s\n",
argv[0],bdm_dev_name,bdmlib_geterror_str(ret));
exit(1);
}
if((ret=bdmlib_setioctl (BDM_SPEED, bdm_delay)) != BDM_NO_ERROR) {
printf("%s: Set bdm_delay failed with error %s\n",
argv[0],bdmlib_geterror_str(ret));
exit(1);
}
hashmark = 1;
if(set_mbar_fl) {
printf ("MBAR setup to %08lX\n",mbar_val);
if(bdmlib_set_mbar(mbar_val) != BDM_NO_ERROR) {
printf("%s: MBAR setup failed with error %s\n",
argv[0],bdmlib_geterror_str(ret));
exit(1);
}
}
if(files2load.count>0)
bdmlib_do_load_macro (files2load.items[0], BEGIN_MACRO);
done = cmd = 0;
do
{
error = 0;
if (reset)
{
/* bdmlib_init(); */
if(bdmlib_reset()<0)
{
printf ("Reset Failed\n");
error=4;
}
else
{
if(cpu_stat(NULL)<0)
{
printf ("CPU Stat Failed\n");
error=4;
}
else
{
u_int32_t rpc;
reset = 0;
if(entry_pt==0)
{
cpu_get_rpc (&rpc);
entry_pt=rpc;
}
}
}
}
if (check && !error)
{
if(flash_check(NULL,0)<0)
{
printf ("Flash Check Failed\n");
error=3;
}
else
check = 0;
}
if (erase && !error)
{
printf ("Erasing Flash...");
fflush (stdout);
if (flash_erase() >= 0)
{
printf ("done.\n");
erase = 0;
}
else
{
printf ("Erase Failed\n");
error = 2;
}
}
if (blankck && !error)
{
int res;
printf ("Flash blank check ...\n");
res=flash_blankck();
if(!res){
printf("Flash blank check OK\n");
blankck = 0;
}else{
error = 5;
if(res<0) printf("Flash blank check FAILED\n");
else printf("Flash is NOT erased\n");
}
}
if (load && !error)
{
bdmlib_load_use_lma = 1;
for(i=0;i<files2load.count;i++){
printf("Loading file : %s\n",files2load.items[i]);
fflush(stdout);
if((ret=bdmlib_load(files2load.items[i], entry_name, &entry_pt))<0)
{
printf ("Load Failed %d\n", ret);
error = 1; //break;
}
}
if(!error) load = 0;
bdmlib_load_use_lma = 0;
}
if (run && !error)
{
printf ("starting at 0x%lx\n", entry_pt);
bdmlib_set_sys_reg (BDM_REG_RPC, entry_pt);
bdmlib_go ();
run=0;
}
if(script)
exit(0);
printf ("bdm-load %d> ", ++cmd);
fgets (buf, 250, stdin);
if (!strncmp (buf, "run", 3))
{
run = 1;
}
if (!strncmp (buf, "reset", 5))
{
reset = 1;
}
if (!strncmp (buf, "erase", 5))
erase = 1;
if (!strncmp (buf, "blankck", 5))
blankck = 1;
if (!strncmp (buf, "load", 4))
{
load = 1;
if ((strlen (buf) > 5))
{
str_list_clear(&files2load);
str_list_add(&files2load,strdup(&buf[5]));
}
}
if (!strncmp (buf, "exit", 4) || !strncmp (buf, "quit", 4))
done = 1;
if (!strncmp (buf, "dump", 4))
mem_dump (buf + 4);
if (!strncmp (buf, "modify", 3))
mem_modify (buf + 3);
if (!strncmp (buf, "stat", 4))
cpu_stat (buf + 4);
if (!strncmp (buf, "check", 5))
flash_check (buf + 5, 0);
if (!strncmp (buf, "autoset", 5))
flash_check (buf + 5, 0xff);
if (!strncmp (buf, "stop", 5))
{
bdmlib_ioctl(BDM_STOP_CHIP);
reset=check=erase=blankck=load=run=0;
}
if (!strncmp (buf, "make", 4))
system (buf);
if (!strncmp (buf, "help", 4) || !strncmp (buf, "?", 1))
{
printf("Next commands are accepted :\n"\
" run - enable full speed ran of target CPU\n"\
" stop - stop target CPU\n"\
" reset - reset target\n"\
" erase - erase all configured FLASH chips\n"\
" blankck - check blank state of chips\n"\
" load - loand all object files specified\n"\
" at command line to RAM or FLASH\n"\
" using VMA addresses, name of file to\n"\
" can be optionaly specified after \"load\"\n"\
" dump <from> <len> - dump target memory\n"\
" modify <from> <byte> ... - modify target memory (even flash)\n"\
" state - print target status\n"\
" check - check presence of configured chips\n"\
" autoset - set FLASH chip types from their IDs\n"\
" make <par> - call make command in current directory\n"\
" quit - leave loader\n"\
);
}
}
while (!done);
str_list_clear(&files2load);
exit (0);
}

View File

@@ -0,0 +1,25 @@
Begin4
Title: bdm-load
Version: 030815
Entered-date: 2003-08-15
Description: Flash writer utility for 683xx target systems through
Background Debug Mode interface for Motorola CPU32 and Linux
Both Public Domain and ICD interfaces are supported.
Code contains first experimental tests of GPLed TPU debugger
project.
* More info about related software and BDM driver at
http://cmp.felk.cvut.cz/~pisa
http://cmp.felk.cvut.cz/~pisa/m683xx/bdm_driver.html
Keywords: debugger GDB m68k 68332 683xx BDM flash embedded TPU
Author: jeff@uclinux.org (D.Jeff Dionne)
adennison@swin.edu.au (Andrew Dennison)
pisa@cvlinux.felk.cvut.cz (Pavel Pisa)
Maintained-by: pisa@cvlinux.felk.cvut.cz (Pavel Pisa)
Primary-site: metalab.unc.edu /pub/Linux/devel/debuggers
210 kB bdm-load-030519.tar.gz
Alternate-site: ftp.cygnus.com /pub/embedded
210 kB bdm-load-030519.tar.gz
Original-site: freeware.aus.sps.mot.com
Platforms: Linux 2.0.xx, 2.2.yy, 2.4.zz ( last tested 2.5.69 )
Copying-policy: GPL
End

115
m683xx/bdm-load/bdm.h Normal file
View File

@@ -0,0 +1,115 @@
#ifndef LINUX_BDM_H
#define LINUX_BDM_H
/*
* $Id: bdm.h,v 1.1 2003/06/04 01:31:32 ppisa Exp $
*
* Linux Device Driver for Public Domain BDM Interface
* based on the PD driver package by Scott Howard, Feb 93
* ported to Linux by M.Schraut
* tested for kernel version 1.2.4
* (C) 1995 Technische Universitaet Muenchen, Lehrstuhl fuer Prozessrechner
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define BDM_MAJOR_NUMBER 53
/* error codes */
#define BDM_FAULT_UNKNOWN -610 /*Error-definitions*/
#define BDM_FAULT_POWER -611
#define BDM_FAULT_CABLE -612
#define BDM_FAULT_RESPONSE -613 /*NOT Ready */
#define BDM_FAULT_RESET -614
#define BDM_FAULT_PORT -615
#define BDM_FAULT_BERR -616
#define BDM_FAULT_NVC -617 /*no valid command */
/* Debug Levels */
#define BDM_DEBUG_NONE 0
#define BDM_DEBUG_SOME 1
#define BDM_DEBUG_ALL 2
/* supported ioctls */
#define BDM_INIT 0 /* no argument */
#define BDM_DEINIT 1 /* no argument */
#define BDM_RESET_CHIP 2 /* no argument */
#define BDM_RESTART_CHIP 3 /* no argument */
#define BDM_STOP_CHIP 4 /* no argument */
#define BDM_STEP_CHIP 5 /* no argument */
#define BDM_GET_STATUS 6 /* no argument */
#define BDM_SPEED 7 /* arg = speed */
#define BDM_RELEASE_CHIP 8 /* no argument */
#define BDM_DEBUG_LEVEL 9 /* arg = level */
#define BDM_GET_VERSION 10 /* arg = &int */
#define BDM_SENSECABLE 11 /* arg =on/off */
#define BDM_NORETURN 0 /* no error, no ret value */
/* functional bits of ioctl BDM_GET_STATUS */
#define BDM_TARGETRESET (1<<0) /* Target reset */
#define BDM_TARGETSTOPPED (1<<2) /* Target (was already) stopped */
#define BDM_TARGETPOWER (1<<3) /* Power failed */
#define BDM_TARGETNC (1<<4) /* Target not Connected */
/* command codes for bdm interface */
#define BDM_RREG_CMD 0x2180
#define BDM_WREG_CMD 0x2080
#define BDM_RSREG_CMD 0x2580
#define BDM_WSREG_CMD 0x2480
#define BDM_READ_CMD 0x1900
#define BDM_WRITE_CMD 0x1800
#define BDM_DUMP_CMD 0x1d00
#define BDM_FILL_CMD 0x1c00
#define BDM_GO_CMD 0x0c00
#define BDM_CALL_CMD 0x0800
#define BDM_RST_CMD 0x0400
#define BDM_NOP_CMD 0x0000
/* system register for RSREG/WSREG */
#define BDM_REG_RPC 0x0
#define BDM_REG_PCC 0x1
#define BDM_REG_SR 0xb
#define BDM_REG_USP 0xc
#define BDM_REG_SSP 0xd
#define BDM_REG_SFC 0xe
#define BDM_REG_DFC 0xf
#define BDM_REG_ATEMP 0x8
#define BDM_REG_FAR 0x9
#define BDM_REG_VBR 0xa
/* system register for RREG/WREG */
#define BDM_REG_D0 0x0
#define BDM_REG_D1 0x1
#define BDM_REG_D2 0x2
#define BDM_REG_D3 0x3
#define BDM_REG_D4 0x4
#define BDM_REG_D5 0x5
#define BDM_REG_D6 0x6
#define BDM_REG_D7 0x7
#define BDM_REG_A0 0x8
#define BDM_REG_A1 0x9
#define BDM_REG_A2 0xa
#define BDM_REG_A3 0xb
#define BDM_REG_A4 0xc
#define BDM_REG_A5 0xd
#define BDM_REG_A6 0xe
#define BDM_REG_A7 0xf
/* op size for READ/WRITE */
#define BDM_SIZE_BYTE 0x0000
#define BDM_SIZE_WORD 0x0040
#define BDM_SIZE_LONG 0x0080
#endif

272
m683xx/bdm-load/bdm_test.c Normal file
View File

@@ -0,0 +1,272 @@
#include <sys/types.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "bdm.h"
#include "bdmlib.h"
char* TestSW(int argc,char *argv[],char swch);
#define swap_l(x) (x>>24) | ((x>>8)&0xff00) | ((x<<8)&0xff0000) | ((x&0xff)<<24)
/* for BDMLIB to work */
char hashmark;
int bdm_autoreset;
int bdm_ttcu;
int bdm_step_chip()
{
int ret;
u_int32_t rpc;
if (!bdmlib_isopen())
return BDM_ERR_NOT_OPEN;
if (!(bdmlib_getstatus()&BDM_TARGETSTOPPED))
if((ret=bdmlib_ioctl(BDM_STOP_CHIP)<0))
{return ret;};
if((ret=bdmlib_get_sys_reg(BDM_REG_RPC, &rpc))<0) return ret;
printf("RPC=%x\n",swap_l(rpc));
ret=bdmlib_ioctl(BDM_STEP_CHIP);
if((ret=bdmlib_get_sys_reg(BDM_REG_RPC, &rpc))<0) return ret;
printf("RPC=%x\n",swap_l(rpc));
return ret;
}
int bdm_show_regs(void)
{
u_int reg;
if (!bdmlib_isopen())
return BDM_ERR_NOT_OPEN;
bdmlib_get_reg(BDM_REG_D0, &reg);
return 0;
};
int rd_test(void)
{
u_int16_t val;
caddr_t adr=(caddr_t)0xFFAA;
int counter=0;
if (!bdmlib_isopen())
return BDM_ERR_NOT_OPEN;
while(1){
if(bdmlib_read_var(adr,BDM_SIZE_WORD,&val)<0)
goto mem_op_error;
//usleep(1);
if(counter++>=10000){
printf(".");
fflush(stdout);
counter=0;
}
}
return 0;
mem_op_error:
printf("Memory read error\n");
return -1;
};
int wr_test(void)
{
u_int16_t val=0xAAAA;
caddr_t adr=(caddr_t)0xFFAA;
int counter=0;
if (!bdmlib_isopen())
return BDM_ERR_NOT_OPEN;
while(1){
if(bdmlib_write_var(adr,BDM_SIZE_WORD,val)<0)
goto mem_op_error;
//usleep(1);
if(counter++>=10000){
printf(".");
fflush(stdout);
counter=0;
}
}
return 0;
mem_op_error:
printf("Memory write error\n");
return -1;
};
int step_test(void)
{
int counter=0;
if (!bdmlib_isopen())
return BDM_ERR_NOT_OPEN;
while(1){
if(bdmlib_ioctl(BDM_STEP_CHIP)<0)
goto step_op_error;
usleep(1);
if(counter++>=10000){
printf(".");
fflush(stdout);
counter=0;
}
}
return 0;
step_op_error:
printf("Stepping error\n");
return -1;
};
int main(int argc, char *argv[])
{
int quit_fl=0;
int ret;
char c;
char *p;
char file_name[100]="";
char bdm_dev_name[100]="/dev/bdm";
unsigned long entry_pt=0;
bdmlib_setdebug(1);
if((p=TestSW(argc,argv,'D'))!=NULL)
strncpy(bdm_dev_name,p,sizeof(bdm_dev_name));
if((ret=bdmlib_open(bdm_dev_name))<0)
{ printf("bdmlib_open : %s\n",bdmlib_geterror_str(ret)); return 1; };
bdmlib_setioctl(BDM_SPEED,0);
if((p=TestSW(argc,argv,'F'))!=NULL)
{
strncpy(file_name,p,sizeof(file_name));
bdmlib_setioctl(BDM_SPEED,100);
bdmlib_reset();
bdmlib_setioctl(BDM_SPEED,10);
bdmlib_go();
sleep(2);
bdm_step_chip();
ret=bdmlib_load(file_name, NULL, &entry_pt);
if(ret<0) printf("bdmlib_load : %s\n",bdmlib_geterror_str(ret));
bdmlib_set_sys_reg(BDM_REG_RPC, entry_pt);
ret=bdmlib_go();
};
do {
c=getchar();
ret=bdmlib_getstatus();
if(ret<0) printf("bdmlib_go : %s\n",bdmlib_geterror_str(ret));
else {
printf("MCU ");
if(ret&BDM_TARGETRESET) printf("Reset ");
if(ret&BDM_TARGETSTOPPED) printf("Stopped ");
if(ret&BDM_TARGETPOWER) printf("NoPower ");
if(ret&BDM_TARGETNC) printf("NoConnect ");
printf("\n");
};
c=toupper(c);
switch(c) {
case 'B':
case 'D':
bdmlib_showpc();
break;
case 'S':
ret=bdm_step_chip();
if(ret<0) printf("bdmlib_go : %s\n",bdmlib_geterror_str(ret));
break;
case 'G':
ret=bdmlib_go();
if(ret<0) printf("bdmlib_go : %s\n",bdmlib_geterror_str(ret));
break;
case 'R':
bdmlib_setioctl(BDM_SPEED,100);
ret=bdmlib_reset();
bdmlib_setioctl(BDM_SPEED,0);
if(ret<0) printf("bdmlib_reset : %s\n",bdmlib_geterror_str(ret));
break;
case 'Q':
quit_fl=1;
break;
case 'X':
wr_test();
break;
case 'Y':
rd_test();
break;
case 'Z':
step_test();
break;
case 'L':
printf("Enter file name : ");
scanf("%s",file_name);
printf("\n");
ret=bdmlib_load(file_name, NULL, &entry_pt);
if(ret<0) printf("bdmlib_load : %s\n",bdmlib_geterror_str(ret));
else
{printf("loaded OK, entrypoint %lx\n",entry_pt);
if((ret=bdmlib_set_sys_reg(BDM_REG_RPC, entry_pt))<0)
printf("set PC error : %s\n",bdmlib_geterror_str(ret));
}
break;
case '\n':
break;
default:
printf ("Help for BDM_TEST\n"
"B: Begin Program Execution from Reset\n"
"D: Dump Target MCU Registers\n"
"H: Print This Help Summary\n"
"L: Load S-Record or Object File into Target\n"
"M: Memory Hex/ASCII Display\n"
"R: Hardware Reset Target MCU\n"
"S: Single Step Target MCU\n"
"G: Go Full Speed Target MCU\n"
"Q: Quit back to DOS\n");
};
} while(!quit_fl);
bdmlib_close(1);
return(0);
};
char* TestSW(int argc,char *argv[],char swch)
{
int i;
char *p;
for(i=1;i<argc;i++)
if((argv[i][0]=='-')&&(toupper(argv[i][1])==swch))
{
p=argv[i]+2;
while(((*p==' ')||(*p=='\t'))&&(*p)) p++;
if((!*p)&&(i<argc)) if(argv[++i][0]!='-')
{
p=argv[i];
while(((*p==' ')||(*p=='\t'))&&(*p)) p++;
}
return p;
}
return(NULL);
}

945
m683xx/bdm-load/bdmflash.c Normal file
View File

@@ -0,0 +1,945 @@
/*******************************************************************
Flash programming algorithms for use with BDM flash utility
bdmflash.c - test driver implementation
(C) Copyright 2000 by Pavel Pisa <pisa@waltz.felk.cvut.cz>
This souce is distributed under the Gnu General Public Licence.
See file COPYING for details.
Source could be used under any other license for embeded systems,
but in such case enhancements must be sent to original author.
If some of contributors does not agree with above two lines,
he can delete them and only GPL will apply.
*******************************************************************/
/*
Revision history
2001-01-16 Added experimental support of single 8 bit flash memory
based on Avi Cohen Stuart <astuart@baan.nl> changes
2001-07-10 Added support for amd_29f010 with x8x2 configuration
based on John S. Gwynne <jsg@jsgpc.mrcday.com> changes
Trying to solve x8x2 race condition with shortest
possible code - needs more tests
2001-08-30 Added alg-info for at_49f040 with x8x2 configuration
x8x2 configuration needs more testing, may be broken
2003-05-19 Added initial support for x32 memory configurations.
The x16x2 and x8x4 should work as well. Changes were
motivated by Andrei Smirnov <andrei.s@myrealbox.com>
code, but his small update results in deeper code redesign.
This could enable to support page writes for modern versions
of FLASH memories in future.
*/
#include <sys/types.h>
#include "bdm.h"
#include "bdmlib.h"
#include "bdmflash.h"
/* predefined flash algorithms metods */
int bdmflash_check_id_x32(const flash_alg_info_t *alg, void *addr, flash_d_t retid[2]);
int bdmflash_prog_x32(const flash_alg_info_t *alg, void *addr, const void *data, long count);
int bdmflash_erase_x32(const flash_alg_info_t *alg, void *addr, long size);
int bdmflash_check_id_x16(const flash_alg_info_t *alg, void *addr, flash_d_t retid[2]);
int bdmflash_prog_x16(const flash_alg_info_t *alg, void *addr, const void *data, long count);
int bdmflash_erase_x16(const flash_alg_info_t *alg, void *addr, long size);
int bdmflash_check_id_x8(const flash_alg_info_t *alg, void *addr, flash_d_t retid[2]);
int bdmflash_prog_x8(const flash_alg_info_t *alg, void *addr, const void *data, long count);
int bdmflash_erase_x8(const flash_alg_info_t *alg, void *addr, long size);
/* predefined flash types */
flash_alg_info_t amd_29f800_x16={
check_id: bdmflash_check_id_x16,
prog: bdmflash_prog_x16,
erase: bdmflash_erase_x16,
addr_mask: 0xfffff, /* 1MB */
reg1_addr: 0x555*2,
reg2_addr: 0x2aa*2,
sec_size: 0x10000,
width: FLASH_ALG_BITS_x16,
cmd_unlock1:0xaa, /* reg1 */
cmd_unlock2:0x55, /* reg2 */
cmd_rdid: 0x90, /* reg1 */
cmd_prog: 0xa0, /* reg1 */
cmd_erase: 0x80, /* reg1 */
cmd_reset: 0xf0, /* any */
erase_all: 0x10, /* reg1 */
erase_sec: 0x30, /* sector */
fault_bit: 0x20,
manid: 1,
devid: 0x2258,
alg_name: "amd29f800"
};
flash_alg_info_t amd_29f400_x16={
check_id: bdmflash_check_id_x16,
prog: bdmflash_prog_x16,
erase: bdmflash_erase_x16,
addr_mask: 0x7ffff, /* 0.5MB */
reg1_addr: 0x555*2,
reg2_addr: 0x2aa*2,
sec_size: 0x10000,
width: FLASH_ALG_BITS_x16,
cmd_unlock1:0xaa, /* reg1 */
cmd_unlock2:0x55, /* reg2 */
cmd_rdid: 0x90, /* reg1 */
cmd_prog: 0xa0, /* reg1 */
cmd_erase: 0x80, /* reg1 */
cmd_reset: 0xf0, /* any */
erase_all: 0x10, /* reg1 */
erase_sec: 0x30, /* sector */
fault_bit: 0x20,
manid: 1,
devid: 0x22ab,
alg_name: "amd29f400"
};
flash_alg_info_t amd_29f040_x8={
check_id: bdmflash_check_id_x8,
prog: bdmflash_prog_x8,
erase: bdmflash_erase_x8,
addr_mask: 0x7ffff, /* 0.5MB */
reg1_addr: 0x555,
reg2_addr: 0x2aa,
sec_size: 0x10000,
width: FLASH_ALG_BITS_x8,
cmd_unlock1:0xaa, /* reg1 */
cmd_unlock2:0x55, /* reg2 */
cmd_rdid: 0x90, /* reg1 */
cmd_prog: 0xa0, /* reg1 */
cmd_erase: 0x80, /* reg1 */
cmd_reset: 0xf0, /* any */
erase_all: 0x10, /* reg1 */
erase_sec: 0x30, /* sector */
fault_bit: 0x20,
manid: 1,
devid: 0xa4,
alg_name: "amd29f040"
};
flash_alg_info_t amd_29f010_x8x2={
check_id: bdmflash_check_id_x16,
prog: bdmflash_prog_x16,
erase: bdmflash_erase_x16,
addr_mask: 0x3ffff, /* 2x128kB = 256kB */
reg1_addr: 0x5555*2,
reg2_addr: 0x2aaa*2,
sec_size: 0x10000,
width: FLASH_ALG_BITS_x8x2,
cmd_unlock1:0xaaaa, /* reg1 */
cmd_unlock2:0x5555, /* reg2 */
cmd_rdid: 0x9090, /* reg1 */
cmd_prog: 0xa0a0, /* reg1 */
cmd_erase: 0x8080, /* reg1 */
cmd_reset: 0xf0f0, /* any */
erase_all: 0x1010, /* reg1 */
erase_sec: 0x3030, /* sector */
fault_bit: 0x2020,
manid: 0x0101,
devid: 0x2020,
alg_name: "amd29f010x2"
};
flash_alg_info_t at_49f040_x8x2={
check_id: bdmflash_check_id_x16,
prog: bdmflash_prog_x16,
erase: bdmflash_erase_x16,
addr_mask: 0xfffff, /* 2x0.5MB = 1MB */
reg1_addr: 0x5555*2,
reg2_addr: 0x2aaa*2,
sec_size: 0x10000,
width: FLASH_ALG_BITS_x8x2,
cmd_unlock1:0xaaaa, /* reg1 */
cmd_unlock2:0x5555, /* reg2 */
cmd_rdid: 0x9090, /* reg1 */
cmd_prog: 0xa0a0, /* reg1 */
cmd_erase: 0x8080, /* reg1 */
cmd_reset: 0xf0f0, /* any */
erase_all: 0x1010, /* reg1 */
erase_sec: 0x3030, /* sector */
fault_bit: 0x2020,
manid: 0x1F1F,
devid: 0x1313,
alg_name: "at49f040x2"
};
#ifdef WITH_TARGET_BUS32
flash_alg_info_t amd_29f080_x8x4={
check_id: bdmflash_check_id_x32,
prog: bdmflash_prog_x32,
erase: bdmflash_erase_x32,
addr_mask: 0x3fffff, /* 4x1MB */
reg1_addr: 0x555*4,
reg2_addr: 0x2aa*4,
sec_size: 0x10000,
width: FLASH_ALG_BITS_x8x4,
cmd_unlock1:0xaaaaaaaa, /* reg1 */
cmd_unlock2:0x55555555, /* reg2 */
cmd_rdid: 0x90909090, /* reg1 */
cmd_prog: 0xa0a0a0a0, /* reg1 */
cmd_erase: 0x80808080, /* reg1 */
cmd_reset: 0xf0f0f0f0, /* any */
erase_all: 0x10101010, /* reg1 */
erase_sec: 0x30303030, /* sector */
fault_bit: 0x20202020,
manid: 0x01010101,
devid: 0xd5d5d5d5,
alg_name: "amd29f080x4"
};
#endif /* WITH_TARGET_BUS32 */
/* please keep sorted by flash sizes, smallest first */
flash_alg_info_t *flash_alg_infos_def[]={
&amd_29f010_x8x2, /* 256 kB */
&amd_29f040_x8, /* 512 kB */
&amd_29f400_x16, /* 512 kB */
&amd_29f800_x16, /* 1 MB */
&at_49f040_x8x2, /* 1 MB */
#ifdef WITH_TARGET_BUS32
&amd_29f080_x8x4, /* 4 MB */
#endif /* WITH_TARGET_BUS32 */
NULL
};
flash_alg_info_t **flash_alg_infos=flash_alg_infos_def;
#if 0
#define FLASH_WR32(adr,val) (*(volatile u_int32_t*)(adr)=(val))
#define FLASH_RD32(adr) (*(volatile u_int32_t*)(adr))
#define FLASH_WR16(adr,val) (*(volatile u_int16_t*)(adr)=(val))
#define FLASH_RD16(adr) (*(volatile u_int16_t*)(adr))
#define FLASH_WR8(adr,val) (*(volatile u_int8_t*)(adr)=(val))
#define FLASH_RD8(adr) (*(volatile u_int8_t*)(adr))
#else
#define FLASH_WR32(adr,val) \
({ \
if(bdmlib_write_var(adr,BDM_SIZE_LONG,val)<0) \
goto mem_op_error; \
val; \
})
#define FLASH_RD32(adr) \
({ u_int32_t temp_val; \
if(bdmlib_read_var(adr,BDM_SIZE_LONG,&temp_val)<0) \
goto mem_op_error; \
temp_val; \
})
#define FLASH_WR16(adr,val) \
({ \
if(bdmlib_write_var(adr,BDM_SIZE_WORD,val)<0) \
goto mem_op_error; \
val; \
})
#define FLASH_RD16(adr) \
({ u_int16_t temp_val; \
if(bdmlib_read_var(adr,BDM_SIZE_WORD,&temp_val)<0) \
goto mem_op_error; \
temp_val; \
})
#define FLASH_WR8(adr,val) \
({ \
if(bdmlib_write_var(adr,BDM_SIZE_BYTE,val)<0) \
goto mem_op_error; \
val; \
})
#define FLASH_RD8(adr) \
({ u_int8_t temp_val; \
if(bdmlib_read_var(adr,BDM_SIZE_BYTE,&temp_val)<0) \
goto mem_op_error; \
temp_val; \
})
#endif
static
int bdmflash_prepval_x16(u_int16_t *pval, void *addr, const void *data, long count)
{
if(!((long)addr&1) && (count>=2)){
*pval=(((u_char*)data)[0]<<8)|(((u_char*)data)[1]);
return 2;
}
if(!count) return count;
if(!((long)addr&1)){
*pval=(((u_char*)data)[0]<<8) | FLASH_RD8((u_char*)addr+1);
}else{
*pval=(FLASH_RD8((u_char*)addr-1)<<8) | (((u_char*)data)[0]);
}
return 1;
mem_op_error:
return -4;
}
#ifdef WITH_TARGET_BUS32
static
int bdmflash_prepval_x32(u_int32_t *pval, void *addr, const void *data, long count)
{
int offs=(long)addr&3;
int rest=4-offs;
u_int32_t val=0;
if(!offs && (count>=4)){
*pval=((u_int32_t)((u_char*)data)[0]<<24)|((u_int32_t)((u_char*)data)[1]<<16)|
(((u_char*)data)[2]<<8)|(((u_char*)data)[3]);
return 4;
}
if(!count) return count;
if(count>rest) count=rest;
while(offs){
val<<=8;
val|=FLASH_RD8((u_char*)addr-offs);
offs--;
}
while(offs<count){
val<<=8;
val|=((u_char*)data)[offs];
offs++;
}
while(offs<rest){
val<<=8;
val|=FLASH_RD8((u_char*)addr+offs);
offs++;
}
*pval=val;
return count;
mem_op_error:
return -4;
}
#endif /* WITH_TARGET_BUS32 */
/*******************************************************************/
/* routines for 16 bit wide Intel or AMD flash or two interleaved
8 bit flashes */
int bdmflash_check_id_x16(const flash_alg_info_t *alg, void *addr, flash_d_t retid[2])
{
int ret=0;
u_int16_t devid, manid;
caddr_t a=(caddr_t)((u_int32_t)addr&~alg->addr_mask);
/* reset */
FLASH_WR16(a,alg->cmd_reset);
/* security sequence */
FLASH_WR16(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR16(a+alg->reg2_addr,alg->cmd_unlock2);
/* read manufacturer ID */
FLASH_WR16(a+alg->reg1_addr,alg->cmd_rdid);
manid=FLASH_RD16(a+0);
if(manid!=alg->manid) ret=-1;
/* reset */
FLASH_WR16(a,alg->cmd_reset);
/* security sequence */
FLASH_WR16(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR16(a+alg->reg2_addr,alg->cmd_unlock2);
/* read device ID */
FLASH_WR16(a+alg->reg1_addr,alg->cmd_rdid);
devid=FLASH_RD16(a+2);
if(devid!=alg->devid) ret=-1;
/* reset */
FLASH_WR16(a,alg->cmd_reset);
if(retid)
{retid[0]=manid;retid[1]=devid;};
return ret;
mem_op_error:
return -5;
}
int bdmflash_prog_x16(const flash_alg_info_t *alg, void *addr, const void *data, long count)
{
int ret;
u_int16_t old,new,fault,val;
caddr_t a=(caddr_t)((u_int32_t)addr&~alg->addr_mask);
ret=bdmflash_prepval_x16(&val,addr,data,count);
if(ret<=0)
return ret;
addr=(void*)((long)addr&~1l);
/* check if FLASH needs programming */
if(1){
old=FLASH_RD16(addr);
if(old==val) return ret;
}
/* security sequence */
FLASH_WR16(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR16(a+alg->reg2_addr,alg->cmd_unlock2);
/* program command */
FLASH_WR16(a+alg->reg1_addr,alg->cmd_prog);
FLASH_WR16(addr,val);
/* wait for result */
old=FLASH_RD16(addr);
while((new=FLASH_RD16(addr))!=old){
if((fault=old&new&alg->fault_bit)){
old=new;
/* check for some false fault at finish or race of x8x2 */
if(!(old^=(new=FLASH_RD16(addr)))) break; /* finished now */
else{
/* one chip of x8x2 configuration can finish earlier */
if(!(old&0x00ff)||(fault&0x00ff))
if(!(old&0xff00)||(fault&0xff00))
{ret=-2;break;}
}
}
old=new;
}
/* reset */
FLASH_WR16(a,alg->cmd_reset);
if((FLASH_RD16(addr)!=val) && (ret>=0)) ret=-3;
return ret;
mem_op_error:
return -5;
}
int bdmflash_erase_x16(const flash_alg_info_t *alg, void *addr, long size)
{
u_int16_t old,new,fault;
int ret=0;
caddr_t a=(caddr_t)((u_int32_t)addr&~alg->addr_mask);
/* reset */
FLASH_WR16(a,alg->cmd_reset);
/* security sequence */
FLASH_WR16(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR16(a+alg->reg2_addr,alg->cmd_unlock2);
/* erase command */
FLASH_WR16(a+alg->reg1_addr,alg->cmd_erase);
/* security sequence */
FLASH_WR16(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR16(a+alg->reg2_addr,alg->cmd_unlock2);
/* select erase range */
a=addr;
if(size==0)
FLASH_WR16(a+alg->reg1_addr,alg->erase_all);
else{
FLASH_WR16(addr,alg->erase_sec);
}
/* wait for result */
old=FLASH_RD16(addr);
while((new=FLASH_RD16(addr))!=old){
if((fault=old&new&alg->fault_bit)){
old=new;
/* check for some false fault at finish or race of x8x2 */
if(!(old^=(new=FLASH_RD16(addr)))) break; /* finished now */
else{
/* one chip of x8x2 configuration can finish earlier */
if(!(old&0x00ff)||(fault&0x00ff))
if(!(old&0xff00)||(fault&0xff00))
{ret=-2;break;}
}
}
old=new;
}
/* reset */
FLASH_WR16(a,alg->cmd_reset);
if(FLASH_RD16(addr)!=0xffff) ret--;
return ret;
mem_op_error:
return -5;
}
/*******************************************************************/
/* routines for single 8 bit wide Intel or AMD flash */
int bdmflash_check_id_x8(const flash_alg_info_t *alg, void *addr,
flash_d_t retid[2])
{
int ret=0;
u_int16_t devid, manid;
caddr_t a=(caddr_t)((u_int32_t)addr&~alg->addr_mask);
/* reset */
FLASH_WR8(a,alg->cmd_reset);
/* security sequence */
FLASH_WR8(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR8(a+alg->reg2_addr,alg->cmd_unlock2);
/* read manufacturer ID */
FLASH_WR8(a+alg->reg1_addr,alg->cmd_rdid);
manid=FLASH_RD8(a+0);
if(manid!=alg->manid) ret=-1;
/* reset */
FLASH_WR8(a,alg->cmd_reset);
/* security sequence */
FLASH_WR8(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR8(a+alg->reg2_addr,alg->cmd_unlock2);
/* read device ID */
FLASH_WR8(a+alg->reg1_addr,alg->cmd_rdid);
devid=FLASH_RD8(a+1);
if(devid!=alg->devid) ret=-1;
/* reset */
FLASH_WR8(a,alg->cmd_reset);
if(retid)
{retid[0]=manid;retid[1]=devid;};
return ret;
mem_op_error:
return -5;
}
int bdmflash_prog_x8(const flash_alg_info_t *alg, void *addr, const void *data, long count)
{
int ret=1;
u_int8_t old,new,val;
caddr_t a=(caddr_t)((u_int32_t)addr&~alg->addr_mask);
val=*(u_int8_t*)data;
/* check if FLASH needs programming */
if(1){
old=FLASH_RD8(addr);
if(old==val) return ret;
}
/* security sequence */
FLASH_WR8(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR8(a+alg->reg2_addr,alg->cmd_unlock2);
/* program command */
FLASH_WR8(a+alg->reg1_addr,alg->cmd_prog);
FLASH_WR8(addr,val);
/* wait for result */
old=FLASH_RD8(addr);
while((new=FLASH_RD8(addr))!=old){
if((old&alg->fault_bit)&&(new&alg->fault_bit)){
if((FLASH_RD8(addr))!=new) ret=-2;
break;
}
old=new;
}
/* reset */
FLASH_WR8(a,alg->cmd_reset);
if((FLASH_RD8(addr)!=val) && (ret>=0)) ret=-3;
return ret;
mem_op_error:
return -5;
}
int bdmflash_erase_x8(const flash_alg_info_t *alg, void *addr, long size)
{
u_int8_t old,new;
int ret=0;
caddr_t a=(caddr_t)((u_int32_t)addr&~alg->addr_mask);
/* reset */
FLASH_WR8(a,alg->cmd_reset);
/* security sequence */
FLASH_WR8(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR8(a+alg->reg2_addr,alg->cmd_unlock2);
/* erase command */
FLASH_WR8(a+alg->reg1_addr,alg->cmd_erase);
/* security sequence */
FLASH_WR8(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR8(a+alg->reg2_addr,alg->cmd_unlock2);
/* select erase range */
a=addr;
if(size==0)
FLASH_WR8(a+alg->reg1_addr,alg->erase_all);
else{
FLASH_WR8(addr,alg->erase_sec);
}
old=FLASH_RD8(addr);
while((new=FLASH_RD8(addr))!=old){
if((old&alg->fault_bit)&&(new&alg->fault_bit)){
if((FLASH_RD8(addr))!=new) ret=-2;
break;
}
old=new;
}
/* reset */
FLASH_WR8(a,alg->cmd_reset);
if(FLASH_RD16(addr)!=0xffff) ret--;
return ret;
mem_op_error:
return -5;
}
/*******************************************************************/
/* routines for two/four interleaved 16/8 bit wide Intel or AMD flashes */
#ifdef WITH_TARGET_BUS32
int bdmflash_check_id_x32(const flash_alg_info_t *alg, void *addr, flash_d_t retid[2])
{
int ret=0;
u_int32_t devid, manid;
caddr_t a=(caddr_t)((u_int32_t)addr&~alg->addr_mask);
/* reset */
FLASH_WR32(a,alg->cmd_reset);
/* security sequence */
FLASH_WR32(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR32(a+alg->reg2_addr,alg->cmd_unlock2);
/* read manufacturer ID */
FLASH_WR32(a+alg->reg1_addr,alg->cmd_rdid);
/* bank slecets swapped as i suspect (360DK only) !!!!!! */
/*manid=FLASH_RD32(a+0xc); */
manid=FLASH_RD32(a+0);
if(manid!=alg->manid) ret=-1;
/* reset */
FLASH_WR32(a,alg->cmd_reset);
/* security sequence */
FLASH_WR32(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR32(a+alg->reg2_addr,alg->cmd_unlock2);
/* read device ID */
FLASH_WR32(a+alg->reg1_addr,alg->cmd_rdid);
devid=FLASH_RD32(a+4);
if(devid!=alg->devid) ret=-1;
/* reset */
FLASH_WR32(a,alg->cmd_reset);
if(retid)
{retid[0]=manid;retid[1]=devid;};
return ret;
mem_op_error:
return -5;
}
int bdmflash_prog_x32(const flash_alg_info_t *alg, void *addr, const void *data, long count)
{
int ret=4;
u_int32_t old,new,fault,val;
caddr_t a=(caddr_t)((u_int32_t)addr&~alg->addr_mask);
ret=bdmflash_prepval_x32(&val,addr,data,count);
if(ret<=0)
return ret;
addr=(void*)((long)addr&~3l);
/* check if FLASH needs programming */
if(1){
old=FLASH_RD32(addr);
if(old==val) return ret;
}
/* security sequence */
FLASH_WR32(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR32(a+alg->reg2_addr,alg->cmd_unlock2);
/* program command */
FLASH_WR32(a+alg->reg1_addr,alg->cmd_prog);
FLASH_WR32(addr,val);
/* wait for result */
old=FLASH_RD32(addr);
while((new=FLASH_RD32(addr))!=old){
if((fault=old&new&alg->fault_bit)){
old=new;
/* check for some false fault at finish or race of x8x2 */
if(!(old^=(new=FLASH_RD32(addr)))) break; /* finished now */
else{
/* one chip of x16x2 or x8x4 configuration can finish earlier */
if(!(old&0x000000ff)||(fault&0x000000ff))
if(!(old&0x0000ff00)||(fault&0x0000ff00))
if(!(old&0x00ff0000)||(fault&0x00ff0000))
if(!(old&0xff000000)||(fault&0xff000000))
{ret=-2;break;}
}
}
old=new;
}
/* reset */
FLASH_WR32(a,alg->cmd_reset);
if((FLASH_RD32(addr)!=val) && (ret>=0)) ret=-3;
return ret;
mem_op_error:
return -5;
}
int bdmflash_erase_x32(const flash_alg_info_t *alg, void *addr, long size)
{
u_int32_t old,new,fault;
int ret=0;
caddr_t a=(caddr_t)((u_int32_t)addr&~alg->addr_mask);
/* reset */
FLASH_WR32(a,alg->cmd_reset);
/* security sequence */
FLASH_WR32(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR32(a+alg->reg2_addr,alg->cmd_unlock2);
/* erase command */
FLASH_WR32(a+alg->reg1_addr,alg->cmd_erase);
/* security sequence */
FLASH_WR32(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR32(a+alg->reg2_addr,alg->cmd_unlock2);
/* select erase range */
a=addr;
if(size==0)
FLASH_WR32(a+alg->reg1_addr,alg->erase_all);
else{
FLASH_WR32(addr,alg->erase_sec);
}
/* wait for result */
old=FLASH_RD32(addr);
while((new=FLASH_RD32(addr))!=old){
if((fault=old&new&alg->fault_bit)){
old=new;
/* check for some false fault at finish or race of x16x2 or x8x4 */
if(!(old^=(new=FLASH_RD32(addr)))) break; /* finished now */
else{
/* one chip of x16x2 or x8x4 configuration can finish earlier */
if(!(old&0x000000ff)||(fault&0x000000ff))
if(!(old&0x0000ff00)||(fault&0x0000ff00))
if(!(old&0x00ff0000)||(fault&0x00ff0000))
if(!(old&0xff000000)||(fault&0xff000000))
{ret=-2;break;}
}
}
old=new;
}
/* reset */
FLASH_WR32(a,alg->cmd_reset);
if(FLASH_RD32(addr)!=0xffffffff) ret--;
return ret;
mem_op_error:
return -5;
}
#endif /* WITH_TARGET_BUS32 */
/*******************************************************************/
/* flash type independent check_id */
int bdmflash_check_id(const flash_alg_info_t *alg, void *addr, flash_d_t retid[2])
{
if(alg->check_id)
return alg->check_id(alg, addr, retid);
else
return -10; /* we really need to define error constants in future */
}
/* flash type independent program one location */
int bdmflash_prog(const flash_alg_info_t *alg, void *addr, const void *data, long count)
{
if(alg->prog)
return alg->prog(alg,addr,data,count);
else
return -10;
}
/* flash type independent erase region */
int bdmflash_erase(const flash_alg_info_t *alg, void *addr, long size)
{
if(alg->erase)
return alg->erase(alg,addr,size);
else
return -10;
}
const flash_alg_info_t *
bdmflash_alg_from_id(flash_d_t id[2])
{
int i;
const flash_alg_info_t *alg;
for(i=0;(alg=flash_alg_infos_def[i])!=NULL;i++)
if((alg->manid==id[0])&&(alg->devid==id[0]))
return alg;
return NULL;
}
const flash_alg_info_t *
bdmflash_alg_probe(caddr_t flash_adr)
{
int i;
const flash_alg_info_t *alg,*alg1;
flash_d_t testid[2];
for(i=0;(alg=flash_alg_infos_def[i])!=NULL;i++){
if(bdmflash_check_id(alg,flash_adr,testid)>=0)
return alg;
alg1=bdmflash_alg_from_id(testid);
if(alg1!=NULL)
if(bdmflash_check_id(alg1,flash_adr,testid)>=0)
return alg1;
}
return NULL;
}
int
bdmflash_wrb_filt(bdmlib_bfilt_t * filt, caddr_t in_adr,
u_int size, u_char * bl_ptr)
{
int offs=0,res;
flash_d_t val;
const flash_alg_info_t *alg=(flash_alg_info_t*)filt->info;
#if 0
if(alg->width!=FLASH_ALG_BITS_x8) {
/* 16 bit wide flash write path */
if((u_long)in_adr&1) {
in_adr-=1;
val=(FLASH_RD16(in_adr)&0xff00)|bl_ptr[offs];
if((res=bdmflash_prog(alg, in_adr, val))<0) {
fprintf(stderr, "flash byte write error %d at 0x%lx\n",
res,(u_long)in_adr);
return offs;
}
in_adr+=2;
size-=1;
offs+=1;
}
while(size>=2) {
val=(bl_ptr[offs]<<8)|bl_ptr[offs+1];
if((res=bdmflash_prog(alg, in_adr, val))<0) {
fprintf(stderr, "flash write error %d at 0x%lx\n",
res,(u_long)in_adr);
return offs;
}
in_adr+=2;
size-=2;
offs+=2;
}
if(size) {
val=(FLASH_RD16(in_adr)&0x00ff)|(bl_ptr[offs]<<8);
if((res=bdmflash_prog(alg, in_adr, val))<0) {
fprintf(stderr, "flash byte write error %d at 0x%lx\n",
res,(u_long)in_adr);
return offs;
}
size-=1;
offs+=1;
}
}
#endif
while(size>=1) {
val=bl_ptr[offs];
if((res=bdmflash_prog(alg, in_adr, bl_ptr+offs, size))<=0) {
fprintf(stderr, "flash write error %d at 0x%lx\n",
res,(u_long)in_adr);
return offs;
}
in_adr+=res;
size-=res;
offs+=res;
}
return offs;
#if 0
mem_op_error:
fprintf(stderr, "bdm memory access error\n");
return 0;
#endif
}
int
bdmflash_erase_filt(bdmlib_bfilt_t * filt, caddr_t in_adr,
u_int size)
{
int res=0;
const flash_alg_info_t *alg=(flash_alg_info_t*)filt->info;
if(!in_adr) in_adr=filt->begin_adr;
res=bdmflash_erase(alg, in_adr,size);
if(res<0)
fprintf(stderr, "flash erase error %d\n",res);
return res;
}
#if 0
/* slow version of blank check */
int
bdmflash_blankck_filt(bdmlib_bfilt_t * filt, caddr_t in_adr,
u_int size)
{
int errors=0;
if(!in_adr||!size){
in_adr=filt->begin_adr;
size=filt->end_adr-in_adr+1;
}
if(((long)in_adr&1)&&size){
if(FLASH_RD8(in_adr)!=0xff){
fprintf(stderr,"blank check error at 0x%06lX",(long)in_adr);
errors++;
}
in_adr++; size--;
}
while(size>=2){
if(FLASH_RD16(in_adr)!=0xffff){
if(errors<5){
if(errors) fprintf(stderr,",0x%06lX",(long)in_adr);
else fprintf(stderr,"blank check error at 0x%06lX",(long)in_adr);
}else if(errors==5) fprintf(stderr, " and more");
errors++;
}
if(!((long)in_adr&0xfff)) bdmlib_propeller(stdout);
in_adr+=2; size-=2;
}
if(size){
if(FLASH_RD8(in_adr)!=0xff){
if(errors) fprintf(stderr,",0x%06lX",(long)in_adr);
else fprintf(stderr,"blank check error at 0x%06lX",(long)in_adr);
errors++;
}
}
if(errors) fprintf(stderr,"\n");
return errors;
mem_op_error:
fprintf(stderr, "bdm memory access error\n");
return -5;
}
#else
/* hopefully faster version of blank check */
int
bdmflash_blankck_filt(bdmlib_bfilt_t * filt, caddr_t in_adr,
u_int size)
{
int errors=0, in_buf;
u_char buf[1024], *p;
if(!in_adr||!size){
in_adr=filt->begin_adr;
size=filt->end_adr-in_adr+1;
}
while(size){
if(size<sizeof(buf)) in_buf=size;
else in_buf=sizeof(buf);
if(bdmlib_read_block(in_adr,in_buf,buf)!=in_buf)
goto mem_op_error;
size-=in_buf;
for(p=buf;in_buf--;in_adr++,p++){
if(*p!=0xff){
if(errors<10){
if(errors) fprintf(stderr,",0x%06lX",(long)in_adr);
else fprintf(stderr,"blank check error at 0x%06lX",(long)in_adr);
}else if(errors==10) fprintf(stderr, " and more");
errors++;
}
}
bdmlib_propeller((u_long)in_adr, stdout);
}
if(errors) fprintf(stderr,"\n");
return errors;
mem_op_error:
fprintf(stderr, "\nbdm memory access error\n");
return -5;
}
#endif

View File

@@ -0,0 +1,74 @@
#ifndef BDMFLASH_H
#define BDMFLASH_H
#include <sys/types.h>
#define FLASH_ALG_BITS_x8 0
#define FLASH_ALG_BITS_x16 2
#define FLASH_ALG_BITS_x8x2 3
#define FLASH_ALG_BITS_x32 4
#define FLASH_ALG_BITS_x16x2 5
#define FLASH_ALG_BITS_x8x4 7
#define WITH_TARGET_BUS32
#ifndef WITH_TARGET_BUS32
typedef u_int16_t flash_d_t; /* Type able to store one flash location */
#else /* WITH_TARGET_BUS32 */
typedef u_int32_t flash_d_t; /* Type able to store one flash location */
#endif /* WITH_TARGET_BUS32 */
/* Structure describing programming operations for flash type */
typedef struct flash_alg_info {
/* Sets retid to manufacturer and type ID, returns <0 in case of error */
int (*check_id)(const struct flash_alg_info *alg, void *addr, flash_d_t retid[2]);
/* Programs one location of flash and returns number of programmed bytes */
int (*prog)(const struct flash_alg_info *alg, void *addr, const void *data, long count);
/* Erase all sectors overlaped by region from addr of size bytes, size=0 => erase all */
/* This version is capable only of full erase (size=0) and one sector (size=1) */
int (*erase)(const struct flash_alg_info *alg, void *addr, long size);
/* Numeric and string fields follows */
u_int32_t addr_mask; /* Mask to take offset inside flash */
u_int32_t reg1_addr; /* Flash control register 1 */
u_int32_t reg2_addr; /* Flash control register 2 */
u_int32_t sec_size; /* block size of bigger blocks */
flash_d_t width; /* FLASH_ALG_BITS_x8 .. 8 bit data bus,
FLASH_ALG_BITS_x16 .. 16 bit data,
FLASH_ALG_BITS_x8x2 .. two interleaved 8 bit */
flash_d_t cmd_unlock1;/* first byte of command sequence */
flash_d_t cmd_unlock2;/* second byte of command sequence */
flash_d_t cmd_rdid; /* read identifier */
flash_d_t cmd_prog; /* program one loc */
flash_d_t cmd_erase; /* erase command */
flash_d_t cmd_reset; /* leave program mode */
flash_d_t erase_all; /* erase all */
flash_d_t erase_sec; /* erase sector */
flash_d_t fault_bit; /* programing of location failed */
flash_d_t manid; /* manufacturer ID */
flash_d_t devid; /* device ID */
char *alg_name; /* informative flash type name */
} flash_alg_info_t;
int bdmflash_check_id(const flash_alg_info_t *alg, void *addr,
flash_d_t retid[2]);
int bdmflash_prog(const flash_alg_info_t *alg, void *addr, const void *data, long count);
int bdmflash_erase(const flash_alg_info_t *alg, void *addr, long size);
flash_alg_info_t **flash_alg_infos;
const flash_alg_info_t *bdmflash_alg_from_id(flash_d_t id[2]);
const flash_alg_info_t *bdmflash_alg_probe(caddr_t flash_adr);
int bdmflash_wrb_filt(bdmlib_bfilt_t * filt, caddr_t in_adr,
u_int size, u_char * bl_ptr);
int bdmflash_erase_filt(bdmlib_bfilt_t * filt, caddr_t in_adr, u_int size);
int bdmflash_blankck_filt(bdmlib_bfilt_t * filt, caddr_t in_adr, u_int size);
int bdmflash_check_id(const flash_alg_info_t *alg, void *addr, flash_d_t retid[2]);
#endif /* BDMFLASH_H */

1701
m683xx/bdm-load/bdmlib.c Normal file

File diff suppressed because it is too large Load Diff

83
m683xx/bdm-load/bdmlib.h Normal file
View File

@@ -0,0 +1,83 @@
/*
* $Id: bdmlib.h,v 1.2 2003/08/15 12:06:47 ppisa Exp $
*/
#ifndef BDMLIB_H
#define BDMLIB_H
#include <sys/types.h>
#include <stdarg.h>
#include <stdio.h>
typedef u_short bdmstatus;
extern int bdmlib_open(char *device);
extern int bdmlib_close(int);
extern int bdmlib_isopen(void);
extern int bdmlib_ioctl(u_int code);
extern int bdmlib_setioctl(u_int code, u_int val);
extern bdmstatus bdmlib_getstatus(void);
extern int bdmlib_write_var(caddr_t adr, u_short size, u_int val);
extern int bdmlib_read_var(caddr_t adr, u_short size, void *val);
extern int bdmlib_write_block(caddr_t adr, u_int size, u_char *block);
extern int bdmlib_read_block(caddr_t adr, u_int size, u_char *block);
extern int bdmlib_load(char *file, char *entry_name, u_long *entry_pt);
extern int bdmlib_do_load_binary(char *file_name, char *entry_name,
u_long *entry_pt);
extern int bdmlib_do_load_macro(char *file_name, int is_begin_macro);
extern int bdmlib_get_sys_reg(u_int, u_int *);
extern int bdmlib_set_sys_reg(u_int, u_int);
extern int bdmlib_get_reg(u_int, u_int *);
extern int bdmlib_set_reg(u_int, u_int);
extern int bdmlib_go(void);
extern char *bdmlib_geterror_str(int);
extern char *bdmlib_getstatus_str(bdmstatus);
extern int bdmlib_set_mbar(u_long mbar_val);
extern int bdmlib_reset(void);
extern void bdmlib_setdebug(int switch_on);
extern int bdmlib_querydebug(void);
extern void bdmlib_showpc(void);
extern void bdmlib_log(const char *format, ...);
extern void bdmlib_propeller(u_long addr, FILE * fp);
extern int bdmlib_do_load_binary_section(char *file_name, char *sect_name);
/* some additional error codes beyond those of the driver */
#define BDM_ERR_NOT_OPEN -650
#define BDM_ERR_ILL_IOCTL -651
#define BDM_ERR_WRITE_FAIL -652
#define BDM_ERR_READ_FAIL -653
#define BDM_ERR_ILL_SIZE -654
#define BDM_ERR_OPEN -655
#define BDM_ERR_LOAD -656
#define BDM_ERR_MACROFILE -657
#define BDM_ERR_SECTION -658
#define BDM_ERR_VERSION -659
#define BDM_NO_ERROR 0
/* support of filtered write for flash programming */
typedef struct bdmlib_bfilt{
struct bdmlib_bfilt *next;
caddr_t begin_adr;
caddr_t end_adr;
int filt_id;
u_int flags;
int (*wrb_filt)(struct bdmlib_bfilt *, caddr_t , u_int, u_char * );
void *info;
void *state;
}bdmlib_bfilt_t;
#define BDMLIB_FILT_ERROR 0x08
#define BDMLIB_FILT_ERASED 0x10
#define BDMLIB_FILT_AUTO 0x20
#define BDMLIB_FILT_FLASH 0x40
int bdmlib_load_use_lma; /* use LMA instead of VMA for load */
bdmlib_bfilt_t * bdmlib_bfilt;
int
bdmlib_wrb_filt(bdmlib_bfilt_t * bdmlib_bfilt, caddr_t in_adr,
u_int size, u_char * bl_ptr);
#endif /* BDMLIB_H */

65
m683xx/bdm-load/cpu32init Normal file
View File

@@ -0,0 +1,65 @@
# initialization macro-file for MO_CPU1
# 0xFFFA00 - SIMCR - SIM Configuration Register
w 0xfffa00 0x40cf 2
# 0xFFFA21 - SYPCR - System Protection Control Register
w 0xfffa21 0x06 1
# 0xFFFA04 - SYNCR Clock Synthesizer Control Register
w 0xfffa04 0xd408 2
# 0xFFFA17 - PEPAR - Port E Pin Assignment Register
w 0xfffa17 0xf4 1
# 0xFFFA1F - PFPAR - Port F Pin Assignment Register
w 0xfffa1f 0 1
# setup STANBY RAM at 0xFFD000
w 0xFFFB40 0x8000 2
w 0xFFFB44 0xFFD000 4
w 0xFFFB40 0x0000 2
# setup TPU RAM at 0xFFE000
w 0xFFFB00 0x8000 2
w 0xFFFB04 0xFFE0 2
w 0xFFFB00 0x0000 2
# 0xYFFA44 - CSPAR0 - Chip Select Pin Assignment Register 0
w 0xfffa44 0x3bff 2
# 0xFFFA46 - CSPAR1 - Chip Select Pin Assignment Register 1
w 0xfffa46 0x03a9 2
# BOOT ROM 0x800000 1MB RW UL - Boot FLASH
w 0xfffa48 0x8007 2
w 0xfffa4A 0x7830 2
# CS0 ROM 0x900000 1MB RW UL - 2nd FLASH
w 0xfffa4c 0x9007 2
w 0xfffa4e 0x7830 2
# CS2 RAM 0x000000 1MB RW UL - Main RAM first 1MB
w 0xfffa54 0x0007 2
w 0xfffa56 0x7830 2
# CS3 RAM 0x100000 1MB RW UL - Main RAM second 1MB
w 0xfffa58 0x1007 2
w 0xfffa5a 0x7830 2
# CS4 PER 0xf00000 512kB RW UL - CMOS RAM, RTC, other devices
w 0xfffa5c 0xf006 2
w 0xfffa5e 0x7cb0 2
# CS7 PER 0xf87000 2k RW UL - MO_PWR
w 0xfffa68 0xf870 2
w 0xfffa6a 0x7c70 2
# CS8 PER 0xf88000 2k RO UL - IRC
w 0xfffa6c 0xf880 2
w 0xfffa6e 0x7c70 2
# CS9 PER 0xf89000 2k WR UL - KBD
w 0xfffa70 0xf890 2
w 0xfffa72 0x7cf0 2

830
m683xx/bdm-load/tpudb.c Normal file
View File

@@ -0,0 +1,830 @@
/*******************************************************************
TPUDB Project to Create Free Motorola 683xx TPU Debugger
tpudb.c - first test
(C) Copyright 2000 by Pavel Pisa - Original Author
e-mail: pisa@cmp.felk.cvut.cz
homepage: http://cmp.felk.cvut.cz/~pisa
work: http://www.pikron.com/
This package can be copied and modified under
GNU General Public License with all its conditions.
See file GPL for details. Under this license nobody can
distribute this work and any derived work without full source code
for all modules compiled and linked into executable.
*******************************************************************/
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <bfd.h>
#include "bdm.h"
#include "bdmlib.h"
#define __val2mfld(mask,val) (((mask)&~((mask)<<1))*(val)&(mask))
#define __mfld2val(mask,val) (((val)&(mask))/((mask)&~((mask)<<1)))
#define val2mfld __val2mfld
#define mfld2val __mfld2val
#if 0
#define TPU_WR16(adr,val) (*(volatile u_int16_t*)(adr)=(val))
#define TPU_RD16(adr) (*(volatile u_int16_t*)(adr))
#else
#define TPU_WR16(adr,val) \
({ \
if(bdmlib_write_var(adr,BDM_SIZE_WORD,val)<0) \
goto mem_op_error; \
val; \
})
#define TPU_RD16(adr) \
({ u_int16_t temp_val; \
if(bdmlib_read_var(adr,BDM_SIZE_WORD,&temp_val)<0) \
goto mem_op_error; \
temp_val; \
})
#endif
char hashmark=0; /* flag set by "set hash" */
int bdm_autoreset=1; /* automatic reset before load */
int bdm_ttcu=0; /* time to come up for init by rom */
char initname[255]; /* need reimplement !!!!!!!!! */
char bdm_dev_name[255]="/dev/bdm"; /* device name */
/* Numberring of TPU register */
/* First part are aliases for main CPU accesible registers */
#define TPUREG_TSTMSRA 0x0 /* Master Shift Register A */
#define TPUREG_TSTMSRB 0x1 /* Master Shift Register B */
#define TPUREG_TSTSC 0x2 /* Test Module Shift Count */
#define TPU_TSTSCA 0xff00 /* Bits Shifted from TSTMSRA to Tested Module */
#define TPU_TSTSCB 0x00ff /* Bits Shifted from Tested Module to TSTMSRB */
#define TPUREG_TSTRC 0x3 /* Test Module Repetition Count */
#define TPUREG_CREG 0x4 /* Test Submodule Control Register */
#define TPU_TSTBUSY 0x8000 /* Test Submodule Busy Status Bit */
#define TPU_TMARM 0x4000 /* Test Mode Armed Status Bit (latched /TSTME) */
#define TPU_COMP 0x2000 /* Compare Status Bit */
#define TPU_IMBTST 0x1000 /* Intermodule Bus Test (SCANA/SCANB) */
#define TPU_CPUTR 0x0800 /* Scan to CPU Test Register */
#define TPU_QBIT 0x0400 /* Quotient Bit at FREEZE/QUOT Pin */
#define TPU_MUXEL 0x0200 /* Multiplexer Select Bit for MSRB from Int/Ext */
#define TPU_ACUT 0x0010 /* Activate Circuit Under Test */
#define TPU_SCONT 0x0008 /* Start Continuous Operation */
#define TPU_SSHOP 0x0004 /* Start Shifting Operation */
#define TPU_SATO 0x0002 /* Start Automatic Test Operation */
#define TPU_EMT 0x0001 /* Enter test mode */
#define TPUREG_DREG 0x5 /* Distributed Register */
#define TPU_WAIT 0x0700 /* Wait Counter Preset 2-16 SCLK */
#define TPU_MSRAHI 0x0e0 /* MSRA High Bits 18-16 */
#define TPU_MSRAC 0x0010 /* Master Shift Register A Configuration */
#define TPU_MSRBHI 0x00e /* MSRB High Bits 18-16 */
#define TPU_MSRBC 0x0001 /* Master Shift Register B Configuration */
#define TPUREG_MCR 0x6 /* TPU Module Configuration Register */
#define TPU_STOP 0x8000 /* Low-Power Stop Mode Enable */
#define TPU_TCR1P 0x6000 /* Timer Count Register 1 Prescaler Control */
#define TPU_TCR2P 0x1800 /* Timer Count Register 2 Prescaler Control */
#define TPU_EMU 0x0400 /* Emulation Control */
#define TPU_T2CG 0x0200 /* TCR2 Clock/Gate Control */
#define TPU_STF 0x0100 /* Stop Flag */
#define TPU_SUPV 0x0080 /* Supervisor/Unrestricted */
#define TPU_PSCK 0x0040 /* Prescaler Clock */
#define TPU_IARB 0x000f /* Interrupt Arbitration ID */
#define TPUREG_TCR 0x7 /* Test Configuration Register */
#define TPU_INCAD 0x1000 /* Increment Address in uPC at ACUTL */
#define TPU_TCR1C 0x0800 /* TCR1 Clock - TCR2 pin */
#define TPU_ACUTR 0x0600 /* Activate Circuit Under Test Response 1, 0 */
#define TPU_ACUTR_NONE 0 /* None */
#define TPU_ACUTR_STEPTPU 1 /* Run ONE TPU microcycle */
#define TPU_ACUTR_SHEOT 2 /* Scheduler End of Time Slot */
#define TPU_SOSEL 0x0070 /* Scan-Out Select */
#define TPU_SISEL 0x000e /* Scan-in Select */
#define TPU_SxSEL_NONE 0 /* None */
#define TPU_SxSEL_PC 1 /* uPC */
#define TPU_SxSEL_IR 2 /* Microinstruction */
#define TPU_SxSEL_BPLA 3 /* Branch PLA */
#define TPU_SxSEL_PCBR 4 /* uPC Breakpoint */
#define TPU_SxSEL_SPLA 5 /* Scheduler PLA */
#define TPU_SxSEL_CHANBR 6 /* Channel Breakpoint */
#define TPU_TMW 0x0001 /* Test Memory Map */
#define TPUREG_DSCR 0x8 /* Development Support Control Register */
#define TPU_HOT4 0x8000 /* Hang on T4 */
#define TPU_BLC 0x0400 /* Branch Latch Control */
#define TPU_CLKS 0x0200 /* Stop Clocks (to TCRs) */
#define TPU_FRZ 0x0180 /* FREEZE Assertion Response */
#define TPU_CCL 0x0040 /* Channel Conditions Latch */
#define TPU_BMSK 0x003F /* Break cond mask */
#define TPU_BP 0x0020 /* Break mPC == mPC breakpoint register */
#define TPU_BC 0x0010 /* Break if CHAN start or set */
#define TPU_BH 0x0008 /* Break if host service latch set */
#define TPU_BL 0x0004 /* Break if link service latch set */
#define TPU_BM 0x0002 /* Break if MRL set at beginning*/
#define TPU_BT 0x0001 /* Break if TDL set at beginnibg */
#define TPUREG_DSSR 0x9 /* Development Support Status Register */
#define TPU_BKPT 0x0080 /* Breakpoint Asserted Flag */
#define TPU_PCBK 0x0040 /* mPC Breakpoint Flag */
#define TPU_CHBK 0x0020 /* Channel Register Breakpoint Flag */
#define TPU_SRBK 0x0010 /* Service Request Breakpoint Flag */
#define TPU_TPUF 0x0008 /* TPU FREEZE Flag */
#define TPUREG_TICR 0xA /* TPU Interrupt Configuration Register */
#define TPU_CIRL 0x0700 /* Channel Interrupt Request Level */
#define TPU_CIBV 0x00f0 /* Bits [7:4] of Channel Interrupt Base Vector */
#define TPUREG_CIER 0xB /* Channel Interrupt Enable Register */
#define TPUREG_CFSR 0xC /* Channel Function Select Register 0 */
#define TPUREG_HSQR 0xD /* Host Sequence Register 0 */
#define TPUREG_HSRR 0xE /* Host Service Request Register 0 */
#define TPUREG_CPR 0xF /* Channel Priority Register 0 */
#define TPUREG_CISR 0x10 /* Channel Interrupt Status Register */
#define TPUREG_LR 0x11 /* Link Register */
#define TPUREG_SGLR 0x12 /* Service Grant Latch Register */
#define TPUREG_DCNR 0x13 /* Decoded Channel Number Register */
/* Registers not accesible from main CPU */
#define TPUREG_P 0x14 /* Parameter Register (16-bit) */
#define TPUREG_A 0x15 /* Accumulator (16-bit) */
#define TPUREG_DIOB 0x16 /* Data I/O Buffer (16-bit) */
#define TPUREG_SR 0x17 /* Shift Register (16-bit) */
#define TPUREG_ERT 0x18 /* Event Temporary Register (16-b.) */
#define TPUREG_CHAN 0x19 /* Channel Number (4-bit) */
#define TPUREG_DEC 0x1A /* Decrementator Reg (4-bit) */
#define TPUREG_TCR2 0x1B /* Timebase Register 2 (16-bit) */
#define TPUREG_TCR1 0x1C /* Timebase Register 1 (16-bit) */
#define TPUREG_PC 0x1D /* Microprogram Counter (9-bit) */
#define TPUREG_IR 0x1E /* */
#define TPUREG_BPLA 0x1F /* */
#define TPUREG_SPLA 0x20 /* */
#define TPUREG_PCBR 0x21 /* */
#define TPUREG_CHANBR 0x22 /* */
/* Aditional CPU Accessible Registers */
#define TPUREG_DEBPAR 0x23 /* Parameter register at 0xFFFF00 for debugging */
#define TRAMREG_CR 0x24 /* TPURAM Configuration Register */
#define TRAM_STOP 0x8000 /* Low-Power Stop Mode Enable */
#define TRAM_RASP 0x0080 /* TPURAM Array Space */
#define TRAMREG_TST 0x25 /* TPURAM Test Register */
#define TRAMREG_BAR 0x26 /* TPURAM Base Address and Status Register */
#define TRAM_ADDR 0xfff0 /* TPURAM Array Base Address */
#define TRAM_RAMDS 0x0001 /* RAM Array Disable */
#define TPUREG_MAX 0x26
/* Descriptor of TPU register access */
typedef struct tpu_reg_des {
int (*reg_rd)(struct tpu_reg_des *des, int indx);
int (*reg_wr)(struct tpu_reg_des *des, int indx, int val);
int adr;
int adr1;
int flags;
int arr_len; /* array size, 0 .. no array */
int bfld_bits; /* bitfield length, 0 .. no bitfields */
int bfld_arr_len; /* bitfield array */
}tpu_reg_des_t;
int tpu_mem_rd16(struct tpu_reg_des *des, int indx);
int tpu_mem_wr16(struct tpu_reg_des *des, int indx, int val);
int tpu_t1_rd(struct tpu_reg_des *des, int indx);
int tpu_t1_wr(struct tpu_reg_des *des, int indx, int val);
int tpu_t2_rd(struct tpu_reg_des *des, int indx);
int tpu_t2_wr(struct tpu_reg_des *des, int indx, int val);
int tpu_reg_rd(int reg, int indx);
int tpu_reg_wr(int reg, int indx, int val);
int tpu_reg_or(int reg, int indx, int val);
int tpu_reg_and(int reg, int indx, int val);
#define TPUREG_FL_SH4 1 /* shift value by 4 bits */
#define TPUREG_FL_PMOD 2 /* modification for reg P */
#define TPUREG_FL_DIOB 4 /* modification for reg DIOB */
#define TPUREG_INDX_BFLD (0x1<<24) /* index for bitfields */
/* Descriptors of TPU register access */
tpu_reg_des_t tpu_regs[]={
/* CPU accessible */
[TPUREG_TSTMSRA]= {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFA30,},
[TPUREG_TSTMSRB]= {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFA32,},
[TPUREG_TSTSC] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFA34,},
[TPUREG_TSTRC] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFA36,},
[TPUREG_CREG] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFA38,},
[TPUREG_DREG] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFA3A,},
[TPUREG_MCR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFE00,},
[TPUREG_TCR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFE02,},
[TPUREG_DSCR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFE04,},
[TPUREG_DSSR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFE06,},
[TPUREG_TICR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFE08,},
[TPUREG_CIER] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFE0A,
arr_len:0,bfld_bits:1,bfld_arr_len:16,},
[TPUREG_CFSR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFE0C,
arr_len:4,bfld_bits:4,bfld_arr_len:16,},
[TPUREG_HSQR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFE14,
arr_len:2,bfld_bits:2,bfld_arr_len:16,},
[TPUREG_HSRR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFE18,
arr_len:2,bfld_bits:2,bfld_arr_len:16,},
[TPUREG_CPR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFE1C,
arr_len:2,bfld_bits:2,bfld_arr_len:16,},
[TPUREG_CISR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFE20,
arr_len:0,bfld_bits:1,bfld_arr_len:16,},
[TPUREG_LR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFE22,},
[TPUREG_SGLR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFE24,},
[TPUREG_DCNR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFE26,},
/* Special TPU - group 1 */
/* internal TPU registers, ounly access possible through forced TPU microengine instructions */
/* adr .. instruction for reg read, adr1 .. instruction for reg write */
[TPUREG_P] = {reg_rd:tpu_t1_rd,reg_wr:tpu_t1_wr,adr:0x3fff,adr1:0x36ff,
flags:TPUREG_FL_PMOD,},
[TPUREG_A] = {reg_rd:tpu_t1_rd,reg_wr:tpu_t1_wr,adr:0x327f,adr1:0x361f},
[TPUREG_DIOB] = {reg_rd:tpu_t1_rd,reg_wr:tpu_t1_wr,adr:0,adr1:0,
flags:TPUREG_FL_DIOB,},
[TPUREG_SR] = {reg_rd:tpu_t1_rd,reg_wr:tpu_t1_wr,adr:0x347f,adr1:0x363f},
[TPUREG_ERT] = {reg_rd:tpu_t1_rd,reg_wr:tpu_t1_wr,adr:0x3c7f,adr1:0x365f},
[TPUREG_CHAN] = {reg_rd:tpu_t1_rd,reg_wr:tpu_t1_wr,adr:0x267f,adr1:0x373f,
flags:TPUREG_FL_SH4,},
[TPUREG_DEC] = {reg_rd:tpu_t1_rd,reg_wr:tpu_t1_wr,adr:0x247f,adr1:0x375f},
[TPUREG_TCR2] = {reg_rd:tpu_t1_rd,reg_wr:tpu_t1_wr,adr:0x387f,adr1:0x379f},
[TPUREG_TCR1] = {reg_rd:tpu_t1_rd,reg_wr:tpu_t1_wr,adr:0x3a7f,adr1:0x37bf},
/* Special TPU - group 2 */
/* access through test subsystem serial scan lines */
/* adr .. number of register bits, adr1 .. TPU scan line selection */
[TPUREG_PC] = {reg_rd:tpu_t2_rd,reg_wr:tpu_t2_wr,adr: 9,adr1:TPU_SxSEL_PC},
[TPUREG_IR] = {reg_rd:NULL,reg_wr:NULL,adr:0,adr1:0},
[TPUREG_BPLA] = {reg_rd:tpu_t2_rd,reg_wr:tpu_t2_wr,adr:16,adr1:TPU_SxSEL_BPLA},
[TPUREG_SPLA] = {reg_rd:tpu_t2_rd,reg_wr:tpu_t2_wr,adr:15,adr1:TPU_SxSEL_SPLA},
[TPUREG_PCBR] = {reg_rd:tpu_t2_rd,reg_wr:tpu_t2_wr,adr: 9,adr1:TPU_SxSEL_PCBR},
[TPUREG_CHANBR] = {reg_rd:tpu_t2_rd,reg_wr:tpu_t2_wr,adr: 4,adr1:TPU_SxSEL_CHANBR},
/* One of parameter registers used for internal registers access */ /* was TPUREG_DEBUR */
[TPUREG_DEBPAR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFF00,},
[TRAMREG_CR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFB00,},
[TRAMREG_TST] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFB02,},
[TRAMREG_BAR] = {reg_rd:tpu_mem_rd16,reg_wr:tpu_mem_wr16,adr:0xFFFB04,},
};
/**************************************************************************/
/* Helper function for test register access */
static int use_fetched_reg;
static u_int16_t fetched_dscr;
static u_int16_t fetched_creg;
static u_int16_t fetched_tcr;
static u_int16_t stored_diob;
static u_int16_t stored_pc;
static u_int16_t stored_debpar2; /* was strored_debur2 */
static u_int32_t stored_ir; /* was strored_x1 */
/* was strored_x2 */
static
void test_shift_wait(unsigned creg)
{
int cnt=0x8000;
tpu_reg_wr(TPUREG_CREG,0,creg|TPU_SSHOP); /* 4 */
do{
creg=tpu_reg_rd(TPUREG_CREG,0);
if(!(creg&TPU_TSTBUSY)) return; /* 0x8000 */
}while(cnt--);
fprintf(stderr,"test_shift_wait : stalled busy condition\n");
}
/* Write 32 Bit Instruction Register */
static /* was test_shift_1 */
void test_shift_irwr(u_int32_t new_ir )
{
u_int16_t dscr; /* [bp-6] */
u_int16_t creg; /* si */
u_int16_t tcr; /* di */
if (!use_fetched_reg){
tpu_reg_wr(TPUREG_TSTMSRB,0,0);
tpu_reg_wr(TPUREG_TSTRC,0,0);
tpu_reg_wr(TPUREG_DREG,0,0);
dscr=tpu_reg_rd(TPUREG_DSCR,0);
creg=tpu_reg_rd(TPUREG_CREG,0);
tcr=tpu_reg_rd(TPUREG_TCR,0);
}else{
creg=fetched_creg;
tcr=fetched_tcr;
dscr=fetched_dscr;
}
creg=(creg|TPU_IMBTST)&~TPU_MUXEL; /*!!!!!!!!!!!*/
tpu_reg_wr(TPUREG_CREG,0,creg);
if(!(dscr&TPU_HOT4)) /* ???????? */
tpu_reg_wr(TPUREG_DSCR,0,dscr|TPU_HOT4);
tcr&=TPU_INCAD | TPU_TCR1C | TPU_TMW; /* 0x1801 */
tpu_reg_wr(TPUREG_TCR,0,tcr | val2mfld(TPU_ACUTR,TPU_ACUTR_STEPTPU) |
val2mfld(TPU_SISEL,TPU_SxSEL_IR)); /* 0x204 */
tpu_reg_wr(TPUREG_TSTSC,0,0x1000);
tpu_reg_wr(TPUREG_TSTMSRA,0,new_ir&0xffff);
test_shift_wait(creg); /* test shift */
tpu_reg_wr(TPUREG_TCR,0,tcr | val2mfld(TPU_ACUTR,TPU_ACUTR_STEPTPU) |
val2mfld(TPU_SISEL,TPU_SxSEL_IR)); /* 0x204 */
tpu_reg_wr(TPUREG_TSTSC,0,0x1000);
tpu_reg_wr(TPUREG_TSTMSRA,0,(new_ir>>16)&0xffff);
test_shift_wait(creg); /* test shift */
if(!(dscr&TPU_HOT4)) /* ???????? */
tpu_reg_wr(TPUREG_DSCR,0,dscr);
}
/* Read 32 Bit Instruction Register */
static /* was test_shift_2 */
u_int32_t test_shift_irrd(void)
{
u_int16_t dscr; /* [bp-0a] */
u_int16_t creg; /* si */
u_int16_t tcr; /* di */
u_int16_t ir_lo,ir_hi;
if (!use_fetched_reg){
tpu_reg_wr(TPUREG_TSTMSRB,0,0);
tpu_reg_wr(TPUREG_TSTRC,0,0);
tpu_reg_wr(TPUREG_DREG,0,0);
dscr=tpu_reg_rd(TPUREG_DSCR,0);
creg=tpu_reg_rd(TPUREG_CREG,0);
tcr=tpu_reg_rd(TPUREG_TCR,0);
}else{
creg=fetched_creg;
tcr=fetched_tcr;
dscr=fetched_dscr;
}
creg=(creg|TPU_IMBTST)&~TPU_MUXEL; /*!!!!!!!!!!!*/
tpu_reg_wr(TPUREG_CREG,0,creg);
if(!(dscr&TPU_HOT4)) /* ???????? */
tpu_reg_wr(TPUREG_DSCR,0,dscr|TPU_HOT4);
tcr&=TPU_INCAD | TPU_TCR1C | TPU_TMW; /* 0x1801 */
tpu_reg_wr(TPUREG_TCR,0,tcr | val2mfld(TPU_ACUTR,TPU_ACUTR_STEPTPU) |
val2mfld(TPU_SOSEL,TPU_SxSEL_IR)); /* 0x220 */
tpu_reg_wr(TPUREG_TSTSC,0,0x0010);
test_shift_wait(creg); /* test shift */
ir_lo=tpu_reg_rd(TPUREG_TSTMSRB,0);
tpu_reg_wr(TPUREG_TCR,0,tcr | val2mfld(TPU_ACUTR,TPU_ACUTR_STEPTPU) |
val2mfld(TPU_SOSEL,TPU_SxSEL_IR) |
val2mfld(TPU_SISEL,TPU_SxSEL_IR)); /* 0x224 */
tpu_reg_wr(TPUREG_TSTSC,0,0x1010);
tpu_reg_wr(TPUREG_TSTMSRA,0,ir_lo);
test_shift_wait(creg); /* test shift */
ir_hi=tpu_reg_rd(TPUREG_TSTMSRB,0);
tpu_reg_wr(TPUREG_TCR,0,tcr | val2mfld(TPU_ACUTR,TPU_ACUTR_STEPTPU) |
val2mfld(TPU_SISEL,TPU_SxSEL_IR)); /* 0x204 */
tpu_reg_wr(TPUREG_TSTSC,0,0x1000);
tpu_reg_wr(TPUREG_TSTMSRA,0,ir_hi);
test_shift_wait(creg); /* test shift */
if(!(dscr&TPU_HOT4)) /* ???????? */
tpu_reg_wr(TPUREG_DSCR,0,dscr);
return ir_lo|((u_int32_t)ir_hi<<16);
}
static /* was test_shift_3 */
int test_shift_regrd(int shiftcnt ,int sxsel)
{
u_int16_t dscr; /* [bp-8] */
u_int16_t creg; /* si */
u_int16_t tcr; /* di */
u_int16_t ret;
if (!use_fetched_reg){
tpu_reg_wr(TPUREG_TSTMSRB,0,0);
tpu_reg_wr(TPUREG_TSTRC,0,0);
tpu_reg_wr(TPUREG_DREG,0,0);
dscr=tpu_reg_rd(TPUREG_DSCR,0);
creg=tpu_reg_rd(TPUREG_CREG,0);
tcr=tpu_reg_rd(TPUREG_TCR,0);
}else{
creg=fetched_creg;
tcr=fetched_tcr;
dscr=fetched_dscr;
}
creg=(creg|TPU_IMBTST)&~TPU_MUXEL; /*!!!!!!!!!!!*/
tpu_reg_wr(TPUREG_CREG,0,creg);
if(!(dscr&TPU_HOT4)) /* ???????? */
tpu_reg_wr(TPUREG_DSCR,0,dscr|TPU_HOT4);
tcr&=TPU_INCAD | TPU_TCR1C | TPU_TMW; /* 0x1801 */
tpu_reg_wr(TPUREG_TCR,0,tcr | val2mfld(TPU_ACUTR,TPU_ACUTR_STEPTPU) |
val2mfld(TPU_SOSEL,sxsel)); /* (sxsel<<4)|0x200 */
tpu_reg_wr(TPUREG_TSTSC,0,shiftcnt);
test_shift_wait(creg); /* test shift */
ret=tpu_reg_rd(TPUREG_TSTMSRB,0)>>(0x10-shiftcnt);
tpu_reg_wr(TPUREG_TCR,0,tcr | val2mfld(TPU_ACUTR,TPU_ACUTR_STEPTPU) |
val2mfld(TPU_SISEL,sxsel)); /* (sxsel<<1)|0x200 */
tpu_reg_wr(TPUREG_TSTSC,0,shiftcnt<<8);
tpu_reg_wr(TPUREG_TSTMSRA,0,ret);
test_shift_wait(creg); /* test shift */
if(!(dscr&TPU_HOT4)) /* ???????? */
tpu_reg_wr(TPUREG_DSCR,0,dscr);
return ret;
}
static /* was test_shift_4 */
int test_shift_regwr(int shiftcnt, int sxsel, int val)
{
u_int16_t dscr; /* di */
u_int16_t creg; /* si */
u_int16_t tcr; /* [bp-6] */
if (!use_fetched_reg){
tpu_reg_wr(TPUREG_TSTMSRB,0,0);
tpu_reg_wr(TPUREG_TSTRC,0,0);
tpu_reg_wr(TPUREG_DREG,0,0);
dscr=tpu_reg_rd(TPUREG_DSCR,0);
creg=tpu_reg_rd(TPUREG_CREG,0);
tcr=tpu_reg_rd(TPUREG_TCR,0);
}else{
creg=fetched_creg;
tcr=fetched_tcr;
dscr=fetched_dscr;
}
if(!(dscr&TPU_HOT4)) /* ???????? */
tpu_reg_wr(TPUREG_DSCR,0,dscr|TPU_HOT4);
creg=(creg|TPU_IMBTST)&~TPU_MUXEL; /*!!!!!!!!!!!*/
tpu_reg_wr(TPUREG_CREG,0,creg);
tcr&=TPU_INCAD | TPU_TCR1C | TPU_TMW; /* 0x1801 */
tpu_reg_wr(TPUREG_TCR,0,tcr | val2mfld(TPU_ACUTR,TPU_ACUTR_STEPTPU) |
val2mfld(TPU_SISEL,sxsel)); /* (sxsel<<1)|0x200 */
tpu_reg_wr(TPUREG_TSTSC,0,shiftcnt<<8);
tpu_reg_wr(TPUREG_TSTMSRA,0,val);
test_shift_wait(creg); /* test shift */
if(!(dscr&TPU_HOT4)) /* ???????? */
tpu_reg_wr(TPUREG_DSCR,0,dscr);
return 0;
}
static /* was test_pha_2 */
void test_forced_inst(u_int32_t new_ir)
{
test_shift_irwr(new_ir);
tpu_reg_or(TPUREG_CREG,0,TPU_ACUT);
}
static /* was test_pha_1 */
void test_store_ir(void)
{
stored_debpar2=tpu_reg_rd(TPUREG_DEBPAR,0);
stored_pc=tpu_reg_rd(TPUREG_PC,0);
stored_ir=test_shift_irrd();
test_forced_inst(0x3ffffc03);
stored_diob=tpu_reg_rd(TPUREG_DEBPAR,0);
}
static /* was test_pha_3 */
void test_restore_ir(void)
{
tpu_reg_wr(TPUREG_DEBPAR,0,stored_diob);
test_forced_inst(0x1ffffc03);
tpu_reg_wr(TPUREG_DEBPAR,0,stored_debpar2);
tpu_reg_wr(TPUREG_PC,0,stored_pc);
test_shift_irwr(stored_ir);
}
/**************************************************************************/
/* Other supporting routines */
static u_int16_t test_dssrdscr_1; /* 0 => stop, 1 =>run */
static u_int16_t test_dscr_arm;
static u_int16_t test_dssr_bkpt;
int test_init_1(void)
{
u_int16_t creg; /* bp-2 */
int cnt=0x1000;
tpu_reg_wr(TPUREG_CREG,0,TPU_MUXEL|TPU_EMT);
creg=tpu_reg_rd(TPUREG_CREG,0);
do{
creg=tpu_reg_rd(TPUREG_CREG,0);
}while(!(creg&TPU_EMT)&&(--cnt));
tpu_reg_wr(TPUREG_CIER,0,0); /* disable interrupt generation */
if(!cnt){
fprintf(stderr,"test_init_1 : cannot enter test mode\n");
return -1;
}
return 0;
}
int test_init_2(void)
{
u_int16_t dssr; /* si */
u_int16_t dscr; /* bx */
dssr=tpu_reg_rd(TPUREG_DSSR,0);
dscr=tpu_reg_rd(TPUREG_DSCR,0);
if((dssr&TPU_BKPT)||(dscr&TPU_HOT4))
test_dssrdscr_1=0;
else
test_dssrdscr_1=1;
test_dscr_arm=dscr&TPU_BMSK;
if (dssr&TPU_BKPT)
test_dssr_bkpt=1;
else
test_dssr_bkpt=0;
return 0;
}
int tpu_halt(void)
{
int i;
if(test_dssrdscr_1==0){
/* already halted */
/* return 0; */
}
tpu_reg_or(TPUREG_CREG,0,TPU_IMBTST); /* stop microengine */
tpu_reg_wr(TPUREG_DSCR,0,TPU_HOT4|TPU_CLKS|test_dscr_arm);
test_dssrdscr_1=0;
/* old_cpr = CPR0,CPR1 */
/* CPR0,CPR1 = 0 */
for(i=0;i<5;i++){
if(tpu_reg_rd(TPUREG_DSSR,0)&TPU_BKPT)
tpu_reg_and(TPUREG_DSSR,0,~TPU_BKPT);
tpu_reg_or(TPUREG_CREG,0,TPU_IMBTST|TPU_ACUT);
}
/* CPR0,CPR1 = old_cpr */
return 0;
}
#define TPU_UCODE_LEN 0x200
u_int32_t tpu_ucode_img[TPU_UCODE_LEN];
int tpu_ucode_read(int print)
{
int adr;
u_int32_t ir;
adr=0;
test_store_ir();
if(print)printf("reading microcode\n");
tpu_reg_wr(TPUREG_PC,0,adr);
for(;adr<TPU_UCODE_LEN;adr++){
test_shift_irwr(0xffffffff);
tpu_reg_or(TPUREG_CREG,0,TPU_ACUT);
ir=test_shift_irrd();
tpu_ucode_img[adr]=ir;
if(print)printf(" %03X: %08lX\n",adr,(unsigned long)ir);
}
test_restore_ir();
return 1;
}
/**************************************************************************/
/* Register read and write routines */
/* read TPU register - method 1 */
int tpu_t1_rd(struct tpu_reg_des *des, int indx)
{
unsigned val;
test_store_ir();
if(des->flags&TPUREG_FL_DIOB){
val=stored_diob; /* DIOB read */
}else{
if(des->flags&TPUREG_FL_PMOD)
test_forced_inst(0xf403|(des->adr<<16)); /* P read */
else
test_forced_inst(0xfc03|(des->adr<<16)); /* rest */
/* read value from mem 0xFFFF00 */
val=tpu_reg_rd(TPUREG_DEBPAR,0);
}
test_restore_ir();
if(des->flags&TPUREG_FL_SH4)
val>>=4;
return val;
}
/* write TPU register - method 1 */
int tpu_t1_wr(struct tpu_reg_des *des, int indx, int val)
{
int ret;
test_store_ir();
if(des->flags&TPUREG_FL_SH4)
val<<=4;
ret=tpu_reg_wr(TPUREG_DEBPAR,0,val);
test_forced_inst(0x1ffffc03);
if(des->flags&TPUREG_FL_DIOB){
stored_diob=val; /* DIOB write */
}else{
test_forced_inst(0xffff|(des->adr1<<16)); /* rest */
}
test_restore_ir();
return 0;
}
/* read TPU register - method 2 */
int tpu_t2_rd(struct tpu_reg_des *des, int indx)
{
return test_shift_regrd(des->adr,des->adr1);
}
/* write TPU register - method 2 */
int tpu_t2_wr(struct tpu_reg_des *des, int indx, int val)
{
return test_shift_regwr(des->adr,des->adr1,val);
}
/* read 16 bit variable from main CPU address space */
int tpu_mem_rd16(struct tpu_reg_des *des, int indx)
{
u_int16_t val;
int adr=des->adr;
if(indx){
if(indx>=des->arr_len) return -1;
adr+=2*indx;
}
val=TPU_RD16((caddr_t)adr);
return val;
mem_op_error:
fprintf(stderr,"tpu_mem_rd16 : read from address %06x error\n",adr);
fflush(NULL);
return -1;
}
/* write 16 bit variable to main CPU address space */
int tpu_mem_wr16(struct tpu_reg_des *des, int indx, int val)
{
int adr=des->adr;
if(indx){
if(indx>=des->arr_len) return -1;
adr+=2*indx;
}
TPU_WR16((caddr_t)adr,val);
return 0;
mem_op_error:
fprintf(stderr,"tpu_mem_wr16 : write to address %06x error\n",adr);
fflush(NULL);
return -1;
}
/* Read TPU register */
int tpu_reg_rd(int reg, int indx)
{
if((reg>TPUREG_MAX)||(tpu_regs[reg].reg_rd==NULL))
return -1;
return tpu_regs[reg].reg_rd(&tpu_regs[reg],indx);
}
/* Write TPU register */
int tpu_reg_wr(int reg, int indx, int val)
{
if((reg>TPUREG_MAX)||(tpu_regs[reg].reg_wr==NULL))
return -1;
return tpu_regs[reg].reg_wr(&tpu_regs[reg],indx,val);
}
int tpu_reg_or(int reg, int indx, int val)
{
int reg_val;
reg_val=tpu_reg_rd(reg,indx);
reg_val|=val;
tpu_reg_wr(reg,indx,reg_val);
return reg_val;
}
int tpu_reg_and(int reg, int indx, int val)
{
int reg_val;
reg_val=tpu_reg_rd(reg,indx);
reg_val&=val;
tpu_reg_wr(reg,indx,reg_val);
return reg_val;
}
/**************************************************************************/
#define swap_l(x) (x>>24) | ((x>>8)&0xff00) | ((x<<8)&0xff0000) | ((x&0xff)<<24)
/* external TPU disassembler */
void DisInst (unsigned long i, FILE * fp);
int cpu_stat(void)
{
int ret;
u_int rpc;
ret=bdmlib_getstatus();
printf("MCU ");
if(ret&BDM_TARGETRESET) printf("Reset ");
if(ret&BDM_TARGETSTOPPED) printf("Stopped ");
if(ret&BDM_TARGETPOWER) printf("NoPower ");
if(ret&BDM_TARGETNC) printf("NoConnect ");
printf("\n");
if(ret&BDM_TARGETSTOPPED) {
if((ret=bdmlib_get_sys_reg(BDM_REG_RPC, &rpc))<0) return ret;
printf("RPC=0x%06x\n",swap_l(rpc));
}
return 0;
}
int main(int argc, char *argv[])
{
int ret;
bdmlib_setdebug(1);
if((ret=bdmlib_open(bdm_dev_name))<0)
{ printf("bdmlib_open : %s\n",bdmlib_geterror_str(ret)); return 1; };
bdmlib_setioctl(BDM_SPEED,0);
if (!(bdmlib_getstatus() & BDM_TARGETSTOPPED))
ret=bdmlib_ioctl(BDM_STOP_CHIP);
if(1){
printf("We need to reset target for first run\n");
if((ret=bdmlib_reset())<0){
printf("Cannot reset target - exitting\n");
exit(1);
}
}
if(cpu_stat()<0){
printf("trying to reset !!!!!!!\n");
ret=bdmlib_reset();
cpu_stat();
}
bdmlib_set_sys_reg(BDM_REG_DFC, 5);
bdmlib_set_sys_reg(BDM_REG_SFC, 5);
ret=test_init_1();
printf("test_init_1 returned %d\n",ret);
ret=test_init_2();
printf("test_init_2 returned %d\n",ret);
printf("test_dssrdscr_1(run)=%d test_dscr_arm=0x%02x test_dssr_bkpt=%d\n",
test_dssrdscr_1,test_dscr_arm,test_dssr_bkpt);
fflush(NULL);
// tpu_halt();
printf("DCNR %04X\n",tpu_reg_rd(TPUREG_DCNR,0));
printf("DSCR %04X\n",tpu_reg_rd(TPUREG_DSCR,0));
// tpu_reg_or(TPUREG_CREG,0,TPU_IMBTST); /* stop microengine */
// tpu_reg_or(TPUREG_DSCR,0,0x8200); /* ???????????? */
printf("P %04X DIOB %04X A %04X SR %04X DEC %01X\n"
"ERT %04X TCR1 %04X TCR2 %04X PC %03X CHAN %01X\n",
tpu_reg_rd(TPUREG_P,0),tpu_reg_rd(TPUREG_DIOB,0),
tpu_reg_rd(TPUREG_A,0),tpu_reg_rd(TPUREG_SR,0),
tpu_reg_rd(TPUREG_DEC,0),tpu_reg_rd(TPUREG_ERT,0),
tpu_reg_rd(TPUREG_TCR1,0),tpu_reg_rd(TPUREG_TCR2,0),
tpu_reg_rd(TPUREG_PC,0),tpu_reg_rd(TPUREG_CHAN,0));
if(0){
printf("TCR2 %04X\n",tpu_reg_rd(TPUREG_TCR2,0));
printf("TCR1 %04X\n",tpu_reg_rd(TPUREG_TCR1,0));
printf("TCR2 %04X\n",tpu_reg_rd(TPUREG_TCR2,0));
tpu_reg_wr(TPUREG_P ,0,0xABCD);tpu_reg_wr(TPUREG_DIOB,0,0xEF01);
tpu_reg_wr(TPUREG_A ,0,0x2345);tpu_reg_wr(TPUREG_SR ,0,0x6789);
tpu_reg_wr(TPUREG_DEC ,0, 0xA);tpu_reg_wr(TPUREG_ERT ,0,0xBCDE);
tpu_reg_wr(TPUREG_TCR1,0,0xF012);tpu_reg_wr(TPUREG_TCR2,0,0x3456);
tpu_reg_wr(TPUREG_PC ,0, 0x789);tpu_reg_wr(TPUREG_CHAN,0, 0xB);
}
{
int i;
tpu_ucode_read(0);
for(i=0;i<TPU_UCODE_LEN;i++){
printf("%03x: %08x ",i,tpu_ucode_img[i]);
DisInst (tpu_ucode_img[i],stdout);
}
}
return 0;
}

684
m683xx/bdm-load/tpudis.c Normal file
View File

@@ -0,0 +1,684 @@
/*******************************************************************
TPUDB Project to Create Free Motorola 683xx TPU Debugger
tpudis.c - TPU microcode disassembler
(C) Copyright 2000 by Wouter Vlothuizen - Original Author
e-mail: wouter@vlothuizen.demon.nl
This package can be copied and modified under
GNU General Public License with all its conditions.
See file GPL for details. Under this license nobody can
distribute this work and any derived work without full source code
for all modules compiled and linked into executable.
*******************************************************************/
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
static FILE *f;
static unsigned long inst;
void
Error (char *s)
{
fprintf (stderr, "\ntpudis: %s\n", s);
exit (1);
}
#define put(x) s=x
#define I(h,l) ( (inst>>(l)) & (((1<<((h)+1-(l))))-1) )
void
T1ABS (void)
{
char *s=NULL;
switch (I (28, 25))
{
case 0:
put ("plow");
break;
case 1:
put ("phi");
break;
case 2:
put ("dec");
break;
case 3:
put ("chan");
break;
case 4:
put ("#0 special");
break;
case 5:
put ("{Illegal T1ABS: 5}");
break;
case 6:
put ("{Illegal T1ABS: 6}");
break;
case 7:
put ("#0");
break;
case 8:
put ("p");
break;
case 9:
put ("a");
break;
case 10:
put ("sr");
break;
case 11:
put ("diob");
break;
case 12:
put ("tcr1");
break;
case 13:
put ("tcr2");
break;
case 14:
put ("ert");
break;
case 15:
put ("#0");
break;
default:
Error ("T1ABS decoding error");
}
fprintf (f, "%s + ", s);
}
void
T3ABD (void)
{
char *s=NULL;
switch (inst >> 21 & 0xF)
{
case 0:
put ("a");
break;
case 1:
put ("sr");
break;
case 2:
put ("ert");
break;
case 3:
put ("diob");
break;
case 4:
put ("phi");
break;
case 5:
put ("{Illegal T3ABD: 5}");
break;
case 6:
put ("plow");
break;
case 7:
put ("p");
break;
case 8:
put ("link");
break;
case 9:
put ("chan");
break;
case 10:
put ("dec");
break;
case 11:
put ("dec&chan");
break;
case 12:
put ("tcr1");
break;
case 13:
put ("tcr2");
break;
case 14:
put ("{Illegal T3ABD: 14}");
break;
case 15:
put ("Nil");
break;
default:
Error ("T3ABD decoding error");
}
fprintf (f, "AU %s :=", s);
}
void
SHF (void)
{
char *s=NULL;
switch (inst >> 19 & 3)
{
case 0:
s = "<<";
break;
case 1:
s = ">>";
break;
case 2:
s = "R>";
break;
case 3:
s = "";
break;
default:
Error ("SHF decoding error");
}
fprintf (f, "%s ", s);
}
void
T1BBSetc (void)
{
char *s=NULL;
switch (inst >> 14 & 7)
{
case 0:
s = "p";
break;
case 1:
s = "a";
break;
case 2:
s = "sr";
break;
case 3:
s = "diob";
break;
case 7:
s = "#0";
break;
case 4:
case 5:
case 6:
s = "{Illegal T1BBS}";
break;
default:
Error ("T1BBS decoding error");
}
fprintf (f, "%s%s%s ",
inst & (1L << 12) ? "" : "!", s, inst & (1L << 13) ? "" : " + 1");
}
void
SRCCCL (void)
{
if (~inst & (1L << 18))
fprintf (f, ", ensr");
if (~inst & (1L << 17))
fprintf (f, ", cc");
}
void
T1BBI (void)
{
fprintf (f, "#$%2lx", inst >> 9 & 0xFF);
}
void
DECEND (void)
{
char *s=NULL;
switch (inst & 3)
{
case 0:
s = "DEC_RTS";
break;
case 1:
s = "DEC_RPT";
break;
case 2:
s = "end";
break;
case 3:
return;
default:
Error ("DECEND decoding error");
}
fprintf (f, "%s", s);
}
void
IOMetc (int rwPos)
{
char *fm=NULL;
int aid=0;
switch (inst >> 9 & 7)
{
case 0:
fm = "RAM p %s @prm%d ; ";
aid = inst >> 2 & 7;
break;
case 1:
fm = "RAM p %s by_diob ; ";
break;
case 2:
fm = "RAM p %s @$%x ; ";
aid = inst >> 2 & 0x7F;
break;
case 4:
fm = "RAM diob %s @prm%d ; ";
aid = inst >> 2 & 7;
break;
case 5:
fm = "RAM diob %s by_diob ; ";
break;
case 6:
fm = "RAM diob %s @$%x ; ";
aid = inst >> 2 & 0x7F;
break;
case 3:
case 7:
return;
default:
Error ("IOM decoding error");
}
fprintf (f, fm, inst & (1L << rwPos) ? "->" : "<-", aid);
}
void
CJCetc (void)
{
char *s=NULL;
if (I (29, 16) == 0x3FFF)
return;
switch (inst >> 26 & 0xF)
{
case 0:
s = "LESS_THAN";
break;
case 1:
s = "LOW_SAME";
break;
case 2:
s = "V";
break;
case 3:
s = "N";
break;
case 4:
s = "C";
break;
case 5:
s = "Z";
break;
case 6:
s = "cflg1";
break;
case 7:
s = "cflg0";
break;
case 8:
s = "TDL";
break;
case 9:
s = "MRL";
break;
case 10:
s = "LSL";
break;
case 11:
s = "SEQ1";
break;
case 12:
s = "SEQ0";
break;
case 13:
s = "PSL";
break;
case 14:
s = "{Illegal branch}";
break;
case 15:
s = "false";
break;
default:
Error ("CJC decoding error");
}
fprintf (f, "if %s = %s then goto $%lx%s; ",
s,
inst & (1L << 8) ? "true" : "false",
inst >> 16 & 0x1FF, inst & (1L << 25) ? "" : ", flsh");
}
void
NMAetc (void)
{
char *s=NULL;
switch (inst >> 26 & 3)
{
case 0:
s = "jmp";
break;
case 1:
s = "jsr";
break;
case 2:
s = "rts";
break;
case 3:
return;
default:
Error ("NMA decoding error");
}
fprintf (f, "%s%s $%lx ; ", s, inst & (1L << 25) ? "" : " ,flsh",
inst >> 16 & 0x1FF);
}
void
TBS (void)
{
char *s=NULL;
switch (I (15, 12))
{
case 0:
s = "in_mtcr1_ctcr1";
break;
case 1:
s = "in_mtcr2_ctcr1";
break;
case 2:
s = "in_mtcr1_ctcr2";
break;
case 3:
s = "in_mtcr2_ctcr2";
break;
case 4:
s = "out_mtcr1_ctcr1";
break;
case 5:
s = "out_mtcr2_ctcr1";
break;
case 6:
s = "out_mtcr1_ctcr2";
break;
case 7:
s = "out_mtcr2_ctcr2";
break;
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
return;
default:
Error ("TBS decoding error");
}
fprintf (f, "tbs:=%s ", s);
}
void
ERWTDLMRL (void)
{
if (~inst & (1L << 29))
fprintf (f, "write_mer ");
if (~inst & (1L << 18))
fprintf (f, "neg_tdl ");
if (~inst & (1L << 17))
fprintf (f, "neg_mrl ");
}
void
PSC (void)
{
char *s=NULL;
switch (I (7, 6))
{
case 0:
s = "PAC";
break;
case 1:
s = "high";
break;
case 2:
s = "low";
break;
case 3:
return;
default:
Error ("PSC decoding error");
}
fprintf (f, "pin:=%s ", s);
}
void
PAC (void)
{
char *s=NULL;
switch (I (11, 9))
{
case 0:
s = "off";
break;
case 1:
s = "high";
break;
case 2:
s = "low";
break;
case 3:
s = "h+l";
break;
case 4:
case 5:
case 6:
case 7:
return;
default:
Error ("PAC decoding error");
}
fprintf (f, "pac:=%s ", s);
}
void
FLC (int pos) /* at position 5 or 15 */
{
char *s=NULL;
fprintf (f, "chan ");
switch (I (pos, pos - 2))
{
case 0:
s = "clr cflg0";
break;
case 1:
s = "set cflg0";
break;
case 2:
s = "clr cflg1";
break;
case 3:
s = "set cflg1";
break;
case 4:
case 5:
case 6:
case 7:
return;
default:
Error ("FLC decoding error");
}
fprintf (f, "%s ", s);
}
void
LSL (int pos) /* at position 8 or 12 */
{
if (~inst & (1L << pos))
fprintf (f, "neg_lsr ");
}
void
CIR (void)
{
if (~inst & (1L << 2))
fprintf (f, "pir ");
}
void
CCM (void)
{
if (~inst & (1L << 2))
fprintf (f, "by_p ");
}
void
MTD (void)
{
char *s=NULL;
switch (I (1, 0))
{
case 0:
s = "en";
break;
case 1:
s = "ds";
break;
case 2:
case 3:
return;
default:
Error ("MTD decoding error");
}
fprintf (f, "%ssr ", s);
}
void
sep (void)
{
fprintf (f, "; ");
}
void
DisInst (unsigned long i, FILE * fp)
{
f = fp;
inst = i;
if (inst != 0xffffffff)
switch (inst >> 30 & 3) /* type of instruction */
{
case 0: /* format 1 */
T3ABD ();
SHF ();
T1ABS ();
T1BBSetc ();
SRCCCL ();
sep ();
IOMetc (29);
DECEND ();
break;
case 1: /* format 2 */
T3ABD ();
SHF ();
T1ABS ();
T1BBSetc ();
sep ();
FLC (5);
ERWTDLMRL ();
PAC ();
LSL (8);
PSC ();
CIR ();
sep ();
DECEND ();
break;
case 2: /* format 3 */
CJCetc ();
FLC (5);
TBS ();
PAC ();
PSC ();
CCM ();
MTD ();
break;
case 3:
if (inst & (1L << 29)) /* format 5 */
{
T3ABD ();
SHF ();
T1ABS ();
T1BBI ();
SRCCCL ();
sep ();
FLC (5);
LSL (8);
CIR ();
sep ();
}
else /* format 4 */
{
NMAetc ();
FLC (15);
LSL (12);
sep ();
IOMetc (28);
}
DECEND ();
break;
default:
Error ("format decoding error");
}
fprintf (f, "\n");
}
#if 0
void
EntryPoint (unsigned int ep)
{
int pc;
pc = ep & 0x1FF;
if (ep >> 9 & 3 == 0)
{
fprintf (f, "Error in EntryPoint format\n");
}
else
{
fprintf (f, "PreLoad=%d ME=%d PPD=%4s PC=$%03x\n",
ep >> 13 & 7,
ep & (1L << 12) ? 1 : 0, ep & (1L << 11) ? "DIOB" : "P", pc);
epCnt[pc]++;
}
}
#endif