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

У меня вопрос про arm-kgp, в части Cortex-M3.

Компиляю им проект под scmRTOS, на плюсах.

Есть класс-критическая секция:

class TCritSect
{
public:
    TCritSect () : StatusReg(__get_interrupt_state()) { __disable_interrupt(); }
     ~TCritSect() { __set_interrupt_state(StatusReg); }
private:
     TStatusReg StatusReg;
};

И есть некая использующая эту критическую секцию функция класса:

        INLINE byte GetCount() const { TCritSect cs; return count; }

То есть, идея такая: при входе в функцию создаётся объект TCritSect, при создании запрещаются прерывания, потом выполняется тело функции, и при выходе из неё объект TCritSect разрушается, восстанавливая состояние прерываний.

Так вот, её вызов компилится при помощи arm-kgp в следующий код:

     mrs    r3, PRIMASK     
      cpsid    i           
      msr    PRIMASK, r3     
      ldrb    r0, [r0, #8]
      bx    lr

Здесь две первые строчки - конструктор TCritSect (сохранение PRIMASK и запрет прерываний), третья строчка - деструктор TCritSect (разрешение прерываний), и только четвёртая строчка - чтение переменной. То есть, работает не так, как мне бы хотелось.

CodeSourcery g++ компилит это вот так:

     mrs    r3, PRIMASK     
      cpsid    i           
      ldrb    r0, [r0, #6]
      msr    PRIMASK, r3     
      bx    lr

, то есть, как мне нужно - запрет прерываний, чтение переменной, восстановление прерываний.

 

Вопрос в следующем: как они этого добились? Делали специальный патч, или просто задали какие-то параметры при сборке? Вернее, вопрос состоит в другом: а нельзя ли сделать как они? :)

 

ЗЫ. Вопрос о том, как положено по стандарту - неясен, долгие баталии по этому поводу не дали однозначного ответа. Но, имхо, для эмбеддед приложений второй вариант предпочтительней.

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


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

ЗЫ. Вопрос о том, как положено по стандарту - неясен, долгие баталии по этому поводу не дали однозначного ответа.
Эт с какой точки зрения смотреть. С моей -
если count (который изменяется где-то независимо от данного участка кода) объявлен как volatile, то всё должно быть нормально в данном случае, так как порядок доступа к volatile-переменным нарушаться не может, а если не volatile, то компилятор вправе двигать
- звучит достаточно однозначно :-).

И count должен быть volatile в любом случае, а TCritSect обеспечивает только атомарность доступа к нему.

Насколько я помню, по итогам обсуждения системный счётчик тиков в scmRTOS стал volatile :-)

Неужели тут count квалифицирован как volatile и всё равно бяка?

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


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

Эт с какой точки зрения смотреть. С моей - - звучит достаточно однозначно :-).

Я потерял ссылку на это обсуждение, потому цитировал по памяти:)

И count должен быть volatile в любом случае, а TCritSect обеспечивает только атомарность доступа к нему.

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

Насколько я помню, по итогам обсуждения системный счётчик тиков в scmRTOS стал volatile :-)

Неужели тут count квалифицирован как volatile и всё равно бяка?

Это TChannel.GetCount(). То есть, там на самом деле не

return count;

а

return Cbuf.get_count();

 

Где Cbuf - TCbuf, и в нём

byte get_count() const { return count; }
...
volatile byte count;

То есть, таки volatile.

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


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

byte get_count() const { return count; }
...
volatile byte count;

То есть, таки volatile.

Тогда, на мой взгляд, это баг.

Чтение count и запись назад в статус менять местами нельзя.

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


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

Тогда, на мой взгляд, это баг.

 

Согласен. А не напомните ссылочку на то обсуждение?

 

---

Хотя...

Запись статуса реализована как

INLINE inline void __set_interrupt_state(TStatusReg status)
{
    __asm__ __volatile__ (
        "MSR PRIMASK, %0\n"
        : : "r"(status)
    );
}

 

Мне не совсем понятно, является ли в этом случае PRIMASK volatile?

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


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

Согласен. А не напомните ссылочку на то обсуждение?
Да оно как-то частично по аськам... Выплеснулось на "исходники.ру", сейчас попробую найти

 

INLINE inline void __set_interrupt_state(TStatusReg status)
{
    __asm__ __volatile__ (
        "MSR PRIMASK, %0\n"
        : : "r"(status)
    );
}

Мне не совсем понятно, является ли в этом случае PRIMASK volatile?

Хм... а поставьте-ка в clobbered list "memory" в качестве барьера...

 

 

upd: вопрос и обсуждение на "исходниках.ру" http://forum.sources.ru/index.php?showtopi...amp;hl=volatile

а история аськи уже утеряна

 

upd2: хм, а там модераторы работают, знатно тему почистили, в конце выстрижены все посты кроме моих ответов с примерами кода

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


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

Хм... а поставьте-ка в clobbered list "memory" в качестве барьера...

 

Да, так всё в порядке. Непонятно только, откуда сборка от CodeSourcery сразу знала про волатильность PRIMASK? :)

Интересная штука с размером кода получается.

Для arm-kgp-elf при внесении "memory" в clobbered list размер моего проекта подрос с 14200 до 14368.

А вот для arm-none-eabi- - наоборот, сократился с 15924 до 15812.

Первое понятно, отключилась какая-то оптимизация. А вот второе просто удивительно:)

 

upd: вопрос и обсуждение на "исходниках.ру" http://forum.sources.ru/index.php?showtopi...amp;hl=volatile

Ага, оно. Большое спасибо!

 

---

Да, забыл главное написать. 2 klen - вопрос снят, ваша сборка -- лучшая:)

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


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

Да, так всё в порядке.
Ну, в общем-то, этот "ломовой" способ должен бы работать и при всех не-volatile (т.е. шо PRIMASK, шо count).

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


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

Да, забыл главное написать. 2 klen - вопрос снят, ваша сборка -- лучшая:)

 

стараимсо!

Кстате, как Вы это измеряете?

 

 

собрал компиллер и бинутилс с поддержкой link time optimization (LTO) - но чето пока никак не пойму как это работает, код в 10 раз больше в бинарь суется(мож это и не код). разберусь - выложу свежак. главно что заработало, дальше посмотрим че не так.

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


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

Ну, в общем-то, этот "ломовой" способ должен бы работать и при всех не-volatile (т.е. шо PRIMASK, шо count).

Ну а как ещё сказать компилеру, что PRIMASK волатильный? Поправил порт для кортекса на всякий случай, закоммитил.

 

стараимсо!

Кстате, как Вы это измеряете?

 

На глазок:) Вот на два поста выше привёл размер кода в сравнении с CodeSourcery.

 

собрал компиллер и бинутилс с поддержкой link time optimization (LTO) - но чето пока никак не пойму как это работает, код в 10 раз больше в бинарь суется(мож это и не код). разберусь - выложу свежак. главно что заработало, дальше посмотрим че не так.

 

Посмотрим:) Но самое главное в новых фичах -- это чтоб их можно было отключить:)

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


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

свежак для мелких arm

 

полный мультитлиб

http://www.klen.org/Files/DevTools/kgp_arm_full_20091116.7z

 

обрезок от полного до cortex-m3

http://www.klen.org/Files/DevTools/kgp_arm...-m3_20091116.7z

напоминаю, что эти тулсы только компилируя с опцией -mcpu=cortex-m3

 

мои проекты уменьшились на 1% :)

 

есть подержка LTO, но както оно странно (не)работает, короче ее не использовать, а то в флеш не вместится результат.

 

брат друг и товаришь по форуму Doka сообщил что ему требуется все тоже самое на хосте x86-64. учитывая что сборка происходит на убунте, если требуется кому, могу выкладывать архивы для нинукса. только свисните.

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


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

Уважаемый klen!

Спасибо большое за Вашу работу по GCC.

Сейчас это лучшая сборка по ARM.

И хочется, чтобы работа с битовыми полями была лучше.

 

Если приведенный ниже пример поможет Вам - буду рад.

 

Пример кода (перекодировка по табличкам)

 

Cortex-M3 -Os

 

extern unsigned char const k[8][16];

typedef union
{
struct
{
	unsigned y0: 4;
	unsigned y1: 4;
	unsigned y2: 4;
	unsigned y3: 4;
	unsigned y4: 4;
	unsigned y5: 4;
	unsigned y6: 4;
	unsigned y7: 4;
} y;
unsigned int x;
} var;

unsigned int func( var v )
{
v.y.y0 = k[0][v.y.y0];
v.y.y1 = k[1][v.y.y1];
v.y.y2 = k[2][v.y.y2];
v.y.y3 = k[3][v.y.y3];
v.y.y4 = k[4][v.y.y4];
v.y.y5 = k[5][v.y.y5];
v.y.y6 = k[6][v.y.y6];
v.y.y7 = k[7][v.y.y7];
return v.x;
}

 

GCC: (Sourcery G++ Lite 2009q3-68) 4.4.1

 

 20              	func:
 24 0000 1A4B     		ldr	r3, .L3
 25 0002 00F00F02 		and	r2, r0, #15
 26 0006 9A5C     		ldrb	r2, [r3, r2]	@ zero_extendqisi2
 27 0008 62F30300 		bfi	r0, r2, #0, #4
 28 000c C0F30312 		ubfx	r2, r0, #4, #4
 29 0010 9A18     		adds	r2, r3, r2
 30 0012 127C     		ldrb	r2, [r2, #16]	@ zero_extendqisi2
 31 0014 62F30710 		bfi	r0, r2, #4, #4
 32 0018 C0F30322 		ubfx	r2, r0, #8, #4
 33 001c 9A18     		adds	r2, r3, r2
 34 001e 92F82020 		ldrb	r2, [r2, #32]	@ zero_extendqisi2
 35 0022 62F30B20 		bfi	r0, r2, #8, #4
 36 0026 C0F30332 		ubfx	r2, r0, #12, #4
 37 002a 9A18     		adds	r2, r3, r2
 38 002c 92F83020 		ldrb	r2, [r2, #48]	@ zero_extendqisi2
 39 0030 62F30F30 		bfi	r0, r2, #12, #4
 40 0034 C0F30342 		ubfx	r2, r0, #16, #4
 41 0038 9A18     		adds	r2, r3, r2
 42 003a 92F84020 		ldrb	r2, [r2, #64]	@ zero_extendqisi2
 43 003e 62F31340 		bfi	r0, r2, #16, #4
 44 0042 C0F30352 		ubfx	r2, r0, #20, #4
 45 0046 9A18     		adds	r2, r3, r2
 46 0048 92F85020 		ldrb	r2, [r2, #80]	@ zero_extendqisi2
 47 004c 62F31750 		bfi	r0, r2, #20, #4
 48 0050 C0F30362 		ubfx	r2, r0, #24, #4
 49 0054 9A18     		adds	r2, r3, r2
 50 0056 92F86020 		ldrb	r2, [r2, #96]	@ zero_extendqisi2
 51 005a 62F31B60 		bfi	r0, r2, #24, #4
 52 005e 03EB1073 		add	r3, r3, r0, lsr #28
 53 0062 93F87030 		ldrb	r3, [r3, #112]	@ zero_extendqisi2
 54 0066 63F31F70 		bfi	r0, r3, #28, #4
 55 006a 7047     		bx	lr

 

GCC: (Klen's GCC package (KGP) for ARM/elf platform) 4.5.0 20091115 (experimental)

 

 10              	func:
 13 0000 F3B5     		push	{r0, r1, r4, r5, r6, r7, lr}
 14 0002 1E4B     		ldr	r3, .L2
 15 0004 00F00F0C 		and	ip, r0, #15
 16 0008 C0F30311 		ubfx	r1, r0, #4, #4
 17 000c 13F80C60 		ldrb	r6, [r3, ip]	@ zero_extendqisi2
 18 0010 5918     		adds	r1, r3, r1
 19 0012 C0F30322 		ubfx	r2, r0, #8, #4
 20 0016 91F810C0 		ldrb	ip, [r1, #16]	@ zero_extendqisi2
 21 001a 9A18     		adds	r2, r3, r2
 22 001c C0F30351 		ubfx	r1, r0, #20, #4
 23 0020 C0F30335 		ubfx	r5, r0, #12, #4
 24 0024 C0F30344 		ubfx	r4, r0, #16, #4
 25 0028 1C19     		adds	r4, r3, r4
 26 002a 0091     		str	r1, [sp, #0]
 27 002c C0F30367 		ubfx	r7, r0, #24, #4
 28 0030 03EB1071 		add	r1, r3, r0, lsr #28
 29 0034 92F82020 		ldrb	r2, [r2, #32]	@ zero_extendqisi2
 30 0038 5D19     		adds	r5, r3, r5
 31 003a 66F30300 		bfi	r0, r6, #0, #4
 32 003e 95F83050 		ldrb	r5, [r5, #48]	@ zero_extendqisi2
 33 0042 6CF30710 		bfi	r0, ip, #4, #4
 34 0046 94F840C0 		ldrb	ip, [r4, #64]	@ zero_extendqisi2
 35 004a 009C     		ldr	r4, [sp, #0]
 36 004c 62F30B20 		bfi	r0, r2, #8, #4
 37 0050 0191     		str	r1, [sp, #4]
 38 0052 65F30F30 		bfi	r0, r5, #12, #4
 39 0056 1919     		adds	r1, r3, r4
 40 0058 91F85020 		ldrb	r2, [r1, #80]	@ zero_extendqisi2
 41 005c DB19     		adds	r3, r3, r7
 42 005e 6CF31340 		bfi	r0, ip, #16, #4
 43 0062 DDF804C0 		ldr	ip, [sp, #4]
 44 0066 93F86010 		ldrb	r1, [r3, #96]	@ zero_extendqisi2
 45 006a 62F31750 		bfi	r0, r2, #20, #4
 46 006e 9CF87030 		ldrb	r3, [ip, #112]	@ zero_extendqisi2
 47 0072 61F31B60 		bfi	r0, r1, #24, #4
 48 0076 63F31F70 		bfi	r0, r3, #28, #4
 49 007a FCBD     		pop	{r2, r3, r4, r5, r6, r7, pc}

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


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

свежак

 

теперь тулсы будут собиратся c EABI, это дает лучший код.

 

че это такое и очем речь можно по диагоняли посмотреть тут http://infocenter.arm.com/help/topic/com.a...0036B_bsabi.pdf

 

www.klen.org/Files/DevTools/kgp_arm_eabi_20091127.7z

 

2_Jat

с EABI стало лучше, Вами предложенный код компиляется на 2 инструкции длинне чем у Sourcery G++ Lite 2009q3-68.

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

кстате это к работе с битами никакого отношения не имеет. толко к registers usage. Работа с битами очень даже хорошо для кортеха генерится.

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


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

2 klen

 

а для AVR вы сборки не делаете?

 

делаю

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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