Перейти к содержанию
    

gladov

Свой
  • Постов

    169
  • Зарегистрирован

  • Посещение

Весь контент gladov


  1. Дело в том, что NXP взял за основу UART 16650. Именно эта архитектура в точности повторена в контроллерах NXP, а, как известно, на этой архитектуре десятилетиями работали компьютеры. Так что оба подхода: "классический микроконтроллерный" и от NXP имеют право на жизнь и тут еще можно поспорить какой вариант более классический и распространенный.
  2. Все сильно зависит от архитектуры процессора, порта ОС на эту архитектуру и, конечно, правильности применения данной ОС. Насчет uCOS не согласен. Она будет пытаться перепланировать задачи при выходе из прерывания ТОЛЬКО в том случае, если в прерывании была вызвана функция C_ISR_ENTER(). Если необходимо 1000 раз выполнить прерывание без перепланирования и только на 1001-й передать управление другой задаче, так и вызовите C_ISR_ENTER() только на 1001 раз. Тогда и оверхеда не получите. С Cortex'ами, например, еще проще. Там даже не надо системе говорить, что началось прерывание. В любой ПРАВИЛЬНО портированной ОС перепланировка будет вызвана при выходе из прерывания ТОЛЬКО в случае активации в этом прерывании каких-либо механизмов межпроцессного взаимодействия, таких как взведение семафоров, флагов, передача сообщений и т.п. Так что при правильном использовании ОС оверхед минимален.
  3. Понадобилось мне в одной задаче приблизительно (но быстро) вычислять квадратный корень. Вся арифметика построена на целых числах, поэтому и корень тоже решено было считать без плавучки. Точность результата +- 1 меня вполне устраивает. На просторах интернета, да и на этом форуме, удалось найти много готовых решений, но их основная масса ИМХО немного устарела, т.к. заточена под АЛУ без умножителя. Меня же интересовал алгоритм для применения на АРМах. Решено было попробовать некоторые из найденных и оценить их скорость работы на АРМах. Для тестов использовался LPC1758, разогнанный до 100МГц. Отвлекающих от вычислений факторов нет, кроме таймера, отсчитывающего миллисекунды. uint32_t sqrt1 (uint32_t L) { int32_t temp, div; uint32_t rslt = L; if (L <= 0) return 0; else if (L & 0xFFFF0000L) if (L & 0xFF000000L) div = 0x3FFF; else div = 0x3FF; else if (L & 0x0FF00L) div = 0x3F; else div = (L > 4) ? 0x7 : L; while (1) { temp = L/div + div; div = temp >> 1; div += temp & 1; if (rslt > div) rslt = (uint32_t)div; else { if (L/rslt == rslt-1 && L%rslt==0) rslt--; return rslt; } } } uint32_t sqrt2 (uint32_t src) { uint32_t wrk; uint32_t dst; int i; dst = 0x8000; wrk = 0x8000; for(i=0; i<16; i++) { if(dst*dst>src) dst &= ~wrk; wrk >>= 1; dst |= wrk; } return dst; } uint32_t sqrt3 (uint32_t src) { uint32_t mask, sqr = 0, temp; int j=16; temp = 0xC0000000; do { if( src & temp ) break; temp>>=2; } while( --j); if( j==0 ) return 0; mask = temp & (temp>>1); do { temp = sqr | mask; sqr >>= 1; if( temp <= src ) { sqr |= mask; src -= temp; } mask >>= 2; } while( --j ); return sqr; } uint32_t sqrt4 (uint32_t Val) { unsigned int bitSqr = 0x40000000; unsigned int root = 0; while (bitSqr != 0) { if (Val >= (bitSqr + root)) { Val = Val - (bitSqr + root); root = (root >> 1) | bitSqr; } else root = (root >> 1); bitSqr = (bitSqr >> 2); } return(root); } int TestSqrt(uint32_t(*func)(uint32_t)) { tick_count_t starttime = get_tick_count(); for (uint32_t i = 0; i < 10000000; i++) { uint32_t s = func(i); //Check the value uint32_t sq = s * s; if (!((sq == i) || (sq > i) && (s-1)*(s-1) < i || (sq < i) && (s+1)*(s+1) > i)) { while (1); } } return get_tick_count() - starttime; } Проверка с бесконечным циклом ни на одном алгоритме не сработала - все вычислялось четко. Результаты замеров в миллисекундах приведены ниже. В скобках приведено время вычисления без проверки правильности, только вычисление корня в цикле. sqrt1() - 0x349d (0x296d) sqrt2() - 0x4286 (0x3986) sqrt3() - 0x4807 (0x3cca) sqrt4() - 0x4933 (0x44df) Явный лидер - sqrt1(). Получается, что среднее время вычисления кв. корня около 1 микросекунды. Алгоритм взят отсюда Меня результат вполне устраивает, но если у кого-то есть другие интересные алгоритмы, давайте и их проверим. Интересно же найти лучший.
  4. Мне тоже не хотелось, но таков LwIP. Цитата с LwIP wiki: Еще одна ссылка
  5. Только один: загнать все в один поток, т.к. LwIP не позволяет работать с одним и тем же соединением из разных потоков.
  6. Никакой ошибки нет. __disable_irq() не предназначена для Cortex-M3, о чем и я Вам выше написал. А как устроена CMSIS не знаю, не пользовался. Все таки правильно тут советовали, что начинать знакомство с новой архитектурой используя чью-то библиотеку неправильно, т.к. наступаете не только на собственные грабли, но еще и на чужие. Я хелп редко читаю. А вот в файле <intrinsics.h> в комментах совершенно четко описано какие функции для чего можно/нужно использовать.
  7. А можно поинтересоваться для чего нужны 2 копии таблицы векторов? Вы очень упорно копаете, но создается стойкое ощущение, что немного не туда :) У Вас же будет бутлоадер? Наверное, он ляжет в один-два сектора в начале ПЗУ, так? А ведь он туда ляжет со своей таблицей, так? Тогда зачем Вам иметь еще и две таблицы у приложения? Его нужно просто сдвинуть на N-е кол-во секторов вперед и все. Только сдвинуть целиком, вместе с таблицей векторов. Например, так: ... /*-Memory Regions-*/ define symbol __ICFEDIT_region_ROM_start__ = 0x00002000; define symbol __ICFEDIT_region_ROM_end__ = 0x0003FFFF; define symbol __ICFEDIT_region_RAM_start__ = 0x10000000; define symbol __ICFEDIT_region_RAM_end__ = 0x10007FFF; /*-Specials-*/ define symbol __ICFEDIT_intvec_start__ = __ICFEDIT_region_ROM_start__; /*-Sizes-*/ ...
  8. Если внимательно прочесть, то ничего дизасмить не придется. После стандартных 16 прерываний ядра Cortex-M3 лежат ВСЕ векторы, которые имеются в данном камне. Считате, умножаете на 4 и т.д. После векторов память используется ИАРом по своему усмотрению. Но имхо и это знать вовсе не обязательно. Какая Вам разница куда именно ИАР положит какой код? Если обязательно сделать "дырку" между векторами и кодом для служебной информации, так сделайте ее с помощью конфига линкера. Точка входа в приложение у ИАРа располагается произвольно и знать ее вовсе не обязательно. Достаточно вычитать адрес начала кода из образа (опять же, см. описание первых 0х40 байтов в кортексе).
  9. Если речь идет про ИАР, то Вы путаете __disable_irq(), которое действительно вызовет проблему на кортексе, и __disable_interrupt(), о котором упоминал Alechek. Последнее на кортексе работает нормально.
  10. Да, придется спецтаблицу передвинуть за таблицу векторов. Но проблемы не вижу, т.к. со сменой ядра Вам обязательно пересобирать как загрузчик, так и основной софт. Вот и сдвиньте все дальше. Адреса 0х40 и выше конечно можно использовать как угодно (и объявлять тоже), но только есть ли гарантия, что не произойдет прерывания, адрес вектора которого попадет на ваши личные данные? Описание на области памяти ищите в DS на контроллер. Cortex-M3 стандартизует лишь область векторов прерываний, да и то не строго, а остальное, как правило, отдано под пользовательский код.
  11. Не верю. Совсем не верю. Такая проблема есть. Сегодня наткнулся. Исследования показали следующее: Допустим, есть массив: static int BigArray[QuiteLargeValue] = 0; Можно "=0" и убрать, разницы никакой. В конфиге ICF имеем строку: place in RAM_region { readwrite, block CSTACK, block HEAP }; Однозначно видно, что линкер пытается разложить блоки в регионе по убыванию размера. Так вот если массив оказывается большего размера, чем CSTACK или HEAP, то видим такую картину: "P2", part 1 of 5: 0x3840 .bss zero 0x1000001c 0x3840 Array.r79 [1] - 0x1000385c 0x3840 "P2", part 2 of 5: 0x2480 HEAP 0x10003860 0x2000 <Block> HEAP uninit 0x10003860 0x2000 <Block tail> CSTACK 0x10005860 0x300 <Block> CSTACK uninit 0x10005860 0x300 <Block tail> .iar.dynexit 0x10005b60 0x180 <Block> .iar.dynexit uninit 0x10005b60 0xc cppinit.o [15] .iar.dynexit uninit 0x10005b6c 0x174 <Block tail> - 0x10005ce0 0x2480 "P2", part 3 of 5: 0xc P2 s0 0x10005ce0 0xc <Init block> .data inited 0x10005ce0 0x4 file1.r79 [4] .data inited 0x10005ce4 0x4 file2.r79 [9] .data inited 0x10005ce8 0x4 cppinit.o [15] - 0x10005cec 0xc "P2", part 4 of 5: 0x217c .bss zero 0x10005cec 0x1024 mem.r79 [9] ... Наш блок Array попал в сегмент .bss, чего мы и хотели, однако, код для его инициализации не был сгенерирован линкером! Линкер начал забивать нулями область, начиная в данном случае с адреса 0x5cec. Если же уменьшить размер массива так, чтобы он оказался меньше кучи и стека, то он попадет к "остальным" членам .bss и все переменные проинициализируюутся. Конечно, уменьшать массив это не выход, поэтому есть другой вариант обхода проблемы в конфиге линкера: place in RAM_region { readwrite }; place in RAM_region { block CSTACK, block HEAP }; Тогда сегмент .bss не будет разорван данными с другими атрибутами и инициализация пройдет нормально.
  12. Начну со второго: да, возможно я излишне строго приравнял C++ и ООП. Это конечно не так, я немного не то имел ввиду. Конечно, C++ дает нам много вкусностей помимо "классического" ООП. Но, согласитесь, основные достоинства языка С++ заключаются в его возможности писать ОО-код. Именно поэтому я не приравнял С++ и ООП, но поставил их совсем рядом и позволил себе в первом посте сместить акцент в сторону ООП. Отношение ООП к динамике? Да никакого! Но во многих учебниках, а также в ВУЗах, преподается ООП (позвольте я все же буду тут писать про ООП, коль уж мой первый пост был де-факто про него) в тесной свзяке с динамической памятью, ибо так легче показать виртуализацию и полиморфизм. Поэтому и написал, что "ООП пытается тянуть за собой ....". Согласитесь, многие вещи удобнее реализовываются если использовать динамику? Однако этого лучше не делать, либо делать с умом, понимая механизмы и возможные последствия. Паттерны? А разве плохо знать о них? А к С++ они имеют прямое отношение: их можно реализовать используя С++, а вот на С сделать то же самое гораздо сложнее.
  13. С++ плохо подходит для ARM. Серьезно! Появляются накладняки на требуемую память, ООП пытается тянуть за собой в проект использование динамической памяти и еще много всяких неудобств. Зачем это Вам? А если серьезно, то я сам пишу под АРМ на С++, но чтобы к этому прийти, надо сначала понять что такое ООП вообще, зачем оно нужно, почему иногда оно удобнее, и лишь потом, если придет просветление (для ускорения процесса можно почитать, например, про шаблоны ООП) можно пытаться прикрутить объекты к АРМам.
  14. Я с EMAC плотно пока не работал, поэтому есть лишь догадка: в первом случае INTSTATUS вычитывается ПОСЛЕ первого обнуления в INTCLEAR, а во втором СНАЧАЛА читается статус, потом очищается прерывание. Может быть тот самый упомянутый выше "спусковой крючок" находится в INTSTATUS и сначала надо его прочитать (как в некоторых self-clear прерываниях), а потом уже принудительно прописать бит в INTCLEAR?
  15. Именно поэтому таймер лишь генерирует запрос на переключение. Аналогичный запрос может быть сгенерирован и "изнутри" ОС, например, при освобождении какого-то ресурса, ожидаемого процессом. А вот обработка запроса переключения производится из PendSV. Операция вынесена в прерывание чтобы была возможность обеспечить атомарность действий.
  16. Ethernet + LPC1758

    Вопросов больше нет, всем огромное спасибо :)
  17. Ethernet + LPC1758

    Логически - так оно и должно быть, но непонятно для чего в регистре SUPP у LPC EMAC есть единственный бит - SPEED: Если бы не это, плюнул бы не детектирование линка да и все. У меня как раз такое приложение которому совсем не обязательно знать, есть ли сейчас связь с внешним миром.
  18. Ethernet + LPC1758

    Ясно, что ужас. Пример кривой. А минимальную настройку я бы все таки сделал, хотя бы чтобы была возможность переопределить значения по-умолчанию. Я правильно понимаю, что у вас из PHY ничего кроме состояния линка не вычитывается? А когда линк поднялся надо перенастраивать EMAC в LPC на возможно новые параметры связи (скорость, дуплекс)? Или EMAC сам умеет по RMII договариваться с PHY? Или ему (EMACу) вообще пофиг какой линк воткнут в PHY? В примере после поднятия линка перенастраивается EMAC в LPC на оперделенную во время auteneg конфигурацию. Это необходимо или это кривость примера?
  19. Ethernet + LPC1758

    На просторах сети нарыл пример исходников LPC17xx + KSZхххх + uIP. Там такая последовательность инициализации PHY в случае Auto-negotiation: 1) Поиск устройства PHY перебором адресов 2) Reset 3) Auto-negotiation setup 4) Запуск Auto-neg и ожидание линка. Если линка нет, выход с ошибкой. 5) Вычитываем из PHY параметры связи (speed, duplex), прописываем их в MAC 6) Прописываем подобранные параметры обратно в PHY жестко, отключив auto-neg. Во-первых меня сильно смущает последний шаг: для чего нужно отключать AN? Ведь тогда без перезагрузки уже не получится, например, переключить устройство в другой порт Ethernet. Так как я раньше с Ethernet не работал, возникает вопрос: есть ли в данном действии скрытый смысл? Может быть действительно для стабильной работы нельзя держать autoneg постоянно включенным? Во-вторых, по-моему неправильно в инициализации ожидать линка. Имхо надо либо настроить прерывание LinkUP от PHY, либо оставить все как есть и из-вне поллингом проверять состояние линка, правильно? Вообще, подскажите, кто как организовывает взаимодействие EMAC <-> PHY, какие есть подводные камни с инициализацией, что еще полезно обрабатывать из типовых PHY-прерываний кроме Link up/down? В приложении вышеупомянутый пример работы с PHY, однако я понимаю, что пример никогда нельзя рассматривать как готовое решение - на него можно лишь опираться иногда, поэтому просьба одна: рассказать как нужно делать, а не просто покритиковать пример :) lpc_eth.zip
  20. Keil+LPC1768+64KB SRAM

    Работать как всегда. Дело в том, что память "порвана" на несколько банков, посмотрите memory map. Там не 64Кб одним куском. По моему 32+32 (не помню сейчас). А куча это сегмент памяти. Компилятор не может "растянуть" один сегмент на разные области памяти. Поэтому куча не может быть более 32кб в данном контроллере. А что касается использования динамической памяти - "если очень хочется, то можно". Надо лишь осознавать последствия и быть к ним готовым.
  21. Если имеется ввиду Olimex ARM-JTAG-USB Tiny, то возможно он и заработает - надо мануал на него смотреть. В ИАРе он работает как J-Link, только надо подменить длл (идет в коробке с оным жтагом). Если же это AVR-JTAG-USB Tiny, то имхо работать не будет.
  22. И не только. Есть масса сторонних IDE для работы с исходниками. SlickEdit, MultiEdit, и т.п. Поиск подскажет, обсуждали не раз. А выбор между Keil, IAR и другими нужно делать исходя ТОЛЬКО из того, какой компилятор больше нравится. редакторы у них у всех кутылые...
  23. Как это??? Можно дескрипторы посмотреть? Присоединюсь к просьбе. Если и правда получится к HID прикрутить bulk то это для меня будет самым правильным решением. Всем спасибо! В голове начало проясняться :)
  24. Уже выбил и уже читаю. А по теме можно ответить?
×
×
  • Создать...