Aerospace



Discussion Forum

Home

Company Information

Information Request

Linux How-to Guides

ADSP 21xx
Digital Signal Processing
Tutorials

SW Utilities

On-line Order Form

Aerospace Projects

Commercial Projects

Circuit Boards

Server Support


bonk

Have you found this site useful? Did we save you time? Did we cure your head-ache? Is your hair growing back now?

Please make a donation to help with maintenance.


Objective Real-Time Software on the ADSP21XX

Getting Started with the ADSP 21XX

General

It is always exceedingly difficult to get a new DSP card started. If you can neither trust the hardware, nor the software, nor the development tools, things can get pretty harrowing. Consequently, it is best to start off with the simplest little program that one can imagine, but which will still give a clear indication that it is indeed working. A LED flasher program fits the bill nicely.

To get you started, we have created some test code and the required batch files to drive the tool kit. The batch files assume that the tool kit is set up in directory adi_dsp and that your work directory is on drive d:. Simply copy the whole adi_dsp and work directories from the CD to your hard disk. You may also need to increase the allocated DOS environment space in your config.sys file, as shown in example 1.

Example 1.   Example file config.sys
files=40
buffers=40
device=mscdex
shell=C:\COMMAND.COM C:\ /e:1024 /p

LED Flasher

Example 2 is a LED flasher program, for the 2185 processor. The LED is connected to the external flag pin PF4. It just so happened that the card we used for test purposes had a LED on PF4, your card will probably not, so you may have to change something, either in the code, or on the card, to make it work.

This routine will create an asymmetrical flash period, to show that there is some intelligence at work and that is not just a runaway program.

Example 2.  LED Flasher Program file led.dsp

/**********************************************************************
*
* Name:        LED.dsp
*
* Description: LED flasher
*
* Copyright (c) Aerospace Software Ltd. 1998.
*
* Revisions:
* --------------------------------------------------------------------
* 1.0       March 98    Herman Oosthuysen
*
**********************************************************************/
.MODULE/RAM/ABS=0 bdm;

/****************************** Literals *****************************/
#define PFTYPE       0x3FE6   /* Programmable Flags */
#define PFDATA       0x3FE5   /* Programmable Flags */


/*********************** Initialized Variables ***********************/

/*
 * LED Flasher program
 * Asymetrical On/Off to show inteligent behaviour
 */
led_reset:
   dis ints;

   ax0 = 0x7F57;              /* out */
   dm(PFTYPE) = ax0;

   ax0 = 0x0010;              /* on */
   dm(PFDATA) = ax0;

   cntr = 0x3FFF;
   do wait1 until ce;
   cntr = 0x0040;
   do wait3 until ce;
   nop;
wait3:
   nop;
wait1:

   ax0 = 0x0000;              /* off */
   dm(PFDATA) = ax0;

   cntr = 0x3FFF;
   do wait2 until ce;
   cntr = 0x0400;
   do wait4 until ce;
   nop;
wait4:
   nop;
wait2:
   nop;
   jump led_reset;

   rti;         /* Put enough rti to cover the vector table */
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;
   rti;

.ENDMOD;

Once we managed to get a card up and running, we always keep a version of this little routine around, for confidence testing purposes.

Byte Memory Loader

The LED flasher program is so small, that the default load action of the 2185 will load the whole program and commence execution, if it is located at EPROM address 0000H. Since the 2185 startup sequence only loads 22 words, it does not leave us much room though, since most programs are bigger than that. We therefore require a BDMA loader that will fit into 22 words and will load our program from byte memory, into program memory.

The SPL21 utility provides the capability to split a program into several pages and add the required BDMA code to it (with the -loader switch), to move the program into PM. This works fine, provided that the program is located at address 0000H in the EPROM. If the program needs to be located somewhere else, we are in trouble and would need to write our own loader.

SPL21 Utility

The SPL21 BDMA code works fine, provided that the program is located at address 0000H in the EPROM.

That is not all however, since the program may be bigger than a single EPROM page of 8 kilobyte, we may also need to write our own file splitter. You are in luck here, since we have already had all these problems and created the required utilities to split files and glue them back together again. The utility EXE2PROM will convert the output of the linker, directly into a set of binary files with the exact byte size you specify on the command line. Therefore, all we need to worry about here, is how to operate the BDMA port. Writing your own loader, provides a good opportunity to learn all the ins and outs of the BDMA.

Example 3 is a complete BDMA loader. This program is small enough to fit into the 22 word limit of the startup loader and will load 2 pages of code from the byte memory into program memory.

Example 3.   BDMA Loader file bdma.dsp

/**********************************************************************
*
* Name:        BDMA.dsp
*
* Description: BDMA Runcode Loader.
*
* Copyright (c) Aerospace Software Ltd.
*
* Revisions:
* --------------------------------------------------------------------
* 1.0       March 98    Herman Oosthuysen
*
**********************************************************************/
.MODULE/RAM/ABS=0 bdm;

/***************************** Literals *****************************/
#define  BIAD        0x3FE1   /* BDMA internal address */
#define  BEAD        0x3FE2   /* BDMA external address */
#define  BCONTROL    0x3FE3   /* BDMA control */
#define  BWCOUNT     0x3FE4   /* BDMA word count */
#define  BMASK       0x0008   /* BDMA interrupt mask */

/*********************************************************************
* Total EPROM size = 32KB
* That is 2AAAH words of 24 bits each
* Program starts at 100H (nearest round number to the checksum position)
*
* BOOT MEMORY MAP
*
*
*
* Code Blocks                   EPROM           Byte Address
*                           128k x 8 bits
*                        ---------------------  7FFFH --
* BLOCK 1                |  Code Address     |         |
* = 1545H words          |                   |         |
* = 3FCFH bytes          |  1545H...2A8AH    |         | Page 1
* = 16335 bytes          |                   |         |
*                        ---------------------  4030H  |
*                        |      Loader       |         |
*                        ---------------------  4000H -- 
* BLOCK 0                |  Code Address     |         |
* = 1545H words          |                   |         |
* = 3FCFH bytes          |  0000H...1545H    |         | Page 0
* = 16335 bytes          |                   |         |
*                        ---------------------  0030H  |
*                        |       Loader      |         |
*                        ---------------------  0000H --
*
* Note: The second copy of the loader at address 4000H in the EPROM
*       is not used.  It is simply inserted to keep the memory map
*       symetrical. (Things being tricky enough as they are!)
*
*       Use SPL21.EXE or EXE2PROM.EXE to split the source into two
*       EPROM blocks, each exactly 4FD0H bytes in size.
*       Make the BDMA loader exactly 30H bytes in size and then
*       cobble the lot together into a 8000H image as defined above.
*
*       The same memory map is used for pages 2 and 3.  The difference
*       lies in the loader, which has to access different pages.
*
*       Clearly, the loader reserved area need only be 30H bytes. 
*
*********************************************************************/

#define  BDM_BLOCK   0x1545      /* Number of words to copy in a page */

#define  BDM_EXT0    0x0030      /* Program start Byte Address in page 0 */
#define  BDM_EXT1    0x0030      /* start of page 1 */
#define  BDM_INT0    0x0000      /* BLOCK0 goes here in internal memory */
#define  BDM_INT1    BDM_BLOCK   /* BLOCK1 goes immediately after BLOCK0 */

#define  BDM_PAGE0   0x0008      /* Page 0, 24 bit word mode, reboot */
#define  BDM_PAGE1   0x0100      /* Page 1, 24 bit words, keep running */
#define  BDM_PAGE2   0x0208      /* Page 2, 24 bit words, reboot */
#define  BDM_PAGE3   0x0300      /* Page 3, 24 bit words, keep running */


/*********************** Initialized Variables ***********************/

/*
 * BDMA Program Loader
 */
bdm_reset:
      /*
       * Load the Top of PM from Page 1
       */
      ax0 = BDM_EXT1;      /* External EPROM address 0030H upwards */
      dm(BEAD) = ax0;

      ax0 = BDM_INT1;      /* Internal PM address 0 upwards */
      dm(BIAD) = ax0;

      ax0 = BDM_PAGE1;     /* Load 24 bit words from page 1 */
      dm(BCONTROL) = ax0;

      ax0 = BDM_BLOCK;     /* Load 16KB into 24 bit PM */
      dm(BWCOUNT) = ax0;

      ifc = BMASK;         /* Clear pending BDMA interrupt */
      nop;
      imask = BMASK;       /* Enable BDMA interrupt */
      idle;                /* Wait for BDMA to finish */

      /*
       * Load bottom of PM from Page 0
       */
      ax0 = BDM_EXT0;      /* External EPROM address 0030H upwards */
      dm(BEAD) = ax0;

      ax0 = BDM_INT0;      /* Internal PM address 2nd block */
      dm(BIAD) = ax0;

      ax0 = BDM_PAGE0;     /* Load 24 bit words from page 0 then reset */
      dm(BCONTROL) = ax0;

      ax0 = BDM_BLOCK;     /* Load 16kB into 24 bit PM */
      dm(BWCOUNT) = ax0;
      idle;                /* Wait for BDMA to finish  - reset when done */

      jump bdm_reset;      /* Error Trap */

      nop;
      nop;
      nop;
      nop;
      nop;
      nop;

      rti;                 /* BDMA Interrupt handler */

      jump bdm_reset;      /* Error Trap */
.ENDMOD;

A complicating matter is the page breaks caused by the 14 bit size limit of the BDMA count register. Fourteen bits of byte addresses translate into a maximum byte address of 3FFFH. The trouble is that our program may not fit very nicely into this space. Also, the program code is 3 bytes wide, which is an odd number. Therefore, we may need to leave one or two bytes empty at the end of the page. It would also be nice to be able to generate a single EPROM load file, instead of a multitude of snippets that need to loaded at different addresses.

Odd Bytes and Page Sizes

The program code is 3 bytes wide, which is an odd number. Therefore, we may need to leave one or two bytes empty at the end of the page.

All this translation between byte and word sizes can be very confusing. You can check the contents of the binary file by converting it back to a 24 bit hexadecimal text file with the binary to hex utility BIN24DAT.

The EXE2PROM utility will convert a .exe file to binary and break it up into multiple blocks,each of the required size. It will fit as many 3 byte words into each block as it can and fill the last few bytes with FFH. Once your project has been broken up into blocks of the required size, you can glue them all together again in the required sequence, with the DOS copy command (use the /b switch!), to form a single EPROM loadable file.

Build and Link

Here is an example of a batch file, that will build the target code and create an EPROM loadable image. The batch file in example 4 assumes that you are working on drive d:, in a directory called work.

Example 4.  Build Batch file b.bat

@echo off
echo Build the Test Program
rem
rem Set up the Environment
SET path=d:\;d:\.;d:\..;d:\...;
SET path=%path%d:\work\bdma;
SET path=%path%d:\work\bdma\incl;
rem
rem Note that the ADI tools HAVE to be in \adi_dsp\21xx directory
rem else they simply won't work.  There are some fixed paths
rem built into some of the tools somehow! This is mindless...
rem The next 7 lines are ABSOLUTELY REQUIRED:
SET path=%path%d:\adi_dsp\21xx\lib;
SET path=%path%d:\adi_dsp\21xx\bin;
SET path=%path%d:\adi_dsp\21xx\etc;
SET path=%path%d:\adi_dsp\21xx\include;
set ADI_DSP=d:\adi_dsp\
set ADI_PATH=d:\work\bdma;
set ADII=d:\adi_dsp\21xx\include;d:\work\bdma\incl;
rem
rem Set up path to Editor and other DOS tools
set path=%path%c:\util;
set path=%path%c:\flexrom2;
set path=%path%c:\tc;c:\tc\include;
rem
rem
echo Build the BDMA Loader
rem
echo Assemble the BDMA loader
ASM21  -l -m -c -cp -2181 bdma.dsp -o objs\bdma
rem
echo link the BDMA loader
LD21 objs\bdma.obj -a target.ach -e bdma -g -x
rem
rem Convert to Binary
exe2prom bdma.exe 0030
rem
echo Assemble the LED flasher
ASM21  -l -m -c -cp -2181 led.dsp -o objs\led
rem
echo link the LED flasher
LD21 objs\led.obj -a target.ach -e led -g -x
rem
rem Convert to Binary
exe2prom led.exe 3FD0
rem
echo Create a single load file test.bin, consisting of two pages
copy /b bdma.b0 /b + led.b0 /b test.bin
rem
echo Convert the binary image back to a .exe
prom2exe test.bin test.exe
rem
echo Convert the .exe to a byte wide .bnm S record for debug with the simulator
echo LR 'test.bnm' command
spl21 test test -us2

After we created the binary EPROM file, we convert it back again into a .exe, which we then run through SPL21 to create a Motorola S record file test.bnm. This way, we ensure that we debug the exact same code in the simulator, as we would run on the target. Since the symbol file was generated by the linker, we can even see all the symbols in the simulator (file target.sym), after going full circle like this!

Once the loader is working correctly, you do not need to jump through all these hoops anymore and can simply debug the file target.exe, the original linker output file.

Locater

The only thing still missing is an explanation of the architecture file target.ach. This file can be generated with the tool BLD21, from a system description file, although it is not quite worth the trouble, since it simply converts a text file from one format, to another format. Since the documentation on this tool is a little vague, the best way to figure it out is to look at the actual contents of an existing .ach file and since this is a text file, you don't need BLD21 anymore, once you know the secrets. Example 5 shows an architecture file which is actually just another name for a locater response file.

Essentially, the link process has two stages. Firstly, the linkage editor has to resolve the label and variable references, after which another process, traditionally known as the locater, has to decide where to pack the code in memory and fix up all the link references. The architecture file tells the locater where to put what. (If we want to link more than one file at a time, we would also need a linker response file, with the file names to be linked).

Example 5.  Architecture file target.ach

$DATARGET 
$ADSP2181 
$MMAP0 
$0000 1FFF paxINT_PM t
$2000 2AA9 paxINT_CONST t
$0000 1FFF dadINT_DM t
$2000 2AA9 dadINT_INIT t
$

The architecture file consists of the following statements:

  • The first line identifies the project as TARGET.
  • The second line indicates the processor type (We are running a 2185, which is a 2181 derivative).
  • The third line shows that the processor has to boot from external memory.
  • We then define 4 memory segments, for code, constants, variables and initialized variables respectively.
  • The last line is only a $, which is required for some weird reason.

Now it should be clear that you really do not need BLD21.

Simulator

The resulting loader code can be observed with the simulator, when using the LR command.

Example 6.  Simulator Batch file s.bat

@echo off
echo QUIT WINDOWS and run the 2181 Simulator in DOS mode
rem Use LR to load the boot loader file test.bnm
sim2181 -a target -o target.log -c

The simulator only runs under plain vanilla DOS. It won't run in a Windows 95 DOS box, unless you replace the Windows 95 memory manager with a version of Quaterdeck QEMM. It is very easy to use. Just play around with it for a while, to get comfortable with it. Probably the most important command is CTRL-G, to move a memory window to a desired address.

If you load the target code with the LR command, selecting chip reset in the miscellaneous menu, will load the first 22 words of the program from byte memory to program memory. You can then set a breakpoint at address 0000H and cycle through the different phases of the program load process.



Copyright © 1996-2008, Aerospace Software Ltd., GPL.