WK2124

news/2024/11/25 10:26:33/

目录

  • WK系列介绍

    • WK2124芯片原理

    • 寄存器介绍

    • 硬件连接

    • 驱动框架

  • 驱动移植

    • 驱动源码分析

    • 驱动信息描述和数据结构

    • 串口驱动的底层操作

    • tty驱动架构

    • wk2xxx_dowork()和wk2xxx_work函数

    • 修改设备树

    • 驱动调试修改

  • 问题

WK2124

WK系列介绍

WK2124能实现SPI拓展4路UART。

每个子通道UART 的波特率、字长、校验格式可以独立设置,最高提供2Mbps 的通信速率。

每个子通道具备收/发独立的256 级FIFO,FIFO 的中断可按用户需求进行编程触发点且具备超时中断功能。

WK2124芯片原理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ceQwMwE9-1664788113856)(image/image_OgdjENIum8.png)]

寄存器介绍

WK2124的寄存器地址按6位地址编码分为全局寄存器子串口寄存器

全局寄存器 5个

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5tMt9CI3-1664788113857)(image/image_vq5jIEx_7E.png)]

子串口寄存器 25个 寄存器地址格式:C0C1 REG[3:0] (C0C1 两位是可分别对应子串口)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eM8jfk6F-1664788113859)(image/image_I5PVp8HvRT.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C6N8HOKT-1664788113862)(image/image_uW0CNlJDER.png)]



硬件连接

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9iICebD5-1664788113869)(image/image_chosDex2jx.png)]

  1. WK 芯片作SPI 从设备和CPU 端的主SPI 需要连接的信号有CS 信号(此信号不能一
    直拉低,需要用主spi 的cs 信号控制)、CLK 信号、MOSI 信号、MISO 信号,具体
    连接方式如上图。

  2. IRQ 信号为WK 芯片的中断输出信号,需要连接到CPU 具有外部中断功能的GPIO
    上。

驱动框架

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ibMtyfsR-1664788113871)(image/image_dzvIy5eTBX.png)]

1、 WK 驱动工作在linux 内核层,向上提供4 个串口设备节点供应用层用户调用。
也就是说WK 驱动注册成功以后,在/dev/ 目录下会生成 ttysWK0、ttysWK1、
ttysWK2、ttysWK3 共4 个串口设备节点,应用层就可以按照操作普通串口节
点的方式操作。
2、 WK 驱动需要和WK 芯片进行数据交互,数据交互是通过SPI 总线进行的,所以
WK 驱动会调用SPI 总线驱动接口进行数据收发。

驱动移植

驱动源码分析

驱动信息描述和数据结构

  1. 串口驱动描述

    鉴于芯片的相关特性和驱动编写的需要,定义了结构体 wk2xxx_port用于对WK的SPI转串口驱动进行描述

    struct wk2xxx_port 
    {const struct wk2xxx_devtype *devtype;struct uart_driver      uart;struct spi_device *spi_wk;struct workqueue_struct *workqueue;struct work_struct work;unsigned char           buf[256];struct kthread_worker   kworker;struct task_struct      *kworker_task;struct kthread_work     irq_work;int irq_gpio_num;                         /*中断IO的GPIO编号*/int rst_gpio_num;                         /*复位引脚的GPIO编号*/int irq_gpio;                            /*中断编号*/int minor;      /* minor number */int tx_empty; struct wk2xxx_one       p[NR_PORTS];
    };
    
  2. 串口端口描述

    定义一个结构体wk2xxx_one来描述WK2xxx芯片的串口端口进行描述,实际上是对uart_port的进一步封装,增加了两个内核队列和芯片子串口一些寄存器。

    struct wk2xxx_one 
    {struct uart_port port;//[NR_PORTS];struct kthread_work     start_tx_work;struct kthread_work     stop_rx_work;uint8_t line;uint8_t new_lcr_reg;uint8_t new_fwcr_reg;uint8_t new_scr_reg; /*baud register*/uint8_t new_baud1_reg;uint8_t new_baud0_reg;uint8_t new_pres_reg;
    };
    

串口驱动的底层操作

  1. 读全局寄存器函数

  2. 写全局寄存器函数

  3. 读子寄存器函数

  4. 写子寄存器函数

  5. 读FIFO寄存器函数

  6. 写FIFO寄存器函数

tty驱动架构

wk拓展uart,需要向驱动提供对串口的操作函数,

static struct uart_ops wk2xxx_pops = {tx_empty:       wk2xxx_tx_empty,set_mctrl:      wk2xxx_set_mctrl,get_mctrl:      wk2xxx_get_mctrl,stop_tx:        wk2xxx_stop_tx,start_tx:       wk2xxx_start_tx,stop_rx:        wk2xxx_stop_rx,enable_ms:      wk2xxx_enable_ms,break_ctl:      wk2xxx_break_ctl,startup:        wk2xxx_startup,shutdown:       wk2xxx_shutdown,set_termios:    wk2xxx_termios,type:           wk2xxx_type,release_port:   wk2xxx_release_port,request_port:   wk2xxx_request_port,config_port:    wk2xxx_config_port,verify_port:    wk2xxx_verify_port,};

wk2xxx_dowork()和wk2xxx_work函数

这两个函数封装中断和内核线程功能,提供给串口操作函数

static int wk2xxx_dowork(struct wk2xxx_port *s)
{
#ifdef _DEBUG_WK_FUNCTIONprintk(KERN_ALERT "%s!!-port:%ld;--in--\n", __func__, s->port.iobase);
#endifif (!s->force_end_work && !work_pending(&s->work) && !freezing(current) && !s->suspending){queue_work(s->workqueue, &s->work); 
#ifdef _DEBUG_WK_FUNCTIONprintk("%s!!--queue_work---ok!---\n", __func__);// printk("work_pending =: %d s->force_end_work  = : %d freezing(current) = :%d s->suspending= :%d\n" ,work_pending(&s->work),s->force_end_work ,freezing(current),s->suspending);
#endifreturn 1;}else{
#ifdef _DEBUG_WK_FUNCTIONprintk("%s!!--queue_work---error!---\n", __func__);printk("work_pending =: %d s->force_end_work  = : %d freezing(current) = :%d s->suspending= :%d\n", work_pending(&s->work), s->force_end_work, freezing(current), s->suspending);
#endif// printk("work_pending =: %d s->force_end_work  = : %d freezing(current) = :%d s->suspending= :%d\n" ,work_pending(&s->work),s->force_end_work ,freezing(current),s->suspending);//   return 0;//  printk("work_pending() =: %d tx_empty_flag = : %d start_tx_flag = :%d stop_tx_flag = :%d conf_flag =: %d irq_flag =: %d tx_empty=:%d\n",work_pending(&s->work),s->tx_empty_flag,s->start_tx_flag,s->stop_tx_flag,s->stop_rx_flag,s->conf_flag,s->irq_flag,s->tx_empty);return 0;}
}
static void wk2xxx_work(struct work_struct *w)
{struct wk2xxx_port *s = container_of(w, struct wk2xxx_port, work);uint8_t rx;int work_start_tx_flag;int work_stop_rx_flag;int work_irq_flag;int work_conf_flag;
#ifdef _DEBUG_WK_FUNCTIONprintk(KERN_ALERT "%s!!-port:%ld;--in--\n", __func__, s->port.iobase);
#endifdo{mutex_lock(&wk2xxs_work_lock);work_start_tx_flag = s->start_tx_flag;if (work_start_tx_flag)s->start_tx_flag = 0;work_stop_rx_flag = s->stop_rx_flag;if (work_stop_rx_flag)s->stop_rx_flag = 0;work_conf_flag = s->conf_flag;if (work_conf_flag)s->conf_flag = 0;work_irq_flag = s->irq_flag;if (work_irq_flag)s->irq_flag = 0;mutex_unlock(&wk2xxs_work_lock);if (work_start_tx_flag){wk2xxx_read_slave_reg(s->spi_wk, s->port.iobase, WK2XXX_SIER, &rx);rx |= WK2XXX_TFTRIG_IEN | WK2XXX_RFTRIG_IEN | WK2XXX_RXOUT_IEN;wk2xxx_write_slave_reg(s->spi_wk, s->port.iobase, WK2XXX_SIER, rx);}if (work_stop_rx_flag){wk2xxx_read_slave_reg(s->spi_wk, s->port.iobase, WK2XXX_SIER, &rx);rx &= ~WK2XXX_RFTRIG_IEN;rx &= ~WK2XXX_RXOUT_IEN;wk2xxx_write_slave_reg(s->spi_wk, s->port.iobase, WK2XXX_SIER, rx);}if (work_irq_flag){wk2xxxirq_app(&s->port);s->irq_fail = 1;}} while (!s->force_end_work && !freezing(current) &&(work_irq_flag || work_stop_rx_flag));if (s->start_tx_fail){wk2xxx_read_slave_reg(s->spi_wk, s->port.iobase, WK2XXX_SIER, &rx);rx |= WK2XXX_TFTRIG_IEN | WK2XXX_RFTRIG_IEN | WK2XXX_RXOUT_IEN;wk2xxx_write_slave_reg(s->spi_wk, s->port.iobase, WK2XXX_SIER, rx);s->start_tx_fail = 0;}if (s->stop_rx_fail){wk2xxx_read_slave_reg(s->spi_wk, s->port.iobase, WK2XXX_SIER, &rx);rx &= ~WK2XXX_RFTRIG_IEN;rx &= ~WK2XXX_RXOUT_IEN;wk2xxx_write_slave_reg(s->spi_wk, s->port.iobase, WK2XXX_SIER, rx);s->stop_rx_fail = 0;}if (s->irq_fail){s->irq_fail = 0;enable_irq(s->port.irq);}#ifdef _DEBUG_WK_FUNCTIONprintk(KERN_ALERT "%s!!-port:%ld;--exit--\n", __func__, s->port.iobase);
#endif
fdef _DEBUG_WK_FUNCTIONprintk(KERN_ALERT "%s!!-port:%ld;--exit--\n", __func__, s->port.iobase);
#endif
}

修改设备树

选择将SPI3拓展成uart口


#define MX6UL_PAD_UART2_RX_DATA__ECSPI3_SCLK                      0x0098 0x0324 0x0554 0x8 0x0
#define MX6UL_PAD_UART2_CTS_B__ECSPI3_MOSI                        0x009C 0x0328 0x055C 0x8 0x0
#define MX6UL_PAD_UART2_RTS_B__ECSPI3_MISO                        0x00A0 0x032C 0x0558 0x8 0x0
#define MX6UL_PAD_UART2_TX_DATA__ECSPI3_SS0                       0x0094 0x0320 0x0560 0x8 0x0

http://www.ppmy.cn/news/256414.html

相关文章

大数据开发之Hive案例篇10-大表笛卡尔积优化

文章目录 一. 问题描述二.解决方案2.1 数据倾斜2.2 SQL改写1:由分析函数改为常规写法2.3 分析数据分布2.4 SQL改写2:重写 参考: 一. 问题描述 需求描述: 表概述: dt 时间分区 data_source 数据来源类别 start_date 时间 data_count 当前时间的数量…

SD卡SPI模式入门教程

▼我是阿荣,关注我,在技术路上一起精进!▼ SD卡简介 SD卡是一种基于半导体快闪记忆器的新一代记忆设备,英文全称Secure Digital Memory Card,中文名又称安全数码卡。 尺寸分类 按尺寸分类,SD卡分为&…

华为 java sd卡,手机添加存储卡 内存变大不卡顿——华为SD卡扩容实例

手机的基本功能是接听电话收发短信,电脑是人工智能机器人,二者合并便是智能手机,也就是今天所说的“手机”。 手机用于记忆和工作的“脑海”里拥挤不堪时便会卡顿频发,这”脑海”就是手机的“内存”。 人的脑海分为大脑和小脑&…

关于Android读取SD卡存储的动态申请

关于Android读取SD卡存储的动态申请 介绍Android的目录结构数据的主要存储方式疑惑原来的代码:MainActivity.java修改后代码: 介绍 这篇文章主要关于我学习SD卡的动态获取权限时的一些问题。 Android的目录结构 参考自解析Android内部存储、外部存储的…

SD卡及SDIO协议简介

1、SD卡分类 STM32F4里,只支持SD 2.0协议,SD和SDHC属于这个范畴,SDXC是4.0协议,所以不支持;另外SDHC卡,有些数据块大小是512,有的是1024,STM32F4只支持读取512大小的,意…

STM32完成SD卡的数据写入

文章目录 一、SD卡模块简介二、读取SD卡三、总结四、参考 一、SD卡模块简介 简介 SD存储卡是一种基于半导体快闪记忆器的新一代记忆设备,由于它体积小、数据传输速度快、可热插拔等优良的特性,被广泛地于便携式装置上使用,例如数码相机、平板…

龙芯2K1000实战开发-kernel 开发

文章目录 概要整体架构流程技术名词解释技术细节小结概要 提示:这里可以添加技术概要 例如: 本文主要解释龙芯2K1000的内核开发。 整体架构流程 提示:这里可以添加技术整体架构 1.从 ftp 上下载的 Kernel 源码一般都会有一个 mymake 的脚本,编译和配置可以 直接借用此…

如何使用 Git

Git 是一种分布式版本控制系统,它可以记录文件的变化历史,并且可以在不同的分支上进行开发。在软件开发中,Git 是一个必不可少的工具。本文将介绍如何使用 Git。 安装 Git 首先,你需要在你的电脑上安装 Git。你可以在 Git 的官网…