Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Прикручиваю ось к LPC2478
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы > scmRTOS
haker_fox
Добрый день, коллеги!

Скачал последнюю версию порта для LPC2xxx. К сожалению, на LPC2478 код не запускается, пришлось маленько пофиксить инициализацию периферии, немного ассемблера в одном из файлов ОСи. Вроде дело пошло. Задачи запускаются. Я не уверен в надежности и стабильности, пока тестирую.

Пока первый вопрос.

Как я понял, планировщик может вызываться из прерывания системного таймера и по софтовому прерыванию. Это задается опцией scmRTOS_CONTEXT_SWITCH_SCHEME. Мне кажется, что для LPC2478 софтовое прерывание не нужно. Достаточно таймерного. Я правильно понимаю? Т.е. можно использовать scmRTOS_CONTEXT_SWITCH_SCHEME = 0?

Гм... скажем так, я, прочитав документацию, так и не понял, чем отличаются два метода вызова планировщика, и какой когда использовать?

Спасибо!
Сергей Борщ
QUOTE (haker_fox @ Aug 21 2012, 09:22) *
Как я понял, планировщик может вызываться из прерывания системного таймера и по софтовому прерыванию. Это задается опцией scmRTOS_CONTEXT_SWITCH_SCHEME.
Неправильно поняли sad.gif. Планировщик вызывается там, где возникла необходимость передать управление другой задаче. Это может быть и в основном коде потока, и в прерывании периферии и в прерывании системного таймера. А вот методов вызова перепланировки предусмотрено два: scmRTOS_CONTEXT_SWITCH_SCHEME = 0 - простой вызов функции, которая будет складывать на стек все регистры, даже если она вызвана на выходе из прерывания и часть регистров уже сохранены обработчиком, и scmRTOS_CONTEXT_SWITCH_SCHEME = 1 - для переключения контекста вызывается отдельное прерывание, обработчик которого написан на асме и это гарантирует, что ни один регистр не будет сохранен дважды. Второй вариант, как видно, менее требователен к стеку. Другое его преимущество - если приоритет этого прерывания сделать самым низким, то при возникновении нескольких прерываний переключение контекста будет выполнено один раз после выхода из последнего обработчика, а не на выходе из каждого. Поэтому такой метод и рекомендуется использовать. "Нулевой" метод используется лишь там, где нет возможности использовать "первый" - например, в ADuC702x, где нет контроллера прерываний и невозможно сгенерить прерывание программно.
haker_fox
Спасибо за остоятельный ответ!
К сожалению, я до сих пор использовал 3-ю версию, и то на AVR. Не все нюансы знаю) Буду разбираться.

У меня уже мечта добавить к этой оси виртуальные таймеры ( это мне точно нужно ).

Спасибо большое за ее создание! Выбирал для арм долго между FreeRTOS, TNKernel и родной, с 2006 года знакомой, scmRTOS. Выбор пал в пользу последней из за того, что она вкорне написана на Си++, который мне более удобен)
_Артём_
Цитата(haker_fox @ Aug 21 2012, 15:48) *
У меня уже мечта добавить к этой оси виртуальные таймеры ( это мне точно нужно ).

А что они такого вам дадут?
haker_fox
QUOTE (_Артём_ @ Aug 21 2012, 22:33) *
А что они такого вам дадут?

Мне они нужны для управления автоматикой. Скажем, каждый день в 9 утра открывать дверь, по понедельникам в 17-00 проветривать помещение)

Думаю, что вклиненные в ядро и сервисы ОС, они будут работать наиболее производительно. Да и потренируюсь маленько. С осями я на ВЫ.
_Артём_
Цитата(haker_fox @ Aug 21 2012, 16:55) *
Мне они нужны для управления автоматикой. Скажем, каждый день в 9 утра открывать дверь, по понедельникам в 17-00 проветривать помещение)

То есть они должны быть привязаны к календарю, времени в часах-минутах?

haker_fox
QUOTE (_Артём_ @ Aug 22 2012, 00:13) *
То есть они должны быть привязаны к календарю, времени в часах-минутах?

Да, привязаны к аппаратным часам. Но "когда-то" они должны вызывать некую функцию в отдельно потоке. Следовательно поллинг здесь мало подходит, т.к. до срабатывания таймера может и день пройти...

Жаль, конечно, что в этой ОСи нельзя динамически создавать/удалять задачи, но я либо обойдусь текущим функционалом, либо попробую что-нить припилить)
_Артём_
Цитата(haker_fox @ Aug 21 2012, 18:19) *
Да, привязаны к аппаратным часам. Но "когда-то" они должны вызывать некую функцию в отдельно потоке.

А аппаратный таймер - это что физически?

Цитата(haker_fox @ Aug 21 2012, 18:19) *
Следовательно поллинг здесь мало подходит

Смотря как часто опрашивать. Я не думаю что ваша задача управления автоматикой выглядит так:
в 9:00 выставить в порт заданный уровень, время реакции - 3 мкс.
haker_fox
QUOTE (_Артём_ @ Aug 22 2012, 00:35) *
А аппаратный таймер - это что физически?

В LPC2478 есть RTC.

QUOTE (_Артём_ @ Aug 22 2012, 00:35) *
мотря как часто опрашивать. Я не думаю что ваша задача управления автоматикой выглядит так:
в 9:00 выставить в порт заданный уровень, время реакции - 3 мкс.

Да, пока поллингом и делаю. На другой платформе. Опрашиваю раз в 0.5 сек.

А может быть действительно - лишнее это (виртуальные таймеры). Буду думать.

Но вот динамическое создание/удаление процессов было бы полезно: сработал таймер, запустили процесс, выдали в сеть команду, удалили процесс. Поскольку этот процесс может занимать иногда ощутимое конечное время (сеть одна, устройств много, много кто хочет с ними пообщаться, приходится ждать), то чтобы не задерживать работу системы, он бы мог работать отдельно.

Хотя здесь может помочь буферизация в очереди.

В общем будем думать. Просто лапки чешутся что-нить "поковырять".

Впрочем, это уже для другой темы разговор.
_Артём_
Цитата(haker_fox @ Aug 21 2012, 19:05) *
В LPC2478 есть RTC.

И что можно разрешить прерывание в заданное время (часы-минуты-дата)?


Цитата(haker_fox @ Aug 21 2012, 19:05) *
Но вот динамическое создание/удаление процессов было бы полезно: сработал таймер, запустили процесс, выдали в сеть команду, удалили процесс.

Видимо динамическое создание/удаление процессов вызовет падение скоростных характеристик Оси.
Но если таких процессов немного (которые создавать-удалять хотите), то что мешает их сделать обычными процессами с низким приоритетом, ожидающими своего события и начинающими работать, например от сигнала пришедшего от RTC_Handler?
haker_fox
QUOTE (_Артём_ @ Aug 22 2012, 01:15) *
И что можно разрешить прерывание в заданное время (часы-минуты-дата)?

Да, на одну дату можно. Но мне нужно больльше. Например 32 таймера. Кажется, что поллингом проще будет.
QUOTE (_Артём_ @ Aug 22 2012, 01:15) *
Видимо динамическое создание/удаление процессов вызовет падение скоростных характеристик Оси.
Но если таких процессов немного (которые создавать-удалять хотите), то что мешает их сделать обычными процессами с низким приоритетом, ожидающими своего события и начинающими работать, например от сигнала пришедшего от RTC_Handler?

Да, можно и так!

Спасибо, хорошее обсуждение получилось, мои мысли упорядочились)
Сергей Борщ
QUOTE (haker_fox @ Aug 22 2012, 07:52) *
Да, на одну дату можно. Но мне нужно больльше. Например 32 таймера. Кажется, что поллингом проще будет.
Почему бы не создать сортированный список времен срабатывания таймеров, как сделано в FreeRTOS? Срабатывает будильник, отсылает сообщение, берет из списка следующее время, программирует его в будильник RTC и т.д.
haker_fox
QUOTE (Сергей Борщ @ Aug 22 2012, 14:21) *
Почему бы не создать сортированный список времен срабатывания таймеров, как сделано в FreeRTOS? Срабатывает будильник, отсылает сообщение, берет из списка следующее время, программирует его в будильник RTC и т.д.

Интересная мысль! Гляну, как это там реализовано. Спасибо!
haker_fox
В общем остановился на scmRTOS_CONTEXT_SWITCH_SCHEME = 0. Так проще пока для меня. ОСь стабильно работает.
haker_fox
Ну вот и следующий вопрос. Хочу сделать оговорку, он, конечно, мало относится к этой оси, но все же.

Хочу прикрутить TCP/IP стек. В настоящее время мое внимание сосредоточено на lwIP и TCP/IP стек от Юрия Темкина (www.tnkernel.com).

Не могу определится с окончательным выборомом. Что от стека нужно:
1. ICMP.
2. TCP.
3. UDP.
4. DHCP.

На базе стека планируется использовать web server (возможно понадобится ftp server, telnet server).

Сосбственно сам вопрос: что лучше - взять и прикрутить lwIP, либо TCP/IP tnkernel? С одной стороны есть примеры интеграции обоих стеков в оси (для первого это FreeRTOS, для второго - сама TNkernel). Но все же. Что, согласно идеологии scmRTOS, для нее больше подойдет в качестве сетевого стека?

Спасибо!
_Артём_
Цитата(haker_fox @ Aug 26 2012, 09:53) *
Не могу определится с окончательным выборомом. Что от стека нужно:
1. ICMP.
2. TCP.
3. UDP.
4. DHCP.

На базе стека планируется использовать web server (возможно понадобится ftp server, telnet server).

Если web, то TCP - точно нужен.
DHCP нужен, если ip-адрес сервера не статический, а выдаётся шлюзом.
ICMP тоже не помешает, хотя бы для того чтобы пропинговать сервер.
UDP может и не нужен, но он настолько мал по сравнению с остальным, что можно его и оставить, может пригодится.
haker_fox
QUOTE (_Артём_ @ Aug 27 2012, 02:44) *
Если web, то TCP - точно нужен.
DHCP нужен, если ip-адрес сервера не статический, а выдаётся шлюзом.
ICMP тоже не помешает, хотя бы для того чтобы пропинговать сервер.
UDP может и не нужен, но он настолько мал по сравнению с остальным, что можно его и оставить, может пригодится.

Спасибо за объяснение rolleyes.gif Но вопрос немножечко не в этом был. Я перечислил, что мне нужно (TCP, DHCP, ICMP, UDP...). У меня вопрос не по составу компонентов, а по выбору стека из двух ранее озвученных. Естественно, как стек брать для конкретной оси - дело десятое. Оба поддерживают многопоточность. Но все же)

В общем решил остановиться на lwIP, т.к. с нуля мне кажется проще прикрутить его к scmRTOS. А вот из стека Юрия Темкина придется вытаскивать кусочки его оси rolleyes.gif Хотя, объективно, его стек лучше (сделан по мотивам BSD).

QUOTE (_Артём_ @ Aug 27 2012, 02:44) *
UDP может и не нужен, но он настолько мал по сравнению с остальным, что можно его и оставить, может пригодится.

Мне DHCP нужен, поэтому без UDP никуда)
shreck
Цитата(haker_fox @ Aug 26 2012, 13:53) *
На базе стека планируется использовать web server (возможно понадобится ftp server, telnet server).

А что за веб сервер будет? Определились уже?

P.S. lwIP 1.4.0 я уже прикрутил к scmRTOS. Нужен?
P.P.S. Под IAR.
haker_fox
QUOTE (shreck @ Aug 27 2012, 14:55) *
А что за веб сервер будет? Определились уже?

Пока нет, но может быть по мотивам примеров из FreeRTOS или openTCP. Либо что-то другое. Нужно CGI обязательно. Ну и "базовый" набор html...
QUOTE (shreck @ Aug 27 2012, 14:55) *
P.S. lwIP 1.4.0 я уже прикрутил к scmRTOS. Нужен?
P.P.S. Под IAR.

Ну если Вам не жалко)
Думаю под gcc переклепать смогу)

Спасибо!


Хотя вот еще два интересных конкурента появились: OpenTCP & Microchip TCP/IP.

Кто нибудь может о них что-нить интересное сказать? OpenTCP неплохо документирован) Мне кажется, что даже очень не плохо. lwIP как-то совсем, ИМХО, скудно)
shreck
Порт lwIP 1.4.0 c использованием scmRTOS.

  1. ipnet_config.h и lwport_config.h - прописать пути для них.
  2. Папку port разместить, например, в верхней папке lwip и прописать путь до port/arch
  3. Прочитать lwport_config.h и подстроить под себя.
  4. Взять ethernetif под свой контроллер (здесь он для stm32).
shreck
Обнаружил досадную ошибку в порте, перекочевавшую из порта FreeRTOS.

Код
Файл sys_arch.cpp, функция sys_sem_new(...), строка 227.
Написано:
if (0 == count)
    t->signal();

Должно быть:
if (count)
    t->signal();
haker_fox
Новое интересное поведение)
Программа работает великолено. Решил на LCD вывести картинку 480x272x24. На Питоне написал скрипт, который конвертнул картинку в const const
CODE
uint32_t logoImg[] = { ... }
. На каждый пиксель, естественно, 4 байта. Получил размер массива 272 * 480 * 4 = 522 240 байт. Массив находится в хидере, который цепляется к программе. Вот тут-то начинается интересный эффект...

При вызове функции OS::sleep или любой другой, вызывающий переключение контекста, программа виснет на время, много превышающее заданный таймаут. Затем, продолжает нормально работать. Причем на sleep у меня построен небольшой цикл, который выводит каждый 15 мс на экран точку (типа линейка, показывающая процесс). Так вот, одна точка висит вместо 15 мс около минуты, затем дорисовываются все точки с необходимой скоростью. Что интересно, если массив маленько урезать, килобайт этак на 30, то программа работает без нареканий. Картинка, конечно, выводится с артефактами.

Посмотрел, что линкер ложит массив "по середине" прошивки.

У меня гипотеза. Я плохо знаю ассемблер, поэтому не очень ясно понимаю код переключения контекста. Но не может ли из за того, что в коде получилась солидная "дыра" в виде не кода, а данных, переключатель контекста отрабатывает не совсем верно. Ну например, перескакивает не на задачу, а на эти данные. Т.е. мы не может перейти "далеко" на код.

Правда, как объяснить, что после первой задержки, все остальные отрабатывают нормально?!

Спасибо! Извините, если немного сумбурно...
shreck
Цитата(haker_fox @ Sep 28 2012, 19:06) *
Новое интересное поведение...

Насколько я помню, в порте scmRTOS под GCC от АНТОХи по умолчанию используется "короткий" прыжок в функции переключения контекста. Может это имеет значение?
haker_fox
QUOTE (shreck @ Sep 28 2012, 21:48) *
Насколько я помню, в порте scmRTOS под GCC от АНТОХи по умолчанию используется "короткий" прыжок в функции переключения контекста. Может это имеет значение?

Может быть) Но как это дело заменить на длинный прыжок? И сколько - короткий (в байтах)? Я так, понимаю, надо ассемблер править...

Может тогда проще как-то линкер уговорить, ложить такие массивы где-то "сбоку" от кода?
_Артём_
Цитата(shreck @ Sep 28 2012, 15:48) *
Насколько я помню, в порте scmRTOS под GCC от АНТОХи по умолчанию используется "короткий" прыжок в функции переключения контекста. Может это имеет значение?

У haker_fox не Cortex-M3, а LPC2478.
haker_fox
QUOTE (_Артём_ @ Sep 28 2012, 21:57) *
У haker_fox не Cortex-M3, а LPC2478.

Так АНТОХА также делал порт под lpc2xxx rolleyes.gif
shreck
Цитата(_Артём_ @ Sep 28 2012, 19:57) *
У haker_fox не Cortex-M3, а LPC2478.

Пардон, ошибся. Но возможно и в этом случае стоит просмотреть asm код.
AHTOXA
Цитата(haker_fox @ Sep 28 2012, 18:06) *
Посмотрел, что линкер ложит массив "по середине" прошивки.

Попробуйте изменить имя массива на z_logoImg - ляжет в конец sm.gif
На самом деле сильно вряд ли, что недопрыгивает. Думаю, что начав выполнять код картинки, проц бы уже ни за что не вернулся к нормальному выполнению программы.
Посмотрите размерности индексных переменных при обращении к массиву. Вдруг где не хватает?
haker_fox
QUOTE (AHTOXA @ Sep 29 2012, 01:25) *
Попробуйте изменить имя массива на z_logoImg - ляжет в конец sm.gif
На самом деле сильно вряд ли, что недопрыгивает. Думаю, что начав выполнять код картинки, проц бы уже ни за что не вернулся к нормальному выполнению программы.
Посмотрите размерности индексных переменных при обращении к массиву. Вдруг где не хватает?

Теперь массив объявле так
CODE
const uint32_t z_logoImg[] = {

Вот, что видим в map-файле
CODE
.rodata._ZL9z_logoImg
                0xa0222160    0x7f800 ./obj/FDesktop.o

Секции в скрипте линкера объявлены так (все во внешней SDRAM)
CODE
MEMORY
{
    RAM (rw)    : ORIGIN = 0xA0600000, LENGTH = 512k
    FLASH (rx)    : ORIGIN = 0xA0200000, LENGTH = 1024k
}


Массив упорно ложится ну не совсем по середине, конечно, но реже прошивку на лапопам rolleyes.gif

При обращении к массиву используется цикл
CODE
        uint32_t* dst = ( uint32_t* )0xa0000000;

        for( int i = 0; i < 480 * 272; i++ )
            *dst++ = z_logoImg[ i ];


Вроде с индексами все в порядке rolleyes.gif

В общем такое ощущение, что размер массива сильно мешает. Но из расределения памяти видно, что никаким образмо область FLASH не может затереть область RAM, т.к. между ними 4 метра...

Блин, загадка! crying.gif
AHTOXA
Цитата(haker_fox @ Sep 29 2012, 06:39) *
Массив упорно ложится ну не совсем по середине, конечно, но реже прошивку на лапопам rolleyes.gif

Странно. Если он в rodata, то всяко должен лежать после .text:
Код
        *(.text)                   /* remaining code */
        *(.text.*)                 /* remaining code */
        *(.rodata)                 /* read-only data (constants) */
        *(.rodata*)

Попробуйте убрать из цикла обращение к logoImg:
Код
        uint32_t* dst = ( uint32_t* )0xa0000000;
    for( int i = 0; i < 480 * 272; i++ )
            *dst++ = i;

Узнаем, кто виноват. Может видеобуфер тормозит.
haker_fox
QUOTE (AHTOXA @ Sep 29 2012, 13:53) *
Узнаем, кто виноват. Может видеобуфер тормозит.

Нет, видеобуфер точно не тормозит. Система виснет до вывода картинки. Извините, что не пояснил этот момент сразу. Сама картинка выводится "влет" rolleyes.gif А до вывода картинки происхоид основательная задержка в sleep, затем все sleep'ы отрабатываются правильно. Программа работает сутками, никаких ошибок...

Если обращение к массиву переместить в другое место к коду - проблема остается...

Кажется, я просчитался:
Если прошивка ложится с адреса 0xa0200000, а массив лежит с 0xa0222160, то он лежит после прошивки (она занимает 145760 байт). Т.е. после секции .text. Но все равно, последний адрес в map-файле это
CODE
text.align     0xa02a3188        0x0
                0xa02a3188                . = ALIGN (0x8)
                0xa02a3188                _etext = .
                0xa02a3188                _data_image = _etext

.data           0xa0600000      0x8d0 load address 0xa02a3188
                0xa0600000                . = ALIGN (0x4)
                0xa0600000                _data = .

Как я понимаю, это фрагмент нам позволяет убедится в том, что секция .data лежит очень далеко после секции .text Т.е. переменные и стек не могут затираться?!

Вставил в оську отладочный код
CODE
void TBaseProcess::sleep(timeout_t timeout)
{
    TCritSect cs;

    FHAL::halPrintf( "\r\nSleep 0" );
    Kernel.ProcessTable[Kernel.CurProcPriority]->Timeout = timeout;
    FHAL::halPrintf( "\r\nSleep 1" );
    Kernel.set_process_unready(Kernel.CurProcPriority);
    FHAL::halPrintf( "\r\nSleep 2" );
    Kernel.scheduler();
    FHAL::halPrintf( "\r\nSleep 3" );
}

На злосчастной функции выводится
CODE
Sleep 0
Sleep 1
Sleep 2

Т.е. висим прилично в шедулере, пока не знаю где.

Затем быстренько через положенный таймаут выводится то, что надо
CODE
Sleep 0
Sleep 1
Sleep 2
Sleep 3.
Sleep 0
Sleep 1
Sleep 2
Sleep 3.
Sleep 0
Sleep 1
Sleep 2
Sleep 3.
Sleep 0
Sleep 1
Sleep 2
Sleep 3.

Точка после тройки, это точка, изображающая диаграммку) т.е. как и должно быть. Интересно, что на шедулере вся оська виснет... Таймаут функции sleep передается без искажений...

В шедулере висим на этом
CODE
os_context_switcher(Curr_SP_addr, Next_SP);

Причем, если отладочного дебага добавить/убавить, то иногда не висим! Дело в выравнивании? Но, как мне кажется, в скрипте все настроено... Да и каким образом массив в конце может влиять на что-то за несколько строк кода до его чтения? Блин, я уже заинтригован blush.gif
Сергей Борщ
QUOTE (haker_fox @ Sep 29 2012, 09:12) *
В шедулере висим на этом
CODE
os_context_switcher(Curr_SP_addr, Next_SP);
Какой метод передачи управления используется? Если по прерыванию, то, возможно, какое-то прерывание на это большое время блокирует остальные и до вызова обработчика переключения контекста дело просто не доходит. Хотя, тогда висели бы в этом обработчике а не в переключении контекста. В общем надо копать в эту сторону - почему не вызывается прерывание переключателя контекста. И почему оно потом вдруг вызывается.
haker_fox
QUOTE (Сергей Борщ @ Sep 29 2012, 17:31) *
Какой метод передачи управления используется? Если по прерыванию, то, возможно, какое-то прерывание на это большое время блокирует остальные и до вызова обработчика переключения контекста дело просто не доходит. Хотя, тогда висели бы в этом обработчике а не в переключении контекста. В общем надо копать в эту сторону - почему не вызывается прерывание переключателя контекста. И почему оно потом вдруг вызывается.

У меня так
CODE
#define  scmRTOS_CONTEXT_SWITCH_SCHEME          0

Да уж... загадка на выходные... 1111493779.gif

По очень злой причине счетчик таймера был не в нулевом положении. И обработчик прерывания стартовал не сразу с необходимым периодом, а с солидной задержкой...
Пришлось в инициализацию добавить это
CODE
T0TC = 0;


Сергей Борщ, долгих лет и счастья! Ваша наводка мне очень помогла! Теперь все работает прекрасно!

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