реклама на сайте
подробности

 
 
> Резервирование RSTACK для AVRMega, Нестабильная работа
Aeore
сообщение May 30 2013, 19:53
Сообщение #1





Группа: Участник
Сообщений: 12
Регистрация: 10-08-07
Из: Odessa
Пользователь №: 29 704



Здравствуйте.

Компилятор: 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
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Aeore
сообщение Jun 2 2013, 08:31
Сообщение #2





Группа: Участник
Сообщений: 12
Регистрация: 10-08-07
Из: Odessa
Пользователь №: 29 704



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


Сообщение отредактировал Aeore - Jun 2 2013, 08:32
Прикрепленные файлы
Прикрепленный файл  REB_Startup.rar ( 13.66 килобайт ) Кол-во скачиваний: 20
 
Go to the top of the page
 
+Quote Post
desh
сообщение Jun 2 2013, 09:33
Сообщение #3


Частый гость
**

Группа: Свой
Сообщений: 113
Регистрация: 25-10-07
Из: Краснодар
Пользователь №: 31 725



Цитата(Aeore @ Jun 2 2013, 12:31) *
а так же добавил строчку в функцию pxPortInitialiseStack:

Все правильно. Забыл про нее.

Что мешает вам запустить и отладить задачи по очереди? Похоже архитектура приложения позволяет это сделать.
Что у вас происходит при переполнении стека? У вас отрабатывает ловушка переполнения стека FreeRTOS?
Поставте в ней бесконечный цикл. При попадании изучите содержимое стека и pxCurrentTCB.
На время отладки отключите сторожевой таймер.
В чем смысл использования фреймворка? На разных платформах вы используете разные операционки?
Обратите внимание на scmRTOS. Она изначально на плюсах.

Какое у вас значение configMINIMAL_STACK_SIZE? Увеличте его. Оно влияет на размер стека задачи IDLE.
В IDLE переполнение стека могут вызывать прерывания.

Сообщение отредактировал desh - Jun 2 2013, 10:02
Go to the top of the page
 
+Quote Post
Aeore
сообщение Jun 3 2013, 18:15
Сообщение #4





Группа: Участник
Сообщений: 12
Регистрация: 10-08-07
Из: Odessa
Пользователь №: 29 704



Цитата(desh @ Jun 2 2013, 12:33) *
Что мешает вам запустить и отладить задачи по очереди? Похоже архитектура приложения позволяет это сделать.

Мешает неопределенное поведение системы. На работоспособность влияют совершенно несвязанные изменения. Вот к примеру :

Стартует первая таска и тут же валится все по переполнению стека:
CODE

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)
<!>


А теперь внимание! Добавляем проверочный код в эту таску (который ничего не делает и ни с чем не связан) и вуалля - все начинает работать хорошо:

CODE

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

Цитата(desh @ Jun 2 2013, 12:33) *
Что у вас происходит при переполнении стека? У вас отрабатывает ловушка переполнения стека FreeRTOS?

да

Цитата(desh @ Jun 2 2013, 12:33) *
Поставте в ней бесконечный цикл.

Цикл есть. Перезагружается всеравно. Возможно из-за преемптивного планировщика

Цитата(desh @ Jun 2 2013, 12:33) *
При попадании изучите содержимое стека и pxCurrentTCB.

Попробую, правда сильно внутринности ОС я пока что не изучал

Цитата(desh @ Jun 2 2013, 12:33) *
На время отладки отключите сторожевой таймер.

Таймер не включен

Цитата(desh @ Jun 2 2013, 12:33) *
В чем смысл использования фреймворка? На разных платформах вы используете разные операционки?
Обратите внимание на scmRTOS. Она изначально на плюсах.

Идея фреймворка - предоставить расширенное и удобное, полностью асинхронное event-driven окружение для разработки ПО. FreeRTOS используется в качестве ядра и так же дает дополнительные плюшки в виде возможности поднимать независимые потоки.
На scmRTOS я смотрел и даже использовал, но его возможности ограниченны по сравнению с FreeRTOS, к примеру там невозможно удалить таску.

Цитата(desh @ Jun 2 2013, 12:33) *
Какое у вас значение configMINIMAL_STACK_SIZE? Увеличте его. Оно влияет на размер стека задачи IDLE.
В IDLE переполнение стека могут вызывать прерывания.

Я написал так:
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 85 + configCALL_STACK_SIZE )

Самм IDLE я пока что не использую, прерывания так же - лишь один таймер работает для функционированния вытесняющего планировщика
Go to the top of the page
 
+Quote Post
framer
сообщение Jun 6 2013, 08:33
Сообщение #5


Участник
*

Группа: Свой
Сообщений: 46
Регистрация: 23-09-04
Пользователь №: 709



Цитата(Aeore @ Jun 3 2013, 21:15) *
А теперь внимание! Добавляем проверочный код в эту таску (который ничего не делает и ни с чем не связан) и вуалля - все начинает работать хорошо:

CODE

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" );
}


А проверяли использование стека сомой таской? Сколько выделяете стека на таск xTaskCreate(task, (signed char *)"task", ??? , 0,tskIDLE_PRIORITY + 2, NULL); ? Как я писал локалные переменные ложаться в стек задачи а у Вас локальная переменная во uint32_t q[500];. Попробуйте динамически выделить память, либо сделать глобальную переменную и посмотреть как себя ведет. А что возвращает uxTaskGetStackHighWaterMark( xTaskHandle xTask ); во вложеных функциях ?
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- Aeore   Резервирование RSTACK для AVRMega   May 30 2013, 19:53
- - desh   Возможно Ваша проблемма не в FreeRTOS, а в приклад...   May 31 2013, 19:13
- - Aeore   Переполнение буфера, очевидно, происходит, но по н...   Jun 1 2013, 21:25
- - desh   Да не спешите Вы. Там от 323 до 128 один регистр с...   Jun 1 2013, 21:50
- - framer   А может еще зависит от размера стека для конкретно...   Jun 2 2013, 06:17
||- - Aeore   Цитата(framer @ Jun 6 2013, 11:33) А пров...   Jun 12 2013, 20:09
||- - framer   Цитата(Aeore @ Jun 13 2013, 00:09) CODE [...   Jun 14 2013, 12:06
||- - framer   Цитата(Aeore @ Jun 16 2013, 23:59) Как он...   Jun 17 2013, 06:11
|- - _Артём_   Цитата(Aeore @ Jun 2 2013, 11:31) Програм...   Jun 2 2013, 12:16
- - desh   Так. ЧуднО у вас все. ЦитатаЦикл есть. Перезагруж...   Jun 3 2013, 20:01
|- - Aeore   Цитата(desh @ Jun 3 2013, 23:01) Запретит...   Jun 5 2013, 18:54
- - desh   ЦитатаПробовал. Симулятор вел себя не вполне адекв...   Jun 7 2013, 13:42
- - desh   У вас как на АВР-е определен базовый тип portBASE_...   Jun 14 2013, 06:52
|- - Aeore   Цитата(desh @ Jun 14 2013, 09:52) У вас к...   Jun 16 2013, 20:59
- - Aeore   Да, это так. Я недавно перевел систему из преемпти...   Jun 25 2013, 08:11


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd June 2025 - 05:04
Рейтинг@Mail.ru


Страница сгенерированна за 0.01435 секунд с 7
ELECTRONIX ©2004-2016