Skip to content

Latest commit

 

History

History
257 lines (182 loc) · 5.87 KB

嵌入式系统设计实验报告三.md

File metadata and controls

257 lines (182 loc) · 5.87 KB
嵌入式系统设计实验报告
(三)




























作者:康赣鹏

学号:14130140377

Email:[email protected]

教师:朱光明


##Tasklet与工作队列 ###一、实验目的

掌握字符设备驱动程序中Tasklet和工作队列的编写和调用方法。

分析对比Tasklet和工作队列的差异。 ###二、实验要求

按实验内容编写驱动程序及测试程序

编译驱动程序

在嵌入式设备上加载驱动程序并进行测试

分析对比Tasklet和工作队列的差异

###三、实验内容

写一个简单的驱动程序,要求:

  • 定义一个Tasklet和一个工作队列,实现打印输出;
  • 定义两个定时器,定时器周期分别为T1和T2;
  • T1周期到时调度Tasklet,T2周期到时调度工作队列;
  • 在加载驱动模块时注册Tasklet和工作队列
  • 在卸载驱动模块时销毁Tasklet和工作队列

###四、实验步骤

参考《嵌入式系统设计》课程第07讲内容,根据实验内容要求设计编写驱动程序及应用程序

编译和加载驱动程序

进行驱动程序测试

卸载驱动程序

make成功

将文件通过网线和路由器将文件发送到树莓派中

insmod 动态加载模块 查看当前的模块

dmesg 查看任务调度过程

设置tasklet和workqueue的时延

#define TIMER_TASKLET_DELAY (7*HZ);

#define TIMER_WORKQUEUE_DELAY (9*HZ);

tasklet worker

void tasklet_worker(unsigned long data) {
  printk("tasklet\n");
}

workqueue

void workqueue_worker(void * data) {
  printk("workqueue\n");
}

调度tasklet

void timer_tasklet(unsigned long arg) {
  tasklet_schedule(&task);
  struct timer_list* pTimer = (struct timer_struct *)arg;
  pTimer->expires += TIMER_TASKLET_DELAY;
  add_timer(pTimer);
}

调度workqueue

void timer_workqueue(unsigned long arg) {
  if(queue_work(workq,&workw) != 1)
    printk("TASK: fail to add workqueue\n");
  struct timer_list* pTimer = (struct timer_struct *)arg;
  pTimer->expires += TIMER_TASKLET_DELAY;
  add_timer(pTimer);
}

加载模块

static int init_task_m(void) {
  printk("TASK: start\n");
  init_timer(&tasklet_timer);
  init_timer(&workq_timer);
  unsigned long j = jiffies;
  tasklet_timer.expires  = j + TIMER_TASKLET_DELAY;
  tasklet_timer.function = timer_tasklet;
  tasklet_timer.data     = (unsigned long)(&tasklet_timer);
  workq_timer.expires    = j + TIMER_WORKQUEUE_DELAY;
  workq_timer.function   = timer_workqueue;
  workq_timer.data       = (unsigned long)(&workq_timer);
  tasklet_init(&task,tasklet_worker,NULL);
  workq = create_singlethread_workqueue("led_task");
  add_timer(&tasklet_timer);
  add_timer(&workq_timer);
}

卸载模块

static void exit_task_m(void) {
  printk("TASK: end\n");
  del_timer(&tasklet_timer);
  del_timer(&workq_timer);
  tasklet_kill(&task);
  destroy_workqueue(workq);
}

Makefile:

obj-m:=taskmod.o
taskmod-y:=tasklet_work.o

KERNELBUILD:=../../linux-rpi-4.4.y/
ccflags-y := -std=gnu99


module: tasklet_work.c
	$(MAKE) ARCH=arm -C $(KERNELBUILD)    M=$(shell pwd) modules ARCH=arm CROSS_COMPILE=armv7-rpi2-linux-gnueabihf-


clean:
	rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

代码清单:

#include <linux/uaccess.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/errno.h>

#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/timer.h>
#include <linux/time.h>
#include <linux/jiffies.h>

#define TASKLET_PUT_STR (_tasklet_str)
#define TASKLET_PUT_STR_SIZE (sizeof(TASKLET_PUT_STR)+1)
#define WORKQUEUE_PUT_STR (_workqueue_str)
#define WORKQUEUE_PUT_STR_SIZE (sizeof(TASKLET_PUT_STR)+1)

// tasklet
void tasklet_worker(unsigned long);
struct tasklet_struct task;

// workqueue
void workqueue_worker(void *);
struct workqueue_struct* workq;
static DECLARE_WORK(workw,workqueue_worker);

// timer
// for tasklet
void timer_tasklet(unsigned long);
struct timer_list tasklet_timer;
#define TIMER_TASKLET_DELAY (7*HZ);
// for workqueue
void timer_workqueue(unsigned long);
struct timer_list workq_timer;
#define TIMER_WORKQUEUE_DELAY (9*HZ);



// tasklet worker
void tasklet_worker(unsigned long data) {
  printk("tasklet\n");
}

// workqueue
void workqueue_worker(void * data) {
  printk("workqueue\n");
}

void timer_tasklet(unsigned long arg) {
  tasklet_schedule(&task);
  struct timer_list* pTimer = (struct timer_struct *)arg;
  pTimer->expires += TIMER_TASKLET_DELAY;
  add_timer(pTimer);
}

void timer_workqueue(unsigned long arg) {
  if(queue_work(workq,&workw) != 1)
    printk("TASK: fail to add workqueue\n");
  struct timer_list* pTimer = (struct timer_struct *)arg;
  pTimer->expires += TIMER_TASKLET_DELAY;
  add_timer(pTimer);
}

// INIT
static int init_task_m(void) {
  printk("TASK: start\n");
  init_timer(&tasklet_timer);
  init_timer(&workq_timer);
  unsigned long j = jiffies;
  tasklet_timer.expires  = j + TIMER_TASKLET_DELAY;
  tasklet_timer.function = timer_tasklet;
  tasklet_timer.data     = (unsigned long)(&tasklet_timer);
  workq_timer.expires    = j + TIMER_WORKQUEUE_DELAY;
  workq_timer.function   = timer_workqueue;
  workq_timer.data       = (unsigned long)(&workq_timer);
  tasklet_init(&task,tasklet_worker,NULL);
  workq = create_singlethread_workqueue("led_task");
  add_timer(&tasklet_timer);
  add_timer(&workq_timer);
}

// EXIT
static void exit_task_m(void) {
  printk("TASK: end\n");
  del_timer(&tasklet_timer);
  del_timer(&workq_timer);
  tasklet_kill(&task);
  destroy_workqueue(workq);
}

module_init(init_task_m);
module_exit(exit_task_m);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("kangkang");