Easyelectronics.ru • Просмотр темы - FreeRTOS проблема (не знаю даже с чем конкретно)

Easyelectronics.ru

Электроника для всех
Текущее время: 14 авг 2018, 13:29

Часовой пояс: UTC + 5 часов



    • JLCPCB - Прототипы 10 PCBs всего за 2$ (100*100mm, 2-layer)
    • Как мы делаем платы, смотрите на YouTube
    • Крупнейшая китайская фабрика прототипов. 300000+ заказчиков и 10000+ заказов в день!
    • LCSC - Крупнейший китайский онлайн магазин комплектующих.

Начать новую тему Ответить на тему  [ Сообщений: 9 ] 
Автор Сообщение
 Заголовок сообщения: FreeRTOS проблема (не знаю даже с чем конкретно)
СообщениеДобавлено: 14 янв 2013, 18:30 
Только пришел

Зарегистрирован: 14 янв 2013, 17:05
Сообщения: 13
Здравствуйте.
Прошу помощи в "разборке" работы с FreeRTOSом.

Пишу программку в IAR ARM 6.21.
Контроллер - STM32F107 и STM32F103.
Программатор/отладчик - ST-Link (STM32_VL_Discovery)

Столкнулся с непонятным "явлением":
Передаю в функцию указатель на переменную, которая в функции должна изменяться.
Однако в функцию передается что-то не то (смотрю через disassembler, окно регистров, окно Watch).

FreeRTOS в режиме вытесняющей многозадачности (#define configUSE_PREEMPTION 1),
поэтому, как я понял, однажды зайдя в функцию-поток(с while()), мк оттуда не выйдет, ну то есть можно сказать, что
эта функция "думает", что она единственная занимает процессор и следовательно переменные объявленные внутри неё, как локальные, можно считать "глобальными", в том смысле, что они остаются и после того, как текущая задача была вытеснена, а затем опять получила управление. Правильно ли я понимаю? Хотя это не относится к основному вопросу.

И еще я не понимаю, как IAR видит(окно Watch) адрес переменной, объявленной в функции-потоке, то есть которая лежит в стеке, ведь FreeRTOS динамически выделяет стек задачам(потокам)? Или это происходит как-то через отладчик?

Код:
Код программки:
void vPBTask(void *pvParameters);
void kyky(int *ptr);

//==============================================================================
int main(void)
{
  // Создаем задачу(поток) PBTask с приоритетом 3
  xTaskCreate(vPBTask, "PBTask", 128, NULL, 3, NULL);

  // запускаем планировщик
  vTaskStartScheduler();
}

//функция, реализующая задачу(поток) PBTask
//==============================================================================
void vPBTask(void *pvParameters)
{
  int b;
 
  b = 0;
 
  while(1)
  {
    kyky(&b);
  }
}

//функция, изменяющяя переменную по указателю на неё
//==============================================================================
void kyky(int *ptr)
{
  *ptr = 125;
}


Из окна Disassembler-а
Код:
void vPBTask(void *pvParameters)
{
vPBTask:
    0x8000cac: 0xb510         PUSH      {R4, LR}
    0x8000cae: 0xb082         SUB       SP, SP, #0x8
    0x8000cb0: 0x0004         MOVS      R4, R0
  b = 0;
    0x8000cb2: 0x2000         MOVS      R0, #0
    0x8000cb4: 0x9000         STR       R0, [SP]
    kyky(&b);
??vPBTask_0:
  [b]  0x8000cb6: 0xa800         ADD       R0, SP, #0x0
    0x8000cb8: 0xf000 0xf801  BL        kyky                       ; 0x8000cbe[/b]
    0x8000cbc: 0xe7fb         B.N       ??vPBTask_0               ; 0x8000cb6
  *ptr = 125;
kyky:
    0x8000cbe: 0x217d         MOVS      R1, #125                ; 0x7d
    0x8000cc0: 0x6001         STR       R1, [R0]
}                                                                               //не пойму к чему эта скобочка ?   
    0x8000cc2: 0x4770         BX        LR



Перед выполнением команды по адресу 0x8000cb6, SP = 0x20004908, адресс переменной b равен 0x20004908.

По идее, после выполнения команды ADD R0, SP, #0x0, R0 будет содержать 0x20004908, но нет...
R0 содержит 0x20000260.

Собственно по этому адресу функция kyky и записывает число 125, смотрел через окно Memory.
Такая же ситуация при выполнении выражения b = 0;(команда STR R0, [SP] должна сохранять R0 по адрессу SP, но не тут то было.)

Пробовал все 3 типа выделения памяти.
Не могу понять, что происходит.


Последний раз редактировалось Scorpion_ak47 14 янв 2013, 19:49, всего редактировалось 3 раз(а).

Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: FreeRTOS проблема (не знаю даже с чем конкретно)
СообщениеДобавлено: 14 янв 2013, 19:25 
Только пришел

Зарегистрирован: 14 янв 2013, 17:05
Сообщения: 13
А если использовать глобальную переменную для функции kyky, то все работает правильно.
И если без FreeRTOS, то тоже все работает правильно.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: FreeRTOS проблема (не знаю даже с чем конкретно)
СообщениеДобавлено: 14 янв 2013, 20:48 
Старожил

Зарегистрирован: 22 мар 2010, 22:54
Сообщения: 3996
Scorpion_ak47 писал(а):
По идее, после выполнения команды ADD R0, SP, #0x0, R0 будет содержать 0x20004908, но нет...
R0 содержит 0x20000260.

R0 становится 0x20000260, а SP продолжает быть 0x20004908?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: FreeRTOS проблема (не знаю даже с чем конкретно)
СообщениеДобавлено: 14 янв 2013, 22:42 
Только пришел

Зарегистрирован: 14 янв 2013, 17:05
Сообщения: 13
R0 становится 0x20000260, а SP продолжает быть 0x20004908?

да, SP = 0x20004908.

Только вот странно, только что запустил отладку, а цифры другие(SP, <адрес>b).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: FreeRTOS проблема (не знаю даже с чем конкретно)
СообщениеДобавлено: 14 янв 2013, 23:59 
Только пришел

Зарегистрирован: 14 янв 2013, 17:05
Сообщения: 13
Я помню в AVR адрес возврата заносился в стек, а здесь, оказывается, есть специальный регистр LR и адрес возврата заносится туда.

Кое-что нашёл:

у ARM M3 есть два указателя стека:
    -Main Stack Pointer (MSP): The default stack pointer; used by the OS kernel and exception handlers
    -Process Stack Pointer (PSP): Used by user application code

Так вот в инструкции ADD R0, SP, #0x0, SP = PSP = не правильное значение(0x20000260), а MSP равен адресу переменной b (0x20004908), то есть то что нужно функции kyky, почему так не понимаю. Я пологаю, что PSP - указатель стека для текущего потока, а вот про MSP даже ничего не приходит в голову.

После Reset, PSP = 0x20000260 и не изменяется по ходу выполнения.

Буду читать описание ARM CortexM3.

адреса: 0x20000260 и 0x20004908 -- поддерживаю первоначальное сообщение.


Последний раз редактировалось Scorpion_ak47 15 янв 2013, 00:13, всего редактировалось 2 раз(а).

Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: FreeRTOS проблема (не знаю даже с чем конкретно)
СообщениеДобавлено: 15 янв 2013, 00:07 
Только пришел

Зарегистрирован: 14 янв 2013, 17:05
Сообщения: 13
То есть если не использовать FreeRTOS, то, в качестве SP, инструкция ADD используют MSP,
а если использовать FreeRTOS, то - PSP.

Но правильное значение лежит в MSP (и с FreeRTOS и без неё).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: FreeRTOS проблема (не знаю даже с чем конкретно)
СообщениеДобавлено: 15 янв 2013, 18:28 
Только пришел

Зарегистрирован: 14 янв 2013, 17:05
Сообщения: 13
Нашёл ещё кое-что:

Регитср R13 -- SP - один, но он "раздваивается" на два SP: MSP и PSP, и в один момент времени виден только один.

Я думаю, что MSP используется при старте, обработке исключений(это автоматически) и при работе ядра FreeRTOS, а PSP используется задачами(потоками), причем задачи(потоки) ни как не могут получить доступ к MSP. За содержимым PSP, перед работой задачи(потока), должна заботиться FreeRTOS.

Правильно ли я думаю?

У Cortex-M3 есть два режима работы(Operation Modes) и два уровня привелегий (Privilege Levels).

Operation Modes: Thread и Exseption(Handle):
    Thread - при работе основной программы.
    Exseption(Handle) - при обработке исключений(прерываний).

Privilege Levels: User и Privileged:
    User - запрещены некоторые инструкции доступа к важным регистрам процессора.
    Privileged - разрешены.

После reset ядро мк находится в Thread mode и privileged level, в качестве SP выбран MSP, значение, которое лежит в MSP, "берется" по адресу 0x8000000(или 0x0000000, если вектора прерываний находятся в RAM памяти), а там лежит число, устанавливаемое, наверное, компилятором (DCD sfe(CSTACK)) , затем в PC грузится число из 0x8000004(адрес Reset Interrupt).

Так вот, если не используется ОС, то никто и не переходит в user level(в котором можно использовать PSP) и в этом случае пример программки работает правильно.(используется MSP)

А если используется ОС, то она должна, ну я так думаю, при передачи процессорного времени задаче(потоку), переключить Privilege Levels в user level и положить нужное значение в PSP и задача(поток) будет работать с SP = PSP(это достигается установкой битика в регистре CONTROL, он не виден в отладке).

Так вобщем и происходит, но почему-то в PSP лежит что-то не то, а в MSP - то, что нужно, но в user level нельзя ни переключиться в privileged level, ни переключить текущий указатель стека.

Что не так, не пойму.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: FreeRTOS проблема (не знаю даже с чем конкретно)
СообщениеДобавлено: 15 янв 2013, 21:19 
Только пришел

Зарегистрирован: 14 янв 2013, 17:05
Сообщения: 13
Нашел загвоздку.

В ходе более детального анализа дизассемблера и области памяти, на которую указывает SP, понял, что FreeRTOS не виновата. Она, как и должна загружает некоторое число в PSP, меняет текущий SP на PSP, переключает процессор в user режим и вызывает задачу(функцию-потока).

Этот вывод cделан НЕ на основе анализа ядра FreeRTOS.

Задача(функция-поток) корректно работает.

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

Это конечно не очень удобно.

Может надо где-то поставить галочку, что бы отладчик следил за текущим SP ?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: FreeRTOS проблема (не знаю даже с чем конкретно)
СообщениеДобавлено: 02 окт 2014, 21:30 
Заглядывает иногда

Зарегистрирован: 15 авг 2012, 16:31
Сообщения: 58
У меня проблема, не знаю даже с чем конкретно.
Нужно сделать фазоимпульсное управление силовым симистором, при переходе через 0 срабатывает прерывание, в нем отдается семафор далее запускается задача.
В задаче такой код
vTaskDelay(6 / portTICK_RATE_MS);
GPIO_SetBits(TRIAC_PORT, TRIAC);
vTaskDelay(1 / portTICK_RATE_MS);
GPIO_ResetBits(TRIAC_PORT, TRIAC);
То есть через 6 млилисек открывается симистор, лампочка должна светится тускло и равномерно, но в реальности моргает.

Если вынести код задачи с FreeRTOS, то есть переключать в самом обработчике прерываний тогда все ОК.
delay_us(6000);
GPIO_SetBits(TRIAC_PORT, TRIAC);
delay_us(200);
GPIO_ResetBits(TRIAC_PORT, TRIAC);

Уже неделю не могу разобратся, помогите. плз.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 9 ] 

Часовой пояс: UTC + 5 часов


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB