<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!DOCTYPE document PUBLIC "-//CNX//DTD CNXML 0.5 plus MathML//EN" "http://cnx.rice.edu/cnxml/0.5/DTD/cnxml_mathml.dtd">
<document xmlns="http://cnx.rice.edu/cnxml" xmlns:m="http://www.w3.org/1998/Math/MathML" xmlns:md="http://cnx.rice.edu/mdml/0.4" xmlns:bib="http://bibtexml.sf.net/" id="m10021">
  
  <name>Using Assembly and a TI DSP</name>
  <metadata>
  <md:version>2.14</md:version>
  <md:created>2001/05/30</md:created>
  <md:revised>2004/02/25 12:17:56.867 US/Central</md:revised>
  <md:authorlist>
      <md:author id="rars">
      <md:firstname>Ricardo</md:firstname>
      <md:othername>Anthony</md:othername>
      <md:surname>Radaelli-Sanchez</md:surname>
      <md:email>ricky@alumni.rice.edu</md:email>
    </md:author>
      <md:author id="dljones">
      <md:firstname>Douglas</md:firstname>
      <md:othername>L.</md:othername>
      <md:surname>Jones</md:surname>
      <md:email>dl-jones@uiuc.edu</md:email>
    </md:author>
  </md:authorlist>

  <md:maintainerlist>
    <md:maintainer id="rars">
      <md:firstname>Ricardo</md:firstname>
      <md:othername>Anthony</md:othername>
      <md:surname>Radaelli-Sanchez</md:surname>
      <md:email>ricky@alumni.rice.edu</md:email>
    </md:maintainer>
    <md:maintainer id="dljones">
      <md:firstname>Douglas</md:firstname>
      <md:othername>L.</md:othername>
      <md:surname>Jones</md:surname>
      <md:email>dl-jones@uiuc.edu</md:email>
    </md:maintainer>
    <md:maintainer id="mjberry">
      <md:firstname>Matthew</md:firstname>
      <md:othername>J.</md:othername>
      <md:surname>Berry</md:surname>
      <md:email>mjberry@uiuc.edu</md:email>
    </md:maintainer>
    <md:maintainer id="dsachs">
      <md:firstname>Daniel</md:firstname>
      <md:othername>Grobe</md:othername>
      <md:surname>Sachs</md:surname>
      <md:email>sachs@uiuc.edu</md:email>
    </md:maintainer>
    <md:maintainer id="butala">
      <md:firstname>Mark</md:firstname>
      <md:othername>D.</md:othername>
      <md:surname>Butala</md:surname>
      <md:email>butala@uiuc.edu</md:email>
    </md:maintainer>
    <md:maintainer id="rlmorris">
      <md:firstname>Robert</md:firstname>
      <md:othername>L.</md:othername>
      <md:surname>Morrison</md:surname>
      <md:email>rlmorris@uiuc.edu</md:email>
    </md:maintainer>
  </md:maintainerlist>
  
  <md:keywordlist>
    <md:keyword>TI TMS320C54x</md:keyword>
    <md:keyword>Arithmetic Logic Unit</md:keyword>
    <md:keyword>ALU</md:keyword>
    <md:keyword>Program Address Generation Unit</md:keyword>
    <md:keyword>PAGEN</md:keyword>
    <md:keyword>PC</md:keyword>
    <md:keyword>DAGEN</md:keyword>
    <md:keyword>Assembly</md:keyword>
    <md:keyword>WAITDATA</md:keyword>
  </md:keywordlist>

  <md:abstract>The intent of this laboratory module is to familiarize you with the
basics of the debugging environment and assembly code for the 
TI-54x DSP. In this module, you will be working with code that 
filters signals using FIR (finite impulse response) filters.</md:abstract>
</metadata>
  <content>
    <section id="procover">
      <name>Processor Overview</name>
      <para id="p1">
	The evaluation board assumed for this module at each station
	includes a Texas-Instruments 320C549 DSP chip which contains
	the primary core systems: internal memory, the <term>central
	processing unit</term> (<term>CPU</term>), and address
	generation logic. For more information about the DSP chip
	itself, look at the <cite>TMS320C54x Reference Set, Volume 1:
	CPU and Peripherals</cite>.
      </para>

      <section id="mem">
	<name>Memory</name>
	<para id="p2">
	  The TI TMS320C54x architecture's addressing is divided up
	  into three separate memory spaces: program memory, data
	  memory, and I/O memory. All three memory spaces are 16 bits
	  wide. The data and I/O spaces are both 64K words long; the
	  program memory space is 8M words long, although accessing
	  program memory past 64K words requires special instructions.
	  The TI TMS320C549 DSP itself has 32K words of on-board
	  memory; the DSP evaluation board provides another 256K words
	  of external memory.  More information about the DSP's memory
	  map is available in the <cite>Core File Documentation</cite>
	  which should be available from your lab instructor.
	</para>
	<para id="p3">
	  The TMS 320C549 DSP uses memory mapped registers; all of the
	  DSP's registers are mapped into the DSP's data memory space
	  between <code>0000h</code> and <code>005Fh</code>.  Special
	  opcodes are provided to speed access to these memory-mapped
	  registers.
	</para>
      </section>
      <section id="alu">
	<name>Arithmetic Logic Unit</name>
	<para id="p4">
	  The central processing unit contains the fundamental
	  components for mathematical and logical operations on data,
	  including a 17x17-bit <term>multiplier</term>, 40-bit
	  <term>adder</term>, 40-bit <term>arithmetic logic
	  unit</term> (<term>ALU</term>), and
	  <term>barrel-shifter</term>.  It also contains necessary
	  registers for performing these operations including two
	  40-bit <term>accumulators</term> (<code>A</code> and
	  <code>B</code>) and a 16-bit temporary storage register
	  (<code>T</code>).
	</para>
      </section>
      <section id="agu">
	<name>Address Generation Unit</name>
	<para id="p5">
	  The address generation logic section is divided into
	  separate program and data address generators and is
	  responsible for fetching program instructions as well as
	  reading and writing data to and from memory.  The
	  <term>program address generation logic</term>
	  (<term>PAGEN</term>) contains (and maintains) the
	  <term>program counter</term> (<term><code>PC</code></term>)
	  register as well as other necessary registers for repeating
	  code.  For data memory manipulation, the <term>data address
	  generation logic</term> (<term>DAGEN</term>) is used and
	  maintains the necessary registers including the auxiliary
	  registers <code>AR0</code> .. <code>AR7</code> acting as
	  "pointers" to data memory, and control registers such as the
	  <term>circular buffer register</term>
	  (<term><code>BK</code></term>).
	</para>
      </section>
    </section>
    <section id="assembly">
      <name>Basics of Assembly Code</name>
      <para id="p6">
	We will introduce the TI TMS320C549 assembly language by
	showing an example of assembly language code. This code calls
	the "<code>core.asm</code>" file to initialize and control the
	six-channel surround-sound board, and then copies the signal
	from channel 1 of the six-channel board's A/D converter to
	channels 1-3 of the D/A converters, and the signal from
	channel 2 of the A/D to channels 4-6 of the D/A.  Your
	laboratory assistant should have a similar file for you to
	use; this code block is provided here for example purposes
	only.
      </para>
      <figure id="figx">
	<name>thru.asm</name>
	<code type="block">
	  <![CDATA[
	  1   	    .copy "v:\54x\dsplib\core.asm"
	  2
	  3	    .sect ".text"
	  4  main
	  5      ; Your initialization goes here.
	  6
	  7  loop
	  8      ; Wait for a new block of 64 samples to come in
	  9      WAITDATA
	  10	
	  11      ; BlockLen = the number of samples that come from WAITDATA (64)
	  12      stm #BlockLen-1, BRC	; Repeat BlockLen=64 times
	  13      rptb block-1		; ...from here to the ``block'' label
	  14
	  15      ld      *AR6,16, A		; Receive ch1
	  16      mar *+AR6(2)                ; Rcv data is in every other word
	  17      ld      *AR6,16, B		; Receive ch2
	  18      mar *+AR6(2)                ; Rcv data is in every other word
	  19
	  20      ; Code to process samples goes here.
	  21
	  22      sth a, *AR7+		; Store into output buffer, ch1
	  23      sth a, *AR7+		; ch2
	  24      sth a, *AR7+		; ch3
	  25  
	  26      sth b, *AR7+		; Store into output buffer, ch4
	  27      sth b, *AR7+		; ch5
	  28      sth b, *AR7+		; ch6
	  29    
	  30  block
	  31      b loop
	  ]]>
	</code>
      </figure>
      <section id="assfields">
	<name>Assembly fields</name>
	<para id="p7">
	  Take a moment to look at the assembly code listed above.
	  Note that anything following a semicolon is a comment and is
	  ignored during the assembly process; for example, <cite>line
	  5</cite> contains only a comment.  You should also notice
	  that there are primarily three columns in the code.  The
	  first column is reserved for <term>labels</term> used to
	  refer to a location during the assembly process.  The second
	  column contains either <term>assembly directives</term> or
	  <term>instructions</term>.  Directives are commands for the
	  assembler to use during the compilation process, to assign a
	  label for example, and do not show up in the final compiled
	  code.  Instructions on the other hand are what the processor
	  will actually execute.  The third column is reserved for
	  operands for the directives or instructions.
	</para>
      </section>
      <section id="asscode">
	<name>Sections of assembly code</name>
	<para id="p8">
	  <cite>Line 3</cite> of this code contains the directive
	  <code>.sect ".text"</code> The <code>.sect</code> directive
	  tells the assembler that the following lines are to be
	  placed in memory in the section named in its operand. There
	  are several sections defined in the assembly process; they
	  are used to define locations in memory at which certain
	  pieces of code or data must be placed.
	</para>
	<para id="p9">
	  There are two important sections you should pay special
	  attention to: <code>.text</code>, in which all of your
	  program code must be placed, and <code>.data</code>, in
	  which your program's data will be placed. The <code>sect
	  ".text"</code> directive tells the assembler to place the
	  following code or data in program memory starting at
	  <code>6000h</code>; the <code>sect ".data"</code> directive
	  tells the assembler to place following code or data in data
	  memory starting at <code>1000h</code> in memory.  <note type="footnote">Certain data, including the coefficients for
	  the "<code>firs</code>" instruction described later, must be
	  placed in the "<code>.text</code>" section as it is required
	  to be located in program memory.</note>
	</para>
	<para id="p10">
	  A third important section to be aware of is the
	  <code>.scratch</code> section. Data placed in this short
	  section (32 words from <code>0060h</code> to
	  <code>007Fh</code> in the data memory space; of these, the
	  first 6 locations are used by the core file and cannot be
	  used by your code) can be accessed quickly using opcodes,
	  such as <code>stm</code>, which are intended to access the
	  memory-mapped registers.
	</para>
	<para id="p11">
	  Although the <code>thru.asm</code> code does not include a
	  <code>.data</code> section, your final FIR implementation
	  will have such a section to define where to place the states
	  or past input samples in addition to initializing memory for
	  the filter coefficients.  In the linking process this data
	  section is assigned starting at the location
	  <code>1000h</code> in data memory.
	</para>
      </section>
      <section id="core">
	<name>Core file basics</name>
	<para id="p12">
	  For this class, you will use the provided
	  <code>core.asm</code> file which initializes and configures
	  the DSP and supports the use of the D/A and A/D converters
	  on the six-channel board as well as the serial port on the
	  DSP evaluation board itself. For this lab, you will be using
	  only the D/A and A/D.  If your laboratory assistant or lab
	  materials have not told you where to obtain this file, you
	  should ask for assistance at this time.
	</para>
	<para id="p13">
	  To describe the core file in more detail, let's analyze the
	  <term>thru</term> code in <cnxn target="figx">thru.asm</cnxn>.
	</para>
	<para id="p14">
	  In this file, <cite>line 1</cite> copies the core file into
	  the source file.  All of the files you write for this class
	  should begin with this line.
	</para>
	<para id="p15">
	  <cite>Line 3</cite> tells the assembler that all of the
	  following code should be placed in the "<code>.text</code>"
	  section.  The "<code>.text</code>" section is internal
	  program RAM, and begins at <code>6000h</code>. Your code
	  will begin somewhat after this, because the core file code
	  appears before your code in the assembled object file.
	</para>
	<para id="p16">
	  <cite>Line 4</cite> is the label "main." The "core" code
	  jumps to this label once initialization is complete. Any
	  initialization that is required, such as setting address
	  registers, should go between the "main" label and the "loop"
	  label on <cite>line 7</cite>.
	</para>
	<para id="p17">
	  <cite>Line 8</cite> is a call to the
	  <term><code>WAITDATA</code></term> macro. Note that this
	  macro overwrites the B accumulator, so don't expect B to
	  stay the same across calls to <code>WAITDATA</code>! This
	  macro sets AR6 to the address of the input buffer, and AR7
	  to the address of the output buffer.
	</para>
	<para id="p18">
	  Since <code>WAITDATA</code> accumulates a block of 64
	  samples before it returns, <cite>Lines 12-13</cite> set up a
	  loop that executes for BlockLen times. (The minus one is
	  required, because on the TI DSP a repeat loop runs one more
	  time than the number specified.)  <cite>Line 12</cite> sets
	  the <term><code>BRC</code></term> register, the <term>Block
	  Repeat Counter</term>, to 63, and <cite>Line 13</cite> tells
	  the DSP to loop from the next location in memory (the
	  <code>ld</code> instruction on <cite>Line 15</cite>) to the
	  location immediately before the label "block."  When you use
	  the <code>rptb</code> instruction, don't forget to include
	  the -1; otherwise, the DSP will execute an extra instruction
	  at the end of the loop.
	</para>
	<para id="p19">
	  <cite>Lines 15-18</cite> read A/D channel 1 into accumulator
	  "A," and A/D channel 2 into accumulator "B." Note that the
	  input data is stored in alternate memory locations.  The
	  instruction <code>ld *AR6,16,A</code> loads the memory
	  location pointed to by AR6, the input buffer pointer, into
	  the high bits of A. (The 16 stands for a shift of 16 bits as
	  A is loaded.) The instruction <code>mar *+AR6(2)</code> adds
	  two to the value of AR6.  The <term><code>mar</code></term>
	  instruction means <term>Modify Address Register</term>, and
	  allows you to do an address-register update without doing
	  any data loads or stores.
	</para>
	<para id="p20">
	  Any code to process single samples, including code that you
	  will work with in this lab, should be placed at <cite>Line
	  20</cite>. The <code>filter.asm</code> file you will work
	  with in later modules has its sample-processing code at this
	  point, for example.
	</para>
	<para id="p21">
	  <cite>Lines 22-28</cite> save the input (contained in
	  accumulators A and B) into the output buffer. The output
	  words are sequential in memory, so no <code>mar</code>
	  directives are required; instead, the <code>*AR7+</code>
	  addressing mode is used to increment AR7 after each word is
	  written.  The <code>sth</code> opcode writes the high-order
	  16 bits of A into memory. The <code>stl</code> opcode is
	  used to move the low-order 16 bits of the A accumulator into
	  memory. Be careful which you use; the two operations are
	  easily confused, and this has resulted in many hard-to-find
	  bugs in past students' code.
	</para>
	<para id="p22">
	  <cite>Line 30</cite> is the "block" label, designating the
	  end of the repeat block.  <cite>Line 31</cite> is a branch
	  (<code>b</code> opcode) back to the "loop" label, sending
	  the DSP back to before the call to <code>WAITDATA</code> to
	  await a new block of 64 samples.
	</para>
	<para id="p23">
	  More complete documentation for the core file is available
	  from the <cite>Core File Documentation</cite>, which your
	  laboratory assistant should be able to provide you. This
	  documentation includes information on the DSP memory map,
	  serial port, and extended-memory access instructions.
	</para>
      </section>
    </section>
  </content>
</document>
