Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Два потока на си
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему
sergey sva
Как на си реализовать два потока, без использования ОС ? к примеру таймер 0 вызывает
программу обработки прерываний, в который происходит переключение между потоками.
Может что прочитать посоветуете или ссылку дадите.
MrYuran
Для начала, обработка прерывания - уже отдельный поток.

Всё зависит от задачи.
Если подразумевается активное взаимодействие процессов, приоритетная обработка и т.д., проще применить готовую RTOS, чем изобретать свой велосипед.
Andrey_M
Принцип реализации многозадачности примерно один что на си что на асме. Описан например в книжке Кристиан Тавернье PIC-микроконтроллеры практика применения страница 172.
Например одна задача выполняется в основном цикле а другая в прерывании. Далее организуем ветвление по необходимым признакам для выполнения дополнительных задач или организуем временной цикл и разносим задачи по времени. beer.gif
sergeeff
Практически такие вещи на "чистом" С не напишешь, слишком много "тонких" моментов придется писать на ассеблере (или inline ассемлере). Деиствительно лучше велосипед не изобретать, а воспользоваться чем-то готовым из RTOS, благо выбор достаточно широк.
Сергей Борщ
Цитата(sergeeff @ Sep 10 2008, 19:02) *
Практически такие вещи на "чистом" С не напишешь
Можно написать. Встречалась (сейчас не могу найти, может у кого-то из участников ссылка сохранилась) реализация корпоративной многозадачности на основе switch() case замаскированного хитрыми макросами препроцессора. Реализовано довольно красиво, но видя, насколько неэффективна реализация switch() case на некоторых (avr) контроллерах, наверное использование ОС (в которой что надо реализовано на ассемблере) будет более предпочтительным.


Цитата(MacGregor @ Sep 13 2008, 21:18) *
выделено мной красным цветом
И что "именно"? Снова доктора сюда занесло?
solosh
Цитата(Сергей Борщ @ Sep 13 2008, 22:08) *
Можно написать. Встречалась (сейчас не могу найти, может у кого-то из участников ссылка сохранилась)


Protothreads - Lightweight, Stackless Threads in C
http://www.sics.se/~adam/pt/expansion.html
Сергей Борщ
Цитата(solosh @ Sep 14 2008, 13:28) *
Protothreads - Lightweight, Stackless Threads in C
Ага, оно.
Rst7
Цитата
Практически такие вещи на "чистом" С не напишешь


Как раз для камней типа AVR пишется на раз. Необходимые средства в штатной сишной библиотеке есть.

Код
#include <setjmp.h>

jmp_buf main_task;
jmp_buf rs_task;
char rs_rstack[8];
char rs_cstack[64];

__interrupt void CNTX_SWT(void)
{
  if (!setjmp(main_task)) //Запомнили контекст осн. задачи
  {
    longjmp(rs_task,1); //Перешли в контекст RS_TRX
  }
}


#pragma vector=USART0_RXC_vect
__interrupt __raw void rs_rx(void)
{
    ((void(*)(void))CNTX_SWT)();
}

#pragma vector=USART0_UDRE_vect
__interrupt __raw void rs_tx(void)
{
    ((void(*)(void))CNTX_SWT)();
}

#pragma vector=USART0_TXC_vect
__interrupt __raw void rs_txc(void)
{
    ((void(*)(void))CNTX_SWT)();
}

#pragma vector=TIMER1_OVF_vect
__interrupt __raw void rs_timeout(void)
{
    ((void(*)(void))CNTX_SWT)();
}

void wait_int()
{
  if (!setjmp(rs_task)) //Запомнили контекст RS_TASK
  {
    longjmp(main_task,1); //Перешли в контекст осн. задачи
  }
}

__task __noreturn RS_TRX(void)
{
  //Ну, например, вечное эхо
  for(;;)
  {
    char c;
    UCSR0B_RXCIE0=1; //Разрешили прерывания от приемника
    wait_int();
    c=UDR;
    UDR=c;
    UCSR0B_TXCIE0=1; //Разрешаем прерывания от передатчика
    wait_int(); //Ждемс
   }
}

void InitRS(void)
{
  __disable_interrupt();
  ((unsigned int *)rs_task)[10]=((unsigned int)rs_rstack)+7; //SP
  ((unsigned int *)rs_task)[8]=((unsigned int)rs_cstack)+64; //Y
  ((unsigned int *)rs_task)[9]=(unsigned int)RS_TRX; //Адрес перехода
  if (!setjmp(main_task)) longjmp(rs_task,1); //Переходим в RS_TRX
  __enable_interrupt();
}


Тут будет выполнен запуск фоновой задачи RS_TRX, которая будет ждать символа из уарта и отправлять его обратно, ждать готовности передатчика и по кругу.
Цыкетчик
Цитата(Rst7 @ Sep 14 2008, 17:51) *
Как раз для камней типа AVR пишется на раз. Необходимые средства в штатной сишной библиотеке есть.

ИМХО, это не от "камня" зависит а от разработчиков компилятора
Rst7
Цитата
ИМХО, это не от "камня" зависит


Если смущает модификатор __raw (а это единственная вещь в приведенном коде, характерная для IAR'а, хотя, имеющая аналог, например, в GCC) - так он только для того, чтобы уменьшить время нахождения в состоянии с запрещенными прерываниями. Без него тоже все стреляет. А основную работу тут делают библиотечные функции setjmp/longjmp.

Объясняю, почему "камень класса AVR" - потому что нет режима супервизора. На ARM, например, метод тоже имеет право на существование, но либо в виде принудительного переключения на другой поток (типа yield()), либо с отдельным костылем (возможно на асме, возможно intrinsic-функцией компилятора, если таковая существует) для сохранения и восстановления User Mode SP в процедуре IRQ.

Аналогичный код с принудительным переключением прекрасно работает на x86 (однако, например MSVC слишком умный, он по longjmp уничтожает все объекты, созданные в стеке, посему работу с setjmp/longjmp надо выносить в отдельный файл, который собирать в режиме C, а не C++).

PS Доктор, Вы теперь в каждой теме считаете нужным отписаться, а вдруг флуд поднимется?
Dog Pawlowa
Цитата(sergey sva @ Sep 10 2008, 15:53) *
Как на си реализовать два потока, без использования ОС ? к примеру таймер 0 вызывает
программу обработки прерываний, в который происходит переключение между потоками.
Может что прочитать посоветуете или ссылку дадите.

Вам точно шашечки потоки нужны?
Для практических целей можно легко ограничить последовательность команд при обслуживании чего-нибудь, выйти и отдать управление другому сервису.
sergey sva
Цитата(Dog Pawlowa @ Sep 24 2008, 22:16) *
Вам точно шашечки потоки нужны?
Для практических целей можно легко ограничить последовательность команд при обслуживании чего-нибудь, выйти и отдать управление другому сервису.

Было бы неплохо на исходник посмотреть ?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.