📄 stdio_uart.c
字号:
///////////////////////////////////////////////////////////////
//
// STDIO_UART
//
// Creates new STDIO Device Driver for UART I/O
//
//(C) Copyright 2004 - Analog Devices, Inc. All rights reserved.
//File Name: stdio_uart.c
//Date Modified: 03/19/04
//
//Hardware: ADSP-BF533 EZ-KIT Lite Board
//
//Special Connections:
// - EIA-232 Serial Cable (1:1)
// - Terminal Program (i.e. Hyperterminal for Windows)
// - 2400 bits per second (default)
// - 8-bit, no parity, 1 stop bit
// - no handshake
// - echo off
//
//Purpose:
// - Registering New STDIO Device Driver for UART I/0
// - Redirect Stdin/Stdout to New STDIO Device Driver
// - (optional)Autobaud Detection using GP Timer 2
//
//Steps:
// - Build and Run
// - Open a Terminal Program (i.e. Hyperterminal for Windows)
// - "Hello World" will print to Terminal Program
// - "Type in something, press <Enter>, and I'll repeat it backwards!"
//
///////////////////////////////////////////////////////////////
#include <device.h>
#include <ccblkfn.h>
#include <cdefBF533.h>
#include <sys/exception.h>
#include <stdio.h>
int UART_init (struct DevEntry *dev);
int UART_open (const char *name, int mode);
int UART_close (int fd);
int UART_write (int fd, unsigned char *buf, int size);
int UART_read (int fd, unsigned char *buf, int size);
long UART_seek (int fd, long offset, int whence);
DevEntry UART_DevEntry =
{
0,
NULL,
UART_init,
UART_open,
UART_close,
UART_write,
UART_read,
UART_seek,
dev_not_claimed,
dev_not_claimed,
dev_not_claimed
};
void UART_inititialize(int divisor);
void UART_disable(void);
int UART_detectAutobaud(void);
void UART_waitForTransferCompletion(void);
void UART_putc(char c);
void UART_puts(char *c);
char UART_getc(void);
int UART_gets(char *str, int max);
int UART_detectAutobaud(void);
int UART_getSCLK(void);
#define MEGA 1000000
extern unsigned short CLKIN;
///////////////////////////////////////////////////////////////
int UART_init ( struct DevEntry *dev )
{
int period=0, divisor=0, SCLK=0;
if ( 0 == (int) dev->data )
{
// If the baud rate is specified as zero, then autobaud.
period = UART_detectAutobaud();
//Apply formula divisor = period / (16 x 8 bits)
divisor = period >> 7;
}
else
{ // use system clock to calc divisor
SCLK = UART_getSCLK();
divisor = SCLK / ( (int) dev->data * 16);
}
UART_inititialize(divisor);
return 0;
}
///////////////////////////////////////////////////////////////
int UART_open (const char *name, int mode)
{
return 0;
}
///////////////////////////////////////////////////////////////
int UART_write (int fd, unsigned char *buf, int size)
{
int i = 0;
for ( ; i < size; ++i) UART_putc( *buf++ );
UART_waitForTransferCompletion();
return 0;
}
///////////////////////////////////////////////////////////////
int UART_read (int fd, unsigned char *buf, int size)
{
fflush( (FILE *) fd ); //for printf
int result = UART_gets( (char *) buf, size );
return result;
}
///////////////////////////////////////////////////////////////
long UART_seek (int fd, long offset, int whence)
{
return 0;
}
///////////////////////////////////////////////////////////////
int UART_close (int fd)
{
UART_disable();
return 0;
}
///////////////////////////////////////////////////////////////
//Configures UART in 8 data bits, no parity, 1 stop bit mode.
///////////////////////////////////////////////////////////////
void UART_inititialize(int divisor)
{
// enable UART clock.
*pUART_GCTL = UCEN;
// Read period value and apply formula: divisor = period/16*8
// Write result to the two 8-bit DL registers (DLH:DLL).
*pUART_LCR = DLAB;
*pUART_DLL = divisor;
*pUART_DLH = divisor>>8;
// Clear DLAB again and set UART frame to 8 bits, no parity, 1 stop bit.
*pUART_LCR = WLS(8);
}
///////////////////////////////////////////////////////////////
//disable UART clock, after polling the TEMT bit
///////////////////////////////////////////////////////////////
void UART_disable(void)
{
UART_waitForTransferCompletion();
*pUART_GCTL = 0;
}
///////////////////////////////////////////////////////////////
//poll the TEMT bit in LSR reg and wait until all data shifted out.
///////////////////////////////////////////////////////////////
void UART_waitForTransferCompletion(void)
{
while (!(*pUART_LSR & TEMT)) { }; // wait
ssync();
}
///////////////////////////////////////////////////////////////
//transmit character by polling the THRE bit in the LSR register.
///////////////////////////////////////////////////////////////
void UART_putc(char c)
{
while (!(*pUART_LSR & THRE)) { }; //wait
*pUART_THR = c;
}
//////////////////////////////////////////////////////////////
void UART_puts(char *c)
{
while (*c)
{
UART_putc(*c);
c++;
}
}
///////////////////////////////////////////////////////////////
//receive character by polling the DR bit in the LSR register.
///////////////////////////////////////////////////////////////
char UART_getc(void)
{
char c;
while (!(*pUART_LSR & DR)) { }; //wait
c = *pUART_RBR;
return c;
}
///////////////////////////////////////////////////////////////
//receive an LF ('ENTER') by polling the DR bit in the LSR register.
///////////////////////////////////////////////////////////////
int UART_gets(char *str, int max)
{
int i;
for(i = 0; i < max; i++)
{
str[i] = UART_getc();
if (str[i] == 13)
{
return i+1;
}
}
return max;
}
///////////////////////////////////////////////////////////////
// Start Auto Baud detection by entering "@" inside Terminal Program
///////////////////////////////////////////////////////////////
int UART_detectAutobaud(void)
{
int period = 0;
// Activate Loopback mode in order the receive channel is disconnected
// from RX pin during autobaud detection.
*pUART_MCR = LOOP_ENA;
// 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.
// Disable Timer 2 first, in case there was an unexpected history.
*pTIMER_DISABLE = TIMDIS2;
*pTIMER_STATUS = TRUN2 | TOVL_ERR2 | TIMIL2;
// 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).
*pTIMER2_CONFIG = TIN_SEL | IRQ_ENA | PERIOD_CNT | WDTH_CAP;
// 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.
*pTIMER_ENABLE = TIMEN2;
// Enable the UART
*pUART_GCTL = UCEN;
while (!(*pTIMER_STATUS & TIMIL2)) {}; //wait
// Disable Timer 2 again
*pTIMER_DISABLE = TIMDIS2;
*pTIMER_STATUS = TRUN2 | TOVL_ERR2 | TIMIL2;
// Save period value
period = *pTIMER2_PERIOD;
// 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.
*pTIMER2_CONFIG = OUT_DIS | IRQ_ENA | PERIOD_CNT | PWM_OUT;
*pTIMER_ENABLE = TIMEN2;
while (!(*pTIMER_STATUS & TIMIL2)) { }; //wait
// Disable Timer 2 again
*pTIMER_DISABLE = TIMDIS2;
*pTIMER_STATUS = TRUN2 | TOVL_ERR2 | TIMIL2;
// Deactive Loopback mode again
*pUART_MCR = 0;
return period;
}
///////////////////////////////////////////////////////////////
//CLKIN is the input clock.The ADSP-BF533 EZ-Kits CLKIN is 27MHz
//This function will check what the system clock is based
//on the MSEL, DF, and SSEL values in the PLL_CTL and PLL_DIV registers.
///////////////////////////////////////////////////////////////
int UART_getSCLK()
{
unsigned short tempPLLCTL, tempPLLDIV;
unsigned short MSEL, SSEL, DF, VCO, SCLK;
tempPLLCTL = *pPLL_CTL;
tempPLLDIV = *pPLL_DIV;
//get MSEL, SSEL, DF
MSEL = ((tempPLLCTL & 0x7E00) >> 9);
SSEL = tempPLLDIV & 0x000f;
DF = tempPLLCTL & 0x0001;
if(DF == 1) CLKIN = CLKIN/2;
VCO = MSEL * CLKIN;
SCLK = VCO/SSEL;
return SCLK * MEGA;
}
///////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -