要使用钩子必须在配置里打开钩子的配置,在rt-config.h里添加HOOK宏定义(如果没有的话)
#define
RT_USING_HOOK
然后在应用程序里设置钩子函数
#ifdef
RT_USING_HOOK
rt_thread_idle_sethook(rt_hw_led_flash)
#endif
下面就是该怎样实现这个函数了
void
rt_hw_led_flash(void)
{
rt_uint32_t
i
rt_hw_led_init()
while
(1)
{
for(i
=
0
i
<
2700000
i++)
//500ms
GPIO_WriteBit(state_led_gpio,
state_led_pin,
(BitAction)(1-GPIO_ReadOutputDataBit(state_led_gpio,
state_led_pin)))
}
}
这样写过之后,在系统空闲的时候就会执行这个函数,当然,如果系统繁忙的时候是不会进入这个idel任务的,不过如果系统一直处于繁忙的状态就是有问题了
另外一点记住,在这个函数里不能调用系统提供的使线程挂起的函数
例如:
rt
thread
delay,
rt
sem
take
等
while
(1)
{
for(i
=
0
i
<
2700000
i++)
//500ms
GPIO_WriteBit(state_led_gpio,
state_led_pin,
(BitAction)(1-GPIO_ReadOutputDataBit(state_led_gpio,
state_led_pin)))
}
关键是这个while(1)没跳出的,所以全部在这里执行了。
好像还有同学对其中一些并不是完全清楚,所以继续解析下,当做结贴:
1.
idle线程是系统中最后一道防线,它将是系统中,如果无其他事可干时的最后能够运行的线程。
--
所以idle线程不应该被阻塞。如果你有自己的线程能够成为这最后一道防线,那么这个限制将不存在。而对于一些原来系统中放在idle线程中做的工作(例如原来的最终的线程删除动作),在0.4.x中,可以手工调用rt_thread_idle_excute函数来执行。
2.
当系统空闲的时候,idle线程将执行这个钩子函数。
假设钩子函数一次运行会执行1ms,如果idle线程有机会运行200ms,那么钩子函数将被调用200次。
3.
钩子函数运行时,不应该把idle线程总是纠结在这个函数中运行,必须要让idle线程有机会去运行rt_thread_idle_excute函数(因为还有一些事情等待idle线程去处理)。
--
所以在钩子函数中,不应该使用while(1)的方式。
while(1)
{
if
(
indicator
==
RT_TRUE)
{
....do
something
}
else
delay(20ms)
}
这样那20ms会执行idle线程吧,问题是idle
20ms够吗,如果我改20ms为5ms呢?
如果没有其他线程处理事务,将转换到idle线程去,通常idle线程中的系统任务会在0.xx
ms以内执行完毕
(1)Posix标准中有有名信号灯和无名信号灯之分,对于有名信号灯,可以用sem_open来创建,其prototype是:sem_t *sem_open(const char *name, int oflag)//打开已有的信号灯
sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned value)//一般是创建信号灯。
期中name是信号灯的名字, oflag是0, O_CREAT 或者 O_CREAT | O_EXCL, 如果指定O_CREAT, 那么mode和value对应创建该信号的模式和初始值。 如果指定了O_EXCL, 而且该信号灯已经在系统中存在,那调用会出错返回SEM_FAILED常量。 对于Linux内核来说,有名信号灯是很晚才加入内核中的,创建或是打开有名信号时候,应该指定”/semname“名字,对应的信号灯创建在/dev/shm目录下,名字是/dev/shm/sem.semname. BTW, 用gcc/g++编译实用信号灯功能的程序时候,应该引用librt库,(e.g., g++ -lrt sem.cpp). 关闭已打开的信号灯,用sem_close(sem_t *sem). 关闭信号灯并不意味着系统会删除它,要删除一个信号灯,需要调用sem_unlink(sem_t *sem)。 有名信号灯一般是为了进程之间同步实用的。 无名信号灯,一般是为一个进程内的不同线程之间同步使用的。 创建无名信号灯的方法如下:
sem_t sem
sem_init(&sem, int shared, unsigned int value)//初始化信号灯。
......
sem_destroy(&sem)//清除信号灯。
(2)信号灯的使用和状态。
信号灯一般用来描述不同线程所共享的公共资源的数量,每一个信号灯都有一个叫做信号量的非负整数与之相连;信号量一般代表公共资源的数目,比如空闲列表中的缓冲区数目,视频中读入帧的数目,等等。对于一个线程可以用sem_wait, sem_post函数来改变一个信号灯的信号量。
sem_wait(sem_t &sem)
sem_wait的语义如下:
{
while(信号量==0)
等待; //此处线程被挂起,等待其他线程调用sem_post唤醒之。
信号量减1;
}
注意:测试信号量是否为零,和减一的操作是原子的,也就是说期间不会发生线程切换。
与sem_wait对应的调用是sem_post,语义如下:
{
信号量加1;
唤醒等待该信号量的线程;//调用sem_wait并等待的线程。
}
该操作也是原子的。
信号灯的状态可以用sem_getvalue来查看。一般来说sem_wait和sem_post的调用不必在同一个线程内成对出现(象mutex那样,lock/unlock要配对出现)。 一般的情形是这样的,一个线程等待资源可用,调用sem_wait, 另外一个线程生成资源,然后调用sem_post,唤醒等待该资源的线程。因为信号灯所描述的是线程间公共资源,使用的时候一般和mutex一起使用,mutex保证访问公共资源的线程排他性,信号灯表示资源的可用性。
在sembuf结构中,sem_num是相对应的信号量集中的某一个资源,所以其值是一个从0到相应的信号量集的资源总数(ipc_perm.sem_nsems)之间的整数。sem_op指明所要执行的操作,sem_flg说明函数semop的行为。sem_op的值是一个整数.释放相应的资源数,将sem_op的值加到信号量的值上.欢迎分享,转载请注明来源:夏雨云
评论列表(0条)