/*********************************************************************************************************
**
** 中國軟件開源組織
**
** 嵌入式實時操作系統
**
** SylixOS(TM)
**
** Copyright All Rights Reserved
**
**--------------文件信息--------------------------------------------------------------------------------
**
** 文 件 名: samsungtty.h
**
** 創 建 人: Han.Hui (韓輝)
**
** 文件創建日期: 2007 年 09 月 20 日
**
** 描 述: tty 驅動.
*********************************************************************************************************/
#ifndef __SAMSUNGTTY_H
#define __SAMSUNGTTY_H
/*********************************************************************************************************
初始化波特率
*********************************************************************************************************/
#define UART_DEFAULT_BAUD (SIO_BAUD_115200) /* 默認波特率 */
#define UART_DEFAULT_OPT (CREAD | CS8) /* 默認選項 */
/*********************************************************************************************************
485 控制命令
*********************************************************************************************************/
#define RS485_SET (FIOUSRFUNC + 1) /* 485 使能或禁能命令 */
#define RS485_GET (FIOUSRFUNC + 2) /* 獲得串口是否工作在 485 狀態 */
/*********************************************************************************************************
485 輸入輸出控制
*********************************************************************************************************/
#define RS485_EN 1 /* 使能485 */
#define RS485_DIS 0 /* 禁能485 */
/*********************************************************************************************************
** Function name: sioChanCreate
** Descriptions: 創建一個 sio 通道
** input parameters: iChannelNum 硬件通道號
** output parameters: NONE
** Returned value: NONE
*********************************************************************************************************/
SIO_CHAN *sioChanCreate(INT iChannelNum);
#endif /* __SAMSUNGTTY_H */
/*********************************************************************************************************
END FILE
*********************************************************************************************************/
/*********************************************************************************************************
**
** 中國軟件開源組織
**
** 嵌入式實時操作系統
**
** SylixOS(TM)
**
** Copyright All Rights Reserved
**
**--------------文件信息--------------------------------------------------------------------------------
**
** 文 件 名: samsungtty.c
**
** 創 建 人: Han.Hui (韓輝)
**
** 文件創建日期: 2007 年 09 月 20 日
**
** 描 述: tty 驅動.
**
** BUG:
2009.05.31 串口開中斷的時機有錯誤.
2009.07.21 修正 485 方向角控制錯誤.
2012.12.14 修正 FIFO 滿判斷錯誤.
2014.05.27 startup 僅僅打開 Tx FIFO 空中斷即可.
2014.07.20 加入設備電源管理.
*********************************************************************************************************/
#define __SYLIXOS_KERNEL
#include "config.h" /* 工程配置 & 處理器相關 */
#include "SylixOS.h"
#include "uart.h"
#include "samsungtty.h"
/*********************************************************************************************************
對指定管腳進行操作
*********************************************************************************************************/
#define __COM1_RS485_SEND_START() BIT_SET(rGPGDAT, 0)
#define __COM1_RS485_SEND_END() BIT_CLR(rGPGDAT, 0)
/*********************************************************************************************************
判斷 FIFO 有效個數
*********************************************************************************************************/
#define __COM_FIFO_CNT 64
#define __COM_FIFO_CNT_MASK 0x7F
/*********************************************************************************************************
STREAM UART CHANNEL (SIO CHANNEL)
*********************************************************************************************************/
typedef struct {
SIO_DRV_FUNCS *pdrvFuncs; /* SIO 驅動程序組 */
LW_PM_DEV pmdev; /* 電源管理節點 */
INT (*pcbGetTxChar)(); /* 中斷回調函數 */
INT (*pcbPutRcvChar)();
PVOID pvGetTxArg; /* 回調函數句柄 */
PVOID pvPutRcvArg;
INT iChannelMode; /* 同步 IO 通道模式 */
UCHAR (*pfuncHwInByte)(INT); /* 物理硬件接收一個字節 */
VOID (*pfuncHwOutByte)(INT, CHAR); /* 物理硬件發送一個字節 */
INT iChannelNum; /* 通道號 */
INT iBaud; /* 波特率 */
INT iHwOption; /* 硬件選項 */
INT iRs485Flag; /* 對串口是否要使能485功能 */
} __SAMSUNGSIO_CHANNEL;
typedef __SAMSUNGSIO_CHANNEL *__PSAMSUNGSIO_CHANNEL; /* 指針類型 */
/*********************************************************************************************************
SIO 通道控制塊
*********************************************************************************************************/
static __SAMSUNGSIO_CHANNEL __GsamsungsiochanUart0;
static __SAMSUNGSIO_CHANNEL __GsamsungsiochanUart1;
static __SAMSUNGSIO_CHANNEL __GsamsungsiochanUart2;
/*********************************************************************************************************
UART 驅動程序
*********************************************************************************************************/
static INT __uartIoctl(SIO_CHAN *psiochanChan, INT iCmd, LONG lArg);/* 端口控制 */
static INT __uartStartup(SIO_CHAN *psiochanChan); /* 發送 */
static INT __uartcbInstall(SIO_CHAN *psiochanChan, /* 安裝回調 */
INT iCallbackType,
VX_SIO_CALLBACK callbackRoute,
PVOID pvCallbackArg);
static INT __uartPollRxChar(SIO_CHAN *psiochanChan,
PCHAR pcInChar); /* 輪詢接收 */
static INT __uartPollTxChar(SIO_CHAN *, CHAR); /* 輪詢發送 */
static irqreturn_t __uartIsr(SIO_CHAN *psiochanChan); /* 接收中斷 */
static VOID __uartHwOptionAnalyse(INT iHwOption,
PUCHAR pucDataBits,
PUCHAR pucStopBits,
PUCHAR pucParity); /* 分析硬件參數 */
/*********************************************************************************************************
SIO 驅動程序
*********************************************************************************************************/
static SIO_DRV_FUNCS __GsiodrvUartDrvFunc = {
(INT (*)(SIO_CHAN *,INT, PVOID))__uartIoctl,
__uartStartup,
__uartcbInstall,
__uartPollRxChar,
(INT (*)(SIO_CHAN *, CHAR))__uartPollTxChar
};
/*********************************************************************************************************
** Function name: __uartHwOptionAnalyse
** Descriptions: 分析 SIO 通道硬件參數
** input parameters: iHwOption 硬件參數
** output parameters: pucDataBits, 數據位數
pucStopBits, 結束位
pucParity 校驗位
** Returned value: NONE
** Created by: Hanhui
** Created Date: 2007/09/24
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
**--------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
static VOID __uartHwOptionAnalyse (INT iHwOption,
PUCHAR pucDataBits,
PUCHAR pucStopBits,
PUCHAR pucParity)
{
if ((iHwOption & CS8) == CS8) { /* 確定數據位數 */
*pucDataBits = 8;
} else if (iHwOption & CS7) {
*pucDataBits = 7;
} else if (iHwOption & CS6) {
*pucDataBits = 6;
} else {
*pucDataBits = 5;
}
if (iHwOption & STOPB) { /* 確定結束位 */
*pucStopBits = TWO_STOPBIT;
} else {
*pucStopBits = ONE_STOPBIT;
}
if (iHwOption & PARENB) { /* 確定校驗位 */
if (iHwOption & PARODD) {
*pucParity = CHK_ODD;
} else {
*pucParity = CHK_EVEN;
}
} else {
*pucParity = CHK_NONE;
}
}
/*********************************************************************************************************
** Function name: sioChanCreate
** Descriptions: 創建一個 sio 通道
** input parameters: iChannelNum 硬件通道號
** output parameters: NONE
** Returned value: NONE
** Created by: Hanhui
** Created Date: 2007/12/20
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
**--------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
SIO_CHAN *sioChanCreate (INT iChannelNum)
{
static PLW_PM_ADAPTER pmadapter = LW_NULL;
__PSAMSUNGSIO_CHANNEL psamsungsiochanUart;
SIO_CHAN *psiochan;
UCHAR ucDataBits;
UCHAR ucStopBits;
UCHAR ucParity;
if (pmadapter == LW_NULL) {
pmadapter = pmAdapterFind("inner_pm");
if (pmadapter == LW_NULL) {
printk(KERN_ERR "can not find power manager.\n");
}
}
switch (iChannelNum) {
case COM0:
pmDevInit(&__GsamsungsiochanUart0.pmdev, pmadapter, 10, LW_NULL);
__GsamsungsiochanUart0.pmdev.PMD_pcName = "uart0";
psamsungsiochanUart = &__GsamsungsiochanUart0;
psamsungsiochanUart->pdrvFuncs = &__GsiodrvUartDrvFunc; /* SIO FUNC */
psamsungsiochanUart->iChannelNum = COM0;
API_InterVectorConnect(VIC_CHANNEL_UART0,
(PINT_SVR_ROUTINE)__uartIsr,
(PVOID)&__GsamsungsiochanUart0,
"uart0_isr"); /* 安裝操作系統中斷向量表 */
break;
case COM1:
pmDevInit(&__GsamsungsiochanUart1.pmdev, pmadapter, 11, LW_NULL);
__GsamsungsiochanUart1.pmdev.PMD_pcName = "uart1";
psamsungsiochanUart = &__GsamsungsiochanUart1;
psamsungsiochanUart->pdrvFuncs = &__GsiodrvUartDrvFunc; /* SIO FUNC */
psamsungsiochanUart->iChannelNum = COM1;
API_InterVectorConnect(VIC_CHANNEL_UART1,
(PINT_SVR_ROUTINE)__uartIsr,
(PVOID)&__GsamsungsiochanUart1,
"uart1_isr"); /* 安裝操作系統中斷向量表 */
break;
case COM2:
pmDevInit(&__GsamsungsiochanUart2.pmdev, pmadapter, 12, LW_NULL);
__GsamsungsiochanUart2.pmdev.PMD_pcName = "uart2";
psamsungsiochanUart = &__GsamsungsiochanUart2;
psamsungsiochanUart->pdrvFuncs = &__GsiodrvUartDrvFunc; /* SIO FUNC */
psamsungsiochanUart->iChannelNum = COM2;
API_InterVectorConnect(VIC_CHANNEL_UART2,
(PINT_SVR_ROUTINE)__uartIsr,
(PVOID)&__GsamsungsiochanUart2,
"uart2_isr"); /* 安裝操作系統中斷向量表 */
break;
default:
return (LW_NULL); /* 通道號錯誤 */
}
psiochan = (SIO_CHAN *)psamsungsiochanUart;
psamsungsiochanUart->iChannelMode = SIO_MODE_INT; /* 使用中斷模式 */
psamsungsiochanUart->iBaud = UART_DEFAULT_BAUD; /* 初始化波特率 */
psamsungsiochanUart->iHwOption = UART_DEFAULT_OPT; /* 硬件狀態 */
psamsungsiochanUart->iRs485Flag = RS485_DIS; /* 默認不使用485功能 */
__uartHwOptionAnalyse(UART_DEFAULT_OPT,
&ucDataBits,
&ucStopBits,
&ucParity); /* 獲得具體參數 */
uartInit(iChannelNum, UNUSE_INF, ucDataBits, ucStopBits,
ucParity, UART_DEFAULT_BAUD, LW_NULL);
return (psiochan);
}
/*********************************************************************************************************
** Function name: __uartcbInstall
** Descriptions: SIO 通道安裝回調函數
** input parameters: psiochanChan 通道
** iCallbackType 回調類型
** callbackRoute 回調函數
** pvCallbackArg 回調參數
** output parameters: NONE
** Returned value: 錯誤號
** Created by: Hanhui
** Created Date: 2007/09/24
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
**--------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
static INT __uartcbInstall(SIO_CHAN *psiochanChan,
INT iCallbackType,
VX_SIO_CALLBACK callbackRoute,
PVOID pvCallbackArg)
{
__PSAMSUNGSIO_CHANNEL psamsungsiochanUart = (__PSAMSUNGSIO_CHANNEL)psiochanChan;
switch (iCallbackType) {
case SIO_CALLBACK_GET_TX_CHAR: /* 發送回電函數 */
psamsungsiochanUart->pcbGetTxChar = callbackRoute;
psamsungsiochanUart->pvGetTxArg = pvCallbackArg;
return (ERROR_NONE);
case SIO_CALLBACK_PUT_RCV_CHAR: /* 接收回電函數 */
psamsungsiochanUart->pcbPutRcvChar = callbackRoute;
psamsungsiochanUart->pvPutRcvArg = pvCallbackArg;
return (ERROR_NONE);
default:
_ErrorHandle(ENOSYS);
return (PX_ERROR);
}
}
/*********************************************************************************************************
** Function name: __uart485Delay
** Descriptions: uart1 485 模式軟延遲, 由於 485 收發器換向頻率限制, 所以在發送前後, 必須加入
軟件延遲, 此程序在 gcc -O3 -Os 測試通過
** input parameters: iTimes 延遲循環數量 (一般爲 40)
** output parameters: NONE
** Returned value: NONE
** Created by: Hanhui
** Created Date: 2007/09/24
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
**--------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
static VOID __uart485Delay (INT iTimes)
{
volatile int i;
for (; iTimes > 0; iTimes--) {
for (i = 0; i < 15; i++);
}
}
/*********************************************************************************************************
** Function name: __uartStartup
** Descriptions: SIO 通道發送(沒有使用中斷)
** input parameters: psiochanChan 通道
** output parameters: NONE
** Returned value: SIO 通道控制塊指針
** Created by: Hanhui
** Created Date: 2007/09/24
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
**--------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
static INT __uartStartup (SIO_CHAN *psiochanChan)
{
__PSAMSUNGSIO_CHANNEL psamsungsiochanUart = (__PSAMSUNGSIO_CHANNEL)psiochanChan;
CHAR cTx;
switch (psamsungsiochanUart->iChannelNum) {
case COM0:
INTER_CLR_SUBMSK(BIT_SUB_TXD0); /* 使能 FIFO 空中斷 */
break;
case COM1:
if (psamsungsiochanUart->iRs485Flag == RS485_EN) { /* 485 模式使用查詢發送方式 */
__COM1_RS485_SEND_START(); /* 485 換向(發送模式) */
__uart485Delay(40); /* 短延遲 */
do {
if (psamsungsiochanUart->pcbGetTxChar(psamsungsiochanUart->pvGetTxArg, &cTx)
!= ERROR_NONE) {
break; /* 發送完畢 */
}
while (rUFSTAT1 & (1 << 14)); /* FIFO 未滿 */
WrUTXH1(cTx); /* 發送數據 */
} while (1);
while ((rUTRSTAT1 & (1 << 2)) == 0); /* 等待發送緩衝器爲空 */
__COM1_RS485_SEND_END(); /* 485 換向(接收模式) */
__uart485Delay(40); /* 短延遲 */
} else { /* 全雙工模式採用中斷髮送 */
INTER_CLR_SUBMSK(BIT_SUB_TXD1); /* 使能 FIFO 空中斷 */
}
break;
case COM2:
INTER_CLR_SUBMSK(BIT_SUB_TXD2); /* 使能 FIFO 空中斷 */
break;
}
return (ERROR_NONE);
}
/*********************************************************************************************************
** Function name: __uartPollRxChar
** Descriptions: SIO 通道輪詢接收
** input parameters: psiochanChan 通道
** output parameters: pcInChar 接收的字節
** Returned value: 接收的個數
** Created by: Hanhui
** Created Date: 2007/09/24
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
**--------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
static INT __uartPollRxChar (SIO_CHAN *psiochanChan, PCHAR pcInChar)
{
__PSAMSUNGSIO_CHANNEL psamsungsiochanUart = (__PSAMSUNGSIO_CHANNEL)psiochanChan;
switch (psamsungsiochanUart->iChannelNum) {
case COM0:
if (rUFSTAT0 & __COM_FIFO_CNT_MASK) {
*pcInChar = RdURXH0();
} else {
_ErrorHandle(EAGAIN);
return (PX_ERROR);
}
break;
case COM1:
if (rUFSTAT1 & __COM_FIFO_CNT_MASK) {
*pcInChar = RdURXH1();
} else {
_ErrorHandle(EAGAIN);
return (PX_ERROR);
}
break;
case COM2:
if (rUFSTAT2 & __COM_FIFO_CNT_MASK) {
*pcInChar = RdURXH2();
} else {
_ErrorHandle(EAGAIN);
return (PX_ERROR);
}
break;
}
return (ERROR_NONE);
}
/*********************************************************************************************************
** Function name: __uartPollTxChar
** Descriptions: SIO 通道輪詢發送
** input parameters: psiochanChan 通道
** cOutChar 發送的字節
** output parameters: NONE
** Returned value: 發送的個數
** Created by: Hanhui
** Created Date: 2007/09/24
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
**--------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
static INT __uartPollTxChar (SIO_CHAN *psiochanChan, CHAR cOutChar)
{
__PSAMSUNGSIO_CHANNEL psamsungsiochanUart = (__PSAMSUNGSIO_CHANNEL)psiochanChan;
switch (psamsungsiochanUart->iChannelNum) {
case COM0:
while (rUFSTAT0 & (1 << 14)); /* FIFO 未滿 */
WrUTXH0(cOutChar); /* 發送數據 */
break;
case COM1:
while (rUFSTAT1 & (1 << 14)); /* FIFO 未滿 */
WrUTXH1(cOutChar); /* 發送數據 */
break;
case COM2:
while (rUFSTAT2 & (1 << 14)); /* FIFO 未滿 */
WrUTXH2(cOutChar); /* 發送數據 */
break;
}
return (ERROR_NONE);
}
/*********************************************************************************************************
** Function name: __uartIsr
** Descriptions: SIO 通道中斷處理函數
** input parameters: psiochanChan 通道
** output parameters: NONE
** Returned value: NONE
** Created by: Hanhui
** Created Date: 2007/09/24
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
**--------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
static irqreturn_t __uartIsr (SIO_CHAN *psiochanChan)
{
__PSAMSUNGSIO_CHANNEL psamsungsiochanUart = (__PSAMSUNGSIO_CHANNEL)psiochanChan;
UCHAR ucData;
switch (psamsungsiochanUart->iChannelNum) {
case COM0:
if (rSUBSRCPND & BIT_SUB_TXD0) {
INTER_CLR_SUBSRCPND(BIT_SUB_TXD0); /* 清除發送中斷 */
}
if (rSUBSRCPND & BIT_SUB_RXD0) {
INTER_CLR_SUBSRCPND(BIT_SUB_RXD0); /* 清除接收中斷 */
}
INTER_CLR_PNDING(BIT_UART0); /* 清除中斷標誌 */
while (((rUFSTAT0 >> 8) & __COM_FIFO_CNT_MASK) < __COM_FIFO_CNT) {
/* TxFIFO 未滿 */
if (psamsungsiochanUart->pcbGetTxChar(psamsungsiochanUart->pvGetTxArg,
(PCHAR)&ucData) != ERROR_NONE) { /* 發送結束 */
INTER_SET_SUBMSK(BIT_SUB_TXD0); /* 發送結束 */
break;
} else {
WrUTXH0(ucData); /* 發送數據 */
}
}
while (rUFSTAT0 & __COM_FIFO_CNT_MASK) { /* 需要接收數據 */
ucData = RdURXH0();
psamsungsiochanUart->pcbPutRcvChar(psamsungsiochanUart->pvPutRcvArg, ucData);
}
break;
case COM1:
if (rSUBSRCPND & BIT_SUB_TXD1) {
INTER_CLR_SUBSRCPND(BIT_SUB_TXD1); /* 清除發送中斷 */
}
if (rSUBSRCPND & BIT_SUB_RXD1) {
INTER_CLR_SUBSRCPND(BIT_SUB_RXD1); /* 清除接收中斷 */
}
INTER_CLR_PNDING(BIT_UART1); /* 清除中斷標誌 */
while (((rUFSTAT1 >> 8) & __COM_FIFO_CNT_MASK) < __COM_FIFO_CNT) {
/* TxFIFO 未滿 */
if (psamsungsiochanUart->pcbGetTxChar(psamsungsiochanUart->pvGetTxArg,
(PCHAR)&ucData) != ERROR_NONE) { /* 發送結束 */
INTER_SET_SUBMSK(BIT_SUB_TXD1); /* 發送結束 */
break;
} else {
WrUTXH1(ucData); /* 發送數據 */
}
}
while (rUFSTAT1 & __COM_FIFO_CNT_MASK) { /* 需要接收數據 */
ucData = RdURXH1();
psamsungsiochanUart->pcbPutRcvChar(psamsungsiochanUart->pvPutRcvArg, ucData);
}
break;
case COM2:
if (rSUBSRCPND & BIT_SUB_TXD2) {
INTER_CLR_SUBSRCPND(BIT_SUB_TXD2); /* 清除發送中斷 */
}
if (rSUBSRCPND & BIT_SUB_RXD2) {
INTER_CLR_SUBSRCPND(BIT_SUB_RXD2); /* 清除接收中斷 */
}
INTER_CLR_PNDING(BIT_UART2); /* 清除中斷標誌 */
while (((rUFSTAT2 >> 8) & __COM_FIFO_CNT_MASK) < __COM_FIFO_CNT) {
/* TxFIFO 未滿 */
if (psamsungsiochanUart->pcbGetTxChar(psamsungsiochanUart->pvGetTxArg,
(PCHAR)&ucData) != ERROR_NONE) { /* 發送結束 */
INTER_SET_SUBMSK(BIT_SUB_TXD2); /* 發送結束 */
break;
} else {
WrUTXH2(ucData); /* 發送數據 */
}
}
while (rUFSTAT2 & __COM_FIFO_CNT_MASK) { /* 需要接收數據 */
ucData = RdURXH2();
psamsungsiochanUart->pcbPutRcvChar(psamsungsiochanUart->pvPutRcvArg, ucData);
}
break;
}
return (LW_IRQ_HANDLED);
}
/*********************************************************************************************************
** Function name: __uartIoctl
** Descriptions: SIO 通道控制
** input parameters: psiochanChan 通道
** iCmd 命令
** lArg 參數
** output parameters: NONE
** Returned value: 命令執行結果
** Created by: Hanhui
** Created Date: 2007/09/24
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
**--------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
static INT __uartIoctl (SIO_CHAN *psiochanChan, INT iCmd, LONG lArg)
{
__PSAMSUNGSIO_CHANNEL psamsungsiochanUart = (__PSAMSUNGSIO_CHANNEL)psiochanChan;
UCHAR ucDataBits;
UCHAR ucStopBits;
UCHAR ucParity;
switch (iCmd) {
case SIO_BAUD_SET: /* 設置模特率 */
__uartHwOptionAnalyse(psamsungsiochanUart->iHwOption,
&ucDataBits,
&ucStopBits,
&ucParity); /* 獲得具體參數 */
uartInit(psamsungsiochanUart->iChannelNum, UNUSE_INF,
ucDataBits, ucStopBits,
ucParity, (INT)lArg, LW_NULL); /* 初始化串口 */
psamsungsiochanUart->iBaud = (INT)lArg;
break;
case SIO_BAUD_GET: /* 獲得波特率 */
*((LONG *)lArg) = psamsungsiochanUart->iBaud;
break;
case SIO_HW_OPTS_SET: /* 設置硬件參數 */
__uartHwOptionAnalyse((INT)lArg,
&ucDataBits,
&ucStopBits,
&ucParity); /* 獲得具體參數 */
uartInit(psamsungsiochanUart->iChannelNum, UNUSE_INF,
ucDataBits, ucStopBits,
ucParity, psamsungsiochanUart->iBaud, LW_NULL); /* 初始化串口 */
psamsungsiochanUart->iHwOption = (INT)lArg; /* 記錄信息 */
break;
case SIO_HW_OPTS_GET: /* 獲取硬件參數 */
*((INT *)lArg) = psamsungsiochanUart->iHwOption;
break;
case SIO_OPEN:
switch (psamsungsiochanUart->iChannelNum) {
case COM0:
pmDevOn(&psamsungsiochanUart->pmdev);
INTER_CLR_PNDING((1u << VIC_CHANNEL_UART0));
INTER_CLR_SUBMSK(BIT_SUB_RXD0); /* 打開接收中斷 */
API_InterVectorEnable(VIC_CHANNEL_UART0); /* 使能串口中斷 */
break;
case COM1:
pmDevOn(&psamsungsiochanUart->pmdev);
INTER_CLR_PNDING((1u << VIC_CHANNEL_UART1));
INTER_CLR_SUBMSK(BIT_SUB_RXD1); /* 打開接收中斷 */
API_InterVectorEnable(VIC_CHANNEL_UART1); /* 使能串口中斷 */
break;
case COM2:
pmDevOn(&psamsungsiochanUart->pmdev);
INTER_CLR_PNDING((1u << VIC_CHANNEL_UART2));
INTER_CLR_SUBMSK(BIT_SUB_RXD2); /* 打開接收中斷 */
API_InterVectorEnable(VIC_CHANNEL_UART2); /* 使能串口中斷 */
break;
}
break;
case SIO_HUP: /* 關閉串口 */
switch (psamsungsiochanUart->iChannelNum) {
case COM0:
pmDevOff(&psamsungsiochanUart->pmdev);
API_InterVectorDisable(VIC_CHANNEL_UART0);
INTER_CLR_PNDING((1u << VIC_CHANNEL_UART0));
break;
case COM1:
pmDevOff(&psamsungsiochanUart->pmdev);
API_InterVectorDisable(VIC_CHANNEL_UART1);
INTER_CLR_PNDING((1u << VIC_CHANNEL_UART1));
break;
case COM2:
pmDevOff(&psamsungsiochanUart->pmdev);
API_InterVectorDisable(VIC_CHANNEL_UART2);
INTER_CLR_PNDING((1u << VIC_CHANNEL_UART2));
break;
}
break;
case RS485_SET: /* 設置 485 狀態 */
if (psamsungsiochanUart->iChannelNum == COM1) {
psamsungsiochanUart->iRs485Flag = (INT)lArg;
if (lArg) {
rGPGCON = (rGPGCON & ~(0x3)) | (0x1); /* GPG0 輸出 */
BIT_CLR(rGPGUP, 0); /* 使能上拉 */
__COM1_RS485_SEND_END(); /* 結束髮送狀態 */
}
}
break;
case RS485_GET: /* 獲取 485 狀態 */
*((LONG *)lArg) = psamsungsiochanUart->iRs485Flag;
break;
default:
_ErrorHandle(ENOSYS);
return (ENOSYS);
}
return (ERROR_NONE);
}
/*********************************************************************************************************
END FILE
*********************************************************************************************************/
/*********************************************************************************************************
**
** 中國軟件開源組織
**
** 嵌入式實時操作系統
**
** SylixOS(TM)
**
** Copyright All Rights Reserved
**
**--------------文件信息--------------------------------------------------------------------------------
**
** 文 件 名: uart.h
**
** 創 建 人: Han.Hui (韓輝)
**
** 文件創建日期: 2007 年 09 月 20 日
**
** 描 述: uart 驅動.
*********************************************************************************************************/
#ifndef __UART_H
#define __UART_H
/*********************************************************************************************************
MACRO
*********************************************************************************************************/
#define COM0 0 /* 串口 0 */
#define COM1 1 /* 串口 1 */
#define COM2 2 /* 串口 2 */
#define CHK_ODD 0x4 /* 奇校驗 */
#define CHK_EVEN 0x5 /* 偶校驗 */
#define CHK_NONE 0x0 /* 沒有校驗 */
#define USE_INF 1 /* 使用紅外模式 */
#define UNUSE_INF 0 /* 不使用紅外模式 */
#define ONE_STOPBIT 0 /* 一個停止位 */
#define TWO_STOPBIT 1 /* 兩個停止位 */
/*********************************************************************************************************
** Function name: uartInit
** Descriptions: 初始化 UART
** input parameters: iCom 串口號
** iInFrared 是否使用紅外模式
** iData 數據位數
** iStopBit 結束位
** iCheck 校驗方法
** iBaud 波特率
** pvIsrRoutine 中斷服務函數, 爲NULL表示不允許中斷
** output parameters: NONE
** Returned value: 正確返回 0, 錯誤返回 -1
*********************************************************************************************************/
int uartInit(int iCom,
int iInFrared,
int iData,
int iStopBit,
int iCheck,
int iBaud,
void *pvIsrRoutine);
/*********************************************************************************************************
** Function name: uartSendByte
** Descriptions: UART 發送一個字節的數據
** input parameters: iCom 串口號
** ucData 數據
** output parameters: NONE
** Returned value: 正確返回 0, 錯誤返回 -1
*********************************************************************************************************/
int uartSendByte(int iCom, unsigned char ucData);
/*********************************************************************************************************
** Function name: uartSendByteCnt
** Descriptions: UART 發送指定長度的數據
** input parameters: iCom 串口號
** pucData 數據緩衝區
** output parameters: NONE
** Returned value: NONE
*********************************************************************************************************/
void uartSendByteCnt(int iCom,
unsigned char *pucData,
int iCnt);
/*********************************************************************************************************
** Function name: uartSendString
** Descriptions: UART 發送一個字符串
** input parameters: iCom 串口號
** pcData 字符串
** output parameters: NONE
** Returned value: NONE
*********************************************************************************************************/
void uartSendString(int iCom, char *pcData);
/*********************************************************************************************************
** Function name: debugChannelInit
** Descriptions: 初始化調試接口
** input parameters: iChannelNum 通道號
** output parameters: NONE
** Returned value: NONE
*********************************************************************************************************/
void debugChannelInit(int iChannelNum);
#endif /* __UART_H */
/*********************************************************************************************************
END FILE
*********************************************************************************************************/
/*********************************************************************************************************
**
** 中國軟件開源組織
**
** 嵌入式實時操作系統
**
** SylixOS(TM)
**
** Copyright All Rights Reserved
**
**--------------文件信息--------------------------------------------------------------------------------
**
** 文 件 名: uart.c
**
** 創 建 人: Han.Hui (韓輝)
**
** 文件創建日期: 2007 年 09 月 20 日
**
** 描 述: uart 驅動.
*********************************************************************************************************/
#define __SYLIXOS_KERNEL
#include "config.h"
#include "uart.h"
#include "SylixOS.h"
/*********************************************************************************************************
宏定義
*********************************************************************************************************/
#define __COM0_CLKBIT (1 << 10) /* COM0 在 CLKCON 中的位置 */
#define __COM1_CLKBIT (1 << 11) /* COM1 在 CLKCON 中的位置 */
#define __COM2_CLKBIT (1 << 12) /* COM2 在 CLKCON 中的位置 */
#define __COM0_GPIO ((1 << 2) | (1 << 3)) /* COM0 在 IO 口線中的位置 */
#define __COM1_GPIO ((1 << 4) | (1 << 5)) /* COM1 在 IO 口線中的位置 */
#define __COM2_GPIO ((1 << 6) | (1 << 7)) /* COM2 在 IO 口線中的位置 */
#define __COM0_GPHCON ((0x2 << 4) | (0x2 << 6)) /* COM0 在 GPHCON 中的設置 */
#define __COM1_GPHCON ((0x2 << 8) | (0x2 << 10)) /* COM1 在 GPHCON 中的設置 */
#define __COM2_GPHCON ((0x2 << 12) | (0x2 << 14)) /* COM1 在 GPHCON 中的設置 */
#define __COM0_MASK ((0x3 << 4) | (0x3 << 6)) /* COM0 在 GPHCON 中的區域 */
#define __COM1_MASK ((0x3 << 8) | (0x3 << 10)) /* COM1 在 GPHCON 中的區域 */
#define __COM2_MASK ((0x3 << 12) | (0x3 << 14)) /* COM2 在 GPHCON 中的區域 */
/*********************************************************************************************************
** Function name: uartInit
** Descriptions: 初始化 UART
** input parameters: iCom 串口號
** iInFrared 是否使用紅外模式
** iData 數據位數
** iStopBit 結束位
** iCheck 校驗方法
** iBaud 波特率
** pvIsrRoutine 中斷服務函數, 爲NULL表示不允許中斷
** output parameters: NONE
** Returned value: 正確返回 0, 錯誤返回 -1
** Created by: Hanhui
** Created Date: 2007/09/18
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
**--------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
int uartInit (int iCom,
int iInFrared,
int iData,
int iStopBit,
int iCheck,
int iBaud,
void *pvIsrRoutine)
{
unsigned int uiUBRDIVn; /* 波特率發生器值 */
unsigned int uiULCONn; /* 線控制器值 */
unsigned int uiUCONn; /* 串口控制寄存器值 */
unsigned int uiUFCONn; /* FIFO 控制寄存器值 */
unsigned int uiInterEn; /* 是否允許中斷 */
if (iData < 5) { /* 數據位數錯誤 */
return (-1);
}
iData -= 5; /* 確定寄存器中的值 */
uiInterEn = (pvIsrRoutine == (void *)0) ? 0 : 1; /* 確定是否需要中斷 */
iBaud = (iBaud << 4); /* baud = baud * 16 */
iBaud = PCLK / iBaud;
iBaud = (int)(iBaud - 0.5);
uiUBRDIVn = iBaud; /* 波特率 */
uiULCONn = ((iInFrared << 6)
| (iCheck << 3)
| (iStopBit << 2)
| (iData)); /* 基本控制信息 */
uiUCONn = ((0x00 << 10) /* PCLK */
| (1 << 9) /* Tx Interrupt Type LEVEL */
| (1 << 8) /* Rx Interrupt Type LEVEL */
| (1 << 7) /* Rx Time Out Enable */
| (0 << 6) /* Rx Error Status */
/* Interrupt Disable */
| (0 << 5) /* Loopback Mode Disable */
| (0 << 4)
| (1 << 2) /* Tx Interrupt or poll */
| (1)); /* Rx Interrupt or poll */
uiUFCONn = ((0x0 << 6) /* Tx FIFO Trigger Level 0 */
| (0x2 << 4) /* Rx FIFO Trigger Level 16 */
| (1 << 2) /* Tx FIFO Reset */
| (1 << 1) /* Rx FIFO Reset */
| (1)); /* FIFO Enable */
if (iCom == COM0) { /* 設置 UART0 的 管腳 */
rGPHCON &= ~(__COM0_MASK);
rGPHCON |= __COM0_GPHCON;
rGPHUP &= ~(__COM0_GPIO); /* 使用上拉電阻 */
rCLKCON |= __COM0_CLKBIT; /* 時鐘掛接 */
rUCON0 = 0;
rUFCON0 = uiUFCONn;
rUMCON0 = 0; /* 關閉流控 */
rULCON0 = uiULCONn;
rUCON0 = uiUCONn;
rUBRDIV0 = uiUBRDIVn;
if (uiInterEn) { /* 鏈接中斷服務函數 */
API_InterVectorConnect(VIC_CHANNEL_UART0,
(PINT_SVR_ROUTINE)pvIsrRoutine,
LW_NULL,
"uart0_isr");
INTER_CLR_MSK((1u << VIC_CHANNEL_UART0)); /* 解除屏蔽中斷 */
INTER_CLR_SUBMSK(BIT_SUB_RXD0); /* 打開接收中斷 */
}
} else if (iCom == COM1) { /* 設置 UART1 的 管腳 */
rGPHCON &= ~(__COM1_MASK);
rGPHCON |= __COM1_GPHCON;
rGPHUP &= ~(__COM1_GPIO); /* 使用上拉電阻 */
rCLKCON |= __COM1_CLKBIT; /* 時鐘掛接 */
rUCON1 = 0;
rUFCON1 = uiUFCONn;
rUMCON1 = 0; /* 關閉流控 */
rULCON1 = uiULCONn;
rUCON1 = uiUCONn;
rUBRDIV1 = uiUBRDIVn;
if (uiInterEn) { /* 鏈接中斷服務函數 */
API_InterVectorConnect(VIC_CHANNEL_UART1,
(PINT_SVR_ROUTINE)pvIsrRoutine,
LW_NULL,
"uart1_isr");
INTER_CLR_MSK((1u << VIC_CHANNEL_UART1)); /* 解除屏蔽中斷 */
INTER_CLR_SUBMSK(BIT_SUB_RXD1); /* 打開接收中斷 */
}
} else if (iCom == COM2) { /* 設置 UART2 的 管腳 */
rGPHCON &= ~(__COM2_MASK);
rGPHCON |= __COM2_GPHCON;
rGPHUP &= ~(__COM2_GPIO); /* 使用上拉電阻 */
rCLKCON |= __COM2_CLKBIT; /* 時鐘掛接 */
rUCON2 = 0;
rUFCON2 = uiUFCONn;
rUMCON2 = 0; /* 關閉流控 */
rULCON2 = uiULCONn;
rUCON2 = uiUCONn;
rUBRDIV2 = uiUBRDIVn;
if (uiInterEn) { /* 鏈接中斷服務函數 */
API_InterVectorConnect(VIC_CHANNEL_UART2,
(PINT_SVR_ROUTINE)pvIsrRoutine,
LW_NULL,
"uart2_isr");
INTER_CLR_MSK((1u << VIC_CHANNEL_UART2)); /* 解除屏蔽中斷 */
INTER_CLR_SUBMSK(BIT_SUB_RXD2); /* 打開接收中斷 */
}
} else { /* 串口出錯 */
return (-1);
}
return (0);
}
/*********************************************************************************************************
** Function name: uartSendByte
** Descriptions: UART 發送一個字節的數據
** input parameters: iCom 串口號
** ucData 數據
** output parameters: NONE
** Returned value: 正確返回 0, 錯誤返回 -1
** Created by: Hanhui
** Created Date: 2007/09/18
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
**--------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
int uartSendByte (int iCom, unsigned char ucData)
{
switch (iCom) {
case COM0:
while (rUFSTAT0 & (1 << 14));
while (((rUFSTAT0) >> 8) & 0x3F); /* Tx_FIFO IS EMPTY */
WrUTXH0(ucData);
break;
case COM1:
while (rUFSTAT1 & (1 << 14));
while (((rUFSTAT1) >> 8) & 0x3F); /* Tx_FIFO IS EMPTY */
WrUTXH1(ucData);
break;
case COM2:
while (rUFSTAT2 & (1 << 14));
while (((rUFSTAT2) >> 8) & 0x3F); /* Tx_FIFO IS EMPTY */
WrUTXH2(ucData);
break;
default: /* 串口號錯誤 */
return (1);
}
return (0);
}
/*********************************************************************************************************
** Function name: uartSendByteCnt
** Descriptions: UART 發送指定長度的數據
** input parameters: iCom 串口號
** pucData 數據緩衝區
** output parameters: NONE
** Returned value: NONE
** Created by: Hanhui
** Created Date: 2007/09/18
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
**--------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
void uartSendByteCnt (int iCom,
unsigned char *pucData,
int iCnt)
{
for (; iCnt != 0; iCnt--) {
uartSendByte(iCom, *pucData); /* 發送數據 */
pucData++;
}
}
/*********************************************************************************************************
** Function name: uartSendString
** Descriptions: UART 發送一個字符串
** input parameters: iCom 串口號
** pcData 字符串
** output parameters: NONE
** Returned value: NONE
** Created by: Hanhui
** Created Date: 2007/09/18
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
**--------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
void uartSendString (int iCom, char *pcData)
{
if (!pcData) { /* 指針爲空 */
return;
}
while (*pcData != '\0') { /* 發送字符串 */
uartSendByte(iCom, (unsigned char)*pcData);
pcData++;
}
}
/*********************************************************************************************************
** Function name: debugChannelInit
** Descriptions: 初始化調試接口
** input parameters: iChannelNum 通道號
** output parameters: NONE
** Returned value: NONE
** Created by: Hanhui
** Created Date: 2007/09/24
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
**--------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
void debugChannelInit (int iChannelNum)
{
uartInit(iChannelNum, UNUSE_INF, 8, ONE_STOPBIT, CHK_NONE, 115200, (void *)0);
}
/*********************************************************************************************************
END FILE
*********************************************************************************************************/