利用qemu触发short设备/dev/shortint中断的方法

   日期:2021-03-14     浏览:101    评论:0    
核心提示:记得2007年的时候,第一次开始学习ldd3这本书,到书的后面需要设计到真实硬件才可以验证学习的内容,当时废了好大的力气。为了验证书里面并口的内容,专门买了电脑、LED灯、电焊、锡、面包板什么的,然后把LED灯焊接在并口的9号和10号引脚并接到面包板上,通过拉高电平触发并口中断,看输出也要看LED灯的闪烁,费死劲了。这几天叫我弟驱动变成,突然想到用虚拟化设备来触发中断,让他验证short设备,于是就改了一下qemu,来从hypervisor里主动触发中断,这样妈妈再也不用担心我的电烙铁烫到我了。这样就大大

记得2007年的时候,第一次开始学习ldd3这本书,到书的后面需要设计到真实硬件才可以验证学习的内容,当时废了好大的力气。为了验证书里面并口的内容,专门买了电脑、LED灯、电焊、锡、面包板什么的,然后把LED灯焊接在并口的9号和10号引脚并接到面包板上,通过拉高电平触发并口中断,看输出也要看LED灯的闪烁,费死劲了。这几天叫我弟驱动变成,突然想到用虚拟化设备来触发中断,让他验证short设备,于是就改了一下qemu,来从hypervisor里主动触发中断,这样妈妈再也不用担心我的电烙铁烫到我了。这样就大大降低了学习linux驱动的门槛,让我们这些软件程序猿再也不用苦恼于没有硬件设备,无法入门了。话不多说,这里来记录一下我的代码修改和实验方法,供新入行的小朋友参考,尽快入手驱动的编写。

我用的qemu版本是:v3.0.0-rc4

首先我们知道LDD3的short设备占用的知名IO端口是并口的,端口地址是 0x378,有了这些知识后,就可以知道并口模拟代码在 hw/char/parallel.c中。触发中断的函数是:parallel_update_irq() ,可以看到做法是发现有中断pending,那么先拉高电平,处理完后,irq_pending为0,那么拉低电平,表示处理完成,以便下一次触发

static void parallel_update_irq(ParallelState *s)
{
    if (s->irq_pending)
        qemu_irq_raise(s->irq);
    else
        qemu_irq_lower(s->irq);
}

那么我们就可以增加我们的触发函数了,hmp_trigger_parallel_update_irq(), 注意我们把irq_pending设为1后,强制用parallel_update_irq拉高电平触发中断,但是千万注意还需要把 irq_pending 设置0,再次用parallel_update_irq把中断线的电平拉低,恢复状态,告诉虚拟中断控制器中断处理完成了。只有这样,才可以再次触发中断,千万注意!!


ParallelState *g_hmp_parallel_s = NULL;
void hmp_trigger_parallel_update_irq(void)
{
    int irq_pending_store = 0;
    if(!g_hmp_parallel_s){
        printf("%s: can not trigger intr because ParallelState is null \n",__func__);    
    }

    printf("%s: trigger a parallel intr\n",__func__);

    irq_pending_store = g_hmp_parallel_s->irq_pending;
    
    g_hmp_parallel_s->irq_pending = 1;
    parallel_update_irq(g_hmp_parallel_s);
    
    g_hmp_parallel_s->irq_pending = 0;
    parallel_update_irq(g_hmp_parallel_s);
    g_hmp_parallel_s->irq_pending = irq_pending_store;
    return;
}



static void parallel_isa_realizefn(DeviceState *dev, Error **errp)
{
    static int index;
    ISADevice *isadev = ISA_DEVICE(dev);
    ISAParallelState *isa = ISA_PARALLEL(dev);
    ParallelState *s = &isa->state;

    
    g_hmp_parallel_s = s;
    

    int base;
    uint8_t dummy;
    //.................

}

 

同时把hmp_trigger_parallel_update_irq(), 声明到头文件里面 include/hw/char/parallel.h


void hmp_trigger_parallel_update_irq(void);

有了功能函数,下面,我们需要添加qemu命令行,就可以按需触发中断了

hmp-commands.hx 中加入

    {
        .name       = "parallel_intr_trigger",
        .args_type  = "",
        .params     = "",
        .help       = "trigger parallel interrupt",
        .cmd        = hmp_parallel_trigger_intr,
    },

STEXI
@item hmp_parallel_trigger_intr
@findex hmp_parallel_trigger_intr
trigger parallel interrupt. Parallel dev must be exsisted
ETEXI

hmp.c中加入


void hmp_parallel_trigger_intr(Monitor *mon, const QDict *qdict)
{
    monitor_printf(mon, "%s: begin trigger parallel intr\n", __func__);
    printf("%s: begin trigger parallel intr\n", __func__);
    hmp_trigger_parallel_update_irq();
    monitor_printf(mon, "%s: trigger parallel intr done\n", __func__);
    printf("%s: trigger parallel intr done\n", __func__);

}

hmp.h中加入声明


void hmp_parallel_trigger_intr(Monitor *mon, const QDict *qdict);

我们现在就可以启动虚拟机实验试一下了,注意qemu中加入如下参数 “ -monitor stdio  -parallel /dev/pts/2 ” 来是能hmp和并口设备,我的命令行如下

sudo gdb --args /home/liufeng/workspace/tools/bin/qemu-system-x86_64 -machine accel=kvm -m 4G \
-hda /home/kvm/disk/vm0.img \
-vnc 192.168.199.166:0 -monitor stdio \
-netdev type=tap,id=eth0,ifname=tap30,script=no,downscript=no -device e1000,netdev=eth0,mac=12:03:04:05:06:08 \
-parallel /dev/pts/2

启动后,看看qemu命令行是否存在 parallel_intr_trigger

我们进入虚拟机,加载short驱动,我们可以看到 0x378开始的7个端口,给了short设备

然后验证一下中断是否起作用,在qemu中运行命令行

运行3次命令行后,在虚拟机中查看中断触发情况,可以看到 short设备注册的7号中断有3次触发

运行short设备的实验情况,可以看到interrupt的中断正常触发了读写

好了,到这里我们可以正常玩弄第十章的所有实验了,对入门同学最难找到环境的 硬件端口通信和中断就可以快速入手验证和学习了,希望对大家有所帮助,再见

 

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
更多>相关资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服