#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <asm/io.h>
#include "rtai.h"
#include "rtai_sched.h"
// Две задачи реального времени
static RT_TASK sound_task;
static RT_TASK delay_task;
static RTIME sound_period_ns = 1e5; // 100 000 нс = 10 kHz
static RTIME delay_period_ns = 1e9; // 1000 000 000 нс = 1 Hz
#define SOUND_PORT 0x61 // адрес порта динамика
#define SOUND_MASK 0x02 // бит порта динамика
// Разделяемая переменная обеими задачами
static int delay_count = 2;
// =============================================================
void sound_function(int arg)
{
int delay_left = delay_count; // Каждый раз уменьшается
unsigned char sound_byte;
unsigned char toggle = 0;
while (1)
{
if (delay_left > 0) // Время задержки еще осталось
{
delay_left--;
}
else // если время переключения динамика
{
sound_byte = inb(SOUND_PORT);
if (toggle)
{
sound_byte = sound_byte | SOUND_MASK;
}
else
{
sound_byte = sound_byte & ~SOUND_MASK;
}
outb(sound_byte, SOUND_PORT);
toggle = ! toggle;
delay_left = delay_count; // Перезагружать время задержки
}
rt_task_wait_period();
}
return;
}
//=========================================
void delay_function(int arg)
{
while (1)
{
delay_count++; //Каждый раз частота увеличивается
rt_task_wait_period();
}
return;
}
//==========================================
int init_module(void)
{
RTIME sound_period_count; //1е5
RTIME delay_period_count; //1е9
RTIME timer_period_count;
//Установка таймера в чисто периодическом режиме
rt_set_periodic_mode();
// Установка периода таймера
sound_period_count = nano2count(sound_period_ns);
delay_period_count = nano2count(delay_period_ns);
//Запускаем таймер
start_rt_timer(sound_period_count);
rt_task_init(&sound_task, sound_function, 0, 1024, 0, 0, 0);
rt_task_init(&delay_task, delay_function, 0, 1024, 1, 0, 0);
rt_task_make_periodic(&sound_task,
rt_get_time() + sound_period_count,
sound_period_count);
rt_task_make_periodic(&delay_task,
rt_get_time()+ delay_period_count,
delay_period_count);
return 0;
}
// ============================================================
void cleanup_module(void)
{
rt_task_delete(&sound_task);
rt_task_delete(&delay_task);
outb(inb(SOUND_PORT) & ~SOUND_MASK, SOUND_PORT);
return;
}