7.2.5. 设计说明
7.2.5.1. 源码说明
CIR模块的源码位于:linux-5.10/drivers/media/rc/zx-cir.c
7.2.5.2. 模块架构
linux内核中rc的基本框架如下图所示:
红外信号的编码和解码工作由内核负责完成。在完成编码后,应用层需要发送的信号被编码为一系列的带有宽度的高低电平(pulse/space),CIR driver在发送端就是需要将这一系列的pulse/space写入发送FIFO,发送出去。在接收红外信号时,CIR driver需要将接收到的一系列高低电平送入到rc core进行解码,最终将解码得到的scancode和keycode反馈到输入子系统,最终送给app程序完成红外信号的接收。所以,CIR驱动的主要任务有:
将编码得到的高低电平信号以游码的形式写入TX-FIFO,发送红外信号
将CIR模块接收的RX-FIFO中的游码正确表示为高低电平的形式,相邻的高电平或低电平需要进行合并。
根据用户空间传递的红外参数,对CIR的底层寄存器进行配置,如配置载波频率,配置占空比等
由于红外信号的数据量都很少,所以在红外信号的发送端,一般是利用循环将所有的数据一次性全部发送出去,而不会采用中断或DMA的方式。在红外信号的接收端,一般是采用中断的方式进行数据的接收,在接收完成后,调用相应的解码函数进行解码。CIR模块可以支持任何的红外协议,对不同红外协议的支持可以通过对载波配置寄存器的设置来实现。CIR驱动中默认配置的是支持NEC协议。
7.2.5.3. 关键流程设计
7.2.5.3.1. 初始化流程
CIR模块的初始化流程如下:
释放clock和reset信号
调用rc_allocate_device为rc_dev结构体分配空间
设置载波的占空比为33%。读取dts中linux,rc-map-name的属性值。若为空,则默认使用内核中的空表
注册红外设备
读取dts中的rx-level属性值,设置RX空闲时的状态
设置噪声阈值,激活阈值,空闲阈值等底层配置
设置载波配置寄存器,驱动中默认配置的是38K载波(NEC协议)
使能CIR中断,发送器,接收器
7.2.5.3.2. 中断处理流程
CIR模块使能RX的溢出中断、RXFIFO可用中断、接收完成中断。
中断执行流程如下:
读取中断状态寄存器和接收状态寄存器
清空所有中断标志位
若为RXFIFO可用中断或接收完成中断,判断RXFIFO是否为空,非空则读取RXFIFO中数据个数,并逐个从RXFIFO中读取数据。若不是这两个中断,则跳转到5
将每次从RXFIFO中读出的游码解析为正确的高低电平宽度,并调用ir_raw_event_store_with_filter将解析后的数据存储到kfifo中
若为接收溢出中断,则调用ir_raw_event_reset,清空kfifo中的数据
若为接收完成中断,此处以完成对所有数据的接收,调用ir_raw_event_handle开始解码
7.2.5.4. 数据结构设计
struct aic_ir {
spinlock_t ir_lock;
struct rc_dev *rc;
void __iomem *base;
struct clk *clk;
struct reset_control *rst;
const char *map_name; /*CIR模块使用的keycode-scancode映射表*/
unsigned int tx_duty; /*发送红外信号时的占空比*/
int irq;
u32 rx_level; /*指示空闲状态下RX的电平状态*/
u8 rx_flag; /*指示RXFIFO中是否已接收到数据*/
};
7.2.5.5. 接口设计
7.2.5.5.1. aic_set_rx_carrier_range
函数原型 |
static int aic_set_rx_carrier_range(struct rc_dev *rcdev, u32 min, u32 max) |
---|---|
功能说明 |
设置CIR模块接收器的采样频率 |
参数定义 |
rcdev:指向红外设备的指针
min:设置的采样频率最小值
max:设置的采样频率最大值
|
返回值 |
执行成功返回0 |
注意事项 |
7.2.5.5.2. aic_set_tx_duty_cycle
函数原型 |
static int aic_set_tx_duty_cycle(struct rc_dev *rcdev, u32 duty_cycle) |
---|---|
功能说明 |
设置CIR模块发送红外信号的占空比 |
参数定义 |
rcdev:指向红外设备的指针
duty_cycle:需要设置的占空比
|
返回值 |
执行成功返回0 |
注意事项 |
7.2.5.5.3. aic_set_tx_carrier
函数原型 |
static int aic_set_tx_carrier(struct rc_dev *rcdev, u32 carrier) |
---|---|
功能说明 |
设置CIR模块发送信号的载波频率 |
参数定义 |
rcdev:指向红外设备的指针
carrier:需要设置的载波频率大小
|
返回值 |
执行成功返回0 |
注意事项 |
7.2.5.5.4. aic_tx_ir
函数原型 |
static int aic_tx_ir(struct rc_dev *rcdev, unsigned int *txbuf, unsigned int count) |
---|---|
功能说明 |
CIR模块发送红外信号的函数 |
参数定义 |
rcdev:指向红外设备的指针
txbuf:需要发送的红外信号的缓存
count:需要发送的红外信号在缓存中的个数
|
返回值 |
执行成功返回0 |
注意事项 |