Jump to content

    

Резервирование RSTACK для AVRMega

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

 

Компилятор: 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

Share this post


Link to post
Share on other sites

Возможно Ваша проблемма не в 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++;
 }
}

Edited by desh

Share this post


Link to post
Share on other sites

Переполнение буфера, очевидно, происходит, но по не совсем понятным причинам. Математика указателей, а тем более доступ без блокировок вообще исключены. Внешнюю память я уже тестировал когда-то, проблем там небыло. Но протестирую еще раз, возможно я что-то упустил. Спасибо за наводку.

 

PS: Я сейчас нашел немного другой порт под мегу128, но под GCC (старый я сам дорабатывал из 323меги, что идет в комплекте). Попробую адаптировать его под иар и посмотрю что получится

Share this post


Link to post
Share on other sites

Да не спешите Вы. Там от 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

Share this post


Link to post
Share on other sites

А может еще зависит от размера стека для конкретной задачи. В этом случае, это не только количество вызовов функции в глубину но и размеры локальных переменных в этих фунциях. Чтобы точно знать, что переполняеться стек задач надо использовать функцию http://www.freertos.org/uxTaskGetStackHighWaterMark.html

Share this post


Link to post
Share on other sites

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());

 

3037b5164846.png

 

В аттаче прикреплены файлы, описанные в диаграмме

 

PS: Дам ссылку на эту тему в теме про __interrupt

REB_Startup.rar

Edited by Aeore

Share this post


Link to post
Share on other sites
а так же добавил строчку в функцию pxPortInitialiseStack:

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

 

Что мешает вам запустить и отладить задачи по очереди? Похоже архитектура приложения позволяет это сделать.

Что у вас происходит при переполнении стека? У вас отрабатывает ловушка переполнения стека FreeRTOS?

Поставте в ней бесконечный цикл. При попадании изучите содержимое стека и pxCurrentTCB.

На время отладки отключите сторожевой таймер.

В чем смысл использования фреймворка? На разных платформах вы используете разные операционки?

Обратите внимание на scmRTOS. Она изначально на плюсах.

 

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

В IDLE переполнение стека могут вызывать прерывания.

Edited by desh

Share this post


Link to post
Share on other sites
Программа запустилась, но сходу упала в stack overfow.

Это хорошо, если программа сразу падает - ошибку найти гораздо легче.

Пройдитесь по шагам до места падения.

Share this post


Link to post
Share on other sites
Что мешает вам запустить и отладить задачи по очереди? Похоже архитектура приложения позволяет это сделать.

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

 

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

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 я пока что не использую, прерывания так же - лишь один таймер работает для функционированния вытесняющего планировщика

Share this post


Link to post
Share on other sites

Так. ЧуднО у вас все.

 

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

Запретите еще и прерывания.

 

Пробовали запускать и отлаживать в симуляторе IAR? Прерываний у вас мало, так что проблемм с запуском минимиум.

Отладку перенаправьте в стандартный вывод. Можно следить за происходящим прямо в симуляторе.

Какой уровень оптимизации у вас стоит?

 

Поофтоплю чуток.

полностью асинхронное event-driven окружени

ИМХО, не распологает выбранная платформа и среда к подобному программированию.

Код получается размазанным и сложным в сопровождении. Ресурсов опять таки не хватает постоянно.

Мне не понравилось так писать. Хотя, все зависит от задачи.

Edited by desh

Share this post


Link to post
Share on other sites
Запретите еще и прерывания.

Запрещал

 

Пробовали запускать и отлаживать в симуляторе IAR? Прерываний у вас мало, так что проблемм с запуском минимиум.

Отладку перенаправьте в стандартный вывод. Можно следить за происходящим прямо в симуляторе.

Какой уровень оптимизации у вас стоит?

 

Пробовал. Симулятор вел себя не вполне адекватно - перепрыгивал через целые участки кода. Уровень оптимизации установлен максимальный, но такое поведение наблюдалось и при минимальной оптимизации. Вот сейчас по какой-то причине код заработал нормально, и симуляция на первый взгляд тоже. Подожду глюка и попробую проверить, а то я был не уверен в его адекватности

 

Поофтоплю чуток.

ИМХО, не распологает выбранная платформа и среда к подобному программированию.

Код получается размазанным и сложным в сопровождении. Ресурсов опять таки не хватает постоянно.

Мне не понравилось так писать. Хотя, все зависит от задачи.

Ну в целом получается достаточно не плохо, главное уделить внимание архитектуре. А то действительно получится паутина. По поводу производительности - вот это я и хочу проверить) Пишу достаточно свободно и пока мега справляется очень хорошо (если не обращать внимание на глюки стека, что другое дело), а вытесняющий планировщик и приоритеты позволяют весьма шустро реагировать на все события. В основном программу можно написать так, что бы лишь малая ее часть была чувствительна к скорости работы и реакции - ее можно выделить в отдельные таски. А основная логика может быть громоздкой и работать относительно медленно - этого вообще не чувствуется. Именно поэтому я без страха использую полиморфизм.

 

Share this post


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

 

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 ); во вложеных функциях ?

Share this post


Link to post
Share on other sites
Пробовал. Симулятор вел себя не вполне адекватно - перепрыгивал через целые участки кода. Уровень оптимизации установлен максимальный, но такое поведение наблюдалось и при минимальной оптимизации. Вот сейчас по какой-то причине код заработал нормально, и симуляция на первый взгляд тоже. Подожду глюка и попробую проверить, а то я был не уверен в его адекватности

Симулятор адекватен. Нужно разобраться со скриптами и у вас в руках будет серьезный инструмент для отладки и тестирования.

Еще я стараюсь не пользоваться максимальной оптимизацией без необходимости. При максимальной оптимизации проявляются неточности программирования (например, забытые volatile),

которые незаметны при низкой оптимизации. Уровень medium вполне себе неплохо жмет.

При отладке оптимизированного кода прыжки - нормальное дело.

Кстати, в среде IAR есть возможность разный уровень оптимизации для разных файлов. Рекомендую.

 

 

Share this post


Link to post
Share on other sites
А проверяли использование стека сомой таской? Сколько выделяете стека на таск 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 все нормально:

ce1fc5afda45.png

 

Т.е. все очень сильно зависит от платформы. Это уже что-то.

 

Edited by Aeore

Share this post


Link to post
Share on other sites

У вас как на АВР-е определен базовый тип portBASE_TYPE как unsigned char.

В принципе функция uxTaskGetStackHighWaterMark больше 255 вернуть не сможет.

Тут же и ограничение на размер очереди в элементах.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this