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

    

Embedded assembler syntax in C

Доброго времени суток!

Прошу подсказать или показать пример, как создать в коде на Си участок из ассемблерного кода (пишу критическую секцию и важно быть уверенным во времени исполнения участка). Нужно ли подключать какие-либо библиотеки и проводить дополнительные настройки?

Пример на сайте ARM видел. Я пытался скопировать его. Компилятор понимает директивы, но команды ассемблера не понимает.

Спасибо!

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


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

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

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

 

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

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

 

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

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


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

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

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


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

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

 

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

 

__asm void HardFault_Handler(void)
{
    B .
    BX LR
}

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


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

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

 

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

__asm void test(int i){
  
}

 

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

 

image.png

 

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


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

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

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


Ссылка на сообщение
Поделиться на другие сайты
Не обращайте внимания. Это не компилятор, и не на void.

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

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


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

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

Если функция целиком на асм, то лучше написать её в отдельном асм-файле.

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


Ссылка на сообщение
Поделиться на другие сайты
Если нужно именно в си-код добавить участок асм-кода (а не целиком функцию на асм), то лучше использовать intrinsic-функции. Если они есть в Keil.

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

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


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

Никак. Но и смешивать си-код и асм, не зная какие регистры и как использует первый - чревато.

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

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


Ссылка на сообщение
Поделиться на другие сайты
Но и смешивать си-код и асм, не зная какие регистры и как использует первый - чревато.

Если только не использовать asm в стиле gcc extended asm

gcc и IAR это поддерживают.

 

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


Ссылка на сообщение
Поделиться на другие сайты
Никак. Но и смешивать си-код и асм, не зная какие регистры и как использует первый - чревато.

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

Какой пролог? Вся функция показана. Название в том числе.

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

 

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

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


Ссылка на сообщение
Поделиться на другие сайты
Какой пролог? Вся функция показана. Название в том числе.

Если это и есть вся функция, то нафига её писать в си-файле??? Для этого существуют асм-файлы.

Про пролог сказано для случая смешивания си-кода и асм-кода в одной функции как хочет автор. Читайте внимательнее.

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

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


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

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

__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 .
}

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

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


Ссылка на сообщение
Поделиться на другие сайты
Поначалу функцию имел следующую:

__asm void HardFault_Handler(void)

Ну - у меня тоже обработчик fault-ов на асм написан. Только он в несколько десятков раз больше. :biggrin:

Защёлкивает содержимое всех важных регистров, кадра стека, разной информации о 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: Если автору "важно быть уверенным во времени исполнения участка" - нужно для минимизации времени запрета прерываний внутри критической секции, то использование подобных операций эксклюзивного доступа даёт возможность обойтись вообще без запретов прерывания. Если уж так хочется.

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


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

Для публикации сообщений создайте учётную запись или авторизуйтесь

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

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
Авторизация