Страница 2 из 3

Re: ОСРВ МАКС

Добавлено: 2019-май-14 16:05
Анисимов Александр
andelie писал(а):Заинтересовался темой и заглянул в ихнее руководство программиста (https://www.astrosoft.ru/upload/rtos-ma ... mmista.pdf).
3.2.2.6. Метод Delay
Данный статический метод выполняет задержку выполнения задачи с блокировкой ее
планирования на время timeout_m
s.
Аргумент timeout_ms определяет величину задержки в миллисекундах.
Прототип:

Код: Выделить всё

static Result Delay(uint32_t timeout_ms);
Пример из этого же описания:

Код: Выделить всё

void Task1::Execute()
{
 puts("Task1 is running");
 while (true)
{
 puts("Task2 is running");
 Task* task = new Task2();
 Add(task, Task::PriorityNormal, 0x50); 
 Delay(700);
 puts("Task2 delete");
 task->Delete();
}
}
Может так получится?

В исходнике под Cortex M3 у них этот метод так реализован:

Код: Выделить всё

Result Task::Delay(uint32_t timeout_ms)
{
	return Sch().BlockCurrentTask(timeout_ms);
}
Похоже действительно к планировщику обращаются.

Ппц.
У меня не такая ОСЬ.
И не на плюсах.
Чистый си.

Миладр, расскажите пожалуйста в что тут происходит?
У меня ось поставлена исключительно в бинорном виде. И есть всего 3 хэдера.(в скрине)
И это всё.
Пользуюсь самой новой версией CM-LYNX.

Re: ОСРВ МАКС

Добавлено: 2019-май-14 16:07
andelie
Тогда извиняюсь, видимо, я не в свое дело полез :oops: .

Re: ОСРВ МАКС

Добавлено: 2019-май-14 17:01
BY_man
МАКС для Cortex и МАКС для 1967 это далеко не близнецы-братья :)
Я почитал на хабре хорошую статью для чайников про МАКС. Но для
этого процессора, насколько я понимаю, еще много чего не сделано.

Re: ОСРВ МАКС

Добавлено: 2019-май-14 17:19
BY_man
по поводу того что выполняется только один поток.
Если самому не лезть в приоритеты , то приоритеты по умолчанию одинаковы и
все потоки должны работать. Если только какой-нибудь поток не блокирнет случайно прерывания и не
вырубит ОС :) Кстати, я не нашел нигде в доке как менять период тиков для ОС.
Пришлось из приложения поменять период 0-го таймера.
Немного подумал над вопросом о реализации задержек и не придумал ничего толкового :)
Не понимаю как в вытесняющей многозадачности как-то точно делать какие-то задержки.
В своих экспериментах я реализовал на RTC 64-разрядный счетчик (чтобы отвязаться от частоты PLL )
и задержку считал как смещение от этого счетчика. При этом если поток не достиг истечения задержки,
то я его переводил в IDLE. т.е. отдавал время не другому потоку(т.к. не знаю как отдать) , а просто экономил электроэнергию.
ОС с некоторым периодом пробуждает поток который ждет задержку и поток повторяет проверку "пора работать или
еще поспать". Итого, чем меньше период тиков для ОС, а также чем меньше потоков, тем точнее задержка.
Поморгать светодиодами получается, но как сделать что-то реальное не знаю :)

Re: ОСРВ МАКС

Добавлено: 2019-май-14 18:20
BY_man
Анисимов Александр писал(а): Миладр, расскажите пожалуйста в что тут происходит?
У меня ось поставлена исключительно в бинорном виде. И есть всего 3 хэдера.(в скрине)
И это всё.
Пользуюсь самой новой версией CM-LYNX.
Автора ОС легко узнать. Это не Миландр.
Бинарник ОС, я так понимаю, бонус к CM-LYNX :) Но чтобы точно что-то узнать,
нужно писать в техподдержку.

Re: ОСРВ МАКС

Добавлено: 2019-май-15 09:29
BY_man
Получилось реализовать задержки с помощью семафоров.
Использование семафора позволяет усыплять поток. Код , который пробуждает ждущий поток,
включил в ОС, используя подмену вектора прерываний таймера 0.
При срабатывании вектора, вызывается код который смотрит нет ли в массиве задержек активных значений.
Если нет, то управление передается в ОС.
Если задержки есть, то проверяется истечение времени задержки.
Если какая-то задержка завершилась, то активируется соответствующий ей семафор
j4 = адрес указателя на созданный семафор;;
cjmp = __ZN4macs9Semaphore6SignalEv;; // название функции в sem_post
CJMP_CALL (abs) (np) ;;
Задача, ждущая этот семафор, реально активируется.
Если просто увеличить счетчик семафора то никакой реакции от спящего потока.
Только через вызов sem_post().

Re: ОСРВ МАКС

Добавлено: 2019-май-29 19:56
Анисимов Александр
Привет.
Новый вопрос по МАКС.

Код: Выделить всё

// -----------------------------------------------------------------------------
int main(void) {
  SystemInit();
}
В main я создаю все нужные треды.
А что делать дальше?
Сейчас у меня код "выхоит из мейна".
Потоки похоже создаются внутри оси с флагом detached.

Если я поставлю while(true), то тогда всё виснит, потому что этот тред никогда не засыпает и соответсчвтенно не даёт исполнятся другим тредом.
Так же не извесно с каким приоритетом этот основной тред.

Сейчас я все треды создаю с приоритетом 0 и Не пишу в мейне while(true). Вроде это работает.
Это верно?

Re: ОСРВ МАКС

Добавлено: 2019-май-30 12:23
BY_man
судя по моему "опыту" работы с этой ОС на примере моргания светодиодами :)
main процедура это такой же поток как и все остальные. Его можно завершить через pthread_exit
или через return. Тогда он исчезнет и никому не мешает.
Приоритеты (если их не трогать) у всех потоков будут одинаковы.
while(true) в каком-то потоке может подвесить систему если этот поток более приоритетный чем другие.
Если приоритет потока с while(true) не выше других, то проблем это не создаст.

Re: ОСРВ МАКС

Добавлено: 2019-июн-12 21:28
Анисимов Александр
Новый вопрос.
Пишу такой код:

Код: Выделить всё

// -----------------------------------------------------------------------------
static void SendFrameDoneHandler(void) {
  pthread_mutex_unlock(&audio_out_mut);
}

// -----------------------------------------------------------------------------
static void * AudioOutThread(void * args) {
  while(true) {
    pthread_mutex_lock(&audio_out_mut);
    /*Do something*/
   }
}
SendFrameDoneHandler - выполняется в прерывании.
Теоретически она должна отпускать поток (который заблокирован на этой функцией pthread_mutex_lock()).
Но этого не происходит. pthread_mutex_lock возвращает значение 4 и код выполняется дальше. Но почему?
(конечно перед этим я создал мютекс с помощью pthread_mutex_init(). Создание происходит успешно. Возвращается ноль)

Re: ОСРВ МАКС

Добавлено: 2019-июн-12 21:30
Анисимов Александр
Я ожидал такого резальтата:
при после того, как произойдёт разблокировка потока, что-то выполнится и на mutex_lock потомк опять заблочится.
Но нет..продолжает выполнятся. Что я делаю не так?

Re: ОСРВ МАКС

Добавлено: 2019-июн-12 21:54
Анисимов Александр
Заменил на семафоры.
Лучше не стало.

Код: Выделить всё

// -----------------------------------------------------------------------------
static void SendFrameDoneHandler(void) {
  sem_post(&audio_out_sem);
}

// -----------------------------------------------------------------------------
static void * AudioOutThread(void * args) {
  while(true) {
    sem_wait(&audio_out_sem);
    /*Do something*/
    }
}
Теперь на sem_wait поток реально блокируется.
Прерываение реально вызывается и вызвает sem_post, который почему-то возвращает 1. (по доку 1 - это "[EINVAL] sem не относится к действительному семафору.")
И повторно поток уже не просыпается никогда.

Что означают слова "sem не относится к действительному семафору." ?А к какому тогда относится, если на него один указатель?


Ещё момент:
При созданиии семафора int sem_init(sem_t *sem, int pshared, unsigned int value);
параметр pshared означает.... (исходя из документации по позиксу)... в присланной мне миландром этого про этот параметр вообще нислова, хотя он есть).

В общем pshared означает это:

The pshared argument indicates whether this semaphore is to be shared
between the threads of a process, or between processes.

If pshared has the value 0, then the semaphore is shared between the
threads of a process, and should be located at some address that is
visible to all threads (e.g., a global variable, or a variable
allocated dynamically on the heap).

If pshared is nonzero, then the semaphore is shared between
processes, and should be located in a region of shared memory (see
shm_open(3), mmap(2), and shmget(2)). (Since a child created by
fork(2) inherits its parent's memory mappings, it can also access the
semaphore.) Any process that can access the shared memory region can
operate on the semaphore using sem_post(3), sem_wait(3), and so on.


Я пробовал и ноль ставить и больше нолю.
Всё равно не пашет ничерта
(((

Re: ОСРВ МАКС

Добавлено: 2019-июн-13 09:48
BY_man
Сочувствую :mrgreen:
Мютекс плох тем, что должен разлочиваться тем же потоком который его и создал.
Когда обращаемся к мютексу из прерывания, то непонятно к какому потоку относится это прерывание и как
ОС разрулит его.
С семафором в этом плане проще. Семафор может быть разлочен любым потоком.
Я писал, что экспериментировал с поддержкой задержек на уровне ОС. Так вот там в функции задержки
потоком устанавливался семафор и поток засыпал.
static void by_delay(unsigned long ms, void *sem)
{
unsigned long long sto;
sto = (ms * KHZ_PLL_FREQ); // delay in xti clocks
if(sto) {
insert_delay(sem,sto);
sem_wait((sem_t *) sem);
}
}
А вот при прерывании от таймера ОС, я использовал обертку вокруг ОС, т.е. сначала вызывал
свой обработчик, а потом уже все отдавал в ОС. В этой обертке я вызывал процедуру установки семафора.
-- сохраняю контекст
cjmp = __ZN4macs9Semaphore6SignalEv;;
j4 = pointer to sem
CJMP_CALL (abs) (np);

Это внутренняя функция которая аналогична sem_pоst.
И это работало.

Так что проблема в "Прерываение реально вызывается и вызвает sem_post, который почему-то возвращает 1."
что-то не нравится ОС при таком вызове.
static void SendFrameDoneHandler(void) {
sem_post(&audio_out_sem);
}

Re: ОСРВ МАКС

Добавлено: 2019-июн-13 18:00
BY_man
Есть еще такая мысль почему семафор не отработал.
В моем случае установка семафора происходила при прерывании от тика, т.е.
от прерывания которое рассматривается как работа ОС.
В вашем случае прерывание от другого источника и при входе в ОС это может проверяться
и соответственно функция изменения семафора из иного прерывания может быть недоступна.

Re: ОСРВ МАКС

Добавлено: 2019-июн-16 02:07
Анисимов Александр
Странно..
Да, у меня действитель это прерывание не от ОС.
Это прерывание об окончании передачи данных по DMA.

Есть ещё такое же прерывание от окончание приёма фрейма данных. (Только семафор другой). Я полагал, что таким образом можно сделать "real-time".
В прерывании ось отпускает семафор и "знает", что на нём висит какой-то ждущий поток. И собсна сразу запускает этот ждущий поток.
Время входа в прерывание и выполнение "отпускания" семафора фиксировано и запуск моего треда тоже фиксировано, поэтому я мог бы сделать оценку "успею ли обработать данные до прихода следующих отсчетов" или нет.

В "школьном" курсе по семафорам :D рассказывали, что это есть один из способов организовать рил-тайм

Re: ОСРВ МАКС

Добавлено: 2019-июн-17 08:42
BY_man
Александр, переезжайте на FreeRTOS :D
Есть исходники, отличная документация. С вашим энтузиазмом всё быстро заработает :D