Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум разработчиков электроники ELECTRONIX.ru _ Keil _ Embedded assembler syntax in C

Автор: MySOL Mar 12 2018, 07:35

Доброго времени суток!
Прошу подсказать или показать пример, как создать в коде на Си участок из ассемблерного кода (пишу критическую секцию и важно быть уверенным во времени исполнения участка). Нужно ли подключать какие-либо библиотеки и проводить дополнительные настройки?
http://electronix.ru/redirect.php?http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0472m/index.html на сайте ARM видел. Я пытался скопировать его. Компилятор понимает директивы, но команды ассемблера не понимает.
Спасибо!

Автор: Baser Mar 12 2018, 11:04

По ссылке на сайте АРМ, там руководство по использованию их ассемблера, это немного не то.
Если вы пишете под Кейлом, то изучайте руководство на Кейл. Напр. у ИАРа все подробно расписано.

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

Если куски ассма большие, лучше в файлы, т.к. вставки ассма в Си плохо воспринимают оптимизаторы компиляторов.

Автор: jcxz Mar 12 2018, 11:05

Цитата(MySOL @ Mar 12 2018, 09:35) *
Прошу подсказать или показать пример, как создать в коде на Си участок из ассемблерного кода (пишу критическую секцию и важно быть уверенным во времени исполнения участка).

Реализовать участок кода в виде отдельной функции в asm-файле.

Автор: ViKo Mar 12 2018, 11:22

"ARM ® Compiler v5.06 for µVision armcc User Guide" документ с сайта ARM нужно скачать и почитать, там очень много полезного, рекомендую.

Единственный кусок асм-кода, что имею:

Код
__asm void HardFault_Handler(void)
{
    B .
    BX LR
}

Автор: MySOL Mar 12 2018, 13:18

Господа, спасибо за ответы!

Почитал кейловский мануал и решил написать простую функцию:

Код
__asm void test(int i){
  
}


Компилятор ругается на "void"

http://electronix.ru/redirect.php?https://postimg.org/image/upkpjj2wj/

Автор: ViKo Mar 12 2018, 13:31

Не обращайте внимания. Это не компилятор, и не на void.

Автор: MySOL Mar 12 2018, 13:39

Цитата(ViKo @ Mar 12 2018, 16:31) *
Не обращайте внимания. Это не компилятор, и не на void.

Понял, спасибо! В ближайшее время опробую и отпишусь!

Автор: jcxz Mar 12 2018, 14:24

Если нужно именно в си-код добавить участок асм-кода (а не целиком функцию на асм), то лучше использовать intrinsic-функции. Если они есть в Keil. В IAR для этого их и использую.
Если функция целиком на асм, то лучше написать её в отдельном асм-файле.

Автор: ViKo Mar 12 2018, 14:41

Цитата(jcxz @ Mar 12 2018, 17:24) *
Если нужно именно в си-код добавить участок асм-кода (а не целиком функцию на асм), то лучше использовать intrinsic-функции. Если они есть в Keil.

В Кейл есть, естественно. Но это же только замена некоторых уникальных asm-команд. Как они могут заменить "участок асм-кода"? laughing.gif

Автор: jcxz Mar 12 2018, 18:12

Цитата(ViKo @ Mar 12 2018, 16:41) *
В Кейл есть, естественно. Но это же только замена некоторых уникальных asm-команд. Как они могут заменить "участок асм-кода"? laughing.gif

Никак. Но и смешивать си-код и асм, не зная какие регистры и как использует первый - чревато.
Вот Вы написали "BX LR", а ведь в LR в конце функции не обязательно будет адрес возврата, если пролог функции "написал" си-компилятор.

Автор: KRS Mar 12 2018, 18:54

Цитата(jcxz @ Mar 12 2018, 21:12) *
Но и смешивать си-код и асм, не зная какие регистры и как использует первый - чревато.

Если только не использовать asm в стиле gcc extended asm
gcc и IAR это поддерживают.

Автор: ViKo Mar 13 2018, 04:13

Цитата(jcxz @ Mar 12 2018, 21:12) *
Никак. Но и смешивать си-код и асм, не зная какие регистры и как использует первый - чревато.
Вот Вы написали "BX LR", а ведь в LR в конце функции не обязательно будет адрес возврата, если пролог функции "написал" си-компилятор.

Какой пролог? Вся функция показана. Название в том числе.
Умный компилятор Кейла (полагаю, как и другие) считает R0, R1 и т.п. не названиями регистров, а именами переменных.

Да, Кейл, естественно, выполняет соглашение о порядке передачи аргументов в функцию.

Автор: jcxz Mar 13 2018, 12:59

Цитата(ViKo @ Mar 13 2018, 06:13) *
Какой пролог? Вся функция показана. Название в том числе.

Если это и есть вся функция, то нафига её писать в си-файле??? Для этого существуют асм-файлы.
Про пролог сказано для случая смешивания си-кода и асм-кода в одной функции как хочет автор. Читайте внимательнее.
"Пролог" - это набор инструкций, который вставляется компилятором (си) в начало функции. Это может быть PUSH ..., может быть PUSH ...;SUB SP,..., могут быть пересылки аргументов в другие регистры или ещё чего - зависит от содержимого функции. К ассемблеру отношения не имеет.

Автор: ViKo Mar 13 2018, 13:25

Поначалу функцию имел следующую:

Код
__asm void HardFault_Handler(void)
{
    TST LR, #4
    ITE EQ
    MRSEQ R0, MSP        ; Main Stack was used, put MSP in R0
    MRSNE R0, PSP        ; Process Stack was used, put PSP in R0
    LDR R0, [R0, #24]    ; Get stacked PC from stack
    
    LDR R1, =0x40020418    ; GPIOB->BSRR
    MOVS R2, #0x0002    ; Bit 2
    STRH R2, [R1, #2]    ; Reset bit (LED_ON)
    B .
}

Здесь без ассемблера не обойтись. Потом упростил. Не пробовал писать ее на С. Думаю, такой простоты на С не получится.

Автор: jcxz Mar 13 2018, 13:43

Цитата(ViKo @ Mar 13 2018, 15:25) *
Поначалу функцию имел следующую:
__asm void HardFault_Handler(void)

Ну - у меня тоже обработчик fault-ов на асм написан. Только он в несколько десятков раз больше. biggrin.gif
Защёлкивает содержимое всех важных регистров, кадра стека, разной информации о fault-е и сохраняет в структуру в памяти.
И расположен он в асм-файле. А потом оттуда - переход на си-функцию, которая эту всю инфу уже использует (выплёвывает в UART в аналог "синего окна смерти" или пишет в журнал событий и перегружает МК).
А вот атомарные операции с эксклюзивным доступом я написал на си, с помощью intrinsic-функций, типа (атомарная операция "сравнение и обмен"):
Код
inline u32 AtomicCmpSwp(u32 volatile *ptr, u32 newVal, u32 cmpVal)
{
  u32 i, i1;
  do {
    i = __LDREX(ptr);
    if (i == cmpVal) i1 = __STREX(newVal, ptr);
  } while (i == cmpVal && i1 == 1);
  return i;
}

Аналог виндовой InterlockedCompareExchange()...

PS: Если автору "важно быть уверенным во времени исполнения участка" - нужно для минимизации времени запрета прерываний внутри критической секции, то использование подобных операций эксклюзивного доступа даёт возможность обойтись вообще без запретов прерывания. Если уж так хочется.

Автор: ViKo Mar 13 2018, 14:04

Цитата(jcxz @ Mar 13 2018, 16:43) *
Ну - у меня тоже обработчик fault-ов на асм написан. Только он в несколько десятков раз больше. biggrin.gif

Есть пример такого обработчика в книгах Джозефа Ю. У меня рабочий макет всегда на столе, подключиться отладчиком в нутро не проблема. Поэтому обошелся тем, что показал.

Автор: jcxz Mar 13 2018, 14:20

Цитата(ViKo @ Mar 13 2018, 16:04) *
Есть пример такого обработчика в книгах Джозефа Ю. У меня рабочий макет всегда на столе, подключиться отладчиком в нутро не проблема. Поэтому обошелся тем, что показал.

Я о том, что подозреваю что ТСу вообще "асм в си" не нужен. А хочет он уменьшить время запрета прерываний в критических секциях. А делается это после прочтения мануала по командам LDREX/STREX. Как всегда приходится домысливать неозвученное за автора.... laughing.gif

Русская версия Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)