📄 btc_asmdemo.asm
字号:
/////////////////////////////////////////////////////////////////////////////
//
// Example assembly program using Background Telemetry Channel (BTC)
// Analog Devices 2003
//
// This program defines several BTCs to allow transfer of data over the BTC
// interface while the DSP is running. Use the BTC Memory window in the
// debugger to view each channels data. The defined channels are described
// below:
//
// Timer Interrupt Counter: This channel is defined to be 1-word (4-bytes)
// in length and simply counts the number of timer
// interrupts that have occured.
//
// PF4 Counter: This channel is defined to be 1-word (4-bytes) in length and
// simply counts the number of times the PF4 pushbutton is pressed
// on the BF535 Ez-Kit.
//
// PF5 Counter: This channel is defined to be 1-word (4-bytes) in length and
// simply counts the number of times the PF5 pushbutton is pressed
// on the BF535 Ez-Kit.
//
// 256 word channel (PF6): This channel is defined to be 256-words (1024-bytes) in length and
// simply counts the number of times the PF6 pushbutton is pressed
// on the Bf535 Ez-Kit. Each byte in the channel is updated with the count.
//
// 256 word channel (PF7): This channel is defined to be 256-words (1024-bytes) in length and
// simply counts the number of times the PF7 pushbutton is pressed
// on the BF535 Ez-Kit. Each byte in the channel is updated with the count.
//
// 256 byte channel: This channel is defined to be 256 bytes in length. The first word of the
// channel is used to count the number of timer interrupts that have occured.
//
// 4k byte channel: This channel is defined to be 4-kbytes in length. The first word of the
// channel is used to count the number of timer interrupts that have occured.
//
/////////////////////////////////////////////////////////////////////////////
#include "defbf535.h"
#include "defblackfin.h"
#include "btc.h"
/////////////////////////
// variable definitions
/////////////////////////
.section data1;
.var timerCounter; // counts the number of timer interrupts that have fired
.var pf4Counter; // counts the number of times the PF4 pushbutton on the ez-kit was pressed
.var pf5Counter; // counts the number of times the PF5 pushbutton on the ez-kit was pressed
.byte pf6Array[256]; // a 256 byte array
.byte pf7Array[256]; // a 256 byte array
.byte array1[0x100]; // a 256 byte array
.byte array2[0x1000]; // a 4k byte array
////////////////////
// BTC Definitions
////////////////////
BTC_MAP_BEGIN
// Channel Name, Starting Address, Length
BTC_MAP_ENTRY('Timer Interrupt Counter', timerCounter, 0x00004)
BTC_MAP_ENTRY('PF4 Counter', pf4Counter, 0x00004)
BTC_MAP_ENTRY('PF5 Counter', pf5Counter, 0x00004)
BTC_MAP_ENTRY('256 byte channel (PF6)', pf6Array, 0x00100)
BTC_MAP_ENTRY('256 byte channel (PF7)', pf7Array, 0x00100)
BTC_MAP_ENTRY('256 byte channel', array1, 0x00100)
BTC_MAP_ENTRY('4k byte channel', array2, 0x01000)
BTC_MAP_END
////////////////////
// main program
////////////////////
.section program;
.extern ldf_stack_end;
.global _main;
_main:
// initialize the stack pointer
sp.h = ldf_stack_end;
sp.l = ldf_stack_end;
// setup the EVT
[--sp] = rets;
call initVectorRegs;
rets = [sp++];
// setup the Core Timer
[--sp] = rets;
call initCoreTimer;
rets = [sp++];
// setup the Programmable Flags
[--sp] = rets;
call initProgFlags;
rets = [sp++];
// initialize the BTC
[--sp] = rets;
call _btc_init;
rets = [sp++];
// R2 is used to hold the value to be displayed on the LEDs of the ez-kit
r2 = 0;
// latch interrupt15 so we can stay in supervisor mode once we return from
// the reset interrupt
raise 15;
// unmask the timer interrupt (EVT6), PF interrupt A (EVT12), and EVT15 in IMASK
i0.h = IMASK >> 16;
i0.l = IMASK & 0xffff;
m0 = 0;
r0.h = 0;
r0.l = EVT_IVTMR | EVT_IVG12 | EVT_IVG15;
[i0] = r0;
// enable the timer
i0.h = TCNTL >> 16;
i0.l = TCNTL & 0xffff;
m0 = 0;
r0 = TMPWR | TMREN | TAUTORLD;
[i0] = r0;
// clear the pending reset interrupt (return to User mode) and
// set all other return regs to a known spot (except RETE)
nop;
r0.h = MAIN_WAIT_LOOP;
r0.l = MAIN_WAIT_LOOP;
reti = r0;
rets = r0;
retn = r0;
retx = r0;
nop;
r0 = 0;
rti; // return from supervisor mode to user mode!!
nop; // never executed
nop; // never executed
// because we've latched int15 we'll never actually get into this
// loop, we should branch directly to the EVT15_LOOP and stay there.
MAIN_WAIT_LOOP:
nop;
nop;
jump MAIN_WAIT_LOOP;
EVT15_LOOP:
nop;
nop;
nop;
[--sp] = rets;
call _btc_poll; // check for incoming BTC commands
rets = [sp++];
nop;
nop;
nop;
jump EVT15_LOOP;
_main.end:
/////////////////////////////////////////////////////////////////////////
// initVectorRegs
//
// initialize the vector (EVT) registers
//
initVectorRegs:
// access to the EVT0 (EMU), EVT1 (RST), and EVT4 (Reserved) cause exceptions so
// don't initialize those entries in the EVT.
// init the vector table
//i0.h = EVT0 >> 16;
//i0.l = EVT0 & 0xffff;
//m0 = 4;
//r0.h = evt0;
//r0.l = evt0;
//[i0++m0] = r0;
//r0.h = evt1;
//r0.l = evt1;
//[i0++m0] = r0;
i0.h = EVT2 >> 16;
i0.l = EVT2 & 0xffff;
m0 = 4;
r0.h = evt2;
r0.l = evt2;
[i0++m0] = r0;
r0.h = evt3;
r0.l = evt3;
[i0++m0] = r0;
//r0.h = evt4;
//r0.l = evt4;
//[i0++m0] = r0;
i0.h = EVT5 >> 16;
i0.l = EVT5 & 0xffff;
m0 = 4;
r0.h = evt5;
r0.l = evt5;
[i0++m0] = r0;
r0.h = evt6;
r0.l = evt6;
[i0++m0] = r0;
r0.h = evt7;
r0.l = evt7;
[i0++m0] = r0;
r0.h = evt8;
r0.l = evt8;
[i0++m0] = r0;
r0.h = evt9;
r0.l = evt9;
[i0++m0] = r0;
r0.h = evt10;
r0.l = evt10;
[i0++m0] = r0;
r0.h = evt11;
r0.l = evt11;
[i0++m0] = r0;
r0.h = evt12;
r0.l = evt12;
[i0++m0] = r0;
r0.h = evt13;
r0.l = evt13;
[i0++m0] = r0;
r0.h = evt14;
r0.l = evt14;
[i0++m0] = r0;
r0.h = evt15;
r0.l = evt15;
[i0++m0] = r0;
rts;
/////////////////////////////////////////////////////////////////////////
// Interrupt Service Routines
//
// functions to handle each interrupt
//
evt0: // Emulation (EMU)
nop;
nop;
nop;
rti;
evt1: // Reset (RST)
nop;
nop;
nop;
rti;
evt2: // Non-Maskable Interrupt (NMI)
nop;
nop;
nop;
rtn;
evt3: // Exception (EVX)
nop;
nop;
nop;
rtx;
evt4: // Reserved
nop;
nop;
nop;
rti;
evt5: // Hardware Error (IVHW)
nop;
nop;
nop;
rti;
evt6: // Timer (IVTMR)
[--sp] = p2;
[--sp] = p1;
[--sp] = r0;
// count the number of timer interrupts
p1.h = timerCounter;
p1.l = timerCounter;
r0 = [p1];
r0 += 1;
[p1] = r0;
// update the first location of array1
p1.h = array1;
p1.l = array1;
[p1] = r0;
// update the first location of array2
p1.h = array2;
p1.l = array2;
[p1] = r0;
// p1 points to PF Set register (turns LEDs on)
p1.h = FIO_FLAG_S >> 16;
p1.l = FIO_FLAG_S & 0xffff;
// p2 points to PF Clear register (turns LEDs off)
p2.h = FIO_FLAG_C >> 16;
p2.l = FIO_FLAG_C & 0xffff;
nop;
w[p2] = r2; // turn LEDs off
bittgl(r2, 3);
w[p1] = r2; // turn LEDs on
r0 = [sp++];
p1 = [sp++];
p2 = [sp++];
rti;
evt7: // Interrupt 7 (IVG7)
nop;
nop;
nop;
rti;
evt8: // Interrupt 8 (IVG8)
nop;
nop;
nop;
rti;
evt9: // Interrupt 9 (IVG9)
nop;
nop;
nop;
rti;
evt10: // Interrupt 10 (IVG10)
nop;
nop;
nop;
rti;
evt11: // Interrupt 11 (IVG11)
nop;
nop;
nop;
rti;
evt12: // Interrupt 12 (IVG12)
[--sp] = p2;
[--sp] = p1;
[--sp] = r0;
[--sp] = lc0;
[--sp] = lt0;
[--sp] = lb0;
[--sp] = astat;
// p1 points to PF Set register (turns LEDs on)
p1.h = FIO_FLAG_S >> 16;
p1.l = FIO_FLAG_S & 0xffff;
// check to see if the PF4 pushbutton was pressed
checkPF4:
r0 = w[p1];
cc = bittst(r0, 4);
if !cc jump checkPF5;
// count the number of times PF4 was pressed
p1.h = pf4Counter;
p1.l = pf4Counter;
r0 = [p1];
r0 += 1;
[p1] = r0;
jump neitherPFpressed;
// check to see if the PF5 pushbutton was pressed
checkPF5:
cc = bittst(r0, 5);
if !cc jump checkPF6;
// count the number of times PF5 was pressed
p1.h = pf5Counter;
p1.l = pf5Counter;
r0 = [p1];
r0 += 1;
[p1] = r0;
jump neitherPFpressed;
// check to see if the PF6 pushbutton was pressed
checkPF6:
cc = bittst(r0, 6);
if !cc jump checkPF7;
// count the number of times PF6 was pressed
p1.h = pf6Array;
p1.l = pf6Array;
r0 = LENGTH(pf6Array);
lc0 = r0;
loop INC_CHAN3 lc0;
loop_begin INC_CHAN3;
r0 = b[p1];
r0 += 1;
b[p1++] = r0;
loop_end INC_CHAN3;
jump neitherPFpressed;
// check to see if the PF7 pushbutton was pressed
checkPF7:
cc = bittst(r0, 7);
if !cc jump neitherPFpressed;
// count the number of times PF7 was pressed
p1.h = pf7Array;
p1.l = pf7Array;
r0 = LENGTH(pf7Array);
lc0 = r0;
loop INC_CHAN4 lc0;
loop_begin INC_CHAN4;
r0 = b[p1];
r0 += 1;
b[p1++] = r0;
loop_end INC_CHAN4;
neitherPFpressed:
// p1 points to PF Set register (turns LEDs on)
p1.h = FIO_FLAG_S >> 16;
p1.l = FIO_FLAG_S & 0xffff;
// p2 points to PF Clear register (turns LEDs off)
p2.h = FIO_FLAG_C >> 16;
p2.l = FIO_FLAG_C & 0xffff;
nop;
[--sp] = r2; // save R2 on stack
r2.h = 0;
r2.l = 0x00f0; // clear the state of the input pins!!
w[p2] = r2;
r2 = [sp++]; // restore R2
w[p2] = r2; // turn LEDs off
bittgl(r2, 0); // toggle LED state
w[p1] = r2; // turn LEDs on
astat = [sp++];
lb0 = [sp++];
lt0 = [sp++];
lc0 = [sp++];
r0 = [sp++];
p1 = [sp++];
p2 = [sp++];
rti;
evt13: // Interrupt 13 (IVG13)
nop;
nop;
nop;
rti;
evt14: // Interrupt 14 (IVG14)
nop;
nop;
nop;
rti;
evt15: // Interrupt 15 (IVG15)
[--sp] = reti; // this allows nesting of interrupts
nop;
p0.h = EVT15_LOOP;
p0.l = EVT15_LOOP;
jump(p0);
// this code will never be reached (intentionally)
nop;
nop;
reti = [sp++]; // restore return address
rti;
/////////////////////////////////////////////////////////////////////////
// initCoreTimer
//
// function to initialize the Core Timer registers
//
initCoreTimer:
i0.h = TCNTL >> 16;
i0.l = TCNTL & 0xffff;
m0 = 4;
r0.h = 0;
r0.l = TMPWR | TAUTORLD; // set TMPWR and TAUTORLD, but don't enable the timer yet
[i0++m0] = r0;
// setup the timer period register
r0.h = 0x0001;
r0.l = 0x0000;
[i0++m0] = r0;
// setup the timer scale register
r0.h = 0x0000;
r0.l = 0x0080;
r3 = 0;
r4 = r0;
[i0++m0] = r0;
// setup the timer count register
r0.h = 0x0001;
r0.l = 0x0000;
[i0++m0] = r0;
rts;
/////////////////////////////////////////////////////////////////////////
// initProgFlags
//
// function to initialize the Programmable Flags registers
//
initProgFlags:
// p0 points to PF Config register
p0.h = FIO_DIR >> 16;
p0.l = FIO_DIR & 0xffff;
// set PF0 - PF3 to outputs, PF4 - PF15 left as inputs
// PF4 - PF7 pushbuttons will be capture as interrupts
r0 = 0xf;
// set all PF's to outputs
w[p0] = r0;
// p1 points to PF Set register (turns LEDs on)
p1.h = FIO_FLAG_S >> 16;
p1.l = FIO_FLAG_S & 0xffff;
// p2 points to PF Clear register (turns LEDs off)
p2.h = FIO_FLAG_C >> 16;
p2.l = FIO_FLAG_C & 0xffff;
// turn all LEDs off
r0 = -1;
w[p2] = r0;
// p3 points to PF Interrupt A Mask Set register
p3.h = FIO_MASKA_S >> 16;
p3.l = FIO_MASKA_S & 0xffff;
// enable PF4 - PF7 interrupts
r0.h = 0;
r0.l = 0x00f0;
w[p3] = r0;
// p3 points to PF Polarity register
p3.h = FIO_POLAR >> 16;
p3.l = FIO_POLAR & 0xffff;
// polarity is Active Hi (0) or Active Low (1)
r0.h = 0;
r0.l = 0x0000;
w[p3] = r0;
// p3 points to PF Interrupt Sensitivity register
p3.h = FIO_EDGE >> 16;
p3.l = FIO_EDGE & 0xffff;
// setup PF4 - PF7 for edge triggered interrupts (1)
r0.h = 0;
r0.l = 0x00f0;
w[p3] = r0;
//Check revision of silicon
// p0 points to CHIPID register
p0.h = 0xffc0;
p0.l = 0x48c0;
r2 = [p0];
r1.h = 0xf000;
r1.l = 0x0000;
// if the CHIPID is non-zero, a "1" in SIC_IMASK will enable system interrupts
r1 = r1 & r2;
cc = az;
if !cc jump newSilicon;
// any rev silicon of 1.0 or later will have system interrupts enabled by writing
// a 1 to the appropriate bit in SIC_IMASK. Revisions prior to 1.0 are enabled
// by writing a 0.
oldSilicon:
//Unmask the PF Interrupt A in System Interrupt Mask Register
p3.l = SIC_IMASK & 0xffff;
p3.h = SIC_IMASK >> 16;
r6 = [p3];
bitclr(r6,17);
[ p3 ] = r6;
rts;
newSilicon:
//Unmask the PF Interrupt A in System Interrupt Mask Register
p3.l = SIC_IMASK & 0xffff;
p3.h = SIC_IMASK >> 16;
r6 = [p3];
bitset(r6,17);
[ p3 ] = r6;
rts;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -