📄 sc16is752.c
字号:
/****************************************************************************
*
* Copyrigth(C), 2002-2005,Sanxing Tech,Co.,Ltd.
* Filename: sc16is752.c
* Version: V1.0
* Description: sc16is752 drive.
*
modification history
---------------------
* $Log: sc16is752.c,v $
* Revision 1.1 2006/10/13 04:23:54 zlm
* 增加F16R16的bsp
*
* Revision 1.1 2006/10/13 04:13:18 zlm
* 增加F8R16的bsp
*
* Revision 1.11 2006/09/18 12:32:51 zlm
* 将常用函数接口分开(extern)
*
* Revision 1.10 2006/09/13 13:27:54 zlm
* 增加taskUnlock() 和tasklock() 来保护spi对各个芯片寄存器的读写
*
* Revision 1.9 2006/09/09 01:58:35 zlm
* 根据最新硬件修改
*
* Revision 1.8 2006/09/06 06:56:31 zlm
* 修改sc16is752中断序号
*
* Revision 1.7 2006/09/05 05:03:38 zlm
* 整理对io的设置
*
* Revision 1.6 2006/09/04 14:01:40 zlm
* 修改一个bug!
*
* Revision 1.5 2006/09/04 06:23:42 zlm
* 修改一个warning!
*
* Revision 1.4 2006/09/01 09:27:54 zlm
* 全面调试通过
*
* Revision 1.3 2006/08/31 02:56:00 zlm
* sc16is752的spi模式修改
*
* Revision 1.2 2006/08/31 02:46:37 zlm
* 修改sc16is752驱动
*
* Revision 1.1 2006/08/24 09:02:26 zlm
* 添加sc16is752驱动
*
*
*******************************************************************************/
/*------------------------------------------------------------------------------
Section: Includes
------------------------------------------------------------------------------*/
#include <vxworks.h>
#include <taskLib.h>
#include <semLib.h>
#include <rngLib.h>
#include <sioLib.h>
#include <ioLib.h>
#include <timers.h>
#include "sc16is752.h"
#include "ppc860spi.h"
/*------------------------------------------------------------------------------
Section: Constant Definitions
------------------------------------------------------------------------------*/
/* Register Address */
/* ----------- Special register ------------- */
#define THR 0x00 /* Transmit Holding Register */
#define RHR 0x00 /* Receive Holding Register */
#define IER 0x01 /* Interrupt Enable Register */
#define FCR 0x02 /* FIFO Control Register */
#define IIR 0x02 /* Interrupt Identification Register */
#define LCR 0x03 /* Line Control Register */
#define S_MCR 0x04 /* Modem Control Register */
#define LSR 0x05 /* Line Status Register */
#define MSR 0x06 /* Modem Status Register */
#define SPR 0x07 /* Scratchpad Register */
#define TCR 0x06 /* Transmission Control Register */
#define TLR 0x07 /* Trigger Level Register */
#define TXLVL 0x08 /* Transmit FIFO Level Register */
#define RXLVL 0x09 /* Receive FIFO Level Register */
#define IODir 0x0A /* I/O pin Direction Register */
#define IOState 0x0B /* I/O pin States Register */
#define IOIntEna 0x0C /* I/O Interrupt Enable Register */
#define IOControl 0x0D /* I/O Interrupt Enable Register */
#define EFCR 0x0F /* Extra Features Control Register (EFCR) */
/* ----------- Special register ------------- */
#define DLL 0x00 /* Divisor Latch LSB */
#define DLH 0x01 /* Divisor Latch MSB */
/* ----------- Special register ------------- */
#define EFR 0x02 /* Enhanced Feature Register */
#define Xon1 0x04 /* Xon1 word */
#define Xon2 0x05 /* Xon2 word */
#define Xoff1 0x06 /* Xoff1 word */
#define Xoff2 0x07 /* Xoff2 word */
#define SC16IS752_FIFO_NUM 64 /* FIFO length */
#define SPI_EN_SC16IS752 spi_cs(CS_SC16IS752, CS_ON) /* 片选SX2132 */
#define SPI_UNEN_SC16IS752 spi_cs(CS_SC16IS752, CS_OFF) /* 取消片选SX2132 */
#define TASK_PRIORITY_SC16IS752 51
#ifndef SETBITS
#define SETBITS(x,y,n) (x) = (n) ? ((x)|(1 << (y))) : ((x) &(~(1 << (y))))/* 设置某一位为n */
#endif
#ifndef BITS
#define BITS(x,y) (((x)>>(y))&0x01) /* 判断某位是否为1 */
#endif
#ifndef BCD2HEX
#define BCD2HEX(x) (((x) >> 4) * 10 + ((x) & 0x0F)) /*20H -> 20*/
#endif
#ifndef HEX2BCD
#define HEX2BCD(x) (((x) % 10) + ((((x) / 10) % 10) << 4)) /*20 -> 20H*/
#endif
#define SC16IS752_IRQ_ID 3/*5*/ /* Spi interrupt number */
#define MAX_IN_IO_NUM 8 /* in io count */
/* Channel Type */
#define CHANNEL_TYPE_A 0x00
#define CHANNEL_TYPE_B 0x01
#define CHANNEL_TYPE_NULL 0x02
#ifndef IO_LOW
#define IO_LOW 0
#endif
#ifndef IO_HIGH
#define IO_HIGH 1
#endif
/*------------------------------------------------------------------------------
Section: Type Definitions
------------------------------------------------------------------------------*/
typedef struct sc16is752Dev { /* sc16is752_DEV */
DEV_HDR devHdr; /* equipment header struct */
int devId; /* equipment id */
BOOL created; /* TRUE if this device has been created */
BOOL opened; /* TRUE if this device has been opened */
uchar moder_LCR; /* uart moder register[LCR] */
uchar moder_DLL; /* uart moder register[DLL] */
uchar moder_DLH; /* uart moder register[DLH] */
uchar efcrReg; /* Extra Features Control Register (EFCR) */
uchar fcrReg; /* trigger register */
SEM_ID syncSem; /* use binary semaphore to block the read serila task */
RING_ID rngRxBuf; /* receive buffer ring */
SEL_WAKEUP_LIST selWakeupList; /* select functions */
} SC16IS752_DEV;
/* 寄存器定义 */
typedef struct sc16is752_REG {
unsigned char IoDir; /* gpio direction */
unsigned char IoState; /* gpio pin state */
}T_SC16IS752_REG;
typedef struct sc16is752_io_event { /* T_SC16IS752_IO_EVENT */
int nInNo; /* IO编号 */
VOIDFUNCPTR pUpFunc; /* 指定IO发生上升延变化时执行的函数指针 */
VOIDFUNCPTR pDownFunc; /* 指定IO发生下降延变化时执行的函数指针 */
int iUpArg; /* 事件函数的参数*/
int iDownArg; /* 事件函数的参数*/
}T_SC16IS752_IO_EVENT;
/*------------------------------------------------------------------------------
Section: Local Variable
------------------------------------------------------------------------------*/
LOCAL SEM_ID s_semSc16is752irqTask;
LOCAL int sc16is752DrvNum[2]={0,0}; /* driver number assigned to this driver */
LOCAL SC16IS752_DEV sc16is752Dev [2]; /* char equipment array */
LOCAL T_SC16IS752_REG sc16is752Reg; /* sc16is752 io registe */
LOCAL T_SC16IS752_IO_EVENT s_sc16is752IoEvent[MAX_IN_IO_NUM];
/*------------------------------------------------------------------------------
Section: Local Function Prototypes
------------------------------------------------------------------------------*/
LOCAL int sc16is752Open (SC16IS752_DEV * pSc16is752Dev,char *name,int mode);
LOCAL int sc16is752Close (int sc16is752DevId);
LOCAL int sc16is752Read (int sc16is752DevId,char * buffer,size_t maxbytes);
LOCAL int sc16is752Write(int sc16is752DevId, char * buffer, size_t nbytes);
LOCAL int sc16is752Ioctl(int sc16is752DevId, int function, int arg);
LOCAL void sc16is752IrqSR(void);
LOCAL void sc16is752irqTask(void);
LOCAL void disposeGpioEvent(void);
LOCAL void readSerialData(uchar channel);
void writeReg(uchar regAddr, uchar channel, uchar regValue);
uchar readReg(uchar regAddr, uchar channel);
void writeData(uchar regAddr, uchar channel, uchar *buf, int len);
LOCAL void sc16isInit(void);
/*------------------------------------------------------------------------------
Section: Function Definitions
------------------------------------------------------------------------------*/
/*******************************************************************************
*
* sc16is752Drv - initialize the sc16is752 serial ports driver
*
* This routine initializes the sc16is752 serial ports driver,
* performs hardware initialization of the sc16is752 serial ports.
*
* This routine should be called exactly once, before any reads, writes,
* or calls to sc16is752DevCreate(). Normally, it is called by usrRoot()
* in usrConfig.c.
*
* RETURNS: OK, or ERROR if the driver cannot be installed.
*
* SEE ALSO: sc16is752DevCreate()
*/
extern STATUS sc16is752Drv(void)
{
int ix;
s_semSc16is752irqTask = semBCreate(SEM_Q_FIFO, SEM_EMPTY);/* synchronization semaphore */
irqEnable(SC16IS752_IRQ_ID, 1, sc16is752IrqSR, (int)NULL);
/* IN IO EVENT */
for (ix = 0; ix < MAX_IN_IO_NUM; ix++){
s_sc16is752IoEvent[ix].pDownFunc = s_sc16is752IoEvent[ix].pUpFunc = NULL;
}
for (ix = 0; ix < 2; ix++){
/* check if driver already installed */
if (sc16is752DrvNum[ix] > 0)
return (OK);
sc16is752Dev[ix].created = FALSE;
sc16is752Dev[ix].opened = FALSE;
sc16is752Dev[ix].devId = ix;
sc16is752Dev[ix].moder_LCR = 0x03;
sc16is752Dev[ix].moder_DLL = 0x48;/* 9600 */
sc16is752Dev[ix].moder_DLH = 0x00;
sc16is752Dev[ix].fcrReg = 0x81;
sc16is752Dev[ix].efcrReg = 0x10;
sc16is752Dev[ix].syncSem = semBCreate (SEM_Q_FIFO, SEM_EMPTY);
sc16is752Dev[ix].rngRxBuf = rngCreate(MAX_FIFO_SIZE);
sc16is752DrvNum[ix] = iosDrvInstall (sc16is752Open, (FUNCPTR) NULL, sc16is752Open,
sc16is752Close, sc16is752Read, sc16is752Write, sc16is752Ioctl);
if (ERROR == sc16is752DrvNum[ix]) return ERROR;
}
/* initiallize the sc16is752 chip */
sc16isInit();
if (taskSpawn("sc16is752irqTask", TASK_PRIORITY_SC16IS752, VX_FP_TASK,
1024*20,(FUNCPTR)sc16is752irqTask,0,0,0,0,0,0,0,0,0,0) == ERROR){
return ERROR;
}
return OK;
}
/*******************************************************************************
*
* sc16is752DevCreate - create a device for an sc16is752 serial port
*
* This routine creates a device for a specified serial port. Each port
* to be used should have exactly one device associated with it by calling
* this routine.
*
* For instance, to create the device `/Ser/0', the proper call would be:
* .CS
* sc16is752DevCreate ("/Ser/0");
* .CE
*
* RETURNS: OK, or ERROR if the driver is not installed, the channel is
* invalid, or the device already exists.
*
* SEE ALSO: sc16is752Drv()
*/
extern STATUS sc16is752DevCreate
(
char *name /* name to use for this device */
)
{
int i, rst = ERROR;
char devName[20];
for (i = 0; i < 2; i++){
if (sc16is752DrvNum[i] <= 0){
errnoSet (S_ioLib_NO_DRIVER);
return (ERROR);
}
/* if this device already exists, don't create it */
if (sc16is752Dev[i].created)
return (ERROR);
/* initialize a select() wake-up list for sc16is752Dev */
selWakeupListInit(&sc16is752Dev[i].selWakeupList);
/* mark the device as created, and add the device to the I/O system */
sc16is752Dev[i].created = TRUE;
sprintf(devName, "%s/%d", name, i);
rst = iosDevAdd (&sc16is752Dev[i].devHdr, devName, sc16is752DrvNum[i]);
if (ERROR == rst) {
return ERROR;
}
}
return OK;
}
/******************************************************************************
*
* sc16is752_read - read data from a gpio.
*
* INPUTS:
int sc16is752DevId :serial descriptor from which to read
char * buffer :pointer to buffer to receive bytes
*
* RETURNS:
* STATUS: if succeed return OK, else return ERROR;
*
******************************************************************************/
extern STATUS sc16is752_read (int sc16is752DevId,char * buffer)
{
if (sc16is752DevId - SC16IS752_IO_PA0 > MAX_IN_IO_NUM) return ERROR;
if (BITS(sc16is752Reg.IoDir, sc16is752DevId - SC16IS752_IO_PA0) == IO_IN) {
*buffer = BITS(sc16is752Reg.IoState, sc16is752DevId - SC16IS752_IO_PA0);
return OK;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -