Настройка таймера с помощью Microblaze?
Каков наилучший способ создать таймер с Microblaze, который позволил бы мне сделать его более похожим на функцию вроде delay_ms()
или же sleep()
в более привычных скриптах?
Легко, я могу создать глупую функцию, как это:
void delay_ms(int i) {
//mind that I am doing this on the top of my head
for(delays=0; delay<(i*((1/frequency of the device)/2)); delays++) {
}
}
... но это не приведет к тому, что процессорный процесс будет ничем, пока он не завершится, в то время как в действительности мне нужно, чтобы эта функция позволяла мне останавливать один процесс на определенный период времени, пока другой продолжает работать.
Такое возможно, без сомнения, но каково будет самое простое решение этой проблемы?
(Я использую Spartan-3A, но я считаю, что решение будет работать для разных наборов, в том числе FPGA.)
1 ответ
TL;DR
Используйте микро ОС, как FreeRTOS.
Плохой ответ
Ну, если у вас нет ОС, нет коммутации задач, но есть внешний таймер, вы можете использовать следующий подход:
Включите прерывание для вашего аппаратного таймера и управляйте счетчиком, управляемым этим прерыванием:
Вы должны иметь что-то вроде
/**timer.c**/
/* The internal counters
* each task have its counter
*/
static int s_timers[NUMBER_OF_TASKS] = {0,0};
/* on each time tick, decrease timers */
void timer_interrupt()
{
int i;
for (i = 0; i < NUMBER_OF_TASKS; ++i)
{
if (s_timer[i] > 0)
{
s_timer[i]--;
}
}
}
/* set wait counter:
* each task says how tick it want to wait
*/
void timer_set_wait(int task_num, int tick_to_wait)
{
s_timer[task_num] = tick_to_wait;
}
/**
* each task can ask if its time went out
*/
int timer_timeout(int task_num)
{
return (0 == s_timer[task_num]);
}
Если у вас есть что-то вроде таймера (приведенный выше код легко настраивается), запрограммируйте свои задачи:
/**task-1.c**/
/*TASK ID must be valid and unique in s_timer */
#define TASK_1_ID 0
void task_1()
{
if (timer_timeout(TASK_1_ID))
{
/* task has wait long enough, it can run again */
/* DO TASK 1 STUFF */
printf("hello from task 1\n");
/* Ask to wait for 150 ticks */
timer_set_wait(TASK_1_ID, 150);
}
}
/**task-2.c**/
/*TASK ID must be valid and unique in s_timer */
#define TASK_2_ID 1
void task_2()
{
if (timer_timeout(TASK_2_ID))
{
/* task has wait long enough, it can run again */
/* DO TASK 2 STUFF */
printf("hello from task 2\n");
/* Ask to wait for 250 ticks */
timer_set_wait(TASK_2_ID, 250);
}
}
И график (большое слово здесь) задач:
/** main.c **/
int main()
{
/* init the program, like set up the timer interruption */
init()
/* do tasks, for ever*/
while(1)
{
task_1();
task_2();
}
return 0;
}
Я думаю, что я описал это неудачное решение, которое не следует серьезно использовать.
Код, который я дал, полон проблем, например, что произойдет, если задача замедлится до выполнения...
Вместо этого вы - могли бы - использовать некоторые ОС RT, такие как FreeRTOS, которые очень помогают в такого рода проблемах.