您不需要破解内核。您只需要将进程移出调度程序队列即可。
#include<sched.h>
struct sched_param param;
param.sched_priority = sched_get_priority_max(SCHED_FIFO);
if( sched_setscheduler( 0, SCHED_FIFO, ¶m ) == -1 )
{
perror("sched_setscheduler");
return -1;
}
从现在开始,我们的流程将从cat /proc/sys/kernel/sched_rt_runtime_us
每个cat /proc/sys/kernel/sched_rt_period_us
毫秒的时间段中获取毫秒数,执行不间断,而在这段时间内没有被抢占的风险(实际上,默认情况下,BerryBoot每秒有0.95s的时间)。这些值,但在这里我不需要更多。
我正在使用计时器功能(以毫秒为单位)(这大约是我需要的精度),clock_gettime()
用以计时延迟。
调用会timer(1)
重置它,调用会timer(0)
返回自重置以来的时间。
#include<time.h>
typedef unsigned long long ulong64;
ulong64 timer(unsigned char reset)
{
struct timespec t;
static struct timespec lt={0,0};
clock_gettime(CLOCK_REALTIME, &t);
if(reset)
{
lt.tv_sec = t.tv_sec;
lt.tv_nsec = t.tv_nsec;
}
int r = ((ulong64)(t.tv_sec - lt.tv_sec))*1000 + (t.tv_nsec - lt.tv_nsec)/1000000;
return r;
}
您需要针对rt
库进行链接以进行编译-添加-lrt
到您的gcc命令中。
现在,进入主循环。我将开关输入用于“用户请求”,但是您可以使用网络,计时器或其他任何方式。您需要做的就是将布尔值放入in
。
while(1)
{
//when idle, return a lot of CPU time back to the system.
//A call every 100ms is perfectly sufficient for responsive reaction.
usleep(100000);
in = bcm2835_gpio_lev(SWITCH_PIN);
out = bcm2835_gpio_lev(TRIAC_PIN);
if(in==out) continue; //nothing to do; wait user input, return control to system.
//The output needs to be changed.
//First, let's wait for zero-crossing event.
timer(TIMER_RESET);
zx = bcm2835_gpio_lev(ZEROXING_PIN);
//We don't want to freeze the system if the zero-xing input is broken.
//If we don't get the event within reasonable time,
// (like three half-sines of the power; ZEROXING_TIMEOUT = 70)
// we're going to bail.
while(timer(TIMER_READ) < ZEROXING_TIMEOUT)
{
if(zx != bcm2835_gpio_lev(ZEROXING_PIN))
{
//Event detected.
timer(TIMER_RESET);
break;
}
}
if(timer(TIMER_READ) >= ZEROXING_TIMEOUT) continue; //Zero-crossing detection is broken, try again soon.
//Now we are mere milliseconds after zero-crossing event arrived
// (but it could have taken some time to arrive) so let's wait for the next one, making adjustments for the system delay.
// This is to be worked out using an oscilloscope and trial and error.
// In my case BIASED_DELAY = 19.
while(timer(TIMER_READ)<BIASED_DELAY) ;
//We can reasonably expect if we perform this right now:
bcm2835_gpio_set_pud(TRIAC_PIN, in);
//the signal will reach the output right on time.
// The 100ms delay on return to start of the loop should be enough
// for the signals to stabilize, so no need for extra debouncing.
}