Android Alarm驱动源代码分析(Alarm.c)

 

前言:

Android在Linux Kernel的基础上增加了很多的驱动程序,Alarm驱动是其中最简单的一个,整个文件只有500多行。作为驱动代码分析的一系列文章的开始,我试图仔细的分析此驱动的几乎所有函数代码,希望籍此作为温习Android驱动源代码一个良好的开端。

Android的增加了一个Alarm驱动,在kernel_root/driver/rtc/alarm.c文件中实现。Android希望提供一种递增的时钟(monotonic ),此时钟应基于硬件,使得Android的应用程序能够在设备进入休眠状态的时候,仍然运行或者唤醒设备,以此达到节电的目的。

 

1.概况

1.1 实现机理

Android Alarm基于硬件时钟,运行在硬中断中。但他本身没有实现硬件RTC的驱动,它是基于Linux高精度时钟hrtimer来实现的。

Linux高精度时钟的实现在kernel_root/kernel/Hrtimer.c文件中。

关于此部分(高精度时钟hrtimer)的分析可以参见如下两篇别人的博文:

http://blog.csdn.net/walkingman321/article/details/6133171

http://blog.csdn.net/walkingman321/article/details/6151172

 

1.2实现方式

Alarm.c在Linux Kernel中注册了一个平台设备(最终注册了一个RTC设备,保存在变量static struct rtc_device *alarm_rtc_dev;中),设备节点为/dev/alarm。

用户空间的程序通过fopen打开此节点还获得控制句柄,然后通过ioctrl来向此驱动程序发送请求。

如下文件直接使用了此驱动:

android_root/system/core/toolbox/alarm.c

android_root/frameworks/base/serices/jni/com_android_server_AlarmManagerService.cpp

android_root/system/core/toolbox/Date.c

android_root/frameworks/base/cmds/runtime/Main_runtime.cpp

android_root/frameworks/base/libs/utils/SystemClock.cpp

android_root/system/core/toolbox/Uptime.c

 

1.3使用Alarm驱动的Demo代码

如果你需要直接操作此驱动,可以参考上面文件中的使用方法。

如下示例摘自SystemClock.cpp:

#if HAVE_ANDROID_OS
    fd = open("/dev/alarm", O_RDWR);
    if(fd < 0) {
        LOGW("Unable to open alarm driver: %s\n", strerror(errno));
        return -1;
    }
    ts.tv_sec = tv.tv_sec;
    ts.tv_nsec = tv.tv_usec * 1000;
    res = ioctl(fd, ANDROID_ALARM_SET_RTC, &ts);
    if(res < 0) {
        LOGW("Unable to set rtc to %ld: %s\n", tv.tv_sec, strerror(errno));
        ret = -1;
    }
    close(fd);
#else
    if (settimeofday(&tv, NULL) != 0) {
        LOGW("Unable to set clock to %d.%d: %s\n",
            (int) tv.tv_sec, (int) tv.tv_usec, strerror(errno));
        ret = -1;
    }
#endif

 

2.驱动代码分析

2.1 主要函数清单

alarm_start_hrtimer 工具函数,alarm驱动的其他函数通过此函数为对应类型(android_alarm_type)的Alarm建立一个hrtimer定时器。

alarm_ioctl alarm驱动的ioctl函数,上层代码通过此接口向驱动程序发送操作请求。

alarm_open

alarm_release

alarm_timer_triggered

alarm_triggered_func

alarm_suspend

alarm_resume

rtc_alarm_add_device

rtc_alarm_remove_device

alarm_late_init 驱动的后置初始化函数,在alarm_init后运行(参见本节的备注)。

alarm_init 驱动的初始化函数

alarm_exit 驱动的退出函数

 

备注: 关于Linux驱动程序的启动顺序(alarm_init 和alarm_late_init)的相关说明,请参见如下博文:

http://blog.csdn.net/cstk502/article/details/6579231

 

2.2 alarm_start_hrtimer 函数

 代码及注释如下:

static void alarm_start_hrtimer(enum android_alarm_type alarm_type)
{
 struct timespec hr_alarm_time;
 if (!(alarm_enabled & (1U << alarm_type))) //根据掩码alarm_enabled来判断此类型的enabled.
  return;
 hr_alarm_time = alarm_time[alarm_type]; //保存该类型的timespec到局部变量
 if (alarm_type == ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP ||
     alarm_type == ANDROID_ALARM_ELAPSED_REALTIME)
  set_normalized_timespec(&hr_alarm_time,  //设置时间格式
   hr_alarm_time.tv_sec + elapsed_rtc_delta.tv_sec,
   hr_alarm_time.tv_nsec + elapsed_rtc_delta.tv_nsec);

//记录日志,当前版本已经Disable了这个宏,所以不会有日志出现。
 ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_FLOW,
  "alarm start hrtimer %d at %ld.%09ld\n",
  alarm_type, hr_alarm_time.tv_sec, hr_alarm_time.tv_nsec);

//为alarm_timer[alarm_type]添加一个hrtimer, 如果alarm_timer[alarm_type]已经存在一个hrtimer,则先删除然后再添加一个新的。请查看hrtimer.c中hrtimer_start_range_ns函数的实现。
 hrtimer_start(&alarm_timer[alarm_type],
        timespec_to_ktime(hr_alarm_time), HRTIMER_MODE_ABS);
}

 

总结:此函数最终为alarm_type类型在数组alarm_timer[alarm_type]上创建了一个hrtimer.

 

2.3 alarm_init函数

 

未完待续。

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
ain()主函数首先执行下面初始化函数 serial_init(); // Setup serial baud rate and interrupts settings_init(); // Load Grbl settings from EEPROM stepper_init(); // 配置步进方向和中断定时器 system_init(); // 配置引脚分配别针和pin-change中断 memset(&sys, 0, sizeof(system_t)); // Clear all system variables sys.abort = true; // Set abort to complete initialization 完成初始化设置中止 sei(); // Enable interrupts #ifdef HOMING_INIT_LOCK //宏运算(settings.flags & (1 << 4)) != 0结果flags等于执行sys.state = STATE_ALARM //系统状态赋值为报警状态 if (bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) { sys.state = STATE_ALARM; } #endif _____________________________________________________________________________________________________________________________________ 接下来是一些主要初始化循环 for(;;) { serial_reset_read_buffer(); // Clear serial read buffer gc_init(); // Set g-code parser to default state spindle_init(); //主轴 coolant_init(); //冷却液 limits_init(); //极限开关 probe_init(); //探测 plan_reset(); // Clear block buffer and planner variables 清晰块缓冲区和规划师变量 st_reset(); // Clear stepper subsystem variables. 清晰的步进系统变量。 // Sync cleared gcode and planner positions to current system position. 同步清除gcode和策划师职位当前系统位置。 plan_sync_position(); gc_sync_position(); // Reset system variables. sys.abort = false; //系统中止标志 sys_rt_exec_state = 0; //系统执行标志状态变量状态位清零。 sys_rt_exec_alarm = 0; //系统执行警报标志变量清零。 sys.suspend = false; //系统暂停标志位,取消,和安全的门。 sys.soft_limit = false; //系统限制标志状态机复位。(布尔) protocol_main_loop(); //主协议循环 } // ___________________________________________________________________________

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值