DSPRelated.com
Forums

about C3x kernel

Started by Ninad Thakoor March 19, 2002
Hi,

Thank you all for sending me Code exlorer.

I have come across some information that might be interesting. This is from help
file of winDSK by Michael G. Morrow.

A complication in writing DSK applications lies in the nature of the Host Port
Interface (HPI) design. Communications between the host computer and the DSK
result in the DSK processor becoming locked in an extended external bus cycle
waiting for the host to complete each transaction. During this time, the
processor cannot respond to interrupts and so cannot service the serial port
interrupts caused by the Analog Interface Circuit (AIC). Older DOS-based tools
were not affected by this, as DOS was a deterministic, single-task system so it
could be counted on to complete a DSK transaction in immediate succession. With
multi-tasking, multi-threaded operating systems such as Windows 9X, application
programs can be suspended at any time as the operating system continuously
shifts execution from thread to thread. If this occurs in the middle of a
host-DSK exchange, the AIC will be unintentionally reprogrammed, generally
resulting in the DSK processor losing communications with the AIC, and a loss of
DSK audio functionality. winDSK overcomes this problem with a modified version
of the Code Explorer communication/debugging kernel that uses the TMS320C31
direct memory access (DMA) controller to complete the HPI transfers. In this
way, only the DMA controller becomes locked in the external bus cycle to the HPI
during host-DSK transactions, while the processor can still service the serial
port (and other) interrupts. This permits reliable operation of DSK
applications while host-DSK communications proceed.

Has anybody modified the DSK kernel to do this?
About new DSK demos and debugger, How can I get them?

Regards
-Ninad Thakoor



Err. this assesment is not quite right, nor is this solution the best for
what I think you are looking for. If I am not mistaken, Michael modified
the DSKWAV.ASM DOS/console based wave player/recorder (you may not this
application does not suffer from any of the afformentioned problems), so you
may want to look that over. There are several ways around this problem as
described in the *.TXT files that accompany the DSK.

The real problem
----------------
If you dig in you will find that the real problem is the serialy programmed
AIC. (This is not a problem with the PCM3003 stereo daughter card mentioned
later).

- Being serialy programmed the AIC tends to want to reprogram
itself whenever serial port updates are stopped.

- Serial port updates are stopped during debug (this should be expected)
and the AIC receives trash.

- The serial port itself also wants to shutdown when no updates are being
written. Again the AIC receives trash.

Simple solution (see file below)
--------------------------------
Use the DMA to continuously copy (without synchronization) a value stored at
a memory location to the DXR, keeping both the serial port and AIC happy.
The DAC is still not updated when the application is stopped for debug, so
keep this in mind if you are working on a control application.

The file that is attached below goes even further by showing you how to
write ISR's that can also be debugged, all without corrupting the AIC.

If you *really* want to use the DMA for HPI transfers
-----------------
If the DMA is to be used for HPI transfers you need to replace the R_HOST
and W_HOST routines (dont forget nibble/byte mode). The starting point
would be the DMA HPI routines that are found in DSKWAV.ASM. Note... - Using the DMA to perform host transfers does not solve the AIC
update problem when an application is stopped for debug mode.

You would have to leave the serial interrupts enabled during debug.
Not only is this tricky, but the main application loop that is
probably maintaining what goes in and out is stalled... No bonus here!

- Using the DMA for host transfers consumes the DMA (you can no
longer use it in your application), and it consumes considerable
memory since the send and receive values are unpacked.

NOTE: DSK3D has the option of loading kernels other than C3X.DSK.
If you start DSK3D with a '?' the help screen pops up and you
will see a K.DSK option. You may want to consider that
debugging a debug kernel is 'interesting'.

More options
------------
Non Interlock Reads
-------------------
Did you know that data can be read (or write) from the HPI without an
interlock occuring? And since the PP dbus is essentialy held by the host,
reception is relatively easy.

The easy method is to poll the PP data bus each time your application
completes a code loop using one of the lines as a strobe. This provides a
simple if limited 'no-click' way to update values in an application. The
Parametric EQ demo (works with PCM3003 stereo daughter card) and host
control demo that I recently finished are two examples that use this method.

On the other hand, sending data to the host does require the data to be
held... But again, there is a C3x feature I bet no one here knows about.
Did you know that if a value is written to the bus that it is 'posted' and
the CPU can go on to the next task? As long as the CPU does not try to
write to the bus before the first write is completed, the CPU will continue
running.
;-
; DACOUT.ASM
; Keith Larson
;
; DACOUT uses the DMA to continuously update the serial port DXR
; even when the application is being debugged.
;
; When the loop in main is run, the floating point value at DAC_VOLTS
; is converted to the corresponding integer value.
;
; You can also directly poke integer values into DAC_INTEGER, but be
; extra careful to not use the bottom two LSB's. If you do, the AIC
; may decide to re-program itself.
;
; ADC and DAC interrupt routines are also included which are compatible
; with the DSK debugger. You can insert code here if you like.
;
;-
.include "C3XMMRS.ASM"
.start "AICTEST",0x809802; Start assembling here
.sect "AICTEST"
;
; Define constants used by program
;
GAIN .set 0 ;
TIM0_PRD .set 1 ; Timer diviser
TA .set 8 ; AIC timing register values
TB .set 14 ;
RA .set 8 ;
RB .set 14 ;
;--------------------------- ;
main ldi 25,R7 ;
andn 0x04,IE ; disable host interrupts
or 0x30,IE ; Enable XINT/RINT
idle ; this is usualy where XINT/RINT are serviced
idle
andn 0x30,IE ; Then, during debug,
or 0x04,IE
or 2000h,ST
ldi @S0_rdata,R0 ; Receiver underrun cleared by simple read
b main
RAMP .float 0
;----------------
DAC_VOLTS .float 1.0
DAC_SCALE .float 4*16384.0/6.0 ; 6 volt full scale 14 bits, shift up by 2

DAC2 push ST ; since debugger uses INTs it enables them
push IE
ldi 0xC4,IE ; Cant debug an ISR while it is enabled
DAC_DBG push R0 ; so start here
pushf R0 ;
push R1 ;
pushf R1 ;
push AR0 ;
andn XINT,IE ; dont debug lines above here

ldf @DAC_VOLTS,R0 ;
mpyf @DAC_SCALE,R0 ;
fix R0,R0 ;
cmpi 32767,R0 ;
ldigt 32767,R0 ;
cmpi -32768,R0 ;
ldilt -32768,R0 ;
andn 3,R0 ;
sti R0,@xdata ; Output DAC value to xdata ->DMA->XSR

pop AR0 ;
popf R1 ;
pop R1 ;
popf R0 ;
pop R0 ;
pop IE
pop ST ;
rets ;
;================================================================
; The ADC receives its value as an analog loopback from the DAC
; With the controller point swinging from +/-P, the output should
; look different as the coefficients change
;----------------------------
ADC2 push ST ; Debugging here reenables INTs
push IE ; so cant have RINT live at the same time
ldi 0xC4,IE ;
ADC_DBG push R0 ;
pushf R0 ;
ldi @S0_rdata,R0 ; Sign extend the data
lsh 16,R0 ; Present data is in lower 16 bits
ash -16,R0 ; >> Sample N-1 is in upper 16 bits
float R0,R0 ;
stf R0,@ADC_FLOATVAL;
popf R0 ;
pop R0 ;
pop IE
pop ST ;
rets ;
;*****************************************************;
ADC_FLOATVAL .float 0
;-----------
; Define the serial port global control bits
;-----------
XCLKSRCE .set 0 << 6 ; 0=external 1= internal
RCLKSRCE .set 0 << 7 ;
XVAREN .set 1 << 8 ; VAREN 0 1
RVAREN .set 1 << 9 ; FS ____---------_____
XFSM .set 0 <<10 ; 0=burst 1=continuous
RFSM .set 0 <<11 ;
CLKXP .set 0 <<12 ;
CLKRP .set 0 <<13 ;
DXP .set 0 <<14 ;
DRP .set 0 <<15 ;
FSXP .set 1 <<16 ;
FSRP .set 1 <<17 ;
XLEN .set 01b<<18 ; 00=8 01 10$ 112
RLEN .set 01b<<20 ;
EXTINT .set 0 <<22 ;
EXINT .set 1 <<23 ;
ERTINT .set 0 <<24 ;
ERINT .set 1 <<25 ;

S0 .sdef XCLKSRCE|RCLKSRCE|XVAREN|RVAREN|XFSM|RFSM|CLKXP|CLKRP
S0 .sdef S0|DXP|DRP|FSXP|FSRP|XLEN|RLEN|EXTINT|EXINT|ERTINT|ERINT
S0_grst .word S0
S0_gctrl_val .word S0|0x0C000000
A_REG .word (TA<<9)+(RA<<2)+0 ; A registers
B_REG .word (TB<<9)+(RB<<2)+2 ; B registers
BPNBL .set 0 <<2 ; 1 nbls ADC band pass filter
LOOPBACK .set 0 <<3 ; 1 nbls internal DAC->ADC connect
AUXIN .set 0 <<4 ; 1 nbls AUXIN (AIN off)
SYNC .set 0 <<5 ; 0 FSR/FSX can differ, 1 FSX/FSR are same
GCTRL .set GAIN <<6 ; 0 b 1=+6db 2=+12db 3 b
C_REG .word GCTRL|SYNC|AUXIN|LOOPBACK|BPNBL|11b ; control
S0_xctrl_val .word 0x00000111 ;
S0_rctrl_val .word 0x00000111 ;
;*****************************************************;
; The startup stub is used during initialization only ;
; and can be safely overwritten by the stack or data ;
;*****************************************************;
.entry ST_STUB ; Debugger starts here
ST_STUB ldp T0_ctrl ; Use kernel data page and stack
ldi @stack,SP
ldi 0,R0 ; Halt TIM0
sti R0,@T0_ctrl ;
sti R0,@T0_count ; Zero the count
ldi TIM0_PRD,R0 ; Set the period
sti R0,@T0_prd ;
ldi 0x2C1,R0 ; Restart the timer
sti R0,@T0_ctrl ;
;---------------------
ldi @S0_xctrl_val,R0;
sti R0,@S0_xctrl ; transmit control
ldi @S0_rctrl_val,R0;
sti R0,@S0_rctrl ; receive control
ldi 0,R0 ;
sti R0,@S0_xdata ; DXR data value
ldi @S0_gctrl_val,R0; Setup serial port
sti R0,@S0_gctrl ; global control
;======================================================;
; This section of code initializes the AIC ;
;======================================================;
AIC_INIT LDI 0x10,IE ; Enable only XINT interrupt
andn 0x34,IF ;
ldi 0,R0 ;
sti R0,@S0_xdata ;
RPTS 0x040 ;
LDI 2,IOF ; XF0=0 resets AIC
rpts 0x40 ;
LDI 6,IOF ; XF0=1 runs AIC
;---------------------
ldi @C_REG,R0 ; Setup control register
call prog_AIC ;
ldi 0xfffc ,R0 ; Program the AIC to be real slow
call prog_AIC ;
ldi 0xfffc|2,R0 ;
call prog_AIC ;
ldi @B_REG,R0 ; Bump up the Fs to final rate
call prog_AIC ; (smallest divisor should be last)
ldi @A_REG,R0 ;
call prog_AIC ;
or 0xC4,IE ; enable host and debug ints
call DMA_PUMP
b main ;
;================================
DMA_RUN .set 0x03 ; Write sync forever (write to XBUFR on XINT)
DMA_STOP .set 0x0 ; DMA is reset and stopped
DMA_DEST .word S0_xdata
DMA_SRCE .word xdata
xdata .word 0
DINT .set 0x400
RINT .set 0x020
XINT .set 0x010
DMA_XINT .word XINT<<16
DMA_PUMP
; or @DMA_XINT,IE ; enable transmit int
ldi DMA_STOP,R0 ; stop and reset DMA
sti R0,@DMA_ctrl ;
ldi 0,R0 ;
sti R0,@DMA_xfr ;
ldi @DMA_SRCE,R0 ;
sti R0,@DMA_srce ;
ldi @DMA_DEST,R0 ;
sti R0,@DMA_dest ;
ldi DMA_RUN,R0 ;
sti R0,@DMA_ctrl ;
rets
;-------------------------------
poll_xint tstb XINT,IF ;
bz $-1 ;
andn XINT,IF ;
rets ;

prog_AIC ldi @S0_xdata,R1 ; Use original DXR data during 2 ndy
sti R1,@S0_xdata ;
call poll_xint
ldi @S0_xdata,R1 ; Use original DXR data during 2 ndy
or 3,R1 ; Request 2 ndy XMIT
sti R1,@S0_xdata ;
call poll_xint
sti R0,@S0_xdata ; Send register value
call poll_xint
andn 3,R1 ;
sti R1,@S0_xdata ; Leave with original safe value in DXR
;---------------------
ldi @S0_rdata,R0 ; Fix the receiver underrun by reading
rets ; the DRR before going to the main loop

stack .word $+1

;****************************************************;
; Install the XINT/RINT ISR handler directly into ;
; the vector RAM location it will be used in ;
;****************************************************;
.start "SP0VECTS",0x809FC5
.sect "SP0VECTS"
b DAC2 ; XINT0
b ADC2 ; RINT0
+-----------+
|Keith Larson |
|Member Group Technical Staff |
|Texas Instruments Incorporated |
| |
| 281-274-3288 |
| |
| www.micro.ti.com/~klarson |
|-----------+
| TMS320C3x/C4x/VC33 Applications |
| |
| TMS320VC33 |
| The lowest cost and lowest power 500 uw/mflop |
| floating point DSP on the planet! |
+-----------+