cq8401-spi-sc16IS751 驱动分析

1 . 工作原理

 

CQ8401 spi总线(master) 通过两个SC16IS752芯片(slave),外扩232,GPS,485422;一块SC16IS752芯片最多只能扩两个设备。

 

涉及到的知识:SPI协议(参考网上资料有很多), UART工作原理(参考设备驱动)。

 

1.1 原理图:

 

 

 

 

原理图说明:

 

SCLKThe divider of the SSICLK, I2SCLK and USB clock can be changed by programming CFCR1.SSIFR, CFCR2.I2SFR and CFCR1.UFR, respectively.

 

/* arch/mips/cq8401/common/setup.c */

clx_clocks.ssiclk = __cpm_get_ssiclk();

 

static __inline__ unsigned int __cpm_get_ssiclk(void)

{

unsigned int ssiclk;

unsigned long cfcr = REG_CPM_CFCR;

unsigned long plcr = REG_CPM_PLCR1;

if ((plcr & CPM_PLCR1_PLL1EN) && (cfcr & CPM_CFCR_SSI))

ssiclk = __cpm_get_pllout() /

(((cfcr&CPM_CFCR_SSIFR_MASK)>>CPM_CFCR_SSIFR_BIT)+1);

else

ssiclk = CLX_EXTAL;

return ssiclk;

}

 

 

CS:芯片片选信号,低有效;在安联板上有2SC16IS752芯片,驱动中应该注意CS信号线

 

SO: 芯片 输出 , CQ8401接收

 

SI: CQ8401 输出 ,芯片 接收

 

IRQ:中断线

 

GPIO 寄存器: 该方案中没有用

 

16C45: 外接 232GPS 或者 485,422

 

1.2数据流程

 

数据发送: CQ8401--> SPI ---> SC16IS752 -->232/485/GPS/422

 

数据接收: 232/485/GPS/422 有数据来产生中断,数据存储在SC16IS752 FIFO--> SPI --->CQ8401处理中断,接收数据

 

 

 

2 驱动分析

 

本驱动最重要的是要注意在发送和接收 的时候,对CS片选信号线要主动的去拉低。比如在发送中,你是知道要向那个芯片发数据的,所以在发送前要将对应的芯片CS信号线拉低。 在接收过程中,由于2块芯片的接收中断是一直开启的,所以来了中断,你在接收中断函数中能通过struct uart_port *port = dev_idport->line 来知道是那块芯片, port->line 对应如下:

 

 

port->line=0 芯片一 cs1  接232

port->line=1 芯片一 cs1 GPS

port->line=2 芯片二 cs2 422

port->line=3 芯片二 cs2 422

 

根据这个关系来确定去拉低那跟CS片选信号线。

 

关于初始化部分,这里不在阐述,重点讲UARTops 操作

 

static struct uart_ops s752_pops = {

tx_empty: s752_tx_empty,

set_mctrl: s752_set_mctrl,

get_mctrl: s752_get_mctrl,

stop_tx: s752_stop_tx,

start_tx: s752_start_tx,

stop_rx: s752_stop_rx,

enable_ms: s752_enable_ms,

break_ctl: s752_break_ctl,

startup: s752_startup,

shutdown: s752_shutdown,

set_termios: s752_set_termios,

type: s752_type,

release_port: s752_release_port,

request_port: s752_request_port,

config_port: s752_config_port,

verify_port: s752_verify_port,

};

 

   这里主要讲以下几个部分:

 

 

 

2.1 start_tx:

s752_start_tx , UART open操作

 

static int s752_startup(struct uart_port *port)

{

uint16_t ret;

int retval=0;

int i=0;

/* 根据port->line 来选择ce1 或者 ce2 */

//spin_lock(&port->lock);

while((!(__ssi_transfer_end())) || __ssi_is_busy());

if(port->line < 2){

__ssi_select_ce(); //spi_ce1 被片选中

sc752_ce1_init(port); // 初始化,分析如下

}

else{

__ssi_select_ce2(); //spi_ce2 被片选中

sc752_ce2_init(port);   // 初始化,分析如下

}

//spin_unlock(&port->lock);   

#ifdef _DEBUG_S752

printk("=====>AFT REG_SSI_CR0=0x%08x/n",REG_SSI_CR0);

printk("s752_startup exit/n");

#endif

 

 

return 0;

 

 

}

 

 

static void sc752_ce1_init(struct uart_port *port)

{

 

int retval=0;

 

/* clears the contents of the transmit and receive FIFO and resets the FIFO

  • level logic and enable the transmit and receive FIFO */

 

 

s752_write_reg(FCR,port->line,0x07);

delay(5);

 

#if 0

/* 232 uart surport HardwareFlow*/

printk("set hartdware flow control!!/n");

if(!port->line)

HardwareFlow(); //channel A 232 hardwareflow

 

/*Force RTS low level for sofeware flow control*/

s752_write_reg(MCR,ChannelA,0x02);

#endif

 

  /* 中断注册,这里用的是共享中断,中断号IRQ_GPIO0+GPIO */

retval = request_irq(port->irq, s752_int, IRQF_SHARED, "ttySC_CE1",port);

 

if (retval){

printk("request irq SPI_CE1 error:%d/n",retval);

return retval;

}

 

/* only enable the RHR interrupt in s752_startup*/

s752_write_reg(IER, port->line, 0x01);

 

}

 

static void sc752_ce2_init(struct uart_port *port)

{

 

unsigned int line=0;

int retval=0;

line=port->line-2;

 

 

/* clears the contents of the transmit and receive FIFO and resets the FIFO

* level logic and enable the transmit and receive FIFO */

s752_write_reg(FCR,line,0x07);

delay(5);

 

/* set RS-485*/

 

rs_485_Multidrop(line);

 

/* 中断注册,这里用的是共享中断,中断号IRQ_GPIO0+GPIO */

retval = request_irq(port->irq, s752_int, IRQF_SHARED, "ttySC_CE2",port);

 

if (retval){

printk("request irq SPI_CE2 error:%d/n",retval);

return retval;

}

 

 

/* only enable the RHR interrupt */

 

s752_write_reg(IER,line, 0x01);

 

 

}

  1.  

2.2 start_tx:

  1.  

    s752_start_tx, 开始发送数据

 

static void s752_start_tx(struct uart_port *port)

{

 

unsigned int line=0;

 

/* 根据port->line 来选择ce1 或者 ce2 */

while((!(__ssi_transfer_end())) || __ssi_is_busy());

if(port->line < 2){

__ssi_select_ce();

line=port->line;

 

}

else {

__ssi_select_ce2();

line=port->line-2;

 

}

/* enable trasmit interrupt */

s752_write_reg(IER,line, 0x03);

 

//s752_tx_chars(port);

 

}

 

2.3 set_termios:

s752_set_termios, set baud_rateeven-odd parity, stop bit,data bit

 

 

 

static void s752_set_termios(struct uart_port *port, struct ktermios *termios,

struct ktermios *old)

{

 

 

unsigned long flags;

unsigned int baud, quot;

unsigned short cval=0, ier, lsr,line=0;

 

if(port->line < 2)

line=port->line;

else

line=port->line-2;

/*

* Ask the core to calculate the divisor for us.

*/

 

baud = uart_get_baud_rate(port, termios, old, 0, 56000*8);

quot = uart_get_divisor(port, baud);

 

spin_lock_irqsave(port->lock,flags);

/* LCR[7]=1,enable divisor latch*/

s752_write_reg(LCR,line,0x80);

s752_write_reg(DLL,line,quot & 0xFF); //baud rate

s752_write_reg(DLH,line,(quot >> 8) & 0xFF);

 

spin_unlock_irqrestore(port->lock, flags);

 

/* set data bit*/

switch (termios->c_cflag & CSIZE) {

case CS5:

cval = UART_LCR_WLEN5;

break;

case CS6:

cval = UART_LCR_WLEN6;

break;

case CS7:

cval = UART_LCR_WLEN7;

break;

default:

case CS8:

cval = UART_LCR_WLEN8;

break;

}

/* set stop bit*/

if (termios->c_cflag & CSTOPB){

 

cval |= UART_LCR_STOP;

}

/* set parity bit*/

if (termios->c_cflag & PARENB){ //如果设置了parity bit,则LCR3位置1

 

cval |= UART_LCR_PARITY;

if (!(termios->c_cflag & PARODD))

 

cval |= UART_LCR_EPAR;

 

}

 

s752_write_reg(LCR, line, cval);

 

}

 

2.4中断处理函数

 

static irqreturn_t s752_int(int irq, void *dev_id)

{

 

struct uart_port *port = dev_id;

uint8_t ret=0,chip;

int i=0;

unsigned int status,line;

 

spin_lock(&port->lock);

/* 根据port->line 来选择ce1 或者 ce2 */

while((!(__ssi_transfer_end())) || __ssi_is_busy());

 

if(port->line < 2){

__ssi_select_ce();

line=port->line;

chip=0;

}

else{

__ssi_select_ce2();

line=port->line-2;

chip=1;

}

 

 

ret=s752_read_reg(IIR,line);

 

 

if(!(ret & 0x01)){

status = s752_read_reg(LSR,line);

if(ret&0x04 && status&0x01) //rx intterrupt

s752_rx_chars(port,status);

if(ret&0x02) //tx interrupt

s752_tx_chars(port);

}

 

spin_unlock(&port->lock);

return IRQ_HANDLED;

 

}

 

 

2.5 具体发送,接收函数分析

s752_rx_chars(port,status)---接收 ,s752_tx_chars(port)--发送,跟普通的串口一样,

 

不具体分析。

  1.  

2.6 485,422,232 介绍

 

RS-422的最大传输距离为4000英尺(约1219),最大传输速率为10Mb/sRS-485是从RS-422基础上发展而来的,所以RS-485许多电气规定与RS-422相仿。RS-485RS-422一样,其最大传输距离约为1219,最大传输速率为10Mb/sRS232传输距离很短只有50m

 

485是半双工的,422是全双工的,232全双工。

4根线:RXTXRTSCTS;一般RTSCTS没怎么用

RX: 数据接收(pc-->8401

TX: 数据发送 (8401-->pc)

RTS: 请求发送,输出信号(请求数据从外设pc-->8401,低有效,驱动需要控制)

CTS:清除发送,输入信号 (表明外设PC已准备好,8401可以发数据给外设PC了,驱动中需要去读取寄存器的这位)

 

232一般只需要2根线(RX,TX),有时在需要流控的时候才需要(RTSCTS

 

485RXTXRTS(控制是发送还是接收)

 

422RXTXRTS(控制是发送还是接收)

 

 

 

3 建议

建议在后续开发中,在2.6的内核中把SSI总线驱动移植了,可参考2.4内核SSI总线驱动;还有

一些SSI驱动的参考如下:

 

2.4内核 : clx_i2s.c (i2s 驱动,CODEC芯片通过SPI总线控制)

2.6内核 : drivers/char/cq8401/clx_spi.c (SPIDMA实现方式,这个程序也是学习

CQ8401 DMA驱动编写的一个好的程序)

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
东南亚位于我国倡导推进的“一带一路”海陆交汇地带,作为当今全球发展最为迅速的地区之一,近年来区域内生产总值实现了显著且稳定的增长。根据东盟主要经济体公布的最新数据,印度尼西亚2023年国内生产总值(GDP)增长5.05%;越南2023年经济增长5.05%;马来西亚2023年经济增速为3.7%;泰国2023年经济增长1.9%;新加坡2023年经济增长1.1%;柬埔寨2023年经济增速预计为5.6%。 东盟国家在“一带一路”沿线国家中的总体GDP经济规模、贸易总额与国外直接投资均为最大,因此有着举足轻重的地位和作用。当前,东盟与中国已互相成为双方最大的交易伙伴。中国-东盟贸易总额已从2013年的443亿元增长至 2023年合计超逾6.4万亿元,占中国外贸总值的15.4%。在过去20余年中,东盟国家不断在全球多变的格局里面临挑战并寻求机遇。2023东盟国家主要经济体受到国内消费、国外投资、货币政策、旅游业复苏、和大宗商品出口价企稳等方面的提振,经济显现出稳步增长态势和强韧性的潜能。 本调研报告旨在深度挖掘东南亚市场的增长潜力与发展机会,分析东南亚市场竞争态势、销售模式、客户偏好、整体市场营商环境,为国内企业出海开展业务提供客观参考意见。 本文核心内容: 市场空间:全球行业市场空间、东南亚市场发展空间。 竞争态势:全球份额,东南亚市场企业份额。 销售模式:东南亚市场销售模式、本地代理商 客户情况:东南亚本地客户及偏好分析 营商环境:东南亚营商环境分析 本文纳入的企业包括国外及印尼本土企业,以及相关上下游企业等,部分名单 QYResearch是全球知名的大型咨询公司,行业涵盖各高科技行业产业链细分市场,横跨如半导体产业链(半导体设备及零部件、半导体材料、集成电路、制造、封测、分立器件、传感器、光电器件)、光伏产业链(设备、硅料/硅片、电池片、组件、辅料支架、逆变器、电站终端)、新能源汽车产业链(动力电池及材料、电驱电控、汽车半导体/电子、整车、充电桩)、通信产业链(通信系统设备、终端设备、电子元器件、射频前端、光模块、4G/5G/6G、宽带、IoT、数字经济、AI)、先进材料产业链(金属材料、高分子材料、陶瓷材料、纳米材料等)、机械制造产业链(数控机床、工程机械、电气机械、3C自动化、工业机器人、激光、工控、无人机)、食品药品、医疗器械、农业等。邮箱:market@qyresearch.com

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值