Aeore 0 30 мая, 2013 Опубликовано 30 мая, 2013 · Жалоба Здравствуйте. Компилятор: 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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
desh 0 31 мая, 2013 Опубликовано 31 мая, 2013 (изменено) · Жалоба Возможно Ваша проблемма не в FreeRTOS, а в прикладной задаче. Переполнение буфера, ошибка в математике указателей, доступ к общей памяти из нескольких задач без блокировок и т.п. Использую FreeRTOS c ATmega2561 как с внешней памятью так и без нее. За несколько лет работы в этой связке все проблемы возникали только из-за ошибок прикладного кода. Сейчас стек вызовов 100 байт (глубина порядка 30). Для себя доработал ядро так, что кроме переполнения CStack я отслеживаю еще и переполнение RStack. Протестируйте внешнюю память на предмет ошибок. Очень может быть у Вас проблемма с железом. Я использую вот такой тест. Попробуйте доработать его под себя. #include "types.h" #include <stdio.h> #include <stdlib.h> #define MEMORY_START 0x1100 #define MEMORY_SIZE 32768 USHORT Errors; ULONG Tests; ULONG Total; void Delay(USHORT Ms) { TCCR1B_WGM12 = 1; // СTС OCR1A = (F_CPU / (2 * 8 * 1000)) - 1; TCNT1 = 0; TCCR1B_CS11 = 1; // Прескаллер 8 while (Ms--) { #ifdef NDEBUG while (!TIFR_OCF1A); // Ждем флаг 1мс TIFR_OCF1A = 1; // Сброс флага #endif } TCCR1B_CS11 = 0; // Таймер отключен } void SetLedGreen(bool State) { DDRF_DDF2 = 1; PORTF_PORTF2 = State ? 0 : 1; } void SetLedRed(bool State) { #if defined(_MA_301_) DDRE_DDE7 = 1; PORTE_PORTE7 = State ? 0 : 1; #else DDRB_DDB4 = 1; PORTB_PORTB4 = State ? 0 : 1; #endif } void UartInit(ULONG Baud) { USHORT Reg = (F_CPU / (Baud * 16)) - 1; #if defined(_MA_301_) UBRR1H = Reg >> 8; UBRR1L = Reg; UCSR1C = (1 << UCSZ11)|(1 << UCSZ10); // 8-N-1 UCSR1B = (1 << RXEN1)|(1 << TXEN1); #elif defined(_M_320_) UBRR1H = Reg >> 8; UBRR1L = Reg; UCSR1C = (1 << UCSZ11)|(1 << UCSZ10); // 8-N-1 UCSR1B = (1 << RXEN1)|(1 << TXEN1); DDRD_DDD6 = 1; PORTD_PORTD6 = 1; #else UBRR0H = Reg >> 8; UBRR0L = Reg; UCSR0C = (1 << UCSZ01)|(1 << UCSZ00); // 8-N-1 UCSR0B = (1 << RXEN0)|(1 << TXEN0); DDRD_DDD7 = 1; PORTD_PORTD7 = 0; #endif } #ifdef NDEBUG int putchar(int Char) { #if defined(_MA_301_) while (!UCSR1A_UDRE1); UDR1 = Char; #elif defined(_M_320_) while (!UCSR1A_UDRE1); UDR1 = Char; #else while (!UCSR0A_UDRE0); UDR0 = Char; #endif return Char; } #endif void MemoryEnable() { DDRF_DDF3 = 1; MCUCR_SRE = 1; } void MemoryInit(UCHAR InitVal) { UCHAR *ExtMem = (UCHAR*)MEMORY_START; for (ULONG Index = 0; Index < MEMORY_SIZE; Index++) { ExtMem[index] = InitVal ^ Index; } } void MemoryTest(UCHAR InitVal) { UCHAR ReadVal; UCHAR *ExtMem = (UCHAR*)MEMORY_START; for (ULONG Index = 0; Index < MEMORY_SIZE; Index++) { ReadVal = ExtMem[index] ^ Index; if (ReadVal != InitVal) Errors++; } } int main( void ) { bool State = false; UartInit(115200); printf("Memory test\r\n"); MemoryEnable(); for (;;) { UCHAR InitVal = rand(); SetLedGreen(State ^= true); MemoryInit(InitVal); MemoryTest(InitVal); Total += Errors; SetLedRed(Total ? true : false); printf("Test %lu, Init 0x%02X, Errors %hu, Total %lu\r\n", Tests, InitVal, Errors, Total); Errors = 0; Tests++; } } Изменено 31 мая, 2013 пользователем desh Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Aeore 0 1 июня, 2013 Опубликовано 1 июня, 2013 · Жалоба Переполнение буфера, очевидно, происходит, но по не совсем понятным причинам. Математика указателей, а тем более доступ без блокировок вообще исключены. Внешнюю память я уже тестировал когда-то, проблем там небыло. Но протестирую еще раз, возможно я что-то упустил. Спасибо за наводку. PS: Я сейчас нашел немного другой порт под мегу128, но под GCC (старый я сам дорабатывал из 323меги, что идет в комплекте). Попробую адаптировать его под иар и посмотрю что получится Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
desh 0 1 июня, 2013 Опубликовано 1 июня, 2013 · Жалоба Да не спешите Вы. Там от 323 до 128 один регистр сохранять надо. portSAVE_CONTEXT MACRO st -y, r0 ; First save the r0 register - we need to use this. in r0, SREG ; Obtain the SREG value so we can disable interrupts... cli ; ... as soon as possible. st -y, r0 ; Store the SREG as it was before we disabled interrupts. in r0, SPL ; Next store the hardware stack pointer. The IAR... st -y, r0 ; ... compiler uses the hardware stack as a call stack ... in r0, SPH ; ... only. st -y, r0 st -y, r1 ; Now store the rest of the registers. Dont store the ... st -y, r2 ; ... the Y register here as it is used as the software st -y, r3 ; stack pointer and will get saved into the TCB. st -y, r4 ... st -y, r30 st -y, r31 in r0, RAMPZ ; Вот этот регистр st -y, r0 ; надо сохранить lds r0, uxCriticalNesting st -y, r0 ; Store the critical nesting counter. lds r26, pxCurrentTCB ; Finally save the software stack pointer (Y ... lds r27, pxCurrentTCB + 1 ; ... register) into the TCB. st x+, r28 st x+, r29 ENDM portRESTORE_CONTEXT MACRO lds r26, pxCurrentTCB lds r27, pxCurrentTCB + 1 ; Restore the software stack pointer from ... ld r28, x+ ; the TCB into the software stack pointer (... ld r29, x+ ; ... the Y register). ld r0, y+ sts uxCriticalNesting, r0 ld r0, y+ ; А здесь out RAMPZ, r0 ; вернуть как был ld r31, y+ ; Restore the registers down to R0. The Y ld r30, y+ ; register is missing from this list as it ld r27, y+ ; has already been restored. ... ld r2, y+ ld r1, y+ ld r0, y+ ; The next thing on the stack is the ... out SPH, r0 ; ... hardware stack pointer. ld r0, y+ out SPL, r0 ld r0, y+ ; Next there is the SREG register. out SREG, r0 ld r0, y+ ; Finally we have finished with r0, so restore r0. ENDM Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
framer 0 2 июня, 2013 Опубликовано 2 июня, 2013 · Жалоба А может еще зависит от размера стека для конкретной задачи. В этом случае, это не только количество вызовов функции в глубину но и размеры локальных переменных в этих фунциях. Чтобы точно знать, что переполняеться стек задач надо использовать функцию http://www.freertos.org/uxTaskGetStackHighWaterMark.html Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Aeore 0 2 июня, 2013 Опубликовано 2 июня, 2013 (изменено) · Жалоба 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 Изменено 2 июня, 2013 пользователем Aeore Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
desh 0 2 июня, 2013 Опубликовано 2 июня, 2013 (изменено) · Жалоба а так же добавил строчку в функцию pxPortInitialiseStack: Все правильно. Забыл про нее. Что мешает вам запустить и отладить задачи по очереди? Похоже архитектура приложения позволяет это сделать. Что у вас происходит при переполнении стека? У вас отрабатывает ловушка переполнения стека FreeRTOS? Поставте в ней бесконечный цикл. При попадании изучите содержимое стека и pxCurrentTCB. На время отладки отключите сторожевой таймер. В чем смысл использования фреймворка? На разных платформах вы используете разные операционки? Обратите внимание на scmRTOS. Она изначально на плюсах. Какое у вас значение configMINIMAL_STACK_SIZE? Увеличте его. Оно влияет на размер стека задачи IDLE. В IDLE переполнение стека могут вызывать прерывания. Изменено 2 июня, 2013 пользователем desh Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 2 июня, 2013 Опубликовано 2 июня, 2013 · Жалоба Программа запустилась, но сходу упала в stack overfow. Это хорошо, если программа сразу падает - ошибку найти гораздо легче. Пройдитесь по шагам до места падения. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Aeore 0 3 июня, 2013 Опубликовано 3 июня, 2013 · Жалоба Что мешает вам запустить и отладить задачи по очереди? Похоже архитектура приложения позволяет это сделать. Мешает неопределенное поведение системы. На работоспособность влияют совершенно несвязанные изменения. Вот к примеру : Стартует первая таска и тут же валится все по переполнению стека: 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 Что у вас происходит при переполнении стека? У вас отрабатывает ловушка переполнения стека FreeRTOS? да Поставте в ней бесконечный цикл. Цикл есть. Перезагружается всеравно. Возможно из-за преемптивного планировщика При попадании изучите содержимое стека и pxCurrentTCB. Попробую, правда сильно внутринности ОС я пока что не изучал На время отладки отключите сторожевой таймер. Таймер не включен В чем смысл использования фреймворка? На разных платформах вы используете разные операционки? Обратите внимание на scmRTOS. Она изначально на плюсах. Идея фреймворка - предоставить расширенное и удобное, полностью асинхронное event-driven окружение для разработки ПО. FreeRTOS используется в качестве ядра и так же дает дополнительные плюшки в виде возможности поднимать независимые потоки. На scmRTOS я смотрел и даже использовал, но его возможности ограниченны по сравнению с FreeRTOS, к примеру там невозможно удалить таску. Какое у вас значение configMINIMAL_STACK_SIZE? Увеличте его. Оно влияет на размер стека задачи IDLE. В IDLE переполнение стека могут вызывать прерывания. Я написал так: #define configMINIMAL_STACK_SIZE ( ( unsigned short ) 85 + configCALL_STACK_SIZE ) Самм IDLE я пока что не использую, прерывания так же - лишь один таймер работает для функционированния вытесняющего планировщика Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
desh 0 3 июня, 2013 Опубликовано 3 июня, 2013 (изменено) · Жалоба Так. ЧуднО у вас все. Цикл есть. Перезагружается всеравно. Возможно из-за преемптивного планировщика Запретите еще и прерывания. Пробовали запускать и отлаживать в симуляторе IAR? Прерываний у вас мало, так что проблемм с запуском минимиум. Отладку перенаправьте в стандартный вывод. Можно следить за происходящим прямо в симуляторе. Какой уровень оптимизации у вас стоит? Поофтоплю чуток. полностью асинхронное event-driven окружени ИМХО, не распологает выбранная платформа и среда к подобному программированию. Код получается размазанным и сложным в сопровождении. Ресурсов опять таки не хватает постоянно. Мне не понравилось так писать. Хотя, все зависит от задачи. Изменено 3 июня, 2013 пользователем desh Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Aeore 0 5 июня, 2013 Опубликовано 5 июня, 2013 · Жалоба Запретите еще и прерывания. Запрещал Пробовали запускать и отлаживать в симуляторе IAR? Прерываний у вас мало, так что проблемм с запуском минимиум. Отладку перенаправьте в стандартный вывод. Можно следить за происходящим прямо в симуляторе. Какой уровень оптимизации у вас стоит? Пробовал. Симулятор вел себя не вполне адекватно - перепрыгивал через целые участки кода. Уровень оптимизации установлен максимальный, но такое поведение наблюдалось и при минимальной оптимизации. Вот сейчас по какой-то причине код заработал нормально, и симуляция на первый взгляд тоже. Подожду глюка и попробую проверить, а то я был не уверен в его адекватности Поофтоплю чуток. ИМХО, не распологает выбранная платформа и среда к подобному программированию. Код получается размазанным и сложным в сопровождении. Ресурсов опять таки не хватает постоянно. Мне не понравилось так писать. Хотя, все зависит от задачи. Ну в целом получается достаточно не плохо, главное уделить внимание архитектуре. А то действительно получится паутина. По поводу производительности - вот это я и хочу проверить) Пишу достаточно свободно и пока мега справляется очень хорошо (если не обращать внимание на глюки стека, что другое дело), а вытесняющий планировщик и приоритеты позволяют весьма шустро реагировать на все события. В основном программу можно написать так, что бы лишь малая ее часть была чувствительна к скорости работы и реакции - ее можно выделить в отдельные таски. А основная логика может быть громоздкой и работать относительно медленно - этого вообще не чувствуется. Именно поэтому я без страха использую полиморфизм. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
framer 0 6 июня, 2013 Опубликовано 6 июня, 2013 · Жалоба А теперь внимание! Добавляем проверочный код в эту таску (который ничего не делает и ни с чем не связан) и вуалля - все начинает работать хорошо: 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 ); во вложеных функциях ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
desh 0 7 июня, 2013 Опубликовано 7 июня, 2013 · Жалоба Пробовал. Симулятор вел себя не вполне адекватно - перепрыгивал через целые участки кода. Уровень оптимизации установлен максимальный, но такое поведение наблюдалось и при минимальной оптимизации. Вот сейчас по какой-то причине код заработал нормально, и симуляция на первый взгляд тоже. Подожду глюка и попробую проверить, а то я был не уверен в его адекватности Симулятор адекватен. Нужно разобраться со скриптами и у вас в руках будет серьезный инструмент для отладки и тестирования. Еще я стараюсь не пользоваться максимальной оптимизацией без необходимости. При максимальной оптимизации проявляются неточности программирования (например, забытые volatile), которые незаметны при низкой оптимизации. Уровень medium вполне себе неплохо жмет. При отладке оптимизированного кода прыжки - нормальное дело. Кстати, в среде IAR есть возможность разный уровень оптимизации для разных файлов. Рекомендую. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Aeore 0 12 июня, 2013 Опубликовано 12 июня, 2013 (изменено) · Жалоба А проверяли использование стека сомой таской? Сколько выделяете стека на таск xTaskCreate(task, (signed char *)"task", ??? , 0,tskIDLE_PRIORITY + 2, NULL); ? Как я писал локалные переменные ложаться в стек задачи а у Вас локальная переменная во uint32_t q[500];. Попробуйте динамически выделить память, либо сделать глобальную переменную и посмотреть как себя ведет. А что возвращает uxTaskGetStackHighWaterMark( xTaskHandle xTask ); во вложеных функциях ? Извиняюсь за то что долго не писал. Стека под каждую задачу выделяется с очень больши запасом. Вот только что застабил и перенес проект на 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 все нормально: Т.е. все очень сильно зависит от платформы. Это уже что-то. Изменено 12 июня, 2013 пользователем Aeore Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
desh 0 14 июня, 2013 Опубликовано 14 июня, 2013 · Жалоба У вас как на АВР-е определен базовый тип portBASE_TYPE как unsigned char. В принципе функция uxTaskGetStackHighWaterMark больше 255 вернуть не сможет. Тут же и ограничение на размер очереди в элементах. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться