Android9.0 S905D3 SPI转UART调试

【平台信息】

Android:9.0
CPU:S905D3
SPI转串口:CH432T

【硬件连接】

编号 S905D3 CH432T
1 GPIOA_1 INT#

说明:
1、CH432T如果只连接 INT#引脚,即两个串口合用一个中断请求,那么单片机在进入中断服务程序后,首
先应该分析出是哪个串口的中断请求。
2、CH432T当 INT0 或者 INT1其中一个有效时(三态输出允许且输出高电平),INT#引脚输出低电平,否则 INT#引脚不输出。
3、CH432 芯片的 SPI 片选 , 低电平有效

【基本概念】

spi_master:确定芯片spi控制器。
spi_device:确定总线的一些属性,比如spi的mode,cs片选,频率等。
spi_driver:描述总线下挂载的设备的驱动,比如spi norflash的驱动和spi lcd的驱动等。

【代码梳理】

1、SPI Controller和SPI Device注册

           spicc0: spi@13000 { --->spi controller
                compatible = "amlogic,meson-g12a-spicc";
                reg = <0x0 0x13000 0x0 0x44>;
                interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&clkc CLKID_SPICC0>,
                     <&clkc CLKID_SPICC0_COMP>;
                clock-names = "core", "comp";
                #address-cells = <1>;
                #size-cells = <0>;
                status = "disabled";
            };
        }
        
&spicc0 {
    status = "okay";
    spidev0 {   --->spi device
        #address-cells = <1>;
        #size-cells = <1>;
        compatible = "wch,ch43x";
        reg = <0>;
        spi-max-frequency = <5000000>;
        interrupt_pin = <&gpio GPIOA_1 GPIO_ACTIVE_LOW>;
        irq_trigger_type = "GPIO_IRQ_LOW";
        status = "okay";
    };
};        

驱动代码:common/drivers/spi/spi-meson-spicc.c

meson_spicc_probe->
    spi_alloc_master->申请spi master结构体
    devm_request_irq(xxx, irq, meson_spicc_irq, xxx);
    devm_spi_register_master->
        spi_register_master-> //注册一个spi控制器,即spi_master
            of_spi_register_master->
            of_register_spi_devices->    // 解析设备树,创建SPI device
                of_register_spi_device-> // 解析设备树,注册spi master下挂的spi device
                    spi_alloc_device->   // 分配一个并简单初始化 spi_device
                    spi_add_device->     //将spi_device 添加的 device 系统
static void of_register_spi_devices(struct spi_master *master)
{
	...
	for_each_available_child_of_node(master->dev.of_node, nc) {
		...
		spi = of_register_spi_device(master, nc);
		...
	}
}    
drivers\spi\spi.c
spi_drv_probe->
    spi->irq = of_irq_get(dev->of_node, 0);    //获取irq中断号  

2、SPI Driver Probe注册

static const struct of_device_id __maybe_unused ch43x_dt_ids[] = {
	{ .compatible = "wch,ch43x",	.data = &ch43x_devtype, },
	{},
};
static struct spi_driver ch43x_spi_uart_driver = {
   .driver = {
	   .name   = CH43X_NAME_SPI,
	   .bus    = &spi_bus_type,
	   .owner  = THIS_MODULE,
	   .of_match_table = of_match_ptr(ch43x_dt_ids),
   },
   .probe          = ch43x_spi_probe,
   .remove         = ch43x_spi_remove,
};
static int __init ch43x_init(void)
{
	return spi_register_driver(&ch43x_spi_uart_driver);
}
module_init(ch43x_init);

查看上面的代码,ch43x_spi_uart_driver注册到module_spi_driver,表示在系统启动的时候会把这个结构体添加到spi driver的链表中,当有新的driver这时候会去查找是否有和它匹配的device,如果查找到匹配的device,ch43x_spi_uart_driver里面的probe函数就会被调用!

3、struct uart_ops

/*
 * This structure describes all the operations that can be
 * done on the physical hardware.
 */
struct uart_ops {
    unsigned int (*tx_empty)(struct uart_port *); /* 串口的Tx FIFO缓存是否为空。如果为空,函数应返回TIOCSER_TEMT,否则返回0。如果端口不支持此操作,返回TIOCSER_TEMT。*/
    void         (*set_mctrl)(struct uart_port *, unsigned int mctrl); /* 设置串口modem控制 */
    unsigned int (*get_mctrl)(struct uart_port *); /* 获取串口modem控制 */
    void         (*stop_tx)(struct uart_port *); /* 禁止串口发送数据 */
    void         (*start_tx)(struct uart_port *); /* 使能串口发送数据 */
    void         (*send_xchar)(struct uart_port *, char ch);/* 发送xChar */
    void         (*stop_rx)(struct uart_port *); /* 禁止串口接收数据 */
    void         (*enable_ms)(struct uart_port *); /* 使能modem的状态信号 */
    void         (*break_ctl)(struct uart_port *, int ctl); /* 设置break信号 */
    int          (*startup)(struct uart_port *); /* 启动串口,应用程序打开串口设备文件时,该函数会被调用 */
    void         (*shutdown)(struct uart_port *); /* 关闭串口,应用程序关闭串口设备文件时,该函数会被调用 */
    void         (*set_termios)(struct uart_port *, struct ktermios *new, struct ktermios *old); /* 设置串口参数 */
    void         (*pm)(struct uart_port *, unsigned int state,
             unsigned int oldstate); /* 串口电源管理 */
    int          (*set_wake)(struct uart_port *, unsigned int state); /*  */
    const char  *(*type)(struct uart_port *); /* 返回一描述串口类型的字符串 */
    void         (*release_port)(struct uart_port *); /* 释放串口已申请的IO端口/IO内存资源,必要时还需iounmap */
    int          (*request_port)(struct uart_port *); /* 申请必要的IO端口/IO内存资源,必要时还可以重新映射串口端口 */
    void         (*config_port)(struct uart_port *, int); /* 执行串口所需的自动配置 */
    int          (*verify_port)(struct uart_port *, struct serial_struct *); /* 核实新串口的信息 */
    int          (*ioctl)(struct uart_port *, unsigned int, unsigned long); /* IO控制 */
};

【调试记录】

1、编译tty_test测试工具
/opt/gcc-linaro-6.3.1-2017.02-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -o tty_test --static tty_test.c
说明:如何确定交叉编译工具路径?
—》在kernel工程中搜索Makefile文件中的CROSS_COMPILE变量,
然后在Makefile设置CROSS_COMPILE变量后加打印$(warning $(CROSS_COMPILE)),看编译日志;

2、查看SPI设备

:/data # cat /sys/bus/spi/devices/spi32766.0/modalias
spi:ch43x
:/data # ls -l /dev/ttyWCH*
crw------- 1 root root 243,   0 1970-01-01 08:00 /dev/ttyWCH0
crw------- 1 root root 243,   1 1970-01-01 08:00 /dev/ttyWCH1

3、设置串口参数

busybox stty -F /dev/ttyWCH0 speed 115200 raw cs8 -parenb –cstopb
busybox stty -a -F /dev/ttyWCH0

busybox stty -F /dev/ttyWCH1 speed 115200 raw cs8 -parenb –cstopb 
busybox stty -a -F /dev/ttyWCH1

4、CH432驱动调测

1)打开内核调测开关

在ch432.c中注释如下两行代码,即可打开内核打印开关
//#undef DEBUG
//#undef VERBOSE_DEBUG

2)在用户态发送数据

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>  
#include <termios.h>  
#include <errno.h>   
#include <string.h>
#include <sys/types.h> 
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <getopt.h>
#include <linux/serial.h>

#ifndef TIOCGRS485
#define TIOCGRS485 _IOR('T', 0x2E, struct serial_rs485)
#endif
#ifndef TIOCSRS485
#define TIOCSRS485 _IOWR('T', 0x2F, struct serial_rs485)
#endif

static const char *device = "/dev/ttyWCH0";
static int speed = 115200;
static int hardflow = 0;
static int verbose = 0;
static int rs485 = 0;
static int savefile = 0;
static FILE *fp;

static const struct option lopts[] = {
	{ "device", required_argument, 0, 'D' },
	{ "speed", optional_argument, 0, 'S' },
	{ "verbose", optional_argument, 0, 'v' },
	{ "hardflow", required_argument, 0, 'f' },
	{ "savefile", required_argument, 0, 's' },
	{ NULL, 0, 0, 0 },
};

static void print_usage(const char *prog)
{
	printf("Usage: %s [-DSvfs]\n", prog);
	puts("  -D --device    tty device to use\n"
		 "  -S --speed     uart speed\n"
		 "  -v --verbose   Verbose (show rx buffer)\n"
		 "  -f --hardflow  open hardware flowcontrol\n"
		 "  -R --rs485     enable rs485 function\n"
		 "  -s --savefile  save rx data to file\n");
	exit(1);
}


int speed_arr[] = {
	B4000000,
	B3000000,
	B2500000,
	B2000000,
	B1000000,
	B921600,
	B460800,
	B230400,
	B115200,
	B57600,
	B38400,
	B19200,
	B9600,
	B4800,
	B2400,
	B1200,
	B600,
	B300,
	B200,
	B150,
	B110,
	B75,
	B50
};

int name_arr[] = {
	4000000,
	3000000,
	2500000,
	2000000,
	1000000,
	921600,
	460800,
	230400,
	115200,
	57600,
	38400,
	19200,
	9600,
	4800,
	2400,
	1200,
	600,
	300,
	200,
	150,
	110,
	75,
	50
};
 
/**
 * libtty_setopt - config tty device
 * @fd: device handle
 * @speed: baud rate to set
 * @databits: data bits to set
 * @stopbits: stop bits to set
 * @parity: parity to set
 * @hardflow: hardflow to set
 *
 * The function return 0 if success, or -1 if fail.
 */
int libtty_setopt(int fd, int speed, int databits, int stopbits, char parity, char hardflow)
{
	struct termios newtio;
	struct termios oldtio;
	int i;
	
	bzero(&newtio, sizeof(newtio));
	bzero(&oldtio, sizeof(oldtio));
	
	if (tcgetattr(fd, &oldtio) != 0) {
		perror("tcgetattr");    
		return -1; 
	}
	newtio.c_cflag |= CLOCAL | CREAD;
	newtio.c_cflag &= ~CSIZE;
 
	/* set tty speed */
	for (i = 0; i < sizeof(speed_arr) / sizeof(int); i++) {
		if (speed == name_arr[i]) {      
			cfsetispeed(&newtio, speed_arr[i]); 
			cfsetospeed(&newtio, speed_arr[i]);   
		} 
	}
	
	/* set data bits */
	switch (databits) {
	case 5:                
		newtio.c_cflag |= CS5;
		break;
	case 6:                
		newtio.c_cflag |= CS6;
		break;
	case 7:                
		newtio.c_cflag |= CS7;
		break;
	case 8:    
		newtio.c_cflag |= CS8;
		break;  
	default:   
		fprintf(stderr, "unsupported data size\n");
		return -1; 
	}
	
	/* set parity */
	switch (parity) {  
	case 'n':
	case 'N':
		newtio.c_cflag &= ~PARENB;    /* Clear parity enable */
		newtio.c_iflag &= ~INPCK;     /* Disable input parity check */
		break; 
	case 'o':  
	case 'O':    
		newtio.c_cflag |= (PARODD | PARENB); /* Odd parity instead of even */
		newtio.c_iflag |= INPCK;     /* Enable input parity check */
		break; 
	case 'e': 
	case 'E':  
		newtio.c_cflag |= PARENB;    /* Enable parity */   
		newtio.c_cflag &= ~PARODD;   /* Even parity instead of odd */  
		newtio.c_iflag |= INPCK;     /* Enable input parity check */
		break;
	default:  
		fprintf(stderr, "unsupported parity\n");
		return -1; 
	} 
	
	/* set stop bits */ 
	switch (stopbits) {  
	case 1:   
		newtio.c_cflag &= ~CSTOPB; 
		break;
	case 2:   
		newtio.c_cflag |= CSTOPB; 
		break;
	default:   
		perror("unsupported stop bits\n"); 
		return -1;
	}
 
	if (hardflow)
		newtio.c_cflag |= CRTSCTS;
	else
		newtio.c_cflag &= ~CRTSCTS;
 
	newtio.c_cc[VTIME] = 20;	/* Time-out value (tenths of a second) [!ICANON]. */
	newtio.c_cc[VMIN] = 128;	/* Minimum number of bytes read at once [!ICANON]. */
	
	tcflush(fd, TCIOFLUSH);  
	
	if (tcsetattr(fd, TCSANOW, &newtio) != 0) {
		perror("tcsetattr");
		return -1;
	}
	return 0;
}
 
/**
 * libtty_open - open tty device
 * @devname: the device name to open
 *
 * In this demo device is opened blocked, you could modify it at will.
 */
int libtty_open(const char *devname)
{
	int fd = open(devname, O_RDWR | O_NOCTTY | O_NDELAY); 
	int flags = 0;
	
	if (fd < 0) {                        
		perror("open device failed");
		return -1;            
	}
	
	flags = fcntl(fd, F_GETFL, 0);
	flags &= ~O_NONBLOCK;
	if (fcntl(fd, F_SETFL, flags) < 0) {
		printf("fcntl failed.\n");
		return -1;
	}
		
	if (isatty(fd) == 0) {
		printf("not tty device.\n");
		return -1;
	}
	else
		printf("tty device test ok.\n");
	
	return fd;
}
 
/**
 * libtty_close - close tty device
 * @fd: the device handle
 *
 * The function return 0 if success, others if fail.
 */
int libtty_close(int fd)
{
	return close(fd);
}
 
/**
 * libtty_tiocmset - modem set
 * @fd: file descriptor of tty device
 * @bDTR: 0 on inactive, other on DTR active
 * @bRTS: 0 on inactive, other on RTS active
 *
 * The function return 0 if success, others if fail.
 */
int libtty_tiocmset(int fd, char bDTR, char bRTS)
{
	unsigned long controlbits = 0;
	
	if (bDTR)
		controlbits |= TIOCM_DTR;
	if (bRTS)
		controlbits |= TIOCM_RTS;
	
	return ioctl(fd, TIOCMSET, &controlbits);
}

/**
 * libtty_tiocmget - modem get
 * @fd: file descriptor of tty device
 *
 * The function return 0 if success, others if fail.
 */
int libtty_tiocmget(int fd)
{
	unsigned long modembits = 0;
	int ret;

	ret = ioctl(fd, TIOCMGET, &modembits);
	if (modembits & TIOCM_DSR)
		printf("DSR Active!\n");
	if (modembits & TIOCM_CTS)
		printf("CTS Active!\n");
	if (modembits & TIOCM_CD)
		printf("DCD Active!\n");
	if (modembits & TIOCM_RI)
		printf("RI Active!\n");
	
	if (ret)
		return ret;
	else
		return modembits;
}

/**
 * libtty_rs485set - rs485 set
 * @fd: file descriptor of tty device
 * @enable: 0 on disable, other on enable
 *
 * The function return 0 if success, others if fail.
 */
int libtty_rs485set(int fd, char enable)
{
	struct serial_rs485 rs485conf;
	
	if (enable)
		rs485conf.flags |= SER_RS485_ENABLED;
	else
		rs485conf.flags &= ~SER_RS485_ENABLED;
	
	return ioctl(fd, TIOCSRS485, &rs485conf);
}

/**
 * libtty_rs485get - rs485 get
 * @fd: file descriptor of tty device
 * @rs485conf: pointer to struct serial_rs485
 *
 * The function return 0 if success, others if fail.
 */
int libtty_rs485get(int fd, struct serial_rs485 *rs485conf)
{
	return ioctl(fd, TIOCGRS485, rs485conf);
}

/**
 * libtty_write - write 100 bytes at one time
 * @fd: file descriptor of tty device
 *
 */
#define WRITE_NUM 12
void libtty_write(int fd)
{
	int nwrite;
	char buf[WRITE_NUM];
	int i;
	
	for (i = 0; i < WRITE_NUM; i++)
		buf[i] = 0x55 + i;
	
	nwrite = write(fd, buf, sizeof(buf));
	printf("write %d bytes already.\n", nwrite);
}

/**
 * libtty_read - reading data cyclically
 * @fd: file descriptor of tty device
 *
 */
void libtty_read(int fd)
{
	int nwrite, nread;
	char buf[4096];
	int i;
	int total = 0;
	
	if (savefile) {
		fp = fopen("./fileoutput", "w+");
		if (fp == NULL) {
			printf("create file failed.\n");
			return;
		}
	}
	
	while (1) {
		nread = read(fd, buf, sizeof(buf));
		if (nread >= 0) {
			total += nread;
			printf("read total %d bytes, %d this time.\n", total, nread);
		} else
			printf("read error!\n");

		if (verbose) {
			printf("*************************\n");
			for (i = 0; i < nread; i++)
				printf(" 0x%.2x", buf[i]);
			printf("\n*************************\n");		
		}
		if (savefile) {
			fwrite(buf, sizeof(char), nread, fp);
		}
	}
}

void sig_handler(int signo)
{
    printf("capture sign no:%d\n",signo);
	if (savefile) {
		fflush(fp);
		fsync(fileno(fp));
		fclose(fp);
	}
	exit(0);
}

int libtty_sendbreak(int fd)
{
	return tcsendbreak(fd, 0);
}

int main(int argc, char *argv[])
{
	int fd;
	int ret;
	char c;

	//parse_opts(argc, argv);
	
	signal(SIGINT, sig_handler); 
	
	fd = libtty_open(device);
	if (fd < 0) {
		printf("libtty_open error.\n");
		exit(0);
	}

	ret = libtty_setopt(fd, speed, 8, 1, 'n', hardflow);
	if (ret != 0) {
		printf("libtty_setopt error.\n");
		exit(0);
	}

    libtty_write(fd);
	ret = libtty_close(fd);
	if (ret != 0) {
		printf("libtty_close error.\n");
		exit(0);
	}
}

3)内核打印调测信息

:/data # dmesg -c > /dev/null
:/data # ./tty_test_wch0
tty device test ok.
write 12 bytes already.
:/data # dmesg -c
[ 3168.364666] ch43x_spi spi1.0: ch43x_pm
[ 3168.366929] ch43x_spi spi1.0: ch43x_port_update_specify.constprop.7 - reg:0x 1, data:0x20
[ 3168.367224] ch43x_spi spi1.0: ch43x_port_write_spefify.isra.1.constprop.9 - reg:0x 1, data:0x 0
[ 3168.367285] ch43x_spi spi1.0: ch43x_startup
[ 3168.367770] ch43x_spi spi1.0: ch43x_port_update_specify.constprop.7 - reg:0x 1, data:0x 0
[ 3168.368304] ch43x_spi spi1.0: ch43x_port_write_spefify.isra.1.constprop.9 - reg:0x 1, data:0x 0
[ 3168.368574] ch43x_spi spi1.0: ch43x_port_write.isra.2 - reg:0x 2, data:0x 6  ---》禁用Fifo,清空接收和发送fifo,接收一个字节产生接收中断
[ 3168.368920] ch43x_spi spi1.0: ch43x_port_write.isra.2 - reg:0x 2, data:0x81  ---》使能Fifo,接收8字节产生接收中断
[ 3168.369186] ch43x_spi spi1.0: ch43x_port_write.isra.2 - reg:0x 3, data:0x 3  ---》线路控制,字长度为8,一个停止位,无奇偶校验、
[ 3168.369474] ch43x_spi spi1.0: ch43x_port_write.isra.2 - reg:0x 1, data:0x d  ---》使能接收数据中断、调制解调器中断、接收线路状态中断
[ 3168.369750] ch43x_spi spi1.0: ch43x_port_write.isra.2 - reg:0x 4, data:0x 8  ---》MODEM输出控制
[ 3168.369819] ch43x_spi spi1.0: ch43x_set_termios
[ 3168.369848] ch43x_spi spi1.0: parity = none
[ 3168.370114] ch43x_spi spi1.0: ch43x_port_write.isra.2 - reg:0x 3, data:0x 3
[ 3168.370147] ch43x_spi spi1.0: ch43x_set_termios disable rts/cts
[ 3168.370478] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 4, data:0x 8
[ 3168.370740] ch43x_spi spi1.0: ch43x_port_write.isra.2 - reg:0x 4, data:0x 8 ---》MODEM输出控制
[ 3168.370813] ch43x_spi spi1.0: ch43x_set_termios - 115200                    ---》设置波特率
[ 3168.371140] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 3, data:0x 3
[ 3168.371468] ch43x_spi spi1.0: ch43x_port_update_specify.constprop.7 - reg:0x 9, data:0x 0
[ 3168.371994] ch43x_spi spi1.0: ch43x_port_write_spefify.isra.1.constprop.9 - reg:0x 9, data:0x 0
[ 3168.372130] ch43x_spi spi1.0: ch43x_port_write.isra.2 - reg:0x 3, data:0x80 ---》线路控制,存取DLL和DLM,字长度5,一个停止位,无奇偶校验、
[ 3168.372263] ch43x_spi spi1.0: ch43x_port_write.isra.2 - reg:0x 1, data:0x 0 ---》禁止接收中断,和其它所有中断
[ 3168.372395] ch43x_spi spi1.0: ch43x_port_write.isra.2 - reg:0x 0, data:0x d ---》发送保持寄存器,用于写入准备发送的数据
[ 3168.372527] ch43x_spi spi1.0: ch43x_port_write.isra.2 - reg:0x 3, data:0x 3
[ 3168.372692] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 3, data:0x 3
[ 3168.372824] ch43x_spi spi1.0: ch43x_port_write.isra.2 - reg:0x 3, data:0x80
[ 3168.372840] ch43x_spi spi1.0: ******Dump register at LCR=DLAB
[ 3168.373004] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 0, data:0x d
[ 3168.373022] ch43x_spi spi1.0: Reg[0x00] = 0x0d
[ 3168.373185] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 3, data:0x80
[ 3168.373316] ch43x_spi spi1.0: ch43x_port_write.isra.2 - reg:0x 3, data:0x 0
[ 3168.373332] ch43x_spi spi1.0: ******Dump register at LCR=Normal
[ 3168.373495] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 0, data:0x10
[ 3168.373512] ch43x_spi spi1.0: Reg[0x00] = 0x10
[ 3168.373676] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 1, data:0x d
[ 3168.373693] ch43x_spi spi1.0: Reg[0x01] = 0x0d
[ 3168.373857] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 2, data:0xc1
[ 3168.373874] ch43x_spi spi1.0: Reg[0x02] = 0xc1
[ 3168.374036] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 3, data:0x 0
[ 3168.374053] ch43x_spi spi1.0: Reg[0x03] = 0x00
[ 3168.374216] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 4, data:0x 8
[ 3168.374233] ch43x_spi spi1.0: Reg[0x04] = 0x08
[ 3168.374397] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 5, data:0x60
[ 3168.374414] ch43x_spi spi1.0: Reg[0x05] = 0x60
[ 3168.374577] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 6, data:0x 0
[ 3168.374594] ch43x_spi spi1.0: Reg[0x06] = 0x00
[ 3168.374757] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 7, data:0xff
[ 3168.374774] ch43x_spi spi1.0: Reg[0x07] = 0xff
[ 3168.374937] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 8, data:0x 0
[ 3168.374954] ch43x_spi spi1.0: Reg[0x08] = 0x00
[ 3168.375119] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 9, data:0x 0
[ 3168.375136] ch43x_spi spi1.0: Reg[0x09] = 0x00
[ 3168.375299] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x a, data:0xc1
[ 3168.375316] ch43x_spi spi1.0: Reg[0x0a] = 0xc1
[ 3168.375478] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x b, data:0x 3
[ 3168.375495] ch43x_spi spi1.0: Reg[0x0b] = 0x03
[ 3168.375760] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x c, data:0x 0
[ 3168.375777] ch43x_spi spi1.0: Reg[0x0c] = 0x00
[ 3168.375986] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x d, data:0x60
[ 3168.376003] ch43x_spi spi1.0: Reg[0x0d] = 0x60
[ 3168.376169] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x e, data:0x 0
[ 3168.376187] ch43x_spi spi1.0: Reg[0x0e] = 0x00
[ 3168.376351] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x f, data:0xff
[ 3168.376368] ch43x_spi spi1.0: Reg[0x0f] = 0xff
[ 3168.376500] ch43x_spi spi1.0: ch43x_port_write.isra.2 - reg:0x 3, data:0x 3
[ 3168.376586] ch43x_spi spi1.0: ch43x_ioctl cmd=21505
[ 3168.376734] ch43x_spi spi1.0: ch43x_ioctl cmd=21505
[ 3168.376776] ch43x_spi spi1.0: ch43x_ioctl cmd=21515
[ 3168.376820] ch43x_spi spi1.0: ch43x_ioctl cmd=21506
[ 3168.376875] ch43x_spi spi1.0: ch43x_start_tx
[ 3168.376897] ch43x_spi spi1.0: ch43x_start_tx schedule
[ 3168.376964] ch43x_spi spi1.0: ch43x_wq_proc
[ 3168.377144] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 1, data:0x d

[ 3168.377244] ch43x_spi spi1.0: ch43x_ist interrupt enter...                  ---》进入ch43x_ist中断处理
[ 3168.377311] ch43x_spi spi1.0: ch43x_port_write.isra.2 - reg:0x 1, data:0x f
[ 3168.377514] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 5, data:0x60  ---》获取LSR寄存器,TEMT:发送保持寄存器 THR 和发送移位寄存器 TSR 全空
																								   THRE:发送保持寄存器 THR 空
[ 3168.377754] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 2, data:0xc2  ---》中断识别寄存器,用于分析中断源并处理
                                                                                    THR寄存器空,发送保持寄存器空
[ 3168.377782] ch43x_spi spi1.0: ch43x_ist
[ 3168.377799] ch43x_spi spi1.0: ch43x_handle_tx 12 bytes                      ---》处理数据发送
[ 3168.378046] ch43x_spi spi1.0: ch43x_raw_write - reg:0x 2                    ---》先进先出缓冲区 FIFO 控制寄存器,用于使能和复位 FIFO
[ 3168.378064] ch43x_spi spi1.0: \x09buf[0]:0x55
[ 3168.378079] ch43x_spi spi1.0: \x09buf[1]:0x56
[ 3168.378093] ch43x_spi spi1.0: \x09buf[2]:0x57
[ 3168.378108] ch43x_spi spi1.0: \x09buf[3]:0x58
[ 3168.378122] ch43x_spi spi1.0: \x09buf[4]:0x59
[ 3168.378136] ch43x_spi spi1.0: \x09buf[5]:0x5a
[ 3168.378151] ch43x_spi spi1.0: \x09buf[6]:0x5b
[ 3168.378165] ch43x_spi spi1.0: \x09buf[7]:0x5c
[ 3168.378179] ch43x_spi spi1.0: \x09buf[8]:0x5d
[ 3168.378193] ch43x_spi spi1.0: \x09buf[9]:0x5e
[ 3168.378207] ch43x_spi spi1.0: \x09buf[10]:0x5f
[ 3168.378222] ch43x_spi spi1.0: \x09buf[11]:0x60
[ 3168.378307] ch43x_spi spi1.0: ch43x_tx_empty                                ---》检查串口的Tx FIFO缓存是否为空                                                                                       
[ 3168.378478] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 5, data:0x 0  ---TEMT(bit6):该位为 1 表示发送保持寄存器 THR 和发送移位寄存器 TSR 全空。
                                                                                    THRE(bit5):该位为 1 表示发送保持寄存器 THR 空。
[ 3168.378608] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 5, data:0x 0
[ 3168.378781] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 2, data:0xc1  ---》串口0,没有中断产生
[ 3168.378808] ch43x_spi spi1.0: ch43x_ist no int, quit
[ 3168.379012] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x d, data:0x60
[ 3168.379208] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x a, data:0xc1  ---》串口1,没有中断产生
[ 3168.379235] ch43x_spi spi1.0: ch43x_ist no int, quit
[ 3168.379259] ch43x_spi spi1.0: ch43x_ist end                                  ---》退出ch43x_ist中断处理

[ 3168.387688] ch43x_spi spi1.0: ch43x_tx_empty
[ 3168.387921] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 5, data:0x 0
[ 3168.389487] ch43x_spi spi1.0: ch43x_ist interrupt enter...
[ 3168.389709] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 5, data:0x20   ---》串口0THRE(bit5)发送保持寄存器 THR 空。
[ 3168.389925] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 2, data:0xc2   ---》串口0,产生发送保持寄存器空中断,说明数据已经发送成功

[ 3168.389979] ch43x_spi spi1.0: ch43x_ist
[ 3168.389994] ch43x_spi spi1.0: ch43x_handle_tx stopped
[ 3168.390196] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 1, data:0x f
[ 3168.390342] ch43x_spi spi1.0: ch43x_port_write.isra.2 - reg:0x 1, data:0x d  ---》串口0,禁止发送保持寄存器空中断
[ 3168.390542] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 5, data:0x20
[ 3168.390744] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 2, data:0xc1   ---》串口0,没有中断产生  
[ 3168.390772] ch43x_spi spi1.0: ch43x_ist no int, quit
[ 3168.390973] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x d, data:0x60
[ 3168.391170] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x a, data:0xc1
[ 3168.391197] ch43x_spi spi1.0: ch43x_ist no int, quit
[ 3168.391221] ch43x_spi spi1.0: ch43x_ist end

[ 3168.399621] ch43x_spi spi1.0: ch43x_tx_empty
[ 3168.399809] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 5, data:0x60   ---》串口0TEMT(bit6):该位为 1 表示发送保持寄存器 THR 和发送移位寄存器 TSR 全空。
                                                                                            THRE(bit5):该位为 1 表示发送保持寄存器 THR 空
[ 3168.399852] ch43x_spi spi1.0: ch43x_stop_rx                                  ---》禁止串口接收数据
[ 3168.399926] ch43x_spi spi1.0: ch43x_stop_rx_work_proc
[ 3168.400102] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 1, data:0x d
[ 3168.400239] ch43x_spi spi1.0: ch43x_port_write.isra.2 - reg:0x 1, data:0x c
[ 3168.400409] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 1, data:0x c

[ 3168.400470] ch43x_spi spi1.0: ch43x_shutdown                                 ---》上层等待tx_empty后,关闭串口
[ 3168.400545] ch43x_spi spi1.0: ch43x_port_write.isra.2 - reg:0x 1, data:0x 8
[ 3168.400761] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 4, data:0x 8
[ 3168.400791] ch43x_spi spi1.0: ch43x_shutdown - MCR:0x8
[ 3168.400959] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 5, data:0x60
[ 3168.400976] ch43x_spi spi1.0: LSR:0x60
[ 3168.401273] ch43x_spi spi1.0: ch43x_port_read.isra.4 - reg:0x 2, data:0xc1
[ 3168.401290] ch43x_spi spi1.0: IIR:0xc1
[ 3168.401427] ch43x_spi spi1.0: ch43x_port_write.isra.2 - reg:0x 1, data:0x 0  ---》禁止所有中断
[ 3168.401562] ch43x_spi spi1.0: ch43x_port_write.isra.2 - reg:0x 4, data:0x 0  ---》关闭所有MODEM控制
[ 3168.401731] ch43x_spi spi1.0: ch43x_port_update_specify.constprop.7 - reg:0x 1, data:0x 0
[ 3168.401869] ch43x_spi spi1.0: ch43x_port_write_spefify.isra.1.constprop.9 - reg:0x 1, data:0x20
[ 3168.401901] ch43x_spi spi1.0: ch43x_pm                                       ---》关闭power,进入sleep模式
[ 3168.402069] ch43x_spi spi1.0: ch43x_port_update_specify.constprop.7 - reg:0x 1, data:0x20
[ 3168.402206] ch43x_spi spi1.0: ch43x_port_write_spefify.isra.1.constprop.9 - reg:0x 1, data:0x20
:/data #

【参考链接】

1、linux3.10系统下CH432T(SPI转串口)调试笔记
https://blog.csdn.net/u010936265/article/details/114181275?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163575419316780265454182%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=163575419316780265454182&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduend~default-2-114181275.pc_search_result_hbase_insert&utm_term=ch432t&spm=1018.2226.3001.4187

2、嵌入式linux spi转CH432驱动
https://blog.csdn.net/yin_feiling/article/details/7545321?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163575419316780265454182%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=163575419316780265454182&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduend~default-5-7545321.pc_search_result_hbase_insert&utm_term=ch432t&spm=1018.2226.3001.4187

3、Linux SPI 驱动分析(1)— 结构框架
https://blog.csdn.net/zhoutaopower/article/details/99866773?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163581605016780261912882%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=163581605016780261912882&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allbaidu_landing_v2~default-2-99866773.pc_search_result_hbase_insert&utm_term=linux+spi%E9%A9%B1%E5%8A%A8&spm=1018.2226.3001.4187

4、OpenWrt 之 MT7628 移植第三方SPI驱动
https://blog.csdn.net/JAZZSOLDIER/article/details/105117141

5、Linux下SPI驱动详解
https://os.51cto.com/art/202103/648463.htm

版权声明:本文为CSDN博主「weixin_43701779」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43701779/article/details/121082238

生成海报
点赞 0

weixin_43701779

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

支持安卓与iphone13和安卓手机的5W无线充电芯片IC

无线充电系统包括初级和次级线圈,通过电磁场限度地相互耦合一起。两个线圈的铁氧体作为其结构的一部分进一步限度地提高场耦合。初级线圈是从AD-DC适配器供电给发射机以开关波形驱动。次级线圈连接整流能直接电池或电子充电器或二次稳压连接输

多功能智能药盒

多功能智能药盒 本设计选取的主控芯片是 STM32F103C8T6 最小单片机系统,利用蓝牙模块实现智能药盒与手机 APP 之间的通讯,达到数据同步和控制。而 APP 的主要功能是服药时间的设定、管理药盒实时采集的

QM2150平台 配置SPI死机

项目场景: 由于在该平台上需要调试一个spi设备,但是在调试过程发现:一旦在spi总线下挂载设备节点就会出现死机。 问题描述: 首先我们打开spi-log: kernel/msm-4.