Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Размер таблицы прерываний STM32
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Rash
День добрый.
Подскажите, как получить размер таблицы прерываний __vector_table из файла startup_stm32f40_41xxx.s , использую IAR.
Obam
Цитата(Rash @ May 26 2015, 10:51) *
День добрый.
Подскажите, как получить размер таблицы прерываний __vector_table из файла startup_stm32f40_41xxx.s , использую IAR.


В datashet-е и в RefMan-е вся расписана.
ViKo
В Keil в стартапе есть такая строка после векторов:
__Vectors_Size EQU __Vectors_End - __Vectors
Но как ее использовать в c-файлах, я не смог найти способа.
aaarrr
Цитата(ViKo @ May 26 2015, 10:51) *
Но как ее использовать в c-файлах, я не смог найти способа.

Cначала EXPORT <var> в ассемблере, затем extern <type> <var> в си. В IAR'е должно быть что-то подобное.
SSerge
В IAR ещё проще
Код
#pragma section=".intvec"
  printf( "intvec segment size = %d\r\n",  (uint32_t)__segment_end(".intvec")
               - (uint32_t)__segment_begin(".intvec") );
ViKo
Цитата(aaarrr @ May 26 2015, 11:22) *
Cначала EXPORT <var> в ассемблере, затем extern <type> <var> в си. В IAR'е должно быть что-то подобное.

Порылся в своем, нашел, вспомнил - в c-файл из ассемблерного можно передать переменную. Вот обратного действия у меня не получилось.
Вот здесь жалился: http://electronix.ru/forum/index.php?showt...t&p=1324623
aaarrr
Цитата(ViKo @ May 26 2015, 11:43) *
Вот обратного действия у меня не получилось.

Так там не переменная, а макроопределение с c-синтаксисом. Такого армовский ассемблер не умеет.
Axel
В CrossWorks (GNU) работает это:

CODE
extern void* __vectors_load_start__;
extern void* __vectors_load_end__;
................................
uint32_t vt_length = (uint32_t)&__vectors_load_end__ - (uint32_t)&__vectors_load_start__;

Имена взяты из map-файла. Может быть и в IAR возможно что-то подобное?
KnightIgor
Цитата(ViKo @ May 26 2015, 09:43) *
Порылся в своем, нашел, вспомнил - в c-файл из ассемблерного можно передать переменную. Вот обратного действия у меня не получилось.

Я не думаю, что IAR в этом смысле сильно отличается от KEIL, а в KEIL для использования в С из S:

s:
EXPORT mysimbol
c:
extern <typedef> mysimbol;

В обратную сторону:

c:
<typedef> mycsimbol;
s:
IMPORT mycsimbol

Мне "удалось" также импортировать в ассемблер символы, генерируемые компоновщиком (касается адресов и размеров секций). Например,

IMPORT |Load$$LR$$LR_IROM2$$Length|,

то есть, длину региона загрузки LR_IROM2 (должно быть обрамлено именно вертикальными линиями). Это все не я раскопал, конечно. Описано на сайте onarm.com, но ссылки я уже не приведу.
SSerge
Цитата(Axel @ May 27 2015, 10:49) *
Может быть и в IAR возможно что-то подобное?

Что-то подобное я уже писал в предыдущем сообщении.
Но у IAR есть ещё одна чрезвычайно полезная штука: папка doc.
Оказывается, кроме __segment_begin и __segment_end есть не менее полезная псевдофункция __segment_size.
Сергей Борщ
Цитата(SSerge @ May 27 2015, 10:37) *
Но у IAR есть ещё одна чрезвычайно полезная штука: папка doc.
Это для слабых! 08.gif
Rash
Спасибо всем. результат таков:
1. через __segment_size получаем размер таблицы векоров, но это значение нельзя использовать препроцессором, т.е.
Код
#pragma section=".intvec"
#define FLASH_VECTOR_TABLE_SIZE        ((uint32_t)__segment_size(".intvec"))

#define FLASH_WRITE_BLOCK_SIZE         (512)

// !!! --- Это работать не будет ---
#if (FLASH_WRITE_BLOCK_SIZE < FLASH_VECTOR_TABLE_SIZE)
  #error "Error FLASH_WRITE_BLOCK_SIZE"
#endif


2. через EXPORT __vector_table в ассемблере (startup_stm32f40_41xxx.s ), затем extern uin32_t __vector_table или extern uin32_t* __vector_table в си, можно определить адрес расположения __vector_table или значение записанное по этому адресу __vector_table[0], но размер таблицы не определить, т.к. опереция sizeof(__vector_table)/sizeof(__vector_table[0]) выдаст 1.
Golikov A.
а почему размер указателя разделить на размер указателя должно давать что-то отличное от 1:)?

uin32_t*

или почему размер 32 битного инта резделить на размер 32 битного инта тоже должно давать что-то кроме 1?

uin32_t
Rash
всё правильно, что даёт 1, я имел виду, что т.о. не получишь длину таблицы векторов, т.к. можно получить указатель __vector_table, а не определение массива.
SSerge
Цитата(Rash @ May 28 2015, 13:04) *
Спасибо всем. результат таков:
1. через __segment_size получаем размер таблицы векоров, но это значение нельзя использовать препроцессором, т.е.

Так не удивительно, что первый, что второй методы работают одинаково: через определение символов (меток) для линкера, и только линкер знает их реальные значения, получившиеся в процессе сборки.
Впрочем, если Вы не сами пишете .s, а используете готовый, то размер таблицы можно вычислить зная максимальный номер вектора. Надо только учесть ещё 16 слов для векторов с отрицательными номерами.

Ищем определение typedef enum{ ... } IRQn_Type;, дописываем две строчки:
Код
typedef enum{
  .....
  HASH_RNG_IRQn               = 80,     /*!< Hash and RNG global interrupt                                     */
  FPU_IRQn                    = 81      /*!< FPU global interrupt                                              */
  ,__MAX_VECTOR_NUM__       /* получит значение на 1 больше максимального номера вектора */
} IRQn_Type;
#define  VECTOR_TABLE_SIZE  (4*(__MAX_VECTOR_NUM__-1+16))


ЗЫ. Сравнивая размер таблицы векторов с FLASH_WRITE_BLOCK_SIZE Вы проявляете завидную дальновидность sm.gif
Пока что даже у самого толстого F756 этот размер составляет (97+16)*4 = 452 байта.
Rash
.s беру стандартные из CMSIS, FLASH_WRITE_BLOCK_SIZE задаётся, может быть изменён в настройках перед компиляцией. Приложение это бутлоадер. И т.к. контроллеры могут быть разные, а ядро одинаковое, решил сделать доп. проверку.
В
Код
typedef enum{  ..... } IRQn_Type;
можно вставить, но это редактирование stm32f4xx.h, хоть и один раз (но при смене версии нужно учитывать), а так подменил .s файл и всё посчитало при компиляции. Вначале просто вычислил все вектора для мк 4-ой серии и записал дефайнами, но стало интересней сделать поумнее.
Golikov A.
Если не ошибаюсь там есть начало и конец таблицы
их разность - это длинна.
если нет конца таблицы (хотя он вроде как есть)
можно использовать начало следующей секции...

А нафига, даже бутлоадеру, знать размер таблицы?
Rash
конца таблицы (хотя он вроде как есть) я не нашёл,
можно использовать начало следующей секции... тоже

Бутлоадер в основной прошивке запишет CRC основной прошивки после векторов прерываний. Естественно основная прошивка для этого зарезервирует место для CRC.
Golikov A.
Цитата
Бутлоадер в основной прошивке запишет CRC основной прошивки после векторов прерываний. Естественно основная прошивка для этого зарезервирует место для CRC.

а зачем он это сделает?

да правда нет

но можно использовать
Reset_Handler
он вроде как идет сразу после таблицы с началом __Vectors
А можно в конце таблице добавить __Vectors_end , так будет совсем красиво....


Не наврал по карте памяти там __main.o вроде как сразу легло... интересно это зафиксировано?
scifi
Цитата(Rash @ May 28 2015, 14:06) *
Бутлоадер в основной прошивке запишет CRC основной прошивки после векторов прерываний. Естественно основная прошивка для этого зарезервирует место для CRC.

В таблице векторов прерываний есть дырки. Туда можно записать.
ViKo
CRC я дописываю в конец файла прошивки. Естественно, CRC всего файла вместе с CRC должна быть равна 0, если принял правильно. При приеме файла вычисляю его размер, и по этому размеру прогоняю вычисление CRC.
Этот же размер я храню в области векторов, конкретно, в дыре по адресу 0x0020. При включении прибора даю время запустить загрузчик с панели управления. Если загрузчик не запускается, читаю по адресу 0x0020 размер прошивки, вычисляю CRC и запускаю рабочую программу, если CRC равна 0. Если CRC не верна, значит, рабочей программы нет.
Rash
да в принципе не важно где хранить в дыре или в конце векторов. Вопрос в том как красиво и макс. универсально организовать получение нужных размеров в данном случае размера таблицы векторов и ассемблерного стартапа . Сделал через __segment_size, меня это устраивает. Единственное думал сделать защиту от "дурака" препроцессором при выборе размера блока флеш (при использовании внутренней флеш - это виртуальный размер блока).

А вот как в конце таблицы добавить метку с адресом __Vectors_end, как писал Golikov A. я не понял. Это возможно решило вопрос с препроцессором.

Использовать дыры во флеш не хочется, что бы не попасть при выходе новых контроллеров.
ViKo
В Keil:
Код
__Vectors       DCD     __initial_sp             ; Top of Stack
                DCD     Reset_Handler            ; Reset Handler
...
                DCD     FPU_IRQHandler                  ; FPU
                                      
__Vectors_End

__Vectors_Size  EQU  __Vectors_End - __Vectors

Ассемблерная строка начинается с метки.
Golikov A.
Цитата
Этот же размер я храню в области векторов, конкретно, в дыре по адресу 0x0020

а мы добили прошивку мусором до полного числа секторов, и конец определяем по первому пустому сектору, при заливке стираем на 1 сектор больше, так у нас конец определен и хранить не надо ничего...
Rash
Цитата(Golikov A. @ May 28 2015, 21:57) *
а мы добили прошивку мусором до полного числа секторов, и конец определяем по первому пустому сектору, при заливке стираем на 1 сектор больше, так у нас конец определен и хранить не надо ничего...

Это всё хорошо когда сектора маленькие. А допустим в 401 (256k Flash), 4 сектора 16k - 2 для бута и 2 эмуляция EEPROM, 1 сектор 64 kB - основная программа и 1 сектор 128 - возможно в будущем ещё одна основная программа. Это всё соединено последовательно друг за другом до 100 устройств по RS-485, скорость ~ 115200. И передавать лишнее килобайты как то не особо хочется, при этом не разрушая работу всей системы.

ViKo, за метки спасибо, завтра попробую.
Golikov A.
а кто передавать то требует?
вы передаете только программу и контрольную сумму, а как ее в сектора класть уже бутлоадер решает.
Именно он может ее дополнить до целого числа секторов и записать во флэш. Можно даже считать что программа дополняется 0xFF и контрольную сумму считать именно для такого дополнения (значением стертого сектора). Бутлоадер получит программу, запишет начало, в конце сектора запишет контрольную сумму и свободен...



ViKo
Цитата(Golikov A. @ May 28 2015, 21:57) *
а мы добили прошивку мусором до полного числа секторов, и конец определяем по первому пустому сектору, при заливке стираем на 1 сектор больше, так у нас конец определен и хранить не надо ничего...

Транжиры вы. biggrin.gif
Golikov A.
да все равно память на борту лежит, какая разница что в ней, 0, мусор или пусто? Ее же не сдашь в магазин обратно, если лишняя оказалась....
Rash
Появилось время попробовать вариант 2
код в .s файле
Код
        EXPORT  VECTOR_TABLE_SIZE

        DATA
__vector_table
      ...
      ...
__vector_table_end
VECTOR_TABLE_SIZE        EQU    __vector_table_end - __vector_tabl


код в .с файле
Код
extern uint32_t VECTOR_TABLE_SIZE;
#define FLASH_VECTOR_TABLE_SIZE         VECTOR_TABLE_SIZE


[b]// !!! --- По прежнему не работает ---[/b]
#if (FLASH_WRITE_BLOCK_SIZE < FLASH_VECTOR_TABLE_SIZE)
  #error "Error FLASH_WRITE_BLOCK_SIZE"
#endif



Цитата
Remark[Pe193]: zero used for undefined preprocessing identifier "FLASH_WRITE_BLOCK_SIZE"


В коде всё как и в 1-ом варианте работает нормально. Думаю заставить препроцессор увидеть переменную раньше дефайна нет. Т.к. в .s файле это дефайн, а при экспорте в .c файл это уже объявление переменной.


Golikov A.
вас спасет assert

через #if, вероятнее такое действительно не пролезет, на уровне препроцессора значение очевидно не вычисляется, адреса меток, наверное будут присвоены на уровне линковки....
toweroff
а если указать, что это значение - во флеш (константно), не поможет?
Код
extern const uint32_t VECTOR_TABLE_SIZE;

так-то да, переменная должна быть в памяти и на этапе компиляции неизвестна
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.