📄 dsploader.c
字号:
/*DM642 DSP PCI loader, could be reformed to working in a different OS. Tao Chen, Oct 18, 2004*/
#include "vxWorks.h" /*for vxworks OS*/
#include "config.h" /*for pentium platform*/
#include "stdio.h"
#include "dirent.h"
#include "stat.h"
#define IRAM_BASE 0x00000000
#define SDRAM_BASE 0x80000000
#define COFF_MAGIC_2 0302
#define ISCOFF(x) ((x) == COFF_MAGIC_2)
#define COFF_SECTYPE_TEXT 0x0020
#define COFF_SECTYPE_DATA 0x0040
#define COFF_SECTYPE_BSS 0x0080
#define COFF_SECTYPE_COPY 0x0050
typedef struct _coff_filehdr coff_filehdr;
struct _coff_filehdr {
UINT16 f_magic; /* magic number */
UINT16 f_nscns; /* number of sections */
INT32 f_timdat; /* time & date stamp */
INT32 f_symptr; /* file pointer to symtab */
INT32 f_nsyms; /* number of symtab entries */
UINT16 f_opthdr; /* sizeof(optional hdr) */
UINT16 f_flags; /* flags */
UINT16 f_target_id; /* target architecture id */
};
typedef struct _coff_aouthdr coff_aouthdr;
struct _coff_aouthdr {
INT16 magic; /* optional file header magic number */
INT16 vstamp; /* version stamp */
INT32 tsize; /* text size in bytes, padded to FW bdry*/
INT32 dsize; /* initialized data " " */
INT32 bsize; /* uninitialized data " " */
INT32 entrypt; /* entry pt. */
INT32 text_start; /* base of text used for this file */
INT32 data_start; /* base of data used for this file */
};
typedef struct _coff_scnhdr coff_scnhdr;
struct _coff_scnhdr {
char s_name[8]; /* old COFF version name fld */
INT32 s_paddr; /* physical address */
INT32 s_vaddr; /* virtual address */
INT32 s_size; /* section size */
INT32 s_scnptr; /* file ptr to raw data for section */
INT32 s_relptr; /* file ptr to relocation */
INT32 s_lnnoptr; /* file ptr to line numbers */
UINT32 s_nreloc; /* number of relocation entries */
UINT32 s_nlnno; /* number of line number entries */
UINT32 s_flags; /* flags */
INT16 s_reserved; /* reserved 2 bytes */
UINT16 s_page; /* memory page id */
};
static UINT32 base0, base1, base2=0;
static int DSPP = 0;
void sysMemOutLong(UINT32 address, UINT32 data)
{
*((UINT32*)address) = data;
}
vDspRegWrite32(UINT32 reg, UINT32 value)
{
UINT32 addr = base1+(reg-0x01800000UL);
sysMemOutLong(addr, value);
}
void vDspEmifInit()
{
UINT32 EmifA[12] = { 0x00092078UL, /* GCTL - 0x01800000*/
0xF3A88E02UL, /* CE1 - 0x01800004*/
0xFFFFFFDEUL, /* CE0 - 0x01800008*/
/* Address split 3*/
0x22a28a22UL, /* CE2 - 0x01800010*/
0x22a28a42UL, /* CE3 - 0x01800014*/
0x57115000UL, /* SDRAMCTL - 0x01800018*/
0x0000081bUL, /* SDRAMTIM - 0x0180001c*/
0x000a8529UL, /* SDRAMEXT - 0x01800020*/
/* Address split 9*/
0x00000002UL, /* CE1ECCTL - 0x01800044*/
0x00000002UL, /* CE0ECCTL - 0x01800048*/
/* Address split */
0x00000002UL, /* CE2ECCTL - 0x01800050*/
0x00000073UL, /* CE3ECCTL - 0x01800054*/
};
vDspRegWrite32(0x01800000UL, EmifA[0]);
vDspRegWrite32(0x01800004UL, EmifA[1]);
vDspRegWrite32(0x01800008UL, EmifA[2]);
vDspRegWrite32( 0x01800010UL, EmifA[3] );
vDspRegWrite32( 0x01800014UL, EmifA[4] );
vDspRegWrite32( 0x01800018UL, EmifA[5] );
vDspRegWrite32( 0x0180001CUL, EmifA[6] );
vDspRegWrite32( 0x01800020UL, EmifA[7] );
vDspRegWrite32( 0x01800044UL, EmifA[8] );
vDspRegWrite32( 0x01800048UL, EmifA[9] );
vDspRegWrite32( 0x01800050UL, EmifA[10] );
vDspRegWrite32( 0x01800054UL, EmifA[11] );
}
int iDspPciInit()
{
int busNo, devNo, fcnNo=0;
UINT16 command = 0;
/* Find DSP PCI device*/
if(pciFindDevice( 0x104C, 0x9065, 0, &busNo, &devNo, &fcnNo) != OK)
return 0;
pciConfigInLong (busNo, devNo, fcnNo, PCI_CFG_BASE_ADDRESS_0, &base0);
pciConfigInLong (busNo, devNo, fcnNo, PCI_CFG_BASE_ADDRESS_1, &base1);
pciConfigInLong (busNo, devNo, fcnNo, PCI_CFG_BASE_ADDRESS_2, &base2);
base0 &= 0xFFFFFFF0;
base1 &= 0xFFFFFFF0;
base2 &= 0xFFF0;
/*read and set the PCI commander register to enable the memory access*/
pciConfigInWord(busNo, devNo, fcnNo, PCI_CFG_COMMAND, &command);
command |= 0x3;
pciConfigOutWord(busNo, devNo, fcnNo, PCI_CFG_COMMAND, command);
printf("DSP PCI commmand register: 0x%0x\n", command);
command = 0;
pciConfigInWord(busNo, devNo, fcnNo, PCI_CFG_COMMAND, &command);
printf("base0: 0x%0x, base1: 0x%0x, base2: 0x%0x\n", base0, base1, base2);
return 1;
}
UINT32 iDsp2PciAddr(UINT32 addr)
{
int count = 0;
if(addr >= 0x400000) /*memory window range 4M, 0~3FFFFF)*/
{
while(addr >= 0x400000)
{
addr -= 0x400000;
count++;
}
}
if(DSPP != count)
{
DSPP = count;
sysOutWord(base2+0x08, DSPP);
}
return base0 + addr;
}
void swap2byte(UINT16 *addr)
{
UINT16 tmp = *addr;
UINT16 tmp1, tmp2;
tmp1 = tmp & 0xff;
tmp2 = (tmp >> 8) & 0xff;
*addr = (tmp1 << 8) | (tmp2);
}
void swap4byte(UINT32 *addr)
{
UINT32 tmp = *addr;
UINT32 tmp1, tmp2, tmp3, tmp4;
tmp1 = tmp & 0xff;
tmp2 = (tmp >> 8) & 0xff;
tmp3 = (tmp >> 16) & 0xff;
tmp4 = (tmp >> 24) & 0xff;
*addr = (tmp1 << 24) | (tmp2 << 16) | (tmp3 << 8) | (tmp4);
}
void vDspMemoryWrite(UINT32 address, int size, UINT32 data)
{
UINT32 pciAddr = 0;
UINT8 byte, count, shift=0;
pciAddr = iDsp2PciAddr(address);
sysMemOutLong(pciAddr, data);
/*printf("Write %08xh to %08xh, DSPP: %xh\n", data, pciAddr, sysInWord(base2+0x8));*/
}
/*load coff file into DSP memory, return the entry point address*/
UINT32 ulDspLoad(char *fname)
{
int i,j;
coff_filehdr *fhdr;
coff_aouthdr *ahdr;
coff_scnhdr *shdr;
struct stat filestat;
FILE *fp;
char *fbuf;
char *fileptr, *fileptr_saved;
char byte_swapped = 0;
/* stat the file and figure out it's size */
if (stat(fname, &filestat) != 0)
{
printf("unable to open target binary `%s' for getting file size.\n", fname);
return 0;
}
/* open the program for reading */
fp = fopen(fname, "r");
if (!fp)
{
printf("unable to open target binary `%s' for reading", fname);
return 0;
}
/* about 1k more than reqd is malloced to read file into memory */
fbuf = (char *) malloc((filestat.st_size + 0x200) & ~(0x200));
/* load the program into memory */
if (fread(fbuf, 1, filestat.st_size, fp) < 1)
{
printf("unable to read from target binary `%s'", fname);
return 0;
}
/* done with the executable, close it */
if (fclose(fp))
{
printf("unable to close target binary '%s'", fname);
return 0;
}
printf("target binary '%s' read in %ld bytes\n", fname, filestat.st_size);
/* start of file ptrs */
fileptr = fbuf;
fileptr_saved = fbuf;
/* goto the file header */
fhdr = (coff_filehdr *) fileptr;
fileptr = fileptr + 22;
/* check magic number */
if (!ISCOFF(fhdr->f_magic))
{
swap2byte(&(fhdr->f_magic));
if (!ISCOFF(fhdr->f_magic))
{
printf("bad magic number %d in target binary `%s' (not an executable)",
fhdr->f_magic, fname);
return 0;
}
byte_swapped = 1;
/* swap the rest of the header */
swap2byte(&(fhdr->f_nscns));
swap4byte(&(fhdr->f_timdat));
swap4byte(&(fhdr->f_symptr));
swap4byte(&(fhdr->f_nsyms));
swap2byte(&(fhdr->f_opthdr));
swap2byte(&(fhdr->f_flags));
swap2byte(&(fhdr->f_target_id));
}
/* goto aout header */
ahdr = (coff_aouthdr *) fileptr;
fileptr = fileptr + sizeof(coff_aouthdr);
/* swap bytes in the aouthdr if necessary */
if (byte_swapped == 1)
{
swap2byte(&(ahdr->magic));
swap2byte(&(ahdr->vstamp));
swap4byte(&(ahdr->tsize));
swap4byte(&(ahdr->dsize));
swap4byte(&(ahdr->bsize));
swap4byte(&(ahdr->entrypt));
swap4byte(&(ahdr->text_start));
swap4byte(&(ahdr->data_start));
}
printf("processing %d sections\n", fhdr->f_nscns);
/* loop through the section headers and then the sections */
fileptr_saved = fileptr;
for (i = 0; i < fhdr->f_nscns; i++)
{
fileptr = fileptr_saved;
shdr = (coff_scnhdr *) fileptr;
fileptr += sizeof(coff_scnhdr);
fileptr_saved = fileptr;
/* swap bytes in the scnhdr if necessary, except s_name */
if (byte_swapped == 1)
{
swap4byte(&(shdr->s_paddr));
swap4byte(&(shdr->s_vaddr));
swap4byte(&(shdr->s_size));
swap4byte(&(shdr->s_scnptr));
swap4byte(&(shdr->s_relptr));
swap4byte(&(shdr->s_lnnoptr));
swap4byte(&(shdr->s_nreloc));
swap4byte(&(shdr->s_nlnno));
swap4byte(&(shdr->s_flags));
swap2byte(&(shdr->s_reserved));
swap2byte(&(shdr->s_page));
}
/*printf("%8s %8u %8x %8x %8x %8x\n", shdr->s_name, shdr->s_size,
shdr->s_paddr, shdr->s_vaddr, shdr->s_scnptr, shdr->s_flags);*/
if (shdr->s_flags == COFF_SECTYPE_COPY) /*skip copy section?*/
{
printf("copy section '%s', flag: 0x%xh, ignored\n", shdr->s_name, shdr->s_flags);
}
else if (shdr->s_flags & COFF_SECTYPE_TEXT) /*load text section*/
{
printf("text section '%s', flag: 0x%xh, starting at 0x%08x with %d bytes\n", shdr->s_name, shdr->s_flags, shdr->s_vaddr, shdr->s_size);
fileptr = fbuf + shdr->s_scnptr;
for (j = 0; j < shdr->s_size; j+=4)
{
UINT8 a, b, c, d;
UINT32 data;
a = *(fileptr+j);
b = *(fileptr+j+1);
c = *(fileptr+j+2);
d = *(fileptr+j+3);
data = (d << 24) | (c << 16) | (b << 8) | (a);
vDspMemoryWrite(shdr->s_vaddr + j, 4, data);
}
}
else if (shdr->s_flags & COFF_SECTYPE_DATA) /*load data section*/
{
if (shdr->s_size > 0)
{
printf("data section '%s', flag: 0x%xh, starting at 0x%08x with %d bytes\n", shdr->s_name, shdr->s_flags, shdr->s_vaddr, shdr->s_size);
fileptr = fbuf + shdr->s_scnptr;
for (j = 0; j < shdr->s_size; j+=4)
{
UINT8 a, b, c, d;
UINT32 data;
a = *(fileptr+j);
b = *(fileptr+j+1);
c = *(fileptr+j+2);
d = *(fileptr+j+3);
data = (d << 24) | (c << 16) | (b << 8) | (a);
vDspMemoryWrite(shdr->s_vaddr + j, 4, data);
}
}
else
printf("section '%s' size equal to zero\n", shdr->s_name);
}
else if (shdr->s_flags & COFF_SECTYPE_BSS) /*skip bss section*/
{
if (shdr->s_size > 0)
{
printf("bss section '%s' starting at 0x%08x with %d bytes, ignored\n", shdr->s_name, shdr->s_vaddr, shdr->s_size);
fileptr = fbuf + shdr->s_scnptr;
for (j = 0; j < shdr->s_size; j+=4)
{
UINT8 a, b, c, d;
UINT32 data;
a = *(fileptr+j);
b = *(fileptr+j+1);
c = *(fileptr+j+2);
d = *(fileptr+j+3);
data = (d << 24) | (c << 16) | (b << 8) | (a);
vDspMemoryWrite(shdr->s_vaddr + j, 4, data);
}
}
else
printf("section '%s' size equal to zero\n", shdr->s_name);
}
else
{
printf("unknown section `%s', flag: 0x%xh, ignored\n", shdr->s_name, shdr->s_flags);
}
}
free(fbuf);
fclose(fp);
return(ahdr->entrypt);
}
/*warm reset the DSP*/
void vDspReset()
{
int i=0;
sysOutByte(base2+0x4, 0x1);
for(i=0; i<10000; i++)
{
/*wait 18 DSP cycle to get response*/
}
}
/*send DSPINT to start the execution*/
void vDspStart()
{
sysOutByte(base2+0x4, 0x2);
printf("DSP started!\n");
}
/*load the coff to dsp and get it running, filename: a coff filename (.out)*/
int iDspLoad(char* filename)
{
char buf = 0;
if(!iDspPciInit())
{
printf("Can't find the DSP PCI device\n");
return 0;
}
/*warm reset the dsp*/
vDspReset();
/*init the EMIF, and clear 4M EMIF space to zero*/
vDspEmifInit();
sysOutWord(base2+0x8, 0x200);
memset(base0, 0, 0x400000);
/*set DSP page register to 0 and clear 256K IRAM space to zero*/
DSPP = 0;
sysOutWord(base2+0x08, DSPP);
memset(base0, 0, 0x40000);
/*check the pci boot mode*/
buf = sysInByte(base2+0x04);
if(!(buf&0x4))
{
printf("Not in PCI boot mode\n");
return 0;
}
/*load .out file to DSP memory*/
ulDspLoad(filename);
/*start dsp*/
vDspStart();
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -