Здравствуйте.
Компилятор: 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 |