Перейти к содержанию
    

Всем доброго дня.

Пытаюсь сделать порт для Cortex R4F (чип RM46L852). Компилятор gcc 5.4.1.

 

Использую схему с программным прерыванием. Но возникает проблема в реализации функции os_start

По примеру порта ARM7

сделал ассемблерный файл со следующий содержимым (подсматривал в других ОСРВ)

 

        .set SYS_MODE,    0x1f
        .set SVC_MODE,    0x13
        .set IRQ_MODE,    0x12
        .set STUB,    0x00


        .global context_restore

context_restore:     // os_start() passes New_SP in R0
    CPS        #SYS_MODE
    LDR        R1, [R0]
    LDR        SP, [R1]



    /* Restore the floating point context, if any. */
    POPNE     {R0}
    VPOPNE    {D0-D15}
    VMSRNE  FPSCR, R0


    /* Restore all system mode registers other than the SP (which is already
    being used). */
    POP        {R0-R12, R14}

    /* Return to the task code, loading CPSR on the way. */
    RFEIA    sp!

 

в отладчике штатно дохожу до строки

LDR        R1, [R0]

и при ее выполнении процессор улетает в dabort handler. Это означает что инструкция обратилась к данным с которыми проблема.

Подскажите пожалуйста в какую сторону начать поиски. у меня подозрение что я что то неверно делаю с заготовкой стека.

 

 

void TBaseProcess::init_stack_frame( stack_item_t * Stack
                                   , void (*exec)()
                                #if scmRTOS_DEBUG_ENABLE == 1
                                   , stack_item_t * StackBegin
                                #endif
                                   )
{
        *Stack = ( stack_item_t ) NULL;
        Stack--;
        *Stack = ( stack_item_t ) NULL;
        Stack--;
        *Stack = ( stack_item_t ) NULL;
        Stack--;
        *Stack = ( stack_item_t ) 0x1f;;

        if((uintptr_t)exec & (0x01UL))  {
               *Stack = *Stack | 0x20;
           }
        Stack--;
        *Stack = reinterpret_cast<stack_item_t>(exec);;
        Stack--;
        *Stack = ( stack_item_t ) 0;    /* R14 */
        Stack--;
        *Stack = ( stack_item_t ) 0; /* R12 */
        Stack--;
        *Stack = ( stack_item_t ) 0; /* R11 */
        Stack--;
        *Stack = ( stack_item_t ) 0; /* R10 */
        Stack--;
        *Stack = ( stack_item_t ) 0; /* R9 */
        Stack--;
        *Stack = ( stack_item_t ) 0; /* R8 */
        Stack--;
        *Stack = ( stack_item_t ) 0; /* R7 */
        Stack--;
        *Stack = ( stack_item_t ) 0; /* R6 */
        Stack--;
        *Stack = ( stack_item_t ) 0; /* R5 */
        Stack--;
        *Stack = ( stack_item_t ) 0; /* R4 */
        Stack--;
        *Stack = ( stack_item_t ) 0; /* R3 */
        Stack--;
        *Stack = ( stack_item_t ) 0; /* R2 */
        Stack--;
        *Stack = ( stack_item_t ) 0; /* R1 */
        Stack--;
        *Stack = ( stack_item_t ) 0; /* R0 */
        Stack--;
        *Stack = ( uint32_t ) 0;
        Stack--;
        *Stack = ( stack_item_t ) 0;

}

 

Это точно не MPU, я его отключал.

 

 

ADD:

 

в этот момент в R0 содержится значение 0xea006068 , память по этому адресу просмотреть нельзя.

 

Прошу сильно не пинать. Процессор для меня новый.

Изменено пользователем Legath

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пытаюсь сделать порт для Cortex R4F (чип RM46L852). Компилятор gcc 5.4.1.
Там есть общий порт для Mx (x=0, 3, 4) под gcc, его нельзя доработать? И добавить ваш процессор в него... Или они настолько радикально разные? Я просто с Rx не сталкивался никогда.

 

        *Stack = ( stack_item_t ) NULL;
        Stack--;
        *Stack = ( stack_item_t ) NULL;
        Stack--;
        *Stack = ( stack_item_t ) NULL;
        Stack--;
        *Stack = ( stack_item_t ) 0x1f;;

        if((uintptr_t)exec & (0x01UL))  {
               *Stack = *Stack | 0x20;
           }
        Stack--;
        *Stack = reinterpret_cast<stack_item_t>(exec);;

А можно ссылку на доку, в которой описан порядок сохранения регистров на стек у R4F? Понятно PSR, адрес возврата, а что это за три нуля над ними? Комментариев в этих строках явно не хватает.

в этот момент в R0 содержится значение 0xea006068 , память по этому адресу просмотреть нельзя.
Надо искать, откуда это значение туда попадает. Там должен быть указатель на стековый кадр самого приоритетного процесса.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Там есть общий порт для Mx (x=0, 3, 4) под gcc, его нельзя доработать? И добавить ваш процессор в него... Или они настолько радикально разные? Я просто с Rx не сталкивался никогда.

 

cortex r ближе к arm7 чем к cortex-m. у R нет global interrupt controller, и ассемблер отличается.

Надо искать, откуда это значение туда попадает. Там должен быть указатель на стековый кадр самого приоритетного процесса.

 

я это понимаю и, по идее, Kernel.ProcessTable должна в кострукторе заполняться.

 

меня еще скрипт линковки смущает

  VECTORS(rx)     : ORIGIN = 0x00000000, LENGTH = 0x00000020
  FLASH  (rx)     : ORIGIN = 0x00000020, LENGTH = 0x0013FFE0
  CPU_STACK (rw)  : ORIGIN = 0x08000000, LENGTH = 0x00001500 /* Stack is configured in sys_core.asm */
  RAM (xrw)       : ORIGIN = 0x08001500, LENGTH = 0x0002EB00
  MEMORY_B1 (rx)  : ORIGIN = 0x60000000, LENGTH = 0K

CPU_STACK отдельно идет

 

Изменено пользователем Legath

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

cortex r ближе к arm7 чем к cortex-m. у R нет global interrupt controller, и ассемблер отличается.
Понятно. Тогда да, отдельный порт.

 

я это понимаю и, по идее, Kernel.ProcessTable должна в кострукторе заполняться.
А конструкторы глобальных объектов вообще вызываются? У множества распроняемого в интернете и в "библиотеках" начального кода запуск конструкторов просто не реализован.

 

меня еще скрипт линковки смущает
Смущает, что стек в отдельной области (region)? А что говорит описание про эту область? Это случайно не аналог Core-coupled memory в M4? тогда размещать в ней стек было бы логично. А в нашем случае логично будет разместить в ней объекты самых высокоприоритетных процессов (сколько влезет), их стеки окажутся в этой же области. Надо завести секцию в этой области и дальше в исходнике помещать в нее объекты:

__attribute__((section(".ccm_mem")))
proc1_type Proc1("Highest priority proc");

Но это уже косметика, для начала надо запустить все остальное.

 

Перечитал еще раз. Кажется понял - область одна, но в скрипте автор зачем-то окусил от нее кусок для стека. Ему виднее, зачем он так сделал. Ваш процессор переключает аппаратно стек при входе в прерывания?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кажется понял - область одна, но в скрипте автор зачем-то окусил от нее кусок для стека. Ему виднее, зачем он так сделал.

 

Это дефолтный скрипт из HalCoGen (аналог CubeMX для процессоров TI). Я просто не нашел другого способа получить инициализацию. Но теперь более менее понятно что можно вернуть область RAM в единую.

Порт Free RTOS от TI еще больше ее дробит. Там ядро (шедулер? ) лежит в своем сегменте

 

KRAM (xrw)      : ORIGIN = 0x08000800, LENGTH = 0x00000800

 

А конструкторы глобальных объектов вообще вызываются? У множества распроняемого в интернете и в "библиотеках" начального кода запуск конструкторов просто не реализован.

 

Подозреваю что не вызываются. S/W BP ниразу не сработал внутри TKernel::register_process.

 

 

Ваш процессор переключает аппаратно стек при входе в прерывания?

 

Чтобы ответить на этот вопрос мне не хватает знаний на данный момент . В документации я нашел

Software normally uses register R13 as a Stack Pointer (SP). The SRS and RFE instructions use Register R13

 

И для каждого из режимов процессора R13 имеет свой суффикс(в вашем порте arm7 я видел подобное)

 

Ссылаюсь на документацию от ARM

 

 

тестовый код main.cpp

#include "sys_common.h"
#include "gio.h"

#include <scmRTOS.h>


typedef OS::process<OS::pr0, 300> TProc0;
typedef OS::process<OS::pr1, 300> TProc1;

TProc0 Proc0;
TProc1 Proc1;

int main(void)
{
    OS::run();
    while(1){

    }
    return 0;
}


namespace OS
{
    template <>
    OS_PROCESS void TProc0::exec()
    {
        for(;;)
        {   for (int i=0;i<10;i++)
            {

            }
            sleep(10);
        }
    }

    template <>
    OS_PROCESS void TProc1::exec()
    {
        for(;;)
        {
            for (int i=0;i<10;i++)
            {

            }
            sleep(10);

        }
    }
}

 

 

Изменено пользователем Legath

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Подозреваю что не вызываются. S/W BP ниразу не сработал внутри TKernel::register_process.
Тогда в коде инициализации после обнуления .bss и копирования .data надо надо добавить что-нибудь вроде
    /* Call constructors */
    void(* const *ctor)();
    for( ctor = __ctors_start; ctor < __ctors_end; )
        (*ctor++)();

Или гляньте у Антона в примерах к кортексам - там у него более современно, с использованием init_array сделано.

И для каждого из режимов процессора R13 имеет свой суффикс
А, ну значит для прерываний отдельный стек. Я использовал под него тот же стек, который работет до запуска ОС.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Добавил в линковку

  /* The program code and other data goes into RAM */
  .text :
  {

        __ctors_start = .;
        KEEP(SORT(*)(.init_array))  /* eabi uses .init_array for static constructor lists */
        __ctors_end = .;

        __dtors_start = .;
        __dtors_end = .;

    . = ALIGN(4);
    *(.text)           /* .text sections (code) */
    *(.text*)          /* .text* sections (code) */
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */
    *(.eh_frame)

    KEEP (*(.init))
    KEEP (*(.fini))

    . = ALIGN(4);
    _etext = .;        /* define a global symbols at end of code */
  } >FLASH

 

 

и перед вызовом main в аналоге reset handler

        extern uint32 __ctors_start, __ctors_end;
    void(* const *ctor)();
    for( ctor = __ctors_start; ctor < __ctors_end; )
            (*ctor++)();

 

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

Изменено пользователем Legath

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

тестовый код main.cpp
for(;;) в main() не нужен - OS::run() - это путь в один конец, возврата из нее нет. for (int i=0;i<10;i++) в процессах тоже лишнее - любой вменяемый компилятор этот цикл выкинет при самой минимальной оптимизации.

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

Так и есть. Чудес ведь не бывает ;)

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

и перед вызовом main в аналоге reset handler

        extern uint32 __ctors_start, __ctors_end;
    void(* const *ctor)();
    for( ctor = __ctors_start; ctor < __ctors_end; )
            (*ctor++)();

По-моему, здесь надо писать &__ctors_start и &__ctors_end.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

да, точно. У меня-то они объявлены как

extern void(* const __ctors_start__[])();
extern void(* const __ctors_end__[])();

странно, что компилятор не выругался на несоответсвие типов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

for(;;) в main() не нужен - OS::run() - это путь в один конец, возврата из нее нет.

 

Это понятно. Я б не стал пытаться делать порт без базовых знаний :bb-offtopic:

for (int i=0;i<10;i++) в процессах тоже лишнее - любой вменяемый компилятор этот цикл выкинет при самой минимальной оптимизации.

 

-O0 , gcc 5.4.1 оставляет если верить дизассемблеру

 

да, точно. У меня-то они объявлены как
extern void(* const __ctors_start__[])();
extern void(* const __ctors_end__[])();

странно, что компилятор не выругался на несоответсвие типов.

 

Действительно не ругается. Странно что ругается на редекларацию регионов памяти.

/Users/legath/Downloads/gcc-arm-none-eabi-5_4-2016q2/bin/../lib/gcc/arm-none-eabi/5.4.1/../../../../arm-none-eabi/bin/ld:/Users/legath/rm46_temp/source/sys_link.ld:19: warning: redeclaration of memory region `VECTORS'
/Users/legath/Downloads/gcc-arm-none-eabi-5_4-2016q2/bin/../lib/gcc/arm-none-eabi/5.4.1/../../../../arm-none-eabi/bin/ld:/Users/legath/rm46_temp/source/sys_link.ld:20: warning: redeclaration of memory region `FLASH'
/Users/legath/Downloads/gcc-arm-none-eabi-5_4-2016q2/bin/../lib/gcc/arm-none-eabi/5.4.1/../../../../arm-none-eabi/bin/ld:/Users/legath/rm46_temp/source/sys_link.ld:22: warning: redeclaration of memory region `RAM'
/Users/legath/Downloads/gcc-arm-none-eabi-5_4-2016q2/bin/../lib/gcc/arm-none-eabi/5.4.1/../../../../arm-none-eabi/bin/ld:/Users/legath/rm46_temp/source/sys_link.ld:23: warning: redeclaration of memory region `MEMORY_B1'

 

CPU_STACK я убрал и память одним куском оставил

Изменено пользователем Legath

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

-O0 , gcc 5.4.1 оставляет если верить дизассемблеру
Ой. Это как раз и есть "без всякой оптимизации. Зачем? Впрочем, это ваше дело.

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Файлы ccs7 архивировал. код инициализации я вставлял в source/sys_startup.c

Вообще хочется самому разобраться, чтоб понимать до конца как все работает. Поэтому прямо мне решение не сообщайте

scm_r4.tar.gz

Изменено пользователем Legath

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

и перед вызовом main в аналоге reset handler

        extern uint32 __ctors_start, __ctors_end;
    void(* const *ctor)();
    for( ctor = __ctors_start; ctor < __ctors_end; )
            (*ctor++)();

 

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

В gcc'шной библиотеке есть специальная функция для прогона ctor loop: ___libc_init_array.

 

Вообще, стартап к кортексов может быть очень простым.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В gcc'шной библиотеке есть специальная функция для прогона ctor loop: ___libc_init_array.

 

Вообще, стартап к кортексов может быть очень простым.

 

Да там это все safety проверки. На данном этапе проекта если их все закомментировать ничего не изменится. Попробую ___libc_init_array ибо ни один из бряков в конструкторах не сработал снова.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...