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

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

问题描述

在 ARM FIQ 中断上,我们保留了一些仅供 FIQ 使用的寄存器,这些是保存状态"的便捷方式,例如 FIQ 调用之间的数据传输.

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.

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

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]

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

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

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

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 ? */

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

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).

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

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..

推荐答案

案例 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]

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

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

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 ? */

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

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天全站免登陆