📄 main.asm
字号:
/*****************************************************************************
** **
** Name: UART Software Interface **
** **
******************************************************************************
(C) Copyright 2006 - Analog Devices, Inc. All rights reserved.
File Name: main.asm
Date Modified: 04/03/03 Rev 1.0
Software: VisualDSP++ 4.5
Hardware: ADSP-BF533 EZ-KIT Lite Board
ADSP-BF533 Blackfin Processor Rev 0.1
Special Connections:
EIA-232 Serial Cable (1:1)
Terminal Program (i.e. Hyperterminal for Windows)
- bit rate doesn't matter
- 8-bit, no parity, 1 stop bit
- no handshake
- echo off
Purpose: Illustration of UART usage
- Autobaud Detection using GP Timer 2
- Polling Operation
- Interrupt Operation
******************************************************************************/
#include <defBF533.h>
#include "uartlib.h"
#include "sicnames.h"
/*****************************************************************************
*
* Example requires a simple hello-world string.
* Initialize on-chip SRAM at boot time accordingly.
*
****************************************************************************/
.section data1;
.byte sHead[] = 13,10,'-------------------------------',
13,10,'ADSP-BF533 Blackfin is speaking',
13,10,'(DL =',0;
.byte sTail[] = ')',
13,10,'-------------------------------',
13,10,0;
.byte sEcho[] = 'Type any character. The Blackfin UART',
13,10,'returns the echo> ',0;
.align 4;
.var aEchoFifo[16];
/*****************************************************************************
*
* Main program starts here!
*
****************************************************************************/
.section L1_code;
.global _main;
_main:
[--sp] = rets;
/*****************************************************************************
*
* First of all, initialize p0 to UART_GCTL register address.
* p0 must not be changed within this example
*
****************************************************************************/
p0.l = lo(UART_GCTL);
p0.h = hi(UART_GCTL);
call uart_autobaud;
/*****************************************************************************
*
* r0 holds the timer period value, now.
* Apply formula DL = PERIOD / (16 x 8 bits) and call uart_init that writes
* the result to the two 8-bit DL registers (DLH:DLL).
*
****************************************************************************/
r0 >>= 7;
call uart_init;
/*****************************************************************************
*
* Transmit a Hello World string and the content of the DL registers.
*
****************************************************************************/
p1.l = sHead;
p1.h = sHead;
call uart_puts;
/*****************************************************************************
*
* Note that r0 still contains the DLH:DLL value
*
****************************************************************************/
call uart_putreg;
p1.l = sTail;
p1.h = sTail;
call uart_puts;
/*****************************************************************************
*
* Wait until operation has finished completely. This is optional.
*
****************************************************************************/
call uart_wait4temt;
/*****************************************************************************
*
* Transmit another string, but use interrupt mode, this time.
* First TX interrupt channel must be assigned and enabled.
* Assign to EVT9.
*
* p3 points to the NULL-terminated string.
*
* Important: if you enable all three UART interrupts channels, it is
* recommended to keep this order of priorities:
* PRIORITY(Error) >= PRIORITY(RX) >= PRIORITY(TX)
*
****************************************************************************/
p1.l = lo(IMASK);
p1.h = hi(IMASK);
p3.l = sEcho;
p3.h = sEcho;
/*****************************************************************************
*
* Register TX service routine at EVT9.
*
****************************************************************************/
r0.l = isr_uart_tx;
r0.h = isr_uart_tx;
[p1 + EVT9 - IMASK] = r0;
/*****************************************************************************
*
* Unmask EVT9 interrupt.
*
****************************************************************************/
r0 = [p1 + IMASK - IMASK];
bitset(r0, bitpos(EVT_IVG9));
[p1 + IMASK - IMASK] = r0;
/*****************************************************************************
*
* Enable UART TX interrupt and assign it to EVT9.
* Constants used below are defined in "sicnames.h" header.
*
****************************************************************************/
p1.l = lo(SIC_IMASK);
p1.h = hi(SIC_IMASK);
r0.l = lo(IVG_SPT0_ERROR(15) | IVG_PPI_ERROR(15) | IVG_DMA_ERROR(15) | IVG_PLL_WAKEUP(15));
r0.h = hi(IVG_RTC(15) | IVG_UART_ERROR(15) | IVG_SPT1_ERROR(15) | IVG_SPI_ERROR(15));
[p1 + SIC_IAR0 - SIC_IMASK] = r0;
r0.l = lo(IVG_SPT1_RX(15) | IVG_SPT0_TX(15) | IVG_SPT0_RX(15) | IVG_PPI(15));
r0.h = hi(IVG_UART_TX( 9) | IVG_UART_RX(16) | IVG_SPI(15) | IVG_SPT1_TX(15));
[p1 + SIC_IAR1 - SIC_IMASK] = r0;
r0.l = lo(IVG_PFA(15) | IVG_TIMER2(15) | IVG_TIMER1(15) | IVG_TIMER0(15));
r0.h = hi(IVG_SWDT(15) | IVG_MEMDMA1(15) | IVG_MEMDMA0(15) | IVG_PFB(15));
[p1 + SIC_IAR2 - SIC_IMASK] = r0;
r0.l = lo(IRQ_UART_TX);
r0.h = hi(IRQ_UART_TX);
[p1 + SIC_IMASK - SIC_IMASK] = r0;
/*****************************************************************************
*
* Enable Interrupt Nesting.
*
****************************************************************************/
[--sp] = reti;
/*****************************************************************************
*
* Finally enable interrupts inside UART module, by setting proper bits
* in the IER register. It is good programming style to clear potential
* UART interrupt latches in advance, by reading RBR, LSR and IIR.
*
* Setting the ETBEI bit automatically fires a TX interrupt request.
*
****************************************************************************/
r0 = w[p0+UART_RBR-UART_GCTL] (z);
r0 = w[p0+UART_LSR-UART_GCTL] (z);
r0 = w[p0+UART_IIR-UART_GCTL] (z);
r0 = ETBEI;
w[p0+UART_IER-UART_GCTL] = r0;
/*****************************************************************************
*
* Wait until operation has finished completely. Again, this is optional.
*
****************************************************************************/
call uart_wait4temt;
/*****************************************************************************
*
* Disable UART TX interrupt again, and enable UART RX interrupt and UART
* Line Error Interrupt.
* Simply echo all received characters back to TX.
*
* Disable nesting during the setup.
*
****************************************************************************/
reti = [sp++];
p1.l = lo(IMASK);
p1.h = hi(IMASK);
/*****************************************************************************
*
* i0 and i1 are used to implement a little FIFO
*
****************************************************************************/
i0.l = aEchoFifo;
i0.h = aEchoFifo;
i1 = i0;
b0 = i0;
b1 = i0;
l0 = length(aEchoFifo);
l1 = l0;
/*****************************************************************************
*
* Register RX service routine at EVT8 and error routine to EVT7.
*
****************************************************************************/
r0.l = isr_uart_error;
r0.h = isr_uart_error;
[p1 + EVT7 - IMASK] = r0;
r0.l = isr_uart_rx;
r0.h = isr_uart_rx;
[p1 + EVT8 - IMASK] = r0;
/*****************************************************************************
*
* Mask EVT9 interrupt and unmask EVT7 and EVT8.
*
****************************************************************************/
r0 = [p1 + IMASK - IMASK];
bitclr(r0, bitpos(EVT_IVG9));
bitset(r0, bitpos(EVT_IVG7));
bitset(r0, bitpos(EVT_IVG8));
[p1 + IMASK - IMASK] = r0;
/*****************************************************************************
*
* Enable and assign interrupts.
*
****************************************************************************/
p1.l = lo(SIC_IMASK);
p1.h = hi(SIC_IMASK);
r0.l = lo(IVG_SPT0_ERROR(15) | IVG_PPI_ERROR(15) | IVG_DMA_ERROR(15) | IVG_PLL_WAKEUP(15));
r0.h = hi(IVG_RTC(15) | IVG_UART_ERROR( 7) | IVG_SPT1_ERROR(15) | IVG_SPI_ERROR(15));
[p1 + SIC_IAR0 - SIC_IMASK] = r0;
r0.l = lo(IVG_SPT1_RX(15) | IVG_SPT0_TX(15) | IVG_SPT0_RX(15) | IVG_PPI(15));
r0.h = hi(IVG_UART_TX(15) | IVG_UART_RX( 8) | IVG_SPI(15) | IVG_SPT1_TX(15));
[p1 + SIC_IAR1 - SIC_IMASK] = r0;
r0.l = lo(IVG_PFA(15) | IVG_TIMER2(15) | IVG_TIMER1(15) | IVG_TIMER0(15));
r0.h = hi(IVG_SWDT(15) | IVG_MEMDMA1(15) | IVG_MEMDMA0(15) | IVG_PFB(15));
[p1 + SIC_IAR2 - SIC_IMASK] = r0;
r0.l = lo(IRQ_UART_RX | IRQ_UART_ERROR);
r0.h = hi(IRQ_UART_RX | IRQ_UART_ERROR);
[p1 + SIC_IMASK - SIC_IMASK] = r0;
/*****************************************************************************
*
* Enable Interrupt Nesting.
*
****************************************************************************/
[--sp] = reti;
/*****************************************************************************
*
* Finally enable interrupts inside UART module, by setting proper bits
* in the IER register. It is good programming style to clear potential
* UART interrupt latches in advance, by reading RBR, LSR and IIR.
*
****************************************************************************/
r0 = w[p0+UART_RBR-UART_GCTL] (z);
r0 = w[p0+UART_LSR-UART_GCTL] (z);
r0 = w[p0+UART_IIR-UART_GCTL] (z);
r0 = ELSI | ERBFI;
w[p0+UART_IER-UART_GCTL] = r0;
/*****************************************************************************
*
* The following endless loop tests whether data is ready in the aEchoFifo
* and trasnmits it, if required. The FIFO is filled by the UART RX ISR.
*
****************************************************************************/
echo:
r0 = i0;
r1 = i1;
CC = r0 == r1;
if CC jump echo;
r0 = [i1++];
call uart_putc;
jump echo;
_main.end: nop;
/*****************************************************************************
*
* UART TX Interrupt Service Rouine.
*
* Load next byte from p3 pointer and moves it to THR register until
* p3 points to NULL character. Note that a write to THR clears the
* TX interrupt request.
*
****************************************************************************/
isr_uart_tx:
[--sp] = r0;
r0 = b[p3++] (z);
CC = r0 == 0;
if CC jump isr_tx_done;
w[p0+UART_THR-UART_GCTL] = r0;
r0 = [sp++];
nop;
ssync;
rti;
/*****************************************************************************
*
* Once a NULL character was detected, the transmission should stop.
* There is a need to clear the TX interrupt request. Since we don't
* want to write to THR again, we can clear the request by reading the
* IIR register. Note that system design needs to ensure that neigher
* an UART RX or Line Status interrupt should be pending!
*
* Note the double ssync instruction, required due to system latencies.
*
****************************************************************************/
isr_tx_done:
r0 = w[p0+UART_IIR-UART_GCTL] (z);
r0 = [sp++];
ssync;
ssync;
rti;
isr_uart_tx.end:
/*****************************************************************************
*
* UART RX Interrupt Service Rouine.
*
* When new data is received this ISR puts the new data into the aEchoFifo.
* Special handling is required for carriage return and backspace.
*
* Note that reading RBR clears the interrupt request.
*
****************************************************************************/
isr_uart_rx:
[--sp] = r0;
[--sp] = r1;
r0 = w[p0+UART_RBR-UART_GCTL] (z);
[i0++] = r0;
r1 = 8; // backspace
CC = r0 == r1;
if !CC jump isr10;
r1 = 32 (z); // blank
[i0++] = r1;
r1 = 8 (z); // another backspace
[i0++] = r1;
isr10:
r1 = 13; // carriage return
CC = r0 == r1;
if !CC jump isr20;
r1 = 10 (z); // line feed
[i0++] = r1;
isr20:
r1 = [sp++];
r0 = [sp++];
ssync;
rti;
isr_uart_rx.end:
/*****************************************************************************
*
* UART Error/Line Status Interrupt Service Rouine.
*
* If an error is reported by the UART Line Status, then this ISR reads
* the LSR register to determine the cause of the error (and to clear the
* interrupt request).
*
* To indicate the error a 0xFF character will be written to the FIFO.
*
****************************************************************************/
isr_uart_error:
[--sp] = r0;
r0 = w[p0+UART_LSR-UART_GCTL] (z);
r0 = 0xFF (z);
[i0++] = r0;
r0 = [sp++];
ssync;
rti;
isr_uart_error.end:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -