|
Прикручиваю ось к LPC2478, Есть и будут вопросы) |
|
|
|
Aug 21 2012, 06:22
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
Добрый день, коллеги!
Скачал последнюю версию порта для LPC2xxx. К сожалению, на LPC2478 код не запускается, пришлось маленько пофиксить инициализацию периферии, немного ассемблера в одном из файлов ОСи. Вроде дело пошло. Задачи запускаются. Я не уверен в надежности и стабильности, пока тестирую.
Пока первый вопрос.
Как я понял, планировщик может вызываться из прерывания системного таймера и по софтовому прерыванию. Это задается опцией scmRTOS_CONTEXT_SWITCH_SCHEME. Мне кажется, что для LPC2478 софтовое прерывание не нужно. Достаточно таймерного. Я правильно понимаю? Т.е. можно использовать scmRTOS_CONTEXT_SWITCH_SCHEME = 0?
Гм... скажем так, я, прочитав документацию, так и не понял, чем отличаются два метода вызова планировщика, и какой когда использовать?
Спасибо!
--------------------
Выбор.
|
|
|
|
|
Aug 21 2012, 08:02
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (haker_fox @ Aug 21 2012, 09:22)  Как я понял, планировщик может вызываться из прерывания системного таймера и по софтовому прерыванию. Это задается опцией scmRTOS_CONTEXT_SWITCH_SCHEME. Неправильно поняли  . Планировщик вызывается там, где возникла необходимость передать управление другой задаче. Это может быть и в основном коде потока, и в прерывании периферии и в прерывании системного таймера. А вот методов вызова перепланировки предусмотрено два: scmRTOS_CONTEXT_SWITCH_SCHEME = 0 - простой вызов функции, которая будет складывать на стек все регистры, даже если она вызвана на выходе из прерывания и часть регистров уже сохранены обработчиком, и scmRTOS_CONTEXT_SWITCH_SCHEME = 1 - для переключения контекста вызывается отдельное прерывание, обработчик которого написан на асме и это гарантирует, что ни один регистр не будет сохранен дважды. Второй вариант, как видно, менее требователен к стеку. Другое его преимущество - если приоритет этого прерывания сделать самым низким, то при возникновении нескольких прерываний переключение контекста будет выполнено один раз после выхода из последнего обработчика, а не на выходе из каждого. Поэтому такой метод и рекомендуется использовать. "Нулевой" метод используется лишь там, где нет возможности использовать "первый" - например, в ADuC702x, где нет контроллера прерываний и невозможно сгенерить прерывание программно.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Aug 21 2012, 15:35
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(haker_fox @ Aug 21 2012, 18:19)  Да, привязаны к аппаратным часам. Но "когда-то" они должны вызывать некую функцию в отдельно потоке. А аппаратный таймер - это что физически? Цитата(haker_fox @ Aug 21 2012, 18:19)  Следовательно поллинг здесь мало подходит Смотря как часто опрашивать. Я не думаю что ваша задача управления автоматикой выглядит так: в 9:00 выставить в порт заданный уровень, время реакции - 3 мкс.
|
|
|
|
|
Aug 21 2012, 16:05
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
QUOTE (_Артём_ @ Aug 22 2012, 00:35)  А аппаратный таймер - это что физически? В LPC2478 есть RTC. QUOTE (_Артём_ @ Aug 22 2012, 00:35)  мотря как часто опрашивать. Я не думаю что ваша задача управления автоматикой выглядит так: в 9:00 выставить в порт заданный уровень, время реакции - 3 мкс. Да, пока поллингом и делаю. На другой платформе. Опрашиваю раз в 0.5 сек. А может быть действительно - лишнее это (виртуальные таймеры). Буду думать. Но вот динамическое создание/удаление процессов было бы полезно: сработал таймер, запустили процесс, выдали в сеть команду, удалили процесс. Поскольку этот процесс может занимать иногда ощутимое конечное время (сеть одна, устройств много, много кто хочет с ними пообщаться, приходится ждать), то чтобы не задерживать работу системы, он бы мог работать отдельно. Хотя здесь может помочь буферизация в очереди. В общем будем думать. Просто лапки чешутся что-нить "поковырять". Впрочем, это уже для другой темы разговор.
--------------------
Выбор.
|
|
|
|
|
Aug 21 2012, 16:15
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(haker_fox @ Aug 21 2012, 19:05)  В LPC2478 есть RTC. И что можно разрешить прерывание в заданное время (часы-минуты-дата)? Цитата(haker_fox @ Aug 21 2012, 19:05)  Но вот динамическое создание/удаление процессов было бы полезно: сработал таймер, запустили процесс, выдали в сеть команду, удалили процесс. Видимо динамическое создание/удаление процессов вызовет падение скоростных характеристик Оси. Но если таких процессов немного (которые создавать-удалять хотите), то что мешает их сделать обычными процессами с низким приоритетом, ожидающими своего события и начинающими работать, например от сигнала пришедшего от RTC_Handler?
|
|
|
|
|
Aug 22 2012, 04:52
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

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

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (haker_fox @ Aug 22 2012, 07:52)  Да, на одну дату можно. Но мне нужно больльше. Например 32 таймера. Кажется, что поллингом проще будет. Почему бы не создать сортированный список времен срабатывания таймеров, как сделано в FreeRTOS? Срабатывает будильник, отсылает сообщение, берет из списка следующее время, программирует его в будильник RTC и т.д.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Aug 26 2012, 06:53
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
Ну вот и следующий вопрос. Хочу сделать оговорку, он, конечно, мало относится к этой оси, но все же.
Хочу прикрутить 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, для нее больше подойдет в качестве сетевого стека?
Спасибо!
--------------------
Выбор.
|
|
|
|
|
Aug 26 2012, 18:44
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(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 может и не нужен, но он настолько мал по сравнению с остальным, что можно его и оставить, может пригодится.
|
|
|
|
|
Aug 27 2012, 03:04
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
QUOTE (_Артём_ @ Aug 27 2012, 02:44)  Если web, то TCP - точно нужен. DHCP нужен, если ip-адрес сервера не статический, а выдаётся шлюзом. ICMP тоже не помешает, хотя бы для того чтобы пропинговать сервер. UDP может и не нужен, но он настолько мал по сравнению с остальным, что можно его и оставить, может пригодится. Спасибо за объяснение  Но вопрос немножечко не в этом был. Я перечислил, что мне нужно (TCP, DHCP, ICMP, UDP...). У меня вопрос не по составу компонентов, а по выбору стека из двух ранее озвученных. Естественно, как стек брать для конкретной оси - дело десятое. Оба поддерживают многопоточность. Но все же) В общем решил остановиться на lwIP, т.к. с нуля мне кажется проще прикрутить его к scmRTOS. А вот из стека Юрия Темкина придется вытаскивать кусочки его оси  Хотя, объективно, его стек лучше (сделан по мотивам BSD). QUOTE (_Артём_ @ Aug 27 2012, 02:44)  UDP может и не нужен, но он настолько мал по сравнению с остальным, что можно его и оставить, может пригодится. Мне DHCP нужен, поэтому без UDP никуда)
--------------------
Выбор.
|
|
|
|
|
Aug 27 2012, 06:55
|

Местный
  
Группа: Свой
Сообщений: 327
Регистрация: 24-06-06
Из: Томск
Пользователь №: 18 328

|
Цитата(haker_fox @ Aug 26 2012, 13:53)  На базе стека планируется использовать web server (возможно понадобится ftp server, telnet server). А что за веб сервер будет? Определились уже? P.S. lwIP 1.4.0 я уже прикрутил к scmRTOS. Нужен? P.P.S. Под IAR.
|
|
|
|
|
Aug 27 2012, 12:40
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
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 как-то совсем, ИМХО, скудно)
--------------------
Выбор.
|
|
|
|
|
Aug 31 2012, 07:51
|

Местный
  
Группа: Свой
Сообщений: 327
Регистрация: 24-06-06
Из: Томск
Пользователь №: 18 328

|
Обнаружил досадную ошибку в порте, перекочевавшую из порта FreeRTOS. Код Файл sys_arch.cpp, функция sys_sem_new(...), строка 227. Написано: if (0 == count) t->signal();
Должно быть: if (count) t->signal();
|
|
|
|
|
Sep 28 2012, 12:06
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
Новое интересное поведение) Программа работает великолено. Решил на LCD вывести картинку 480x272x24. На Питоне написал скрипт, который конвертнул картинку в const const CODE uint32_t logoImg[] = { ... } . На каждый пиксель, естественно, 4 байта. Получил размер массива 272 * 480 * 4 = 522 240 байт. Массив находится в хидере, который цепляется к программе. Вот тут-то начинается интересный эффект... При вызове функции OS::sleep или любой другой, вызывающий переключение контекста, программа виснет на время, много превышающее заданный таймаут. Затем, продолжает нормально работать. Причем на sleep у меня построен небольшой цикл, который выводит каждый 15 мс на экран точку (типа линейка, показывающая процесс). Так вот, одна точка висит вместо 15 мс около минуты, затем дорисовываются все точки с необходимой скоростью. Что интересно, если массив маленько урезать, килобайт этак на 30, то программа работает без нареканий. Картинка, конечно, выводится с артефактами. Посмотрел, что линкер ложит массив "по середине" прошивки. У меня гипотеза. Я плохо знаю ассемблер, поэтому не очень ясно понимаю код переключения контекста. Но не может ли из за того, что в коде получилась солидная "дыра" в виде не кода, а данных, переключатель контекста отрабатывает не совсем верно. Ну например, перескакивает не на задачу, а на эти данные. Т.е. мы не может перейти "далеко" на код. Правда, как объяснить, что после первой задержки, все остальные отрабатывают нормально?! Спасибо! Извините, если немного сумбурно...
--------------------
Выбор.
|
|
|
|
|
Sep 28 2012, 16:25
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(haker_fox @ Sep 28 2012, 18:06)  Посмотрел, что линкер ложит массив "по середине" прошивки. Попробуйте изменить имя массива на z_logoImg - ляжет в конец  На самом деле сильно вряд ли, что недопрыгивает. Думаю, что начав выполнять код картинки, проц бы уже ни за что не вернулся к нормальному выполнению программы. Посмотрите размерности индексных переменных при обращении к массиву. Вдруг где не хватает?
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Sep 29 2012, 00:39
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
QUOTE (AHTOXA @ Sep 29 2012, 01:25)  Попробуйте изменить имя массива на z_logoImg - ляжет в конец  На самом деле сильно вряд ли, что недопрыгивает. Думаю, что начав выполнять код картинки, проц бы уже ни за что не вернулся к нормальному выполнению программы. Посмотрите размерности индексных переменных при обращении к массиву. Вдруг где не хватает? Теперь массив объявле так 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 } Массив упорно ложится ну не совсем по середине, конечно, но реже прошивку на лапопам При обращении к массиву используется цикл CODE uint32_t* dst = ( uint32_t* )0xa0000000;
for( int i = 0; i < 480 * 272; i++ ) *dst++ = z_logoImg[ i ]; Вроде с индексами все в порядке В общем такое ощущение, что размер массива сильно мешает. Но из расределения памяти видно, что никаким образмо область FLASH не может затереть область RAM, т.к. между ними 4 метра... Блин, загадка!
--------------------
Выбор.
|
|
|
|
|
Sep 29 2012, 04:53
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(haker_fox @ Sep 29 2012, 06:39)  Массив упорно ложится ну не совсем по середине, конечно, но реже прошивку на лапопам  Странно. Если он в 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; Узнаем, кто виноват. Может видеобуфер тормозит.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Sep 29 2012, 06:12
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
QUOTE (AHTOXA @ Sep 29 2012, 13:53)  Узнаем, кто виноват. Может видеобуфер тормозит. Нет, видеобуфер точно не тормозит. Система виснет до вывода картинки. Извините, что не пояснил этот момент сразу. Сама картинка выводится "влет"  А до вывода картинки происхоид основательная задержка в 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); Причем, если отладочного дебага добавить/убавить, то иногда не висим! Дело в выравнивании? Но, как мне кажется, в скрипте все настроено... Да и каким образом массив в конце может влиять на что-то за несколько строк кода до его чтения? Блин, я уже заинтригован
--------------------
Выбор.
|
|
|
|
|
Sep 29 2012, 08:31
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (haker_fox @ Sep 29 2012, 09:12)  В шедулере висим на этом CODE os_context_switcher(Curr_SP_addr, Next_SP); Какой метод передачи управления используется? Если по прерыванию, то, возможно, какое-то прерывание на это большое время блокирует остальные и до вызова обработчика переключения контекста дело просто не доходит. Хотя, тогда висели бы в этом обработчике а не в переключении контекста. В общем надо копать в эту сторону - почему не вызывается прерывание переключателя контекста. И почему оно потом вдруг вызывается.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 29 2012, 09:22
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
QUOTE (Сергей Борщ @ Sep 29 2012, 17:31)  Какой метод передачи управления используется? Если по прерыванию, то, возможно, какое-то прерывание на это большое время блокирует остальные и до вызова обработчика переключения контекста дело просто не доходит. Хотя, тогда висели бы в этом обработчике а не в переключении контекста. В общем надо копать в эту сторону - почему не вызывается прерывание переключателя контекста. И почему оно потом вдруг вызывается. У меня так CODE #define scmRTOS_CONTEXT_SWITCH_SCHEME 0 Да уж... загадка на выходные...  По очень злой причине счетчик таймера был не в нулевом положении. И обработчик прерывания стартовал не сразу с необходимым периодом, а с солидной задержкой... Пришлось в инициализацию добавить это CODE T0TC = 0; Сергей Борщ, долгих лет и счастья! Ваша наводка мне очень помогла! Теперь все работает прекрасно! Очень интересно, как это связано с длинной массива?
--------------------
Выбор.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|