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

не получается перенести вектора прерываний

хочу сделать загрузчик по адресу 0x800000 st32L496

пока загрузчик не написан

т.о. сама прога должна быть с адреса 0x8000000 + 0x4000

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

файл для линкера такой: 
 

_Min_Heap_Size = 0x8000;    /* required amount of heap  */
_Min_Stack_Size = 0x800;    /* required amount of stack */

/* Memories definition */
MEMORY
{
  RAM    (xrw)   : ORIGIN = 0x20000000,   LENGTH = 320K
  FLASH  (rx)    : ORIGIN = 0x8000000 + 0x4000,   LENGTH = 0xFC000 /*1024K - 0x4000 */
}

 

 

захожу в SystemInit() 

и ставлю   SCB->VTOR =  0x8000000 + 0x4000; /* Vector Table Relocation in Internal FLASH */

если запускаю из студии - все работает, если просто включением питания, то нет

где я что то сделал неверно или не дописал?

чую что этот SCB->VTOR должен быть где то в стартовом ассемблерной файле

после назначения адреса стека и перед прыжком на SystemInit. 

 

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


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

1 час назад, inventor сказал:

где я что то сделал неверно или не дописал?

В командном файле компоновщика не поместили таблицу векторов прерываний в нужное место (0x8000000 + 0x4000 или куда там вам надо).

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


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

3 часа назад, inventor сказал:

и ставлю   SCB->VTOR =  0x8000000 + 0x4000; /* Vector Table Relocation in Internal FLASH */

Это должен делать ваш загрузчик, вместо которого у вас пустое место.

Напишите простейшую заглушку, которая будет писать VTOR, заполнять указатель стека содержимым ячейки 0x8004000 и передавать управление по адресу, указанному в ячейке 0x8004004.

Да, можно VTOR прописывать и в самой программе, но как-то это кривововато выглядит.

Ваша студия перед запуском загружает в PC адрес, указанный директивой ENTRY() скрипта компоновщика - поэтому при запуске из студии все работает. Правда непонятно, что при запуске из студии заносится в указатель стека.

1 час назад, jcxz сказал:

В командном файле компоновщика не поместили таблицу векторов прерываний в нужное место

Это необязательно - в таблице хранятся абсолютные адреса, от перемещения они не изменятся.

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


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

то есть в загрузчике сделать нечто подобное: 


   

/* Disable all interrupts */
    RCC->CIR = 0x00000000;

    SCB->VTOR = APP_ADDRESS;
    __set_MSP(*(uint32_t *) APP_ADDRESS);
    __DMB();

    (*((pfunc *) (APP_ADDRESS + 4))) ();

 

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


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

Да, примерно так. Только лучше это оформить ассемблерной вставкой, чтобы компилятор не напихал туда лишних команд работы со стеком. Я делаю так:

__attribute__((noreturn))
inline void start_application(uintptr_t msp_init, void (*pc)())
{
    // start application, need asm inline to avoid stack corruption between MSR and BLX
    asm volatile (
        "msr\tmsp, %[MSP]\n"
        "\tblx\t%[PC]\n"
        :
        : [MSP] "r"  (msp_init)
        , [PC] "r"  (pc)
        :
        );
    __builtin_unreachable();
}

 

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


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

35 минут назад, Сергей Борщ сказал:

__attribute__((noreturn))
inline void start_application(...)
{
  ...
}

Допускаю, что здесь не совсем корректно выбран атрибут noreturn. Скорее, naked нужен.

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


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

Почему же? Возврата из этой функции нет, значит компилятор вправе выкинуть весь ненужный код (восстановление стека, возврат из функции) после нее. Смысла в naked тоже не вижу - пусть компилятор делает все то, что считает нужным.

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


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

6 минут назад, Сергей Борщ сказал:

Возврата из этой функции нет, значит компилятор вправе выкинуть весь ненужный код (восстановление стека, возврат из функции) после нее...

На малых уровнях оптимизации noreturn, все-таки, не гарантирует отсутствие операций со стеком (прологи и эпилоги).

Например, Keil, -O0, ARM Compiler 6.12

__attribute__((noreturn))
void noreturn_func(u32 i) {
  __asm("str r0, [r1]");
  while(1);
}
    75: void noreturn_func(u32 i) { 
0x08000E68 B082      SUB      sp,sp,#0x08
0x08000E6A 4601      MOV      r1,r0
0x08000E6C 9001      STR      r0,[sp,#0x04]
    76:   __asm("str r0, [r1]"); 
0x08000E6E 6008      STR      r0,[r1,#0x00]
    77:   while(1); 
0x08000E70 9100      STR      r1,[sp,#0x00]
0x08000E72 E7FF      B        0x08000E74

 

__attribute__((naked))
void naked_func(u32 i) {
  __asm("str r0, [r1]");
  __asm("loop: b loop");
}
    69: void naked_func(u32 i) { 
    70:   __asm("str r0, [r1]"); 
0x08000E64 6008      STR      r0,[r1,#0x00]
    71:   __asm("loop: b loop"); 
    72: } 
    73:
0x08000E66 E7FE      B        0x08000E66

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


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

Я бы спросил: "Зачем именно MSR MSP, ... ?"

Ведь корректным будет обеспечить, чтобы на момент старта приложения, активным был MSP (и вообще все условия работы CPU должны быть как после RESET). А тогда достаточно: MOV SP, ... что короче.

Хотя это конечно и не существенно....

Например у меня аналогичное действие:

.asm:

               SECTION  .text:CODE:NOROOT(2)
               THUMB
               PUBLIC   StartWorkFw
StartWorkFw:   LDR      R0, =PFLASH_BEGIN_C + FW_WORK_BEGIN
               LDMIA    R0!, {R1, R2}
               MOV      SP, R1
               BX       R2

               LTORG

где: (PFLASH_BEGIN_C + FW_WORK_BEGIN) - это адрес начала образа запускаемого кода (начало таблицы векторов прерываний).

И на входе в эту функцию, все прерывания должны быть запрещены.

Вызов:

extern "C" void StartWorkFw();
StartWorkFw();

 

PS: Лучше бы заострить внимание ТСа на необходимости выполнения вышеозвученного требования:

Все условия работы CPU должны быть как после RESET

Т.е. - режим работы CPU, состояние регистров управления CPU (регистр CONTROL, NVIC, MPU и др.), состояние периферии (вся периферия, использованная в загрузчике, должна быть сброшена/переведена в исходное состояние). Чтобы потом не наступать на неожиданные грабли, когда с загрузчиком и без оного, прикладное приложение работает по-разному.

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


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

2 минуты назад, jcxz сказал:

Чтобы потом не наступать на неожиданные грабли, когда с загрузчиком и без оного, прикладное приложение работает по-разному.

Некий признак в NOINIT-регионе ОЗУ + повторный сброс (ручной или по WDT).

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


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

2 минуты назад, Arlleex сказал:

Некий признак в NOINIT-регионе ОЗУ + повторный сброс (ручной или по WDT).

А во всех МК это возможно? Например: в некоторых продвинутых МК (Infineon например) есть опция "Контроль чётности ОЗУ". Если включить её и выполнить чтение ОЗУ (в которое после RESET-а и до этого момента ещё не было выполнено ни одной записи), то получим Exception. Да, конечно, можно отключить этот контроль и прочитать, но может есть МК, в которых такой контроль неотключаем?

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


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

11 минут назад, Arlleex сказал:

Некий признак в NOINIT-регионе ОЗУ

(RCC->CSR & RCC_CSR_SFTRSTF) ?

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


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

9 минут назад, Сергей Борщ сказал:

(RCC->CSR & RCC_CSR_SFTRSTF) ?

Ну да. В STM32 использую этот флажок периферии, а в каких-то проектах дополнительно делаю мониторинг кодового слова в ОЗУ.

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


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

2 минуты назад, Сергей Борщ сказал:

(RCC->CSR & RCC_CSR_SFTRSTF) ?

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

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


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

1 минуту назад, jcxz сказал:

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

NVIC_SystemReset(). Опять же, в случае, если приложение может генерировать программный сброс только для входа в этот самый прошиватор.

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


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

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

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

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

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

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

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

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

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

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