📄 uartlib.asm
字号:
/*****************************************************************************
** **
** Name: UART Software Interface **
** **
******************************************************************************
(C) Copyright 2003 - Analog Devices, Inc. All rights reserved.
File Name: uartlib.asm
Date Modified: 04/03/03 BK Rev 1.0
Software: VisualDSP++ 3.1 beta
Purpose: This file contains some library functions
commonly used on UART processing.
******************************************************************************/
#include <defBF533.h>
.section L1_code;
///////// uart_autobaud //////////////////////////////////////////////////////
/*****************************************************************************
*
* Assuming 8 data bits, this functions expects a '@' (ASCII 0x40) character
* on the UART RX pin.
* Timer 2 performs the autobaud detection. Also special support for
* half-duplex systems is provided.
*
* Input parameters: none
* Return values: r0 holds timer period value (equals 8 bits)
* Assumptions: p0 contains UART_GCTL register address
*
****************************************************************************/
.global uart_autobaud;
uart_autobaud:
[--sp] = r2;
[--sp] = p1;
/*****************************************************************************
*
* First of all, enable UART clock. It is required for autobaud detection on
* silicon revision 0.0.
*
****************************************************************************/
r0 = UCEN (z);
w[p0+UART_GCTL-UART_GCTL] = r0;
/*****************************************************************************
*
* Activate Loopback mode in order the receive channel is disconnected
* from RX pin during autobaud detection.
*
****************************************************************************/
r0 = LOOP_ENA (z);
w[p0+UART_MCR-UART_GCTL] = r0;
/*****************************************************************************
*
* Setup Timer 2 Controller to do the autobaud detection. Timer captures
* duration between two falling edges. It expects a '@' (ASCII 0x40)
* character. 8-bit, no parity assumed.
*
****************************************************************************/
p1.h = hi(TIMER_STATUS);
p1.l = lo(TIMER_STATUS);
/*****************************************************************************
*
* Disable Timer 2 first, in case there was an unexpected history.
*
****************************************************************************/
r0 = TIMDIS2 (z);
w[p1 + TIMER_DISABLE - TIMER_STATUS] = r0;
r0 = TRUN2 | TOVL_ERR2 | TIMIL2 (z);
w[p1 + TIMER_STATUS - TIMER_STATUS] = r0;
/*****************************************************************************
*
* Capture from UART RxD pin. Select period capture from falling edge to
* falling edge. Enable IRQ_ENA, but don't enable the interrupt at system
* level (SIC).
*
****************************************************************************/
r0 = TIN_SEL | IRQ_ENA | PERIOD_CNT | WDTH_CAP (z);
w[p1 + TIMER2_CONFIG - TIMER_STATUS] = r0;
/*****************************************************************************
*
* Start the timer and wait until the according interrupt latch bit TIMIL2
* in the TIMER_STATUS register is set. Then, two falling edges on the RxD
* pin have been detected.
*
****************************************************************************/
r0 = TIMEN2 (z);
w[p1 + TIMER_ENABLE - TIMER_STATUS] = r0;
wait_autobaud:
r0 = w[p1 + TIMER_STATUS - TIMER_STATUS] (z);
CC = bittst (r0, bitpos (TIMIL2) );
if !CC jump wait_autobaud;
/*****************************************************************************
*
* Disable Timer 2 again
*
****************************************************************************/
r0 = TIMDIS2 (z);
w[p1 + TIMER_DISABLE - TIMER_STATUS] = r0;
r0 = TRUN2 | TOVL_ERR2 | TIMIL2 (z);
w[p1 + TIMER_STATUS - TIMER_STATUS] = r0;
/*****************************************************************************
*
* Save period value to R2
*
****************************************************************************/
r2 = [p1 + TIMER2_PERIOD - TIMER_STATUS];
/*****************************************************************************
*
* In order to support also half-duplex connections, we need to delay any
* transmission, in order the sent character does not overlap the autobaud
* pattern.
*
* Use Timer 2 to perform this delay. Note that the Period Register still
* contains the proper value and the Width Register is not used.
*
****************************************************************************/
r0 = OUT_DIS | IRQ_ENA | PERIOD_CNT | PWM_OUT (z);
w[p1 + TIMER2_CONFIG - TIMER_STATUS] = r0;
r0 = TIMEN2 (z);
w[p1 + TIMER_ENABLE - TIMER_STATUS] = r0;
wait_delay:
r0 = w[p1 + TIMER_STATUS - TIMER_STATUS] (z);
CC = bittst (r0, bitpos (TIMIL2) );
if !CC jump wait_delay;
/*****************************************************************************
*
* Disable Timer 2 again
*
****************************************************************************/
r0 = TIMDIS2 (z);
w[p1 + TIMER_DISABLE - TIMER_STATUS] = r0;
r0 = TRUN2 | TOVL_ERR2 | TIMIL2 (z);
w[p1 + TIMER_STATUS - TIMER_STATUS] = r0;
/*****************************************************************************
*
* Deactive Loopback mode again
*
****************************************************************************/
r0 = 0 (z);
w[p0+UART_MCR-UART_GCTL] = r0;
/*****************************************************************************
*
* done !
*
****************************************************************************/
r0 = r2;
p1 = [sp++];
r2 = [sp++];
rts;
uart_autobaud.end:
///////// uart_init //////////////////////////////////////////////////////////
/*****************************************************************************
*
* Configures UART in 8 data bits, no parity, 1 stop bit mode.
*
* Input parameters: r0 holds divisor latch value to be written into
* DLH:DLL registers.
* Return values: none
* Assumptions: p0 contains UART_GCTL register address
*
****************************************************************************/
.global uart_init;
uart_init:
[--sp] = r1;
/*****************************************************************************
*
* First of all, enable UART clock.
*
****************************************************************************/
r1 = UCEN (z);
w[p0+UART_GCTL-UART_GCTL] = r1;
/*****************************************************************************
*
* Read period value and apply formula: DL = PERIOD / 16 / 8
* Write result to the two 8-bit DL registers (DLH:DLL).
*
****************************************************************************/
r1 = DLAB (z);
w[p0+UART_LCR-UART_GCTL] = r1;
w[p0+UART_DLL-UART_GCTL] = r0;
r1 = r0 >> 8;
w[p0+UART_DLH-UART_GCTL] = r1;
/*****************************************************************************
*
* Clear DLAB again and set UART frame to 8 bits, no parity, 1 stop bit.
* This may differ in other scenarious.
*
****************************************************************************/
r1 = WLS(8) (z);
w[p0+UART_LCR-UART_GCTL] = r1;
r1 = [sp++];
rts;
uart_init.end:
///////// uart_wait4temt /////////////////////////////////////////////////////
/*****************************************************************************
*
* This function polls the TEMT bit in the LSR register and waits until
* all data has been shifted out.
*
* Input parameters: none
* Return values: none
* Assumptions: p0 contains UART_GCTL register address
*
****************************************************************************/
.global uart_wait4temt;
uart_wait4temt:
[--sp] = r1;
temt_wait:
r1 = w[p0+UART_LSR-UART_GCTL] (z);
CC = bittst(r1,bitpos(TEMT));
if !CC jump temt_wait;
r1 = [sp++];
ssync;
rts;
uart_wait4temt.end:
///////// uart_disble ////////////////////////////////////////////////////////
/*****************************************************************************
*
* This function disables the UART clock, but polls the TEMT bit before
*
* Input parameters: none
* Return values: none
* Assumptions: p0 contains UART_GCTL register address
*
****************************************************************************/
.global uart_disable;
uart_disable:
[--sp] = r0;
[--sp] = rets;
call uart_wait4temt;
r0 = 0 (z);
w[p0+UART_GCTL-UART_GCTL] = r0;
rets = [sp++];
r0 = [sp++];
rts;
uart_disable.end:
///////// uart_putc //////////////////////////////////////////////////////////
/*****************************************************************************
*
* This function transmits a character by polling THRE bit in the LSR
* register.
*
* Input parameters: r0 holds the character to transmit
* Return values: none
* Assumptions: p0 contains UART_GCTL register address
*
****************************************************************************/
.global uart_putc;
uart_putc:
[--sp] = r1;
putc_wait:
r1 = w[p0+UART_LSR-UART_GCTL] (z);
CC = bittst(r1,bitpos(THRE));
if !CC jump putc_wait;
w[p0+UART_THR-UART_GCTL] = r0;
r1 = [sp++];
rts;
uart_putc.end:
///////// uart_puts //////////////////////////////////////////////////////////
/*****************************************************************************
*
* This function transmits a byte string by polling THRE bit in the LSR
* register. The string must be NULL-terminated (C-style).
*
* Input parameters: p1 holds the start address of the string to transmit
* Return values: none
* Assumptions: p0 contains UART_GCTL register address
*
****************************************************************************/
.global uart_puts;
uart_puts:
[--sp] = rets;
[--sp] = r0;
puts_loop:
r0 = b[p1++] (z);
CC = r0 == 0;
if CC jump puts_end;
call uart_putc;
jump puts_loop;
puts_end:
r0 = [sp++];
rets = [sp++];
rts;
uart_puts.end:
///////// uart_putreg ////////////////////////////////////////////////////////
/*****************************************************************************
*
* This function transmits the content of the r0 register in hexdecimal
* representation. This is based on polling operation.
*
* Input parameters: r0 holds hex value
* Return values: none
* Assumptions: p0 contains UART_GCTL register address
*
****************************************************************************/
.global uart_putreg;
uart_putreg:
[--sp] = rets;
[--sp] = (r7:1, p5:5);
r1 = r0;
r0 = 0x20; // ' '
call uart_putc;
r0 = 0x30; // '0'
call uart_putc;
r0 = 0x78; // 'x'
call uart_putc;
r2 = 0x0400;
r3 = 0x0030;
[--sp] = r3;
r4 = 0x0037;
r5 = 9;
r6 = 0x1C04;
p5 = 8;
lsetup (putreg_lbegin, putreg_lend) lc0=p5;
putreg_lbegin:
r0 = extract(r1,r6.l)(z) || r3 = [sp]; // Read next nibble
CC = r0 <= r5;
if !CC r3 = r4; // 0..9 or A..F
r0 = r0 + r3; // Make ASCII
call uart_putc;
putreg_lend:
r6 = r6 - r2; // next nibble position
sp+= 4;
(r7:1, p5:5) = [sp++];
rets = [sp++];
rts;
uart_putreg.end:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -