文章目录[隐藏]
【平台信息】
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 ---》串口0,THRE(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 ---》串口0,TEMT(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
暂无评论