从FIQ中断处理程序访问内核驱动的数据失败 [英] Accessing kernel driver data from FIQ interrupt handler failing

查看:407
本文介绍了从FIQ中断处理程序访问内核驱动的数据失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在ARM FIQ中断,我们只为FIQ使用而保留一些寄存器,而这些都是一个方便的方式来拯救国家之间。例如FIQ调用的数据传输。

目前我正在引发从​​FIQ一些 GPIO 引脚,它工作正常。当设置FIQ处理程序,我通过指针数据寄存器,在被映射用的ioremap。工作code是这样的:

  //驱动程序初始化:
静态字符* dout0;
静态字符* DIN0;
...
静态INT driver_probe(结构platform_device * PDEV)
{
结构pt_regs暂存器;
...
dout0 =的ioremap(HW_PINCTRL_DOUT0,0xFFFF的);
DIN0 =的ioremap(HW_PINCTRL_DIN0,0xFFFF的);
...
regs.ARM_r8 =(长)dout0;
regs.ARM_r9 =(长)DIN0;
set_fiq_regs(安培;暂存器);
...//在FIQ处理程序:
LDR R12,[R8]
ORR R12,R12,#为0x20 / * SET引脚5高dout0寄存器* /
STR R12,[R8]

以上code执行正如所料,引脚5 被执行FIQ处理程序后置高。

有关更复杂的操作,我想prepare一个结构,将保存的数据指针等加工相关的数据,包括多个映射到不同的寄存器 - 和它传递给FIQ处理程序。但是,迁移上述code这个当事情错了那里了。

我修改了code以上看起来像这样

  //在驱动程序:
结构fiq_processing {
    字符* DIN0;
    字符* dout0;
};静态fiq_processing * PDATA; //指向我们的处理数据结构...
静态INT driver_probe(结构platform_device * PDEV)
{
结构pt_regs暂存器;
PDATA =的kmalloc(sizeof的(* PDATA),GFP_KERNEL); //为分配的内存结构
printk的(数据结构%d个\\ n的大小,sizeof的(* PDATA)); //我得到8的大小
...
pdata-> DIN0 = ioremap的(HW_PINCTRL_DIN0,0xFFFF的);
pdata-> dout0 = ioremap的(HW_PINCTRL_DOUT0,0xFFFF的);
...
regs.ARM_r8 =(长)PDATA;
set_fiq_regs(安培;暂存器);
...//在FIQ处理程序:
#定义OFFSET_DIN0为0x0
#定义OFFSET_DOUT0为0x4 //我们知道,大小为8,为DOUT因此抵消一半是从
...
LDR R12,[R8,#OFFSET_DOUT0]
ORR R12,R12,#为0x20 / * SET引脚5高dout0寄存器* /
STR R12,[R8,#OFFSET_DOUT0] / *这会做什么? * /

在我已经分配结构的内存,并绘制了寄存器指针,我的地址PDATA结构传递给FIQ处理程序。
在FIQ处理程序,我对 DIN0 dout0 ,这是我认为是 为0x0 和分别为0x4(从8结构尺寸扣除)。

但由于某些原因,现在我的FIQ是无法设置输出引脚高了 - 我想不出我在做什么错在这里..
我在计算偏移错在那里?或者是呼叫 STR R12,[R8,#OFFSET_DOUT0] 不正确的?
实际的FIQ是较为较长(读取输入状态,并从该输入产生一定的条件),但即使是基本的置位,现在看来要失败。


解决方案

案例1

  regs.ARM_r8 =(长)dout0;
set_fiq_regs(安培;暂存器);

...

  //在FIQ处理程序:
LDR R12,[R8]
ORR R12,R12,#为0x20 / * SET引脚5高dout0寄存器* /
STR R12,[R8]

在这里, R8 值映射I / O寄存器内存的地址。德引用它从正确的位置读取。

案例2

 结构fiq_processing {
    字符* DIN0;
    字符* dout0;
};
静态fiq_processing * PDATA; //指向我们的处理数据结构
pdata-> DIN0 = ioremap的(HW_PINCTRL_DIN0,0xFFFF的);
pdata-> dout0 = ioremap的(HW_PINCTRL_DOUT0,0xFFFF的);
...
//在FIQ处理程序:
LDR R12,[R8,#OFFSET_DOUT0]
ORR R12,R12,#为0x20 / * SET引脚5高dout0寄存器* /
STR R12,[R8,#OFFSET_DOUT0] / *这会做什么? * /

在这种情况下,您检索了GPIO控制器的地址,并与您的地址为 ORR ING!你需要去再次参照

  LDR R11,[R8,#OFFSET_DOUT0]#获取控制器的地址
LDR R12,[R11]#获取当前的I / O值。
ORR R12,R12,#0x20的设置#5脚高dout0寄存器* /
STR R12,[R11]#写出来。

On ARM FIQ interrupts, we have some registers reserved only for FIQ use, and those are a handy way to "save the state" for example of data transfer between FIQ calls.

Currently I'm triggering some GPIO pins from the FIQ, and it is working as expected. When setting up the FIQ handler, I pass the pointers to the data registers, that were mapped with ioremap. Working code looks like this:

//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]

The above code performs as expected, the pin 5 is set high after FIQ handler is executed.

For more complicated operation, I want to prepare a struct, that will hold data-pointers, and other processing related data, including more mappings to different registers - and pass this to the FIQ handler. But something is going wrong there already when migrating the above code to this.

I modified the code above to look like this

//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, r12, #0x20 /* set pin 5 high in dout0 register */
STR r12, [r8, #OFFSET_DOUT0] /* This will do nothing ? */

After I have allocated the memory for the structure, and mapped the register pointers, I pass the address for pdata structure to the FIQ handler. In the FIQ handler, I have offsets for din0 and dout0, which I have thought to be 0x0 and 0x4 respectively (deducted from the structure size of 8).

But for some reason, now my FIQ is unable to set the output pin high anymore - I can't figure out what I'm doing wrong here.. Am I calculating the offset wrong there ? OR is the call STR r12, [r8, #OFFSET_DOUT0] incorrect ? The actual FIQ is somewhat more longer (it reads input state, and input from that creates some conditions), but even basic bit set seems to fail now..

解决方案

Case 1

regs.ARM_r8 = (long) dout0;
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]

Here the value in r8 is the address of the memory mapped I/O register. De-referencing it reads from the correct location.

Case 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);
pdata->dout0 = ioremap(HW_PINCTRL_DOUT0, 0xffff);
...
//In the FIQ handler:
LDR r12, [r8, #OFFSET_DOUT0]
ORR r12, r12, #0x20 /* set pin 5 high in dout0 register */
STR r12, [r8, #OFFSET_DOUT0] /* This will do nothing ? */

In this case, you have retrieved the address of the GPIO controller and your are ORRing with the address! You need to de-reference once again.

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

这篇关于从FIQ中断处理程序访问内核驱动的数据失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆