加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

linux-kernel – 从FIQ中断处理程序访问内核驱动程序数据失败

发布时间:2020-12-14 01:01:14 所属栏目:Linux 来源:网络整理
导读:在ARM FIQ中断上,我们有一些寄存器仅保留用于FIQ,这些是“保存状态”的便捷方式,例如FIQ调用之间的数据传输. 目前我正在从FIQ触发一些GPIO引脚,它正在按预期工作.在设置FIQ处理程序时,我将指针传递给使用ioremap映射的数据寄存器.工作代码如下所示: //Drive
在ARM FIQ中断上,我们有一些寄存器仅保留用于FIQ,这些是“保存状态”的便捷方式,例如FIQ调用之间的数据传输.

目前我正在从FIQ触发一些GPIO引脚,它正在按预期工作.在设置FIQ处理程序时,我将指针传递给使用ioremap映射的数据寄存器.工作代码如下所示:

//Driver initialization:
static char* dout0;
static char* din0;
...
static int driver_probe(struct platform_device *pdev) 
{
struct pt_regs regs;
...
dout0 = ioremap(HW_PINCTRL_DOUT0,0xffff);
din0  = ioremap(HW_PINCTRL_DIN0,0xffff);
...
regs.ARM_r8 = (long) dout0;
regs.ARM_r9 = (long) din0;
set_fiq_regs(&regs);
...

//In the FIQ handler:
LDR r12,[r8]
ORR r12,r12,#0x20 /* set pin 5 high in dout0 register */
STR r12,[r8]

上述代码按预期执行,引脚5在执行FIQ处理程序后设置为高电平.

对于更复杂的操作,我想准备一个结构,它将保存数据指针和其他处理相关的数据,包括更多映射到不同的寄存器 – 并将其传递给FIQ处理程序.但是在将上述代码迁移到此时已经出现了问题.

我修改了上面的代码看起来像这样

//In Driver:
struct fiq_processing {
    char* din0;
    char* dout0;
};

static fiq_processing * pdata; //Pointer to our processing data structure

...
static int driver_probe(struct platform_device *pdev) 
{
struct pt_regs regs;
pdata = kmalloc(sizeof(*pdata),GFP_KERNEL); //Allocate memory for struct
printk("Size of the data struct %d n",sizeof(*pdata)); //I get "8" as the size
...
pdata->din0  = ioremap(HW_PINCTRL_DIN0,0xffff);
pdata->dout0 = ioremap(HW_PINCTRL_DOUT0,0xffff);
...
regs.ARM_r8 = (long) pdata;
set_fiq_regs(&regs);
...

//In the FIQ handler:
#define OFFSET_DIN0 0x0 
#define OFFSET_DOUT0 0x4 //We know size is 8,so offset for dout is half from that
...
LDR r12,[r8,#OFFSET_DOUT0]
ORR r12,#OFFSET_DOUT0] /* This will do nothing ? */

在为结构分配内存并映射寄存器指针后,我将pdata结构的地址传递给FIQ处理程序.
在FIQ处理程序中,我有din0和dout0的偏移量,我认为它们分别是0x0和0x4(从结构大小8中扣除).

但由于某种原因,现在我的FIQ无法再将输出引脚设置为高电平 – 我无法弄清楚我在这里做错了什么..
我在那里计算错误的偏差吗? OR是调用STR r12,#OFFSET_DOUT0]不正确?
实际的FIQ更长一些(它读取输入状态,并从中输入创建一些条件),但即使是基本位设置似乎也失败了..

解决方法

情况1

regs.ARM_r8 = (long) dout0;
set_fiq_regs(&regs);

//In the FIQ handler:
LDR r12,[r8]

这里r8中的值是存储器映射的I / O寄存器的地址.取消引用它从正确的位置读取.

案例2

struct fiq_processing {
    char* din0;
    char* dout0;
};
static fiq_processing * pdata; //Pointer to our processing data structure
pdata->din0  = ioremap(HW_PINCTRL_DIN0,0xffff);
...
//In the FIQ handler:
LDR r12,#OFFSET_DOUT0] /* This will do nothing ? */

在这种情况下,您已检索到GPIO控制器的地址,并且您正在使用该地址进行ORRing!你需要再次取消引用.

LDR r11,#OFFSET_DOUT0]  # Get address of controller
LDR R12,[R11]                # Get current I/O value.
ORR r12,#0x20           # Set pin 5 high in dout0 register */
STR r12,[r11]                # Write it out.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读