📄 auto_baud.asm
字号:
#include <defBF533.h>
.section L1_code;
.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.
*
****************************************************************************/
p0.l = lo(UART_GCTL);
p0.h = hi(UART_GCTL);
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;
/*****************************************************************************
*
* 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;
p1 = [sp++];
r2 = [sp++];
rts;
_uart_autobaud.end:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -