/*********************************************************************************************************
**
** 中国软件开源组织
**
** 嵌入式实时操作系统
**
** SylixOS(TM) LW : long wing
**
** Copyright All Rights Reserved
**
**--------------文件信息--------------------------------------------------------------------------------
**
** 文 件 名: sio.c
**
** 创 建 人: HouJinYu (侯进宇)
**
** 文件创建日期: 2017 年 12 月 15 日
**
** 描 述: SIO 驱动.
*********************************************************************************************************/
#define __SYLIXOS_KERNEL
#define __SYLIXOS_STDIO
#include "config.h"
#include "SylixOS.h"
#include "fsl_common.h"
#include "fsl_iomuxc.h"
#include "fsl_lpuart.h"
#include "clk/clk.h"
#include "sio/sio.h"
#include "pinmux/pinmux.h"
/*********************************************************************************************************
宏定义
*********************************************************************************************************/
#define LPUART_BAUD (SIO_BAUD_115200) /* 缺省波特率 */
#define LPUART_OPT (CREAD | CS8) /* 缺省选项 */
#define LPUART_NUM (8) /* 串口通道数量 */
#define GETTXCHAR(pChar) pLpuartSioChan->SIOCHAN_pcbGetTxChar(pLpuartSioChan->SIOCHAN_pvGetTxArg, pChar)
/*********************************************************************************************************
LPUART SIO 通道控制块类型定义
SIO_CHAN 结构只有一项 (SIO_DRV_FUNCS *),而 LPUART_SIOCHAN 的第一项同样为 (SIO_DRV_FUNCS *)
所以 LPUART_SIOCHAN 为 SIO_CHAN 的子类
*********************************************************************************************************/
typedef struct {
SIO_DRV_FUNCS *SIOCHAN_pDrvFuncs; /* 必须为第一项 */
INT SIOCHAN_iChan; /* 通道号 */
LPUART_Type *SIOCHAN_pBase; /* 寄存器基址 */
ULONG SIOCHAN_ulVector; /* 向量号 */
INT SIOCHAN_iBaud; /* 波特率 */
INT SIOCHAN_iHwOption; /* 硬件选项 */
INT (*SIOCHAN_pcbGetTxChar)(); /* 发送中断回调函数 */
INT (*SIOCHAN_pcbPutRcvChar)(); /* 接收中断回调函数 */
PVOID SIOCHAN_pvGetTxArg; /* 发送回调函数参数 */
PVOID SIOCHAN_pvPutRcvArg; /* 接收回调函数参数 */
INT SIOCHAN_iTxFifoSize; /* 发送缓存大小 */
INT SIOCHAN_iRxFifoSize; /* 接收缓存大小 */
} LPUART_SIOCHAN;
/*********************************************************************************************************
** 函数名称: __sioIsr
** 功能描述: lpuart 中断响应函数
** 输 入 : pvArg 网络结构
** ulVector 中断号
** 输 出 : 错误号
*********************************************************************************************************/
static irqreturn_t __sioIsr (PVOID pvArg, ULONG ulVector)
{
LPUART_SIOCHAN *pLpuartSioChan = (LPUART_SIOCHAN *)pvArg;
LPUART_Type *pBase = pLpuartSioChan->SIOCHAN_pBase;
CHAR cChar;
/*
* RXFIFO非空,读出FIFO中的数据
*/
while (!(kLPUART_RxFifoEmptyFlag & LPUART_GetStatusFlags(pBase))) {
cChar = LPUART_ReadByte(pBase);
pLpuartSioChan->SIOCHAN_pcbPutRcvChar(pLpuartSioChan->SIOCHAN_pvPutRcvArg, cChar);
}
/*
* 发送完成中断,Txfifo 已空,无可发数据则关闭中断,有数据则装填 FIFO
*/
if (kLPUART_TransmissionCompleteFlag & LPUART_GetStatusFlags(pBase)) {
if (GETTXCHAR(&cChar) == ERROR_NONE) {
do {
LPUART_WriteByte(pBase, cChar);
} while ((kLPUART_TxDataRegEmptyFlag & LPUART_GetStatusFlags(pBase)) &&
(GETTXCHAR(&cChar) == ERROR_NONE));
} else {
LPUART_DisableInterrupts(pBase, kLPUART_TransmissionCompleteInterruptEnable);
}
}
/*
* 清除中断
*/
LPUART_ClearStatusFlags(pBase, 0xffffffff);
return (LW_IRQ_HANDLED);
}
/*********************************************************************************************************
** 函数名称: __sioConfig
** 功能描述: 配置 SIO 通道
** 输 入 : pLpuartSioChan lpuart 结构
** 输 出 : ERROR CODE
*********************************************************************************************************/
static INT __sioConfig (LPUART_SIOCHAN *pLpuartSioChan)
{
lpuart_config_t lpuart_config;
LPUART_GetDefaultConfig(&lpuart_config); /* 将初始化结构填为默认值 */
lpuart_config.baudRate_Bps = pLpuartSioChan->SIOCHAN_iBaud; /* 设置波特率 */
if (pLpuartSioChan->SIOCHAN_iHwOption & PARENB) { /* 设置校验位 */
if (pLpuartSioChan->SIOCHAN_iHwOption & PARODD) {
lpuart_config.parityMode = kLPUART_ParityOdd;
} else {
lpuart_config.parityMode = kLPUART_ParityEven;
}
} else {
lpuart_config.parityMode = kLPUART_ParityDisabled;
}
if ((pLpuartSioChan->SIOCHAN_iHwOption & CSIZE) == CS8) { /* 设置数据位 */
lpuart_config.dataBitsCount = kLPUART_EightDataBits;
} else if ((pLpuartSioChan->SIOCHAN_iHwOption & CSIZE) == CS7) {
lpuart_config.dataBitsCount = kLPUART_SevenDataBits;
} else {
return (PX_ERROR);
}
if (pLpuartSioChan->SIOCHAN_iHwOption & STOPB) { /* 设置停止位 */
lpuart_config.stopBitCount = kLPUART_TwoStopBit;
} else {
lpuart_config.stopBitCount = kLPUART_OneStopBit;
}
lpuart_config.txFifoWatermark = pLpuartSioChan->SIOCHAN_iTxFifoSize - 1;
lpuart_config.rxFifoWatermark = pLpuartSioChan->SIOCHAN_iRxFifoSize - 1;
lpuart_config.rxIdleType = kLPUART_IdleTypeStopBit;
lpuart_config.rxIdleConfig = kLPUART_IdleCharacter1;
lpuart_config.enableTx = true;
lpuart_config.enableRx = true;
LPUART_Init(pLpuartSioChan->SIOCHAN_pBase, &lpuart_config, clkLpuartClkGet());
/*
* enables the assertion of RDRF when the receiver is idle for a number of idle characters and
* the FIFO is not empty
*/
pLpuartSioChan->SIOCHAN_pBase->FIFO |= 0x01 << 10;
/*
* LPUART_Init 函数中有硬件复位操作会清除中断使能,所以中断使能要放在LPUART_Init后面
*/
LPUART_EnableInterrupts(pLpuartSioChan->SIOCHAN_pBase, kLPUART_RxDataRegFullInterruptEnable);
return (ERROR_NONE);
}
/*********************************************************************************************************
** 函数名称: __sioOpen
** 功能描述: 打开 SIO 通道
** 输 入 : pLpuartSioChan lpuart 结构
** 输 出 : ERROR CODE
*********************************************************************************************************/
static INT __sioOpen (LPUART_SIOCHAN *pLpuartSioChan)
{
const INT iFifoSize[] = {1, 4, 8, 16, 32, 64, 128, 256};
LPUART_Type *pBase = pLpuartSioChan->SIOCHAN_pBase;
CHAR cName[] = "lpuart_0";
pLpuartSioChan->SIOCHAN_iTxFifoSize = iFifoSize[(pBase->FIFO >> 4) & 0x07];
pLpuartSioChan->SIOCHAN_iRxFifoSize = iFifoSize[(pBase->FIFO >> 0) & 0x07];
pinmuxLpuartEnable(pLpuartSioChan->SIOCHAN_iChan);
__sioConfig(pLpuartSioChan);
API_InterVectorSetPriority(pLpuartSioChan->SIOCHAN_ulVector, 0xe);
cName[7] += pLpuartSioChan->SIOCHAN_iChan;
API_InterVectorConnect(pLpuartSioChan->SIOCHAN_ulVector,
(PINT_SVR_ROUTINE)__sioIsr,
(PVOID)pLpuartSioChan,
cName);
API_InterVectorEnable(pLpuartSioChan->SIOCHAN_ulVector);
return (ERROR_NONE);
}
/*********************************************************************************************************
** 函数名称: __sioHup
** 功能描述: 挂起 SIO 通道
** 输 入 : pLpuartSioChan lpuart 结构
** 输 出 : ERROR CODE
*********************************************************************************************************/
static INT __sioHup (LPUART_SIOCHAN *pLpuartSioChan)
{
LPUART_Deinit(pLpuartSioChan->SIOCHAN_pBase);
API_InterVectorDisable(pLpuartSioChan->SIOCHAN_ulVector); /* Disable Vector */
API_InterVectorDisconnect(pLpuartSioChan->SIOCHAN_ulVector,
(PINT_SVR_ROUTINE)__sioIsr,
(PVOID)pLpuartSioChan);
return (ERROR_NONE);
}
/*********************************************************************************************************
** 函数名称: __ioctl
** 功能描述: SIO 通道控制
** 输 入 : pSioChan SIO 通道
** iCmd 命令
** lArg 参数
** 输 出 : ERROR_CODE
*********************************************************************************************************/
static INT __ioctl (SIO_CHAN *pSioChan, INT iCmd, PVOID pArg)
{
LPUART_SIOCHAN *pLpuartSioChan = (LPUART_SIOCHAN *)pSioChan;
switch (iCmd) {
case SIO_OPEN: /* 打开串口 */
__sioOpen(pLpuartSioChan);
break;
case SIO_HUP: /* 关闭串口 */
__sioHup(pLpuartSioChan);
break;
case SIO_BAUD_SET: /* 设置波特率 */
pLpuartSioChan->SIOCHAN_iBaud = (INT)pArg; /* 记录波特率 */
__sioConfig(pLpuartSioChan);
break;
case SIO_BAUD_GET: /* 获得波特率 */
*((LONG *)pArg) = pLpuartSioChan->SIOCHAN_iBaud;
break;
case SIO_HW_OPTS_SET: /* 设置硬件参数 */
pLpuartSioChan->SIOCHAN_iHwOption = (INT)pArg; /* 记录硬件参数 */
__sioConfig(pLpuartSioChan);
break;
case SIO_HW_OPTS_GET: /* 获取硬件参数 */
*((LONG *)pArg) = pLpuartSioChan->SIOCHAN_iHwOption;
break;
default:
_ErrorHandle(ENOSYS);
return (PX_ERROR);
}
return (ERROR_NONE);
}
/*********************************************************************************************************
** 函数名称: __txStartup
** 功能描述: SIO 通道发送(没有使用中断)
** 输 入 : pSioChan SIO 通道
** 输 出 : ERROR_CODE
*********************************************************************************************************/
static INT __txStartup (SIO_CHAN *pSioChan)
{
LPUART_SIOCHAN *pLpuartSioChan = (LPUART_SIOCHAN *)pSioChan;
LPUART_Type *pBase = pLpuartSioChan->SIOCHAN_pBase;
CHAR cChar;
if (!(kLPUART_TransmissionCompleteInterruptEnable & LPUART_GetEnabledInterrupts(pBase))) {
if (GETTXCHAR(&cChar) == ERROR_NONE) {
LPUART_WriteByte(pBase, cChar);
}
LPUART_EnableInterrupts(pBase, kLPUART_TransmissionCompleteInterruptEnable);
}
return (ERROR_NONE);
}
/*********************************************************************************************************
** 函数名称: __callbackInstall
** 功能描述: SIO 通道安装回调函数
** 输 入 : pSioChan SIO 通道
** iCallbackType 回调类型
** callbackRoute 回调函数
** pvCallbackArg 回调参数
** 输 出 : ERROR_CODE
*********************************************************************************************************/
static INT __callbackInstall (SIO_CHAN *pSioChan,
INT iCallbackType,
VX_SIO_CALLBACK callbackRoute,
PVOID pvCallbackArg)
{
LPUART_SIOCHAN *pLpuartSioChan = (LPUART_SIOCHAN *)pSioChan;
switch (iCallbackType) {
case SIO_CALLBACK_GET_TX_CHAR: /* 发送回调函数 */
pLpuartSioChan->SIOCHAN_pcbGetTxChar = callbackRoute;
pLpuartSioChan->SIOCHAN_pvGetTxArg = pvCallbackArg;
return (ERROR_NONE);
case SIO_CALLBACK_PUT_RCV_CHAR: /* 接收回调函数 */
pLpuartSioChan->SIOCHAN_pcbPutRcvChar = callbackRoute;
pLpuartSioChan->SIOCHAN_pvPutRcvArg = pvCallbackArg;
return (ERROR_NONE);
default:
_ErrorHandle(ENOSYS);
return (PX_ERROR);
}
}
/*********************************************************************************************************
** 函数名称: __pollInput
** 功能描述: SIO 通道轮询接收
** 输 入 : pSioChan SIO 通道
** pcInChar 接收的字节
** 输 出 : ERROR_CODE
*********************************************************************************************************/
static INT __pollInput (SIO_CHAN *pSioChan, PCHAR pcInChar)
{
LPUART_SIOCHAN *pLpuartSioChan = (LPUART_SIOCHAN *)pSioChan;
LPUART_Type *pBase = pLpuartSioChan->SIOCHAN_pBase;
if (kLPUART_RxDataRegFullFlag & LPUART_GetStatusFlags(pBase)) {
*pcInChar = LPUART_ReadByte(pBase);
return (ERROR_NONE);
} else {
return (PX_ERROR);
}
}
/*********************************************************************************************************
** 函数名称: __pollOutput
** 功能描述: SIO 通道轮询发送
** 输 入 : pSioChan SIO 通道
** cOutChar 发送的字节
** 输 出 : ERROR_CODE
*********************************************************************************************************/
static INT __pollOutput (SIO_CHAN *pSioChan, CHAR cOutChar)
{
LPUART_SIOCHAN *pLpuartSioChan = (LPUART_SIOCHAN *)pSioChan;
LPUART_Type *pBase = pLpuartSioChan->SIOCHAN_pBase;
while (!(kLPUART_TxDataRegEmptyFlag & LPUART_GetStatusFlags(pBase))) {
}
LPUART_WriteByte(pBase, cOutChar);
return (ERROR_NONE);
}
/*********************************************************************************************************
UART SIO 驱动程序
*********************************************************************************************************/
/*********************************************************************************************************
** 函数名称: sioChanCreate
** 功能描述: 创建一个 SIO 通道
** 输 入 : uiChannel UART 通道号
** 输 出 : SIO 通道
*********************************************************************************************************/
SIO_CHAN *sioChanCreate (UINT uiChannel)
{
static SIO_DRV_FUNCS sioDrvFuncs = {
.ioctl = __ioctl,
.txStartup = __txStartup,
.callbackInstall = __callbackInstall,
.pollInput = __pollInput,
.pollOutput = __pollOutput,
};
static LPUART_SIOCHAN lpuartSioChan[LPUART_NUM] = {
{
.SIOCHAN_pDrvFuncs = &sioDrvFuncs,
.SIOCHAN_iChan = 0,
.SIOCHAN_pBase = LPUART1,
.SIOCHAN_ulVector = BSP_IRQ_TO_VECTOR(LPUART1_IRQn),
.SIOCHAN_iBaud = LPUART_BAUD,
.SIOCHAN_iHwOption = LPUART_OPT,
},
{
.SIOCHAN_pDrvFuncs = &sioDrvFuncs,
.SIOCHAN_iChan = 1,
.SIOCHAN_pBase = LPUART2,
.SIOCHAN_ulVector = BSP_IRQ_TO_VECTOR(LPUART2_IRQn),
.SIOCHAN_iBaud = LPUART_BAUD,
.SIOCHAN_iHwOption = LPUART_OPT,
},
{
.SIOCHAN_pDrvFuncs = &sioDrvFuncs,
.SIOCHAN_iChan = 2,
.SIOCHAN_pBase = LPUART3,
.SIOCHAN_ulVector = BSP_IRQ_TO_VECTOR(LPUART3_IRQn),
.SIOCHAN_iBaud = LPUART_BAUD,
.SIOCHAN_iHwOption = LPUART_OPT,
},
{
.SIOCHAN_pDrvFuncs = &sioDrvFuncs,
.SIOCHAN_iChan = 3,
.SIOCHAN_pBase = LPUART4,
.SIOCHAN_ulVector = BSP_IRQ_TO_VECTOR(LPUART4_IRQn),
.SIOCHAN_iBaud = LPUART_BAUD,
.SIOCHAN_iHwOption = LPUART_OPT,
},
{
.SIOCHAN_pDrvFuncs = &sioDrvFuncs,
.SIOCHAN_iChan = 4,
.SIOCHAN_pBase = LPUART5,
.SIOCHAN_ulVector = BSP_IRQ_TO_VECTOR(LPUART5_IRQn),
.SIOCHAN_iBaud = LPUART_BAUD,
.SIOCHAN_iHwOption = LPUART_OPT,
},
{
.SIOCHAN_pDrvFuncs = &sioDrvFuncs,
.SIOCHAN_iChan = 5,
.SIOCHAN_pBase = LPUART6,
.SIOCHAN_ulVector = BSP_IRQ_TO_VECTOR(LPUART6_IRQn),
.SIOCHAN_iBaud = LPUART_BAUD,
.SIOCHAN_iHwOption = LPUART_OPT,
},
{
.SIOCHAN_pDrvFuncs = &sioDrvFuncs,
.SIOCHAN_iChan = 6,
.SIOCHAN_pBase = LPUART7,
.SIOCHAN_ulVector = BSP_IRQ_TO_VECTOR(LPUART7_IRQn),
.SIOCHAN_iBaud = LPUART_BAUD,
.SIOCHAN_iHwOption = LPUART_OPT,
},
{
.SIOCHAN_pDrvFuncs = &sioDrvFuncs,
.SIOCHAN_iChan = 7,
.SIOCHAN_pBase = LPUART8,
.SIOCHAN_ulVector = BSP_IRQ_TO_VECTOR(LPUART8_IRQn),
.SIOCHAN_iBaud = LPUART_BAUD,
.SIOCHAN_iHwOption = LPUART_OPT,
},
};
if (uiChannel >= LPUART_NUM) {
return (LW_NULL); /* 通道号错误 */
}
return ((SIO_CHAN *)(&lpuartSioChan[uiChannel]));
}
/*********************************************************************************************************
END
*********************************************************************************************************/
sylixos下imxrt1050串口驱动实现
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.