ecos kernel 是个典型的抢占式多任务的rtos,我这里想从代码上,把它的实现搭个框架出来。

分时的多任务系统是靠定时时间中断实现的,所以我从这里做切入点

有kernel 的ecos重写了interrupt 处理代码,原来的在drv_api.c里实现的,现在的在kernel/intr/intr.cxx里,时间中断的注册在kernel/common/clock.cxx里

Cyg_RealTimeClock Cyg_RealTimeClock::rtc CYG_INIT_PRIORITY( CLOCK );

// -------------------------------------------------------------------------

Cyg_RealTimeClock::Cyg_RealTimeClock()

: Cyg_Clock(rtc_resolution),

interrupt(CYGNUM_HAL_INTERRUPT_RTC,

CYGNUM_KERNEL_COUNTERS_CLOCK_ISR_PRIORITY,

(CYG_ADDRWORD)this, isr, dsr)

{

CYG_REPORT_FUNCTION();

HAL_CLOCK_INITIALIZE( CYGNUM_KERNEL_COUNTERS_RTC_PERIOD );

interrupt.attach();

interrupt.unmask_interrupt(CYGNUM_HAL_INTERRUPT_RTC);

Cyg_Clock::real_time_clock = this;

}

中断的注册很好理解,但这里有个有趣的是这个函数是怎样被调用到的,直接搜索ecos所有的代码是找不到的。一般我们有个概念c++的类在声明后就会被自动调用里面和自己名字一样的那个函数,(很久没有接触c++,忘记叫什么名字了)

这里也是这样,这里第一句就是声明这个实例,然后编译器会把这个函数放到一个特殊的段__CTOR_LIST__里面(target.ld),

然后cyg_hal_invoke_constructors()会遍历__CTOR_LIST__并执行所有的函数,cyg_hal_invoke_constructors() 是在vector.S里面被调用到的。这个“自动调用”就是这样实现的。

再看时间中断服务程序,ecos 把中断服务分为两块ISR和DSR,ISR里只做些最简单的事情,发生中断后会被直接调到,以保证kernel快速响应的效果。把其他的事情都放到DSR里面,DSR会被稍后调用,先看DSR里面代码

// -------------------------------------------------------------------------

void Cyg_RealTimeClock::dsr(cyg_vector vector, cyg_ucount32 count, CYG_ADDRWORD data)

{

//    CYG_REPORT_FUNCTION();

Cyg_RealTimeClock *rtc = (Cyg_RealTimeClock *)data;

CYG_INSTRUMENT_CLOCK( TICK_START,

rtc->current_value_lo(),

rtc->current_value_hi());

>>这里是提供系统时钟

rtc->tick( count );

#ifdef CYGSEM_KERNEL_SCHED_TIMESLICE

#if    0 == CYGINT_KERNEL_SCHEDULER_UNIQUE_PRIORITIES

// If timeslicing is enabled, call the scheduler to

// handle it. But not if we have unique priorities.

>>分时多任务的处理,它的实现在算法里,我以mlqueue为例

Cyg_Scheduler::scheduler.timeslice();

#endif

#endif

CYG_INSTRUMENT_CLOCK( TICK_END,

rtc->current_value_lo(),

rtc->current_value_hi());

}

timeslice()调用timeslice_cpu(),timeslice_cpu里要找出同一priority任务队列中下一个任务,如果有,则设置reschedule的标志:需要做任务切换。

到这里这条路就断了。但是前面我没有讲到DSR是怎样被调到的,这里要看interrupt_end()

在vector.S里被调到,interrupt_end代码在kernel/intr/intr.cxx里

//-------------------------------------

externC void

interrupt_end(

cyg_uint32          isr_ret,

Cyg_Interrupt       *intr,

HAL_SavedRegisters  *regs

)

{

//    CYG_REPORT_FUNCTION();

#ifdef CYGPKG_KERNEL_SMP_SUPPORT

Cyg_Scheduler::lock();

#endif

// Sometimes we have a NULL intr object pointer.

cyg_vector vector = (intr!=NULL)?intr->vector:0;

CYG_INSTRUMENT_INTR(END, vector, isr_ret);

CYG_UNUSED_PARAM( cyg_vector, vector ); // prevent compiler warning

#ifndef CYGIMP_KERNEL_INTERRUPTS_CHAIN

// Only do this if we are in a non-chained configuration.

// If we are chained, then chain_isr below will do the DSR

// posting.

>>这里把当前的DSR post出去,其实就是加入一个DSR 任务链表里去,之后再拿出来处理

if( isr_ret & Cyg_Interrupt::CALL_DSR && intr != NULL ) intr->post_dsr();

#endif

// Now unlock the scheduler, which may also call DSRs

// and cause a thread switch to happen.

>>这里就是多任务处理的入口了,下面再去看里面的实现

Cyg_Scheduler::unlock();

CYG_INSTRUMENT_INTR(RESTORE, vector, 0);

}

unlock()会调用unlock_inner,unlock_inner是kernel最重要的一个函数了,它是多任务切换的

执行者,来看它的实现,代码很长,只挑其中一段

//-------------------------------------

void Cyg_Scheduler::unlock_inner( cyg_ucount32 new_lock )

{

do {

#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS

// Call any pending DSRs. Do this here to ensure that any

// threads that get awakened are properly scheduled.

>>调用前面post的所有的DSR,注意里面会有reschedule flag的设置

>>下面就要用到

if( new_lock == 0 && Cyg_Interrupt::DSRs_pending() )

Cyg_Interrupt::call_pending_DSRs();

#endif

Cyg_Thread *current = get_current_thread();

// If the current thread is going to sleep, or someone

// wants a reschedule, choose another thread to run

>>这里有几种情况需要处理,一个是当前的任务主动要求休息(调用yield()),当然就要切换给别的任务;

>>另外一个就是在DSR的timeslice中找到优先级相同的下个任务需要运行;

>>还有一种是当有新的高优先级的任务加入。(所有都会调用set_need_reschedule())        if( current->state != Cyg_Thread::RUNNING || get_need_reschedule() ) {

CYG_INSTRUMENT_SCHED(RESCHEDULE,0,0);

// Get the next thread to run from scheduler

Cyg_Thread *next = scheduler.schedule();

if( current != next )

{

CYG_INSTRUMENT_THREAD(SWITCH,current,next);

// Count this thread switch

thread_switches[CYG_KERNEL_CPU_THIS()]++;

>>上下文切换,在contexts.S里

// Switch contexts

HAL_THREAD_SWITCH_CONTEXT( &current->stack_ptr,

&next->stack_ptr );

// Worry here about possible compiler

// optimizations across the above call that may try to

// propogate common subexpresions.  We would end up

// with the expression from one thread in its

// successor. This is only a worry if we do not save

// and restore the complete register set. We need a

// way of marking functions that return into a

// different context. A temporary fix would be to

// disable CSE (-fdisable-cse) in the compiler.

// We return here only when the current thread is

// rescheduled.  There is a bit of housekeeping to do

// here before we are allowed to go on our way.

>>一般就不会跑到这里了,cpu pc指针已经切换到别的任务上去了,只有等这个任务再次

>>被reschedule时,才会从这里开始执行

current_thread[CYG_KERNEL_CPU_THIS()] = current;   // restore current thread pointer

}

#ifdef CYGSEM_KERNEL_SCHED_TIMESLICE

// Reset the timeslice counter so that this thread gets a full

// quantum.

reset_timeslice_count();

#endif

clear_need_reschedule();    // finished rescheduling

}

return;

} while( 1 );

}

至此,整个框架已经出来了,对于schedule,thread,semphone,mutex,flag,mailbox等等其他概念,在ecos 发布的文档上

有比较详细的介绍(ecos reference manual),我就不再赘述了。

ecos kernel 分析 转自黑嘴公 PiPi Cat相关推荐

  1. ecos kernel 分析

    ecos kernel 是个典型的抢占式多任务的rtos,我这里想从代码上,把它的实现搭个框架出来.     分时的多任务系统是靠定时时间中断实现的,所以我从这里做切入点 有kernel 的ecos重 ...

  2. ecos代码分析(2)

    ecos代码分析(2) 228         bl      hal_mmu_init 此前内存初始化好了,sp也设置好了,可以运行C程序 170 void 171 hal_mmu_init(voi ...

  3. ecos代码分析(1)

    ecos代码分析(1) 前面分析了u-boot,再分析一下ecos,听说ecos比较复杂,所以还是采取挨船下竿的原则,分析u-boot相似的smdk2410这块开发板. 1. 首先找到链接文件 < ...

  4. (原创)eCos驱动分析 之 ISR是如何与硬件中断联系起来的?

    要想知道ecos的中断ISR是怎么与硬件中断向量联系起来的,是怎么被调用的? 那就要看下面这两个关键的函数: cyg_drv_interrupt_create() cyg_drv_interrupt_ ...

  5. 海思hi3520dv400 kernel分析(3)——设备树支持

    概念: FDT:Flattened Device Tree (扁平设备树)是一种数据结构,用来描述设备的硬件配置信息,它源自开放固件使用的设备树格式. DTS:Device tree source(设 ...

  6. kaggle竞赛系列1----elo竞赛kernel分析1

    比赛介绍: https://www.kaggle.com/c/elo-merchant-category-recommendation kerne来源: https://www.kaggle.com/ ...

  7. I.MX6ULL_Linux_系统篇(20) kernel分析-menuconfig

    linux内核的功能非常丰富,大多功能可以通过menuconfig图形界面来选择配置,但是我们面对众多的功能,往往不能快速确定配置项位置或无法理解配置项功能,本篇将对配置项做一下简要解析!(作者不建议 ...

  8. Linux kernel分析前的准备

    分析工具 "欲善其事,先利其器".Linux内核的代码量非常大,如果没有一个好的察看分析工具,那将是一件非常繁琐的事情. Vim+cscope cscope,如果你知道ctags, ...

  9. kernel停在Starting kernel 分析

    解决方法: 1.看门狗问题,可能会造成这种显现. 2.IMX6Q的PMU被bypass导致cpu没有供电而无法开机,只要donwload imx6q ldo版本的boot image即可. log: ...

  10. little kernel分析

    little kernel做为Android系统的bootloader,最早用google工程师实现,其后由高通,MTK等芯片厂商做了各自平台的适配. lk的主要功能: 初始化硬件模块,如时钟,中断, ...

最新文章

  1. 小程序 navigator 无法跳转 tabBar上的页面
  2. LeetCode 37. Sudoku Solver--数独求解(回溯法)--Java 3ms,Python 80ms 解法
  3. html清除矩形边区域,canvas清除矩形指定颜色
  4. 在Swift中使用C语言的指针
  5. HTML网页设计期末课程大作业 ---H5移动端电商购物网页设计35页面(包括主页,商品详情,转账,付款,购物车等页面) 功能齐全
  6. uniapp获取当前城市编号和信息
  7. HTTP、HTTPS、SPDY、HTTP2.0、HTTP3.0 —— 通信协议学习笔记(二)
  8. Mac 安装仿宋GB2312 For Word/WPS
  9. 小米笔记本关闭UEFI secure boot
  10. GPS同步时钟(NTP时钟服务器)常见故障解决与价格差异分析
  11. 牛客网--16128--小名的回答
  12. java win7 管理员权限_win7系统获取管理员权限批处理的操作方法
  13. python--DataFrame随机抽样
  14. 应届生为什么觉得女生更适合银行工作?(上)
  15. 关闭Win10自动磁盘碎片整理
  16. 视频教程-【CVPR2018】3D Pose Estimation and 3D Model Retriev-强化学习
  17. MSRA实习申请经验分享
  18. 中学物理教学参考杂志社中学物理教学参考编辑部2022年第21期目录
  19. java.double和 floa 的区别
  20. 查新检索报告哪里出?

热门文章

  1. 异常与调试之SEH、UEH、VEH、VCH以及SEH原理
  2. php webshell 过狗
  3. IT大学生成长周报 | 第 6 期
  4. ffmpeg 裁剪视频
  5. 安装已中止,安装程序并未成功地运行完成 - Windows
  6. tortoisegit 小乌龟的使用
  7. python+opencv修改像素值、创建图像
  8. python中if语句中可用break_python跳出if语句
  9. RegExp-2 【正则量词、属性、方法、使用技巧】
  10. 巡检设备RFID技术应用浅析