Jump to content

    

Aeore

Участник
  • Content Count

    12
  • Joined

  • Last visited

Everything posted by Aeore


  1. Да, это так. Я недавно перевел систему из преемптивного в кооперативный режим - глюки исчезли полностью, хотя функция uxTaskGetStackHighWaterMark() в целом возвращает те же значения
  2. Опс.. да, действительно. По поводу очереди - у меня в каждой очереди по 16 элементов, так что не страшно. Как он может зависеть от платформы, если я сам указываю размеры стеков?
  3. Извиняюсь за то что долго не писал. Стека под каждую задачу выделяется с очень больши запасом. Вот только что застабил и перенес проект на WIN32 и тут появились такие новости с uxTaskGetStackHighWaterMark: На данный момент есть такие таски: CPLBKLogicService: 1024 CPPlatformService: 2048 CPHMILogicService: 2048 CPControllerService: 4096 Цифры это размер стеков этих задач. taskStart - это то место, где они запускаются. Вот кусок трейсов с платформы avr (цифры это результат работы функции uxTaskGetStackHighWaterMark в различных местах): P45G Broadband Radio Controller 2013, YGurin ---------------------------------------- [sS]: LBKLogic SHW CPLBKLogicService::taskStart 54 [sS]: Platform [sS]: HMI SHW CPHMILogicService::taskStart 54 SHW CPPlatformService::taskStart 54 [sS]: BeepMaster [sS]: Controller SHW CPControllerService::taskStart 52 SHW CPControllerService::onQueueCommandActioned 7 SHW CPStrategyPOSTCommand::start 246 SHW CPControllerService::onQueueCommandActioned 246 SHW CPControllerService::onQueueCommandActioned 236 SHW CPControllerService::onQueueCommandActioned 234 Nothing more to run А вот то же самое, но с WIN32. Как видно, на avr uxTaskGetStackHighWaterMark() возвращает всего ничего, а на win32 все нормально: Т.е. все очень сильно зависит от платформы. Это уже что-то.
  4. Запрещал Пробовал. Симулятор вел себя не вполне адекватно - перепрыгивал через целые участки кода. Уровень оптимизации установлен максимальный, но такое поведение наблюдалось и при минимальной оптимизации. Вот сейчас по какой-то причине код заработал нормально, и симуляция на первый взгляд тоже. Подожду глюка и попробую проверить, а то я был не уверен в его адекватности Ну в целом получается достаточно не плохо, главное уделить внимание архитектуре. А то действительно получится паутина. По поводу производительности - вот это я и хочу проверить) Пишу достаточно свободно и пока мега справляется очень хорошо (если не обращать внимание на глюки стека, что другое дело), а вытесняющий планировщик и приоритеты позволяют весьма шустро реагировать на все события. В основном программу можно написать так, что бы лишь малая ее часть была чувствительна к скорости работы и реакции - ее можно выделить в отдельные таски. А основная логика может быть громоздкой и работать относительно медленно - этого вообще не чувствуется. Именно поэтому я без страха использую полиморфизм.
  5. И так причину такого поведения я раскрыл, но как ее поправить пока не ясно. Причина: Похоже что линкер видит, что директива org попадает в сегмент прерываний, но он не просто добавляет код инструкции в сегмент начиная с заданного адреса, а усекает весь сегмент на размер org + размер всех инструкций после него (пока не встретится директива смены сегмента). Таким образом ORG TIMER1_COMPA_vect ; Vector address jmp SIG_OUTPUT_COMPARE1A; ISR (TIMER1_COMPA_vect = 0x30) и ошибка Error[e16]: Segment INTVEC (size: 0x84 align: 0x1) is too long for segment definition. At least 0x2c more bytes needed. для USART1_TXC_vect (= 0x80) связанны таким соотношением: 0x8C - (0x30 + 4) = 0x58 Таким образом он считает, что максимальный размер сегмента равен 0x58 байт. Проверяем так - берем два вектора #define ADC_vect (0x54) #define EE_RDY_vect (0x58) и пытаемся их использовать. Первый работает, второй нет. Компилируется, спасибо!
  6. Мешает неопределенное поведение системы. На работоспособность влияют совершенно несвязанные изменения. Вот к примеру : Стартует первая таска и тут же валится все по переполнению стека: Svc: LBKLogic started <!> Fatal: FreeRTOS stack overflow (Task: "ОJжJцJыJ$%6ПJ", Stack ptr: 4af6, Stack base: 4afb) <!> Fatal: FreeRTOS stack overflow (Task: "ОJжJцJыJ$%6ПJ", Stack ptr: 4ac1, Stack base: 4ae6) <!> Fatal: FreeRTOS stack overflow (Task: "ОJжJцJыJ$%6ПJ", Stack ptr: 4a8c, Stack base: 4ae6) <!> Fatal: FreeRTOS stack overflow (Task: "ОJжJцJыJ$%6ПJ", Stack ptr: 4a57, Stack base: 4ae6) <!> Fatal: FreeRTOS stack overflow (Task: "ОJжJцJыJ$%6ПJ", Stack ptr: 4a22, Stack base: 4ae6) <!> Fatal: FreeRTOS stack overflow (Task: "ОJжJцJыJ$%6ПJ", Stack ptr: 49ed, Stack base: 4ae6) <!> Fatal: FreeRTOS stack overflow (Task: "ОJжJцJыJ$%6ПJ", Stack ptr: 49b8, Stack base: 4ae6) <!> Fatal: FreeRTOS stack overflow (Task: "ОJжJцJыJ$%67A7[2 1u._ ^"ВВ/^"ВВ/^"ВВ/^"ВВ/^"ВВ/^"ВВ/^"ВВ/^"ВВ&j&»&3"^›", Stack ptr: 4983, Stack base: 4ae6) <!> Fatal: FreeRTOS stack overflow (Task: "ОJ7A7[2 1u._ ^"ВВ/^"ВВ/^"ВВ/^"ВВ/^"ВВ/^"ВВ/^"ВВ/^"ВВ/^"ВВ&j&»&3"^›", Stack ptr: 494e, Stack base: 4ae6) <!> А теперь внимание! Добавляем проверочный код в эту таску (который ничего не делает и ни с чем не связан) и вуалля - все начинает работать хорошо: void o(string s) { TRACE(const_cast<char*>(s.c_str())); } void m(string s) { o(s); } void l(string s) { m(s); } void k(string s) { l(s); } void g(string s) { k(s); } void f(string s) { g(s); } void e(string s) { f(s); } void d(string s) { e(s); } void c(string s) { d(s); } void b(string s) { c(s); } void a(string s) { b(s); } // -------------------------------------------------------------------------- void CPLBKLogicService::taskStart( void* const pContext ) // -------------------------------------------------------------------------- { uint32_t q[500]; q[300] = 5; if (q[300] == 5) { a("affected!"); } TRACE( "Svc: LBKLogic started" ); } И вот что полияло на результат? O_o да Цикл есть. Перезагружается всеравно. Возможно из-за преемптивного планировщика Попробую, правда сильно внутринности ОС я пока что не изучал Таймер не включен Идея фреймворка - предоставить расширенное и удобное, полностью асинхронное event-driven окружение для разработки ПО. FreeRTOS используется в качестве ядра и так же дает дополнительные плюшки в виде возможности поднимать независимые потоки. На scmRTOS я смотрел и даже использовал, но его возможности ограниченны по сравнению с FreeRTOS, к примеру там невозможно удалить таску. Я написал так: #define configMINIMAL_STACK_SIZE ( ( unsigned short ) 85 + configCALL_STACK_SIZE ) Самм IDLE я пока что не использую, прерывания так же - лишь один таймер работает для функционированния вытесняющего планировщика
  7. Эм.. удалил у себя - все осталось по прежнему O_o
  8. desh, RAMPZ у меня не сохранялся, спасибо. Я сейчас добавил ваши изменения, а так же добавил строчку в функцию pxPortInitialiseStack: ... *pxTopOfStack = ( portSTACK_TYPE ) 0x30; /* R30 Z */ pxTopOfStack--; *pxTopOfStack = ( portSTACK_TYPE ) 0x31; /* R31 */ pxTopOfStack--; // вот эти две *pxTopOfStack = ( portSTACK_TYPE ) 0x3B; /* RAMPZ */ pxTopOfStack--; *pxTopOfStack = portNO_CRITICAL_NESTING; /* Critical nesting is zero when the task starts. */ .. Программа запустилась, но сходу упала в stack overfow. Вот на всякий случай показыаю как выглядит участок фреймворка, который собственно и запускает таски: До старта операциооной системы вызываются эти функции. Все эти классы являются наследниками класса CServiceBase и пока что не содержат интересного кода: static_cast<void>(CPBeepMasterService::run()); static_cast<void>(CPControllerService::run()); static_cast<void>(CPPlatformService::run()); static_cast<void>(CPHMILogicService::run()); static_cast<void>(CPAuxADCService::run()); В аттаче прикреплены файлы, описанные в диаграмме PS: Дам ссылку на эту тему в теме про __interrupt REB_Startup.rar
  9. _Артём_, часть фреймворка я выложил в этой ветке: http://electronix.ru/forum/index.php?showt...p;#entry1166837 Портировал под М128 я сам. На счет RETI или RESET - линкеру указан ключ "-H1895 -h(CODE)0-_..X_INTVEC_SIZE" (см первый пост), где это делается автоматически (0x1895 это опкод reti) desh, у меня размер бинарника всего лишь что-то около 30КБ. А по поводу 64KB - RAMPZ влияет если оперативной памяти больше, а у меня как раз ровно 64КБ. Команды записи во флеш из юзеркода не вызываются, так что RAMPZ по идее никак не должен влиять.
  10. Переполнение буфера, очевидно, происходит, но по не совсем понятным причинам. Математика указателей, а тем более доступ без блокировок вообще исключены. Внешнюю память я уже тестировал когда-то, проблем там небыло. Но протестирую еще раз, возможно я что-то упустил. Спасибо за наводку. PS: Я сейчас нашел немного другой порт под мегу128, но под GCC (старый я сам дорабатывал из 323меги, что идет в комплекте). Попробую адаптировать его под иар и посмотрю что получится
  11. Контроллер : ATMega128 + 64KB внешней памяти Используется внешний xcl файл (настройки линкера) Есть смешанный C/C++ проект, в котором крутится FreeRTOS. Во FreeRTOS используется одно прерывание, которое там описано в ассемблерном исходнике с помощью директивы ORG. Проект компилится и кое-как работает, с прерываниями проблем нет. Теперь я хочу описать еще одно прерывание, пишу: // -------------------------------------------------------------------------- // USART1_TXC_vect = 0x80 #pragma vector = USART1_TXC_vect extern "C" __interrupt void interrupt_UART1_TXComplete( void ) // -------------------------------------------------------------------------- { // nop } и тут же получаю ошибку: Building configuration: p45g - Debug Updating build tree... CPTracePrinterStrategy.cpp Linking Error[e16]: Segment INTVEC (size: 0x84 align: 0x1) is too long for segment definition. At least 0x2c more bytes needed. The problem occurred while processing the segment placement command "-Z(CODE)INTVEC=0-(_..X_INTVEC_SIZE-1)", where at the moment of placement the available memory ranges were "CODE:0-2f,CODE:34-8b" Reserved ranges relevant to this placement: CODE:0-2f ?FILL1 CODE:30-33 Absolute code from portmacro CODE:34-8b ?FILL2 Warning[w18]: Segment INTVEC (seg part no 7, symbol "interrupt_UART1_TXComplete::??INTVEC 128" in module "CPTracePrinterStrategy", address [0-83]) overlaps segment ?FILL1 (from module "?FILLER_BYTES", address [0-2f]) Warning[w18]: Segment on the address 30-33 in the module portmacro (F:\PROJECTS\Ð-45\P45G\Firmware\1.00\out\obj\ Debug\portmacro.r90) overlaps segment INTVEC (seg part no 7, symbol "interrupt_UART1_TXComplete::??INTVEC 128" in module "CPTracePrinterStrategy", address [0-83]) Warning[w18]: Segment INTVEC (seg part no 7, symbol "interrupt_UART1_TXComplete::??INTVEC 128" in module "CPTracePrinterStrategy", address [0-83]) overlaps segment ?FILL2 (from module "?FILLER_BYTES", address [34-8b]) Warning[w70]: The segment "?FILL1" on address 0 overlaps previous content in the raw-binary output file. The previously content will be overwritten. Error while running Linker Total number of errors: 1 Total number of warnings: 4 Теперь немного арифметики: размер сегмента INTVEC_SIZE равен 8C (140 байт), а значит сюда поместятся 35 (140 / 4) векторов. В параметре vector указан адрес 0x80, что равно 128 байтам, т.е. адрес находится в пределе сегмента кода прерываний. Так что его тогда не устраивает? Вот XCL с конфигурацией: -ca90 -D_..X_INTVEC_SIZE=8C /* 4 bytes * 35 vectors */ -D_..X_FLASH_TEND=FF /* End of tiny flash memory */ -D_..X_FLASH_NEND=FFFF /* End of near flash memory */ -D_..X_FLASH_END=1FFFF /* End of flash memory */ -D_..X_SRAM_BASE=100 /* Start of ram memory */ -D_..X_SRAM_TEND=100 /* End of tiny ram memory */ -D_..X_SRAM_END=10FF /* End of ram memory */ -D_..X_EEPROM_END=FFF /* End of eeprom memory */ -D_..X_CSTACK_SIZE=400 /* 1024 bytes for auto variables and saved registers. */ -D_..X_RSTACK_SIZE=400 /* 1024 bytes for return addresses */ -D_SVC_STACK_SIZE=0 /* not used */ -D_IRQ_STACK_SIZE=0 /* scmRTOS uses CSTACK for irq */ -D_..X_NEAR_HEAP_SIZE=CAFA /* 0 bytes of heap. */ -D_..X_EXT_SRAM_BASE=1100 -D_..X_EXT_SRAM_END=FFFF -D_..X_EXT_EPROM_BASE=_..X_SRAM_BASE -D_..X_EXT_EPROM_END=_..X_SRAM_END -D_..X_EXT_EEPROM_BASE=_..X_SRAM_BASE -D_..X_EXT_EEPROM_END=_..X_SRAM_END -Z(CODE)INTVEC=0-(_..X_INTVEC_SIZE-1) -H1895 -h(CODE)0-_..X_INTVEC_SIZE /* RETI */ -Z(CODE)TINY_F=_..X_INTVEC_SIZE-_..X_FLASH_TEND -Z(CODE)NEAR_F,SWITCH,DIFUNCT=_..X_INTVEC_SIZE-_..X_FLASH_NEND -Z(CODE)CODE=_..X_INTVEC_SIZE-_..X_FLASH_END -Z(FARCODE)FAR_F=_..X_INTVEC_SIZE-_..X_FLASH_END -Z(CODE)HUGE_F,INITTAB=_..X_INTVEC_SIZE-_..X_FLASH_END -Z(CODE)TINY_ID,NEAR_ID=_..X_INTVEC_SIZE-_..X_FLASH_END -Z(CODE)CHECKSUM#_..X_FLASH_END -Z(DATA)TINY_I,TINY_Z,TINY_N=_..X_SRAM_BASE-_..X_SRAM_TEND -Z(DATA)NEAR_I,NEAR_Z=_..X_EXT_SRAM_BASE-_..X_EXT_SRAM_END -Z(DATA)RSTACK+_..X_RSTACK_SIZE=_..X_EXT_SRAM_BASE-_..X_EXT_SRAM_END -Z(DATA)CSTACK+_..X_CSTACK_SIZE=_..X_EXT_SRAM_BASE-_..X_EXT_SRAM_END -Z(DATA)IOSTREAM_N#_..X_EXT_SRAM_BASE-_..X_EXT_SRAM_END -Z(DATA)NEAR_HEAP+_..X_NEAR_HEAP_SIZE=_..X_EXT_SRAM_BASE-_..X_EXT_SRAM_END -Z(XDATA)EEPROM_I,EEPROM_N=0-_..X_EEPROM_END -Z(CONST)NEAR_C=_..X_EXT_EPROM_BASE-_..X_EXT_EPROM_END -Z(DATA)NEAR_N=_..X_EXT_EEPROM_BASE-_..X_EXT_EEPROM_END -e_PrintfLarge=_Printf -e_medium_write=_formatted_write -e_small_write_P=_formatted_write_P -e_ScanfLarge=_Scanf -e_medium_read=_formatted_read -e_medium_read_P=_formatted_read_P -w29 А вот и два MAP файла (сегменты) ДО добавления прерывания INTVEC CODE 00000000 - 00000003 4 Common 1 ?FILL1 CODE 00000004 - 0000002F 2C Relative 0 ?FILL2 CODE 00000034 - 0000008B 58 Relative 0 NEAR_F CODE 0000008C - 00000275 1EA Relative 0 SWITCH CODE 00000276 - 000002A9 34 Relative 1 CODE CODE 000002AA - 000070D5 6E2C Relative 1 HUGE_F CODE 000070D6 Predefined 0 INITTAB CODE 000070D6 - 000070E3 E Relative 0 TINY_ID CODE 000070E4 Predefined 0 NEAR_ID CODE 000070E4 - 000072ED 20A Relative 0 и ПОСЛЕ: ?FILL1 CODE 00000000 - 0000002F 30 Relative 0 INTVEC CODE 00000000 - 00000083 84 Common 1 ?FILL2 CODE 00000034 - 0000008B 58 Relative 0 NEAR_F CODE 0000008C - 00000275 1EA Relative 0 SWITCH CODE 00000276 - 000002A9 34 Relative 1 CODE CODE 000002AA - 000070D7 6E2E Relative 1 HUGE_F CODE 000070D8 Predefined 0 INITTAB CODE 000070D8 - 000070E5 E Relative 0 TINY_ID CODE 000070E6 Predefined 0 NEAR_ID CODE 000070E6 - 000072EF 20A Relative 0
  12. Здравствуйте. Компилятор: IAR AVR Контроллер: AVR ATMega128 + 64КБ внешней памяти Менеджер памяти: heap_3.c Описание проблемы: Прошивка представляет собой связку из нескольких слоев: ОС + Самописный фреймворк + Пользовательская программа. Специфика фреймворка и программы такова, что глубина вызовов может быть достаточно большой - приблизительно 20-30 вызовов в глубину. Вся эта связка в режиме симуляции под win32 работает нормально, но при прошивке контроллера начинаются проблемы - происходит циклическая перезагрузка, при том не всегда с самого начала. После очередного запуска программа может запуститься откуда-то с середины. Это все я контроллирую по трейсам в терминале. Вобщем искал я искал и нашел такую проблему: в конфигурационном файле FreeRTOSConfig.h есть макроопределение configCALL_STACK_SIZE, которое по умолчанию установлено в 20. Исследование исходников показало, что это 20 байт, которые ОС резервирует в стеке задачи под адреса возврата из функций. Так как у меня мега, то получается максимальная глубина всего 10 вызовов, а дальше RSTACK начинает перетирать уже сохраненные регистры и все прочее, от чего начинаются проблемы. Ну хорошо, увеличим размер этой области до, скажем, 128 байт (глубина до 64 вызовов), при этом всем общего размера стека хватает - я его устанавливаю с запасом, скажем 8 КБ. Результат: программа не работает. Глючит уже по другому, но с тем же результатом. Вобщем экспериментальным образом я нашел, что при размере 45 текущая программа работает стабильно, но всеравно при дальнейшем усложнении кода начинаются похожие проблемы. Вопрос: Как установить большой размер для стека возвратов? Очень надеюсь на вашу помощь. PS: Да, еще была проблема - вместе с этим постоянно срабатывал каллбэк vApplicationStackOverflowHook(), пока я не увеличил стандартные значения макросов configTIMER_QUEUE_LENGTH и configTIMER_TASK_STACK_DEPTH. После этого каллбэк срабатывал только после большого количества этих перезагрузок при глючащей системе. Теперь же, после небольшого допиливания программы (дописал несколько пустых классов-тасок и запустил их), опять начал срабатывать, но уже без таких феерических циклов перезагрузок как раньше (всего лишь одна): Вот пример трейсов, тут работа начинается с "Svc: LBKLogic started". Видно, что програма стартует нормально, но потом начинаются уже какие=-то глюки, после чего контроллер перезагружается (следующий "Svc: LBKLogic started") и дальше пока что все идет хорошо! (это до поры до времени) Svc: LBKLogic started <!> Fatal: FreeRTOS stack overflow (Task: "J¤JјJНJСJ$%ҐJ", Stack ptr: 4acd, Stack base: 4ad1) <!> Fatal: FreeRTOS stack overflow (Task: "J¤JјJНJСJ$%ҐJ", Stack ptr: 4a99, Stack base: bcf7) <!> Fatal: FreeRTOS stack overflow (Task: "J¤JјJНJСJ$%ҐJ", Stack ptr: 4a65, Stack base: bcf7) <!> Fatal: FreeRTOS stack overflow (Task: "J¤JјJНJСJ$%ҐJ", Stack ptr: 4a31, Stack base: bcf7) <!> Fatal: FreeRTOS stack overflow (Task: "J¤JјJНJСJ$%ҐJ", Stack ptr: 49fd, Stack base: bcf7) <!> Fatal: FreeRTOS stack overflow (Task: "J¤JјJНJСJ$%ҐJ", Stack ptr: 49c9, Stack base: bcf7) <!> Fatal: FreeRTOS stack overflow (Task: "J¤JјJНJСJ$%ҐJ", Stack ptr: 4995, Stack base: bcf7) <!> Fatal: FreeRTOS stack overflow (Task: "J¤JјJНJСJ$%6—6±1b0Л-µЗб"9дCлб"9дCлб"9дCлб"9дCлб"9дCлб"9дCлб"9дCлб"9дC%А&%i3"^›", Stack ptr: 4961, Stack base: bcf7) <!> Fatal: FreeRTOS stack overflow (Task: "J¤J6—6±1b0Л-µЗб"9дCлб"9дCлб"9дCлб"9дCлб"9дCлб"9дCлб"9дCлб"9дCлб"9дC%А&%i3"^›", Stack ptr: 492d, Stack base: bcf7) Svc: LBKLogic started Svc: Platform started Svc: HMILogic started Svc: BeepMaster started Svc: Controller started Nothing more to run PPS: Фрагмент текущей конфигурации из FreeRTOSConfig.h: #ifndef WIN32 # include <iom128.h> #endif #define configCALL_STACK_SIZE 45 // 20 by default #define configUSE_PREEMPTION 1 #define configUSE_IDLE_HOOK 0 #define configUSE_TICK_HOOK 0 #define configCPU_CLOCK_HZ ( ( unsigned long ) 16000000 ) #define configTICK_RATE_HZ ( ( portTickType ) 1000 ) #define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 9 ) #define configMINIMAL_STACK_SIZE ( ( unsigned short ) 85 + configCALL_STACK_SIZE ) // 85 by default #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 51200 ) ) #define configMAX_TASK_NAME_LEN ( 16 ) #ifdef DEBUG // ygurin #define configUSE_TRACE_FACILITY 1 #else #define configUSE_TRACE_FACILITY 0 #endif #define configUSE_16_BIT_TICKS 1 #define configIDLE_SHOULD_YIELD 1 #define configUSE_TIMERS 1 #define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1) #define configTIMER_QUEUE_LENGTH 64 // 20 by default 64 #define configTIMER_TASK_STACK_DEPTH 92 // 64 by default 92 #define configUSE_CO_ROUTINES 0 #define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) #define INCLUDE_vTaskPrioritySet 1 #define INCLUDE_uxTaskPriorityGet 1 #define INCLUDE_vTaskDelete 1 #define INCLUDE_vTaskCleanUpResources 0 #define INCLUDE_vTaskSuspend 1 #define INCLUDE_vTaskDelayUntil 1 #define INCLUDE_vTaskDelay 1 А это MAP файл с сегментами, который сгенерировал компилятор: Имя Пространство Адрес Размер Тип Выравнивание NEAR_I DATA 00001100 - 00001309 20A Relative 0 NEAR_Z DATA 0000130A - 00001390 87 Relative 0 RSTACK DATA 00001391 - 00001790 400 Predefined 0 CSTACK DATA 00001791 - 00001B90 400 Predefined 0 NEAR_HEAP DATA 00001B91 - 0000E68A CAFA Predefined 0