Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Стек main после запуска планировщика
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы > FreeRTOS
glonium
Доброго времени суток всем!
Использую в своём проекте freeRTOS на stm32 компилятор Keil.
Вот недавно столкнулся с особенностью что после запуска планировщика из main портиться итек main, то есть при попытке обратиться к локальным переменным main типа класс с виртуальными функциями внутри по заданному адресу из задачи ввалимся в HardFault_Handler. При анализе обнаружил мусор по адресу данной переменной хотя адрес верный и до запуска планировщика было всё нормально. Кто нибудь сталкивался почему портиться стек main?

Сейчас выяснил что стек портиться после вызова функции:
Код
__asm void vPortStartFirstTask( void )
{
    PRESERVE8

    /* Use the NVIC offset register to locate the stack. */
    ldr r0, =0xE000ED08
    ldr r0, [r0]
    ldr r0, [r0]
    /* Set the msp back to the start of the stack. */
    msr msp, r0
    /* Globally enable interrupts. */
    cpsie i
    /* Call SVC to start the first task. */
    svc 0
    nop
}


Я просто в асме не очень кто нибудь подскажите что тут твориться?
_Артём_
Цитата(glonium @ Feb 26 2014, 19:10) *
Использую в своём проекте freeRTOS на stm32 компилятор Keil.
Вот недавно столкнулся с особенностью что после запуска планировщика из main портиться итек main, то есть при попытке обратиться к локальным переменным main типа класс с виртуальными функциями внутри по заданному адресу из задачи ввалимся в HardFault_Handler.

Видимо стек портится потому, что после запуска планировщика он используется как стек прерываний. Переключение стеков реализовано в Cortex аппаратно.
Если хотите использовать переменные из стека main (а оно надо такое?), то расположите стек прерываний в другой области ОЗУ.
megajohn
>Я просто в асме не очень кто нибудь подскажите что тут твориться?
включается прерывание SvCall и это по сути запрос на переключение контекста

увеличьте стек
либо поставьте бряк к примеру на 0x10000020 и смотрите кто пишет
для удобства можно до startup_main проиннициализировать main-стек

Цитата(megajohn @ Feb 26 2014, 19:27) *
для удобства можно до startup_main проиннициализировать main-стек


для IAR делается так, открываете startup*.s

MODULE ?cstartup

;; Forward declaration of sections.
SECTION CSTACK:DATA:NOROOT(3)

SECTION .intvec:CODE:NOROOT(2)

EXTERN _InitStacks добавляете строку
EXTERN SystemInit
EXTERN __iar_program_start

берете из аттача файл, переименовываете в fill_stacks.s и добавляете к проекту. И всё
glonium
Не надо впринципе просто хотелось выяснить причины. Невыясненная причина потом может вылезти!
megajohn
>Если хотите использовать переменные из стека main (а оно надо такое?), то расположите стек прерываний в другой области ОЗУ.

по стартапу контроллер находится в Thread Mode с MSP
по запуску операционки задачи работают в Thread Mode с PSP
в прерывании режим Handler Mode с MSP

то есть до старта ОС и прерывания это одна область памяти. Зачем её разделять - не понятно, наоборот трата ресурсов
_Артём_
Цитата(megajohn @ Feb 26 2014, 19:39) *
по стартапу контроллер находится в Thread Mode с MSP

МК стартует в handler mode и потом может переключиться в Thread mode. Если не путаю конечно...Иначе что мешает задаче переключится в режим обработчика?
glonium
Спасибо за ответы!
Буду разбираться, впринципе static помогает!

Разобрался!
В упор не видел!
Код
    /* Use the NVIC offset register to locate the stack. */
    ldr r0, =0xE000ED08
    ldr r0, [r0]
    ldr r0, [r0]
    /* Set the msp back to the start of the stack. */
    msr msp, r0

восстанавливает верхушку стека таким образом сбрасывая её!
Всем спасибо большое за помощь!
Думаю тему можно считать исчерпанной!
_Артём_
Цитата(glonium @ Feb 26 2014, 22:06) *
Буду разбираться, впринципе static помогает!

static - тоже что и глобальная переменная. Может так и объявить?
Цитата(glonium @ Feb 26 2014, 22:06) *
Код
    /* Use the NVIC offset register to locate the stack. */
    ldr r0, =0xE000ED08
    ldr r0, [r0]
    ldr r0, [r0]
    /* Set the msp back to the start of the stack. */
    msr msp, r0

И что там было? Можно ведь понятней писать...Нужно стремится к этому.
kolobok0
Цитата(glonium @ Feb 26 2014, 22:06) *
..восстанавливает верхушку стека...


да, там нужно немного подправить азм. чтоб корректно сохранять-восстанавливать данную область памяти.
делал когда-то, для останова FreeRTOS. Правда по второму кругу так и не удалось застартовать ось уже, пришлось сделать
кондово(и стабильней) - через ресет.
AHTOXA
Цитата(_Артём_ @ Feb 27 2014, 03:43) *
И что там было? Можно ведь понятней писать...Нужно стремится к этому.

Там MAIN стек переставляют в начало перед запуском оси. Чтоб стек зря не пропадал. После старта оси этот стек будет использоваться для прерываний.
Им не пришло в голову, что кто-то перед запуском оси может завести локальные переменные на стеке и потом работать с ними.
glonium
Да все верно! Но использовать переменные из стека маин не критично, просто хотелось разобраться в чем дело исключить баги в программе!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.