rt2860v2源码分析一

git出源码:
https://github.com/wuqiong/rt2860v2-for-openwrt-mt7620

再rt2860v2中搜索字符串__init, 找到驱动模块的入口函数:

os/linux/rbus_main_dev.c:37:int __init rt2880_module_init(VOID);
os/linux/pci_main_dev.c:46:static int __init rt2860_init_module(void);
os/linux/pci_main_dev.c:276:static INT __init rt2860_init_module(VOID)

查看rbus_main_dev.cpci_main_dev.c文件,可以发现rt2860v2驱动在pci_main_dev.c中进行了pci设备模块初始化,在rbus_main_dev.c 中是网络设备模块初始化。

pci_main_dev.c 中分析rt2860v2驱动程序的pci设备模块初始化:

static INT __init rt2860_init_module(VOID)
{
    DBGPRINT(RT_DEBUG_ERROR, ("register %s\n", RTMP_DRV_NAME));

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
    return pci_register_driver(&rt2860_driver);
#else
    return pci_module_init(&rt2860_driver);
#endif
}


/* */
/* Driver module unload function */
/* */
static VOID __exit rt2860_cleanup_module(VOID)
{
    pci_unregister_driver(&rt2860_driver);
}

module_init(rt2860_init_module);
module_exit(rt2860_cleanup_module);

__init 中,pci_register_driver 进行了pci设备注册,rt2860v2驱动模块挂载在pci总线上。

/* */
/* Our PCI driver structure */
/* */
static struct pci_driver rt2860_driver =
{
    name:       RTMP_DRV_NAME,
    id_table:   rt2860_pci_tbl,
    probe:      rt2860_probe,
#if LINUX_VERSION_CODE >= 0x20412
    remove:     __devexit_p(rt2860_remove_one),
#else
    remove:     __devexit(rt2860_remove_one),
#endif

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
#ifdef CONFIG_PM
    suspend:    rt2860_suspend,
    resume:     rt2860_resume,
#endif
#endif
};

PCI设备驱动结构,填充结构体

  • name : RTMP_DRV_NAME 就是rt2860
  • id_talbe :pci设备表,指明该驱动适合那些设备
  • probe :检测驱动设备
  • remove:卸载驱动设备
  • suspend:挂起设备使之处于节能状态
  • resume:唤醒处于挂起态的设备

id_table 中,驱动将选择对应的硬件设备,用此id来识别硬件信息:

/* */
/* Ralink PCI device table, include all supported chipsets */
/* */
static struct pci_device_id rt2860_pci_tbl[] __devinitdata =
{
#ifdef RT2860
    {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2860_PCI_DEVICE_ID)},     /*RT28602.4G */
    {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2860_PCIe_DEVICE_ID)},
    {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2760_PCI_DEVICE_ID)},
    {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2790_PCIe_DEVICE_ID)},
    {PCI_DEVICE(VEN_AWT_PCI_VENDOR_ID, VEN_AWT_PCIe_DEVICE_ID)},
    {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7708)},
    {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7728)},
    {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7758)},
    {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7727)},
    {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7738)},
    {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7748)},
    {PCI_DEVICE(EDIMAX_PCI_VENDOR_ID, 0x7768)},
#endif /* RT2860 */
    {0,}        /* terminate list */
};

分析pci设备的probe函数,即rt2860v2_probe,该函数内容如下:


/* */
/* PCI device probe & initialization function */
/* */
static INT __devinit   rt2860_probe(
    IN  struct pci_dev              *pci_dev, 
    IN  const struct pci_device_id  *pci_id)
{
    VOID                *pAd = NULL;
    struct  net_device  *net_dev;
    PVOID               handle;
    PSTRING             print_name;
    ULONG               csr_addr;
    INT rv = 0;
    RTMP_OS_NETDEV_OP_HOOK  netDevHook;
    ULONG                   OpMode;

    DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_probe\n"));

/*PCIDevInit============================================== */
    /* wake up and enable device */
    if ((rv = pci_enable_device(pci_dev))!= 0)//使能pci设备
    {
        DBGPRINT(RT_DEBUG_ERROR, ("Enable PCI device failed, errno=%d!\n", rv));
        return rv;
    }

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
    print_name = pci_name(pci_dev);
#else
    print_name = pci_dev->slot_name;
#endif /* LINUX_VERSION_CODE */

    if ((rv = pci_request_regions(pci_dev, print_name)) != 0)//申请PCI的resource
    {
        DBGPRINT(RT_DEBUG_ERROR, ("Request PCI resource failed, errno=%d!\n", rv));
        goto err_out;
    }

    /* map physical address to virtual address for accessing register */
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我会尽力回答你的问题。首先,RT-Thread是一个实时操作系统,它提供了一些基本的实时操作系统功能,例如线程、信号量、消息队列、定时器等。其中,定时器是一种非常重要的实时操作系统功能,它可以用来在指定的时间间隔内执行一些操作。 在RT-Thread中,定时器的实现是基于软件定时器,即在内核中维护一个定时器列表,每个定时器都有一个超时时间。当定时器到期时,内核会调用定时器回调函数来执行相应的操作。 下面是RT-Thread定时器的源码分析: 1. 定时器结构体 在RT-Thread中,定时器的结构体定义如下: ```c struct rt_timer { char name[RT_NAME_MAX]; /* 定时器名称 */ rt_list_t list; /* 定时器列表 */ rt_tick_t timeout_tick; /* 定时器超时时间 */ rt_tick_t init_tick; /* 定时器初始时间 */ rt_uint8_t flag; /* 定时器标志 */ rt_uint8_t state; /* 定时器状态 */ void (*timeout_func)(void* parameter); /* 定时器回调函数 */ void* parameter; /* 回调函数参数 */ }; ``` 可以看到,定时器结构体包含了定时器的名称、超时时间、标志、状态、回调函数等信息。 2. 定时器创建 在RT-Thread中,定时器的创建函数是rt_timer_create(),它的函数原型如下: ```c rt_err_t rt_timer_create(rt_timer_t *timer, const char *name, void (*timeout_func)(void* parameter), void* parameter, rt_tick_t time, rt_uint8_t flag); ``` 其中,timer表示定时器指针,name表示定时器名称,timeout_func表示定时器回调函数,parameter表示回调函数参数,time表示定时器超时时间,flag表示定时器标志。 rt_timer_create()函数会在内核中创建一个定时器,并将定时器添加到定时器列表中。如果创建成功,函数返回RT_EOK,否则返回错误码。 3. 定时器启动 在RT-Thread中,定时器的启动函数是rt_timer_start(),它的函数原型如下: ```c rt_err_t rt_timer_start(rt_timer_t timer); ``` rt_timer_start()函数会启动指定的定时器,并将其状态设置为RT_TIMER_FLAG_ACTIVATED。如果启动成功,函数返回RT_EOK,否则返回错误码。 4. 定时器停止 在RT-Thread中,定时器的停止函数是rt_timer_stop(),它的函数原型如下: ```c rt_err_t rt_timer_stop(rt_timer_t timer); ``` rt_timer_stop()函数会停止指定的定时器,并将其状态设置为RT_TIMER_FLAG_DEACTIVATED。如果停止成功,函数返回RT_EOK,否则返回错误码。 5. 定时器删除 在RT-Thread中,定时器的删除函数是rt_timer_delete(),它的函数原型如下: ```c rt_err_t rt_timer_delete(rt_timer_t timer); ``` rt_timer_delete()函数会删除指定的定时器,并释放相应的资源。如果删除成功,函数返回RT_EOK,否则返回错误码。 以上就是RT-Thread定时器的源码分析,希望能对你有所帮助。如果你有其他问题,可以继续问我。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值