Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: реализация булевых переменных в bit-band
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Страницы: 1, 2
_Pasha
Привет
Вижу для родного gcc - самое правильное
Код
typedef uint32_t __attribute__((section(".bitmap"))) bit;

Какбы вопросы, возникающие в связи с этим:
1. Как избежать использование области памяти в не bit-band в линкер скрипте?
2. Как наоборот, - проще получить параметры этой области или ее части для быстрого обнуления?

Спасибо.
ps
вот увидел такое http://stackoverflow.com/questions/1655271...ection-in-c-gcc
Код
/**
* Assuming you've tagged some stuff earlier with:
* __attribute((__section__("my_custom_section")))
*/

struct thing *iter = &__start_my_custom_section;

for (; iter < &__stop_my_custom_section; ++iter) {
    /* do something with *iter */
}

т.е. получается, что я могу выделить под битмап что-то
и его размер будет
Код
extern char bitmap[((uint) __stop_my_custom_section - __start_my_custom_section)/32];

а как мне на этапе компиляции назначить адрес этой области?
AVI-crak
Цитата(_Pasha @ Oct 16 2015, 14:00) *
а как мне на этапе компиляции назначить адрес этой области?

CODE

Bit-band - via a linker.
Код для GCC - линкер.
xxx_sram/flash.ld

MEMORY
{
ROM (rx) : ORIGIN = 0x08000000, LENGTH = __
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = __
BITRAM (rw) : ORIGIN = 0x22000000, LENGTH = 2048K // - LENGTH(RAM) * 128
}
----
/* SRAM base address in the bit-band region*/
_sramflag = .;
sflagadres = ((_sramflag - ORIGIN(RAM)) << 5 );
.flag (NOLOAD):
{
. += sflagadres;
. = ALIGN(4);
_sflag = .;
KEEP(*(.flag))
. = ALIGN(128);
_eflag = .;
} > BITRAM
_eramflag = ((_eflag - _sflag) >> 5);
/* SRAM base address in the bit-band region*/
.bss (NOLOAD):
{
__bss_start__ = .;
. += _eramflag;
*(.bss*)
*(COMMON)
__bss_end__ = .;
} > RAM

С код.
#define _FLAG __attribute__ ((section(".flag")))

Далее по коду С.
volatile uint32_t temp_name_flag _FLAG;
jcxz
Например так (IAR):
распредление памяти: u8 noSleepDMA @ ".BITBAND_RAM" = 0;
объявления бит: enum {DMA_CH_lcd_RX, DMA_CH_lcd_TX};
Операция присваивания (через макрос): *BITBAND_RAM(&noSleepDMA, DMA_CH_lcd_RX) = ...
icf-файл линкёра:
define region RAM_regionB = mem:[from 0x20000000 size 0x8000]; //peripheral RAM
place in RAM_regionB {section .BITBAND_RAM, section .dma, section .ethernet};
_Pasha
гран мерси.
т.е. суть приема в том, что назначаем область битовых флагов в начале доступной области SRAM и корректируем начало .bss в соответствии с использованием секции флагов
отдельное спасибо за
Код
. = ALIGN(128);

rolleyes.gif
гарантированно сидел бы фтыкал sm.gif
--
а, ну и по _FLAG - все-таки bit через typedef uint32_t итд правильнее.
AVI-crak
Код
typedef uint32_t __attribute__((section(".bitmap"))) bit;


Вы уверенны что смена названия типа переменной лучше макроса? У меня GCC матерится на смену типа.

copov
Можно обычным дифайном обойтись. Например у меня в одном из проектов.
Код
#define PortF_Bit0 (*((volatile unsigned long *) 0x43D00000))
//PortF_Bit0 = 1;//установить бит 0 в единицу
//PortF_Bit0 = 0;//установить бит 0 в ноль

#define PortF_Bit1 (*((volatile unsigned long *) 0x43D00004))
//PortF_Bit1 = 1;//установить бит 1 в единицу
//PortF_Bit1 = 0;//установить бит 1 в ноль

jcxz
Цитата(copov @ Oct 19 2015, 15:05) *
Можно обычным дифайном обойтись. Например у меня в одном из проектов.
...

Только как память выделить в Вашем случае?
Golikov A.
а зачем память выделять, разве это не зарезирвированное адресное пространство?
jcxz
Цитата(Golikov A. @ Oct 20 2015, 00:53) *
а зачем память выделять, разве это не зарезирвированное адресное пространство?

Это обычная память. Для которой есть область - алиас. Человек пишет в алиас-область, при этом опущено выделение этой памяти по настоящим адресам.
Golikov A.
это типа чтобы через удобные переменные работать что ли? Почему по прямым адресам нельзя писать?
jcxz
Цитата(Golikov A. @ Oct 21 2015, 11:25) *
это типа чтобы через удобные переменные работать что ли? Почему по прямым адресам нельзя писать?

Блин! прочитайте про bit-banding.
scifi
Какой ужас. Зачем идти на все эти извращения? Чтобы сэкономить несколько байтов? Или у вас в программе 100500 флагов? Не стоит оно всей этой возни, ИМХО...
copov
Цитата(jcxz @ Oct 21 2015, 08:23) *
Это обычная память. Для которой есть область - алиас. Человек пишет в алиас-область, при этом опущено выделение этой памяти по настоящим адресам.

По настоящим адресам и есть обращение. Например:
(*((volatile unsigned long *) 0x43D00000))
И не надо ничего выдумывать, такой вариант работает в компиляторах для ARM и для любых других.
_Pasha
Цитата(scifi @ Oct 21 2015, 10:30) *
Какой ужас.

biggrin.gif
правильный ответ уже содержится в сообщ. №2
scifi
Цитата(_Pasha @ Oct 21 2015, 10:59) *
правильный ответ уже содержится в сообщ. №2

Дык там тоже ужас laughing.gif
Вопрос-то был "зачем?"
Сказали бы "из любви к искусству" - я бы понял. Куда же без этого rolleyes.gif
Golikov A.
Цитата
Блин! прочитайте про bit-banding.

чего читать то? Я не понимаю зачем возня и почему нельзя писать напрямую через адрес, ну типа вот так (*((volatile unsigned long *) 0x43D00000)) ?

пробил дефайнами нужные биты и сиди ими щелкай, чего я не учитываю?
scifi
Цитата(Golikov A. @ Oct 21 2015, 11:20) *
пробил дефайнами нужные биты и сиди ими щелкай, чего я не учитываю?

Всё-таки приятнее, когда память выделяется автоматически и всё такое.
Но всё равно семантика типа bool не соблюдается, приходится приписывать какое-то волшебное слово. Короче, получается непереносимый код. Даже в том же Cortex-M0 нет никакого bit banding.
Так что фтопку 1111493779.gif
zltigo
QUOTE (scifi @ Oct 21 2015, 10:30) *
Какой ужас. Зачем идти на все эти извращения? Чтобы сэкономить несколько байтов?

Я использую "это" для обеспечения атомарности доступа к флагам. Великолепный механизм позволяющий кроме обеспечения атомарности еще и количество тактов сократить.
А вот без этого получается реальный ужас c запретами-восстановлениями прерываний для обеспечения атомарного доступа.

Golikov A.
ПЛАКАТЬ ХОЧЕТСЯsm.gif...
нафига памяти то выделятся? Вы же когда в периферию обращаетесь вы же не делаете выделения памяти, а запись в регистры идет тоже просто по адресам, зачем тут чего то выделять?

кстати тут недавно было что обращение через битбанд к регистрам только записи, типа флагов прерываний вызывает проблемы, так как битбанд всегда читает, изменяет, пишет, а это приводит к неопределенным результатам с регистрами только записи...
zltigo
QUOTE (Golikov A. @ Oct 21 2015, 11:20) *
пробил дефайнами нужные биты и сиди ими щелкай, чего я не учитываю?

1) Атомарности операции.
2) Затрат времени исполение дополнительной кучи команд.

Учитесь думать самостоятельно.




_Pasha
Цитата(Golikov A. @ Oct 21 2015, 11:33) *
ПЛАКАТЬ ХОЧЕТСЯsm.gif...
нафига памяти то выделятся? Вы же когда в периферию обращаетесь вы же не делаете выделения памяти, а запись в регистры идет тоже просто по адресам, зачем тут чего то выделять?

Товарищ не понимааает (с)
Если у Вас есть возможность заводить static bool в разных модулях, то это гораздо интереснее чем вручную и глобально их определять.
Насчет BSRR - история давняя, типа масляного масла получается, неудивительно что там конфликты возникают.
zltigo
QUOTE (Golikov A. @ Oct 21 2015, 11:33) *
ПЛАКАТЬ ХОЧЕТСЯsm.gif...
нафига памяти то выделятся? Вы же когда в периферию обращаетесь вы же не делаете выделения памяти, а запись в регистры идет тоже просто по адресам, зачем тут чего то выделять?

Слезами делу не поможешь. Так что наморщите ум и подумайте.
scifi
Опять 25 laughing.gif
Пришёл хамоватый тролль zltigo, а Голиков никак не может перестать его кормить.
Осталось откинуться в кресле и достать попкорн biggrin.gif
_Pasha
Цитата(scifi @ Oct 21 2015, 11:47) *
достать попкорн biggrin.gif

если десяток строчек в скрипте линкера вызывает столько воплей, то я, пожалуй, випью biggrin.gif
Golikov A.
Цитата
Если у Вас есть возможность заводить static bool в разных модулях

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

Цитата
Слезами делу не поможешь. Так что наморщите ум и подумайте.

Цитата
Учитесь думать самостоятельно.

Есть подозрения среднеуважаемый zltigo что вы испытываете некие комплексы, связанные с вашим уровнем интеллекта, и потому по поводу и без пытаетесь словами всем объяснить что вы умнее%)....
Однако как показала практика с понималкой у вас не очень, потому я вам разжую:
я предлагал дефайном пробить область в битбанде, чтобы как бы непонятному адресу поставить в соответствие понятное название бита, и задефайнить прямо макрос, чтобы писать по его имени прямо в эту область. Как делают с регистрами периферии. Теперь поняли?
zltigo
QUOTE (Golikov A. @ Oct 21 2015, 12:05) *
Теперь поняли?

Понял что Вы так и не поняли причины "нафига памяти то выделятся? ", продолжаете нести пургу про переферийные адреса и поучать как писать define. Область RAM это в отличие фиксированных адресов периферии, распределяемая компилятором и линкером память.
Golikov A.
Эта область плавающая?
то есть в одном контроллере в разных программах при одной конфигурации проца, может при обращении по адресу 0x43D00000 происходить запись в разные биты? Или не происходит вообще?
_Pasha
Цитата(AVI-crak @ Oct 16 2015, 19:05) *
Код
typedef uint32_t __attribute__((section(".bitmap"))) bit;


Вы уверенны что смена названия типа переменной лучше макроса? У меня GCC матерится на смену типа.

Здравствуйте.
Еще не добрался до проекта.
Но обязательно проверю и сообщу.
AVI-crak
И всё-же прочитайте доку на Bit-band.

Для работы через макрос необходимо сначала выделить немножко простой памяти под обычную 32b переменную, из которой потом макрос будет брать по одному биту под имя. Это муторно и неудобно, в какой-то момент можно совершить ошибку со свободным битом, и сношаться с отладчиком долгое время. Макрос нормально работает с физикой, у которой реальный адрес. Но когда флаги создаются в простой памяти в разных местах - следить уже сложно.
Я предлагаю переложить всю работу по поиску нужного куска памяти - на линкер, это его первичная обязанность.

Кстати, у меня проект на 18 постоянных и 200 с копейкой подгружаемых потоков, на каждую нитку по 8 флагов минимум. Я-б рехнулся с выделением памяти под флаги. А так, я даже не задумываюсь - где они хранятся.

Есно для проекта уровня "поморгать светодиодом" - использование моего способа чисто академическое.
AHTOXA
Цитата(Golikov A. @ Oct 21 2015, 14:30) *
то есть в одном контроллере в разных программах при одной конфигурации проца, может при обращении по адресу 0x43D00000 происходить запись в разные биты?

Речь идёт о том, что при объявлении бит-банд переменной по адресу 0x43D00000 нужно как-то указать линкеру, что область ОЗУ, с которой мы работаем бит-бандом при обращении по адресу 0x43D00000, занята.
jcxz
Цитата(copov @ Oct 21 2015, 13:50) *
По настоящим адресам и есть обращение. Например:
(*((volatile unsigned long *) 0x43D00000))
И не надо ничего выдумывать, такой вариант работает в компиляторах для ARM и для любых других.

Опять 25... Я писал не про обращение, а про выделение. Чувствуете разницу?
Если разжевать: когда Вы так обратились к какому-то флагу, соответственно - изменился некий байт адреса в области RAM.
Вот чтобы этот байт не оказался занятым чем-то полезным, нужно выделить на его месте переменную, в которой и хранится этот флаг.
zltigo
QUOTE (Golikov A. @ Oct 21 2015, 12:30) *
Эта область плавающая?
то есть в одном контроллере в разных программах при одной конфигурации проца, может при обращении по адресу 0x43D00000 происходить запись в разные биты?

В одни и те-же ФИКСИРОВАННЫЕ адреса основной области памяти. Но в этой основной области памяти именно по этому адресу должна находится именно та 32bit переменная в котрой меняется бит. Оба варианта адресации должны быть взаимоувязанными. Обращение по фиксированому адресу не позволяет этого сделать. Привязывать к фиксированному адресу еще и 32bit переменную не предлагать по причине глупости такого "решения". Адрес бита совершенно естественно и без всяких плясок пересчитывается из назначенного компилятором и линкером адреса в основной области. Постой макрос и все.




jcxz
Цитата(Golikov A. @ Oct 21 2015, 14:20) *
чего читать то? Я не понимаю зачем возня и почему нельзя писать напрямую через адрес, ну типа вот так (*((volatile unsigned long *) 0x43D00000)) ?
пробил дефайнами нужные биты и сиди ими щелкай, чего я не учитываю?

Не учитываете, что когда Вы делаете: *((volatile unsigned long *) 0x43D00000) = 1, то в реальной ОЗУ, соответсвующей этому адресу, меняется этот бит.
И где этот бит находится? Куда попадает?
Вы всё своё ПО пишете так: *((volatile unsigned long *)addr_XXX = y;
или всё-таки выделяете память для переменной и делаете так: int XXX; XXX = y; ?
zltigo
QUOTE (jcxz @ Oct 21 2015, 13:06) *
Вот чтобы этот байт не оказался занятым чем-то полезным, нужно выделить на его месте переменную, в которой и хранится этот флаг.

Увы, удручающему большинству здесь выступающих, понять эту очевидный факт не по силам sad.gif.

jcxz
Цитата(zltigo @ Oct 21 2015, 16:12) *
Увы, удручающему большинству здесь выступающих, понять эту очевидный факт не по силам sad.gif.

И не говорите.....
Такое ощущение, что многие из здесь присутствующих не знают что такое распределение памяти под переменные и для чего нужен линкёр, а пишут весь свой код как: *(int *)0x000XXX = y
scifi
Цитата(zltigo @ Oct 21 2015, 13:12) *
Увы, удручающему большинству здесь выступающих, понять эту очевидный факт не по силам sad.gif.

Цитата(jcxz @ Oct 21 2015, 13:16) *
И не говорите.....
Такое ощущение, что многие из здесь присутствующих не знают что такое распределение памяти под переменные и для чего нужен линкёр, а пишут весь свой код как: *(int *)0x000XXX = y

Нет. Зато есть ощущение, что некоторые из здесь присутствующих выражаются недостаточно чётко, их понимают превратно, а они списывают это на скудоумие аудитории и своё интеллектуальное превосходство.
lol.gif
Golikov A.
Погодите-погодите... а зачем регион бит-банда включен в общую оперативную память? А если он не включен, то как линкер там может разместить какие-то переменные? Чего то я реально не понимаю, вот с сайта арма

Код
#define BITBAND_SRAM_REF 0x20000000
#define BITBAND_SRAM_BASE 0x22000000
#define BITBAND_SRAM(a,b) ((BITBAND_SRAM_BASE + (a-BITBAND_SRAM_REF)*32 \    + (b*4))) // Convert SRAM address

#define BITBAND_PERI_REF 0x40000000
#define BITBAND_PERI_BASE 0x42000000
#define BITBAND_PERI(a,b) ((BITBAND_PERI_BASE + (a-BITBAND_PERI_REF)*32 \    + (b*4))) // Convert PERI address

#define MAILBOX 0x20004000
#define TIMER 0x40004000// Mailbox bit 0
#define MBX_B0 *((volatile unsigned int *)(BITBAND_SRAM(MAILBOX,0)))// Mailbox bit 7
#define MBX_B7 *((volatile unsigned int *)(BITBAND_SRAM(MAILBOX,7)))// Timer bit 0
#define TIMER_B0 *((volatile unsigned char *)(BITBAND_PERI(TIMER,0)))// Timer bit 7
#define TIMER_B7 *((volatile unsigned char *)(BITBAND_PERI(TIMER,7)))
int main(void){    unsigned int temp = 0;
    MBX_B0 = 1; // Word write    
    temp = MBX_B7; // Word read  
    TIMER_B0 = temp; // Byte write    
    return TIMER_B7; // Byte read
}


_Pasha
Цитата(_Pasha @ Oct 21 2015, 12:47) *
Еще не добрался до проекта.
Но обязательно проверю и сообщу.

ааа. Понятно. Действительно, аттрибут к typedef неприменим rolleyes.gif
Код
gcc -Wall -c "tst.c" -I.  --std=gnu99
tst.c:18:61: error: section attribute not allowed for ‘bit’
typedef volatile  uint32_t __attribute__((section(".bss"))) bit;
                                                             ^
Compilation failed.

Так что только дефайном.
jcxz
Цитата(Golikov A. @ Oct 21 2015, 16:50) *
Погодите-погодите... а зачем регион бит-банда включен в общую оперативную память? А если он не включен, то как линкер там может разместить какие-то переменные? Чего то я реально не понимаю, вот с сайта арма

В Cortex есть регион адресного пространства (в котором может находиться физическое ОЗУ), такой особенный регион (назовём его регион_A), что для каждого его бита в другом регионе адресного пространства (назовём его регион_B) существует 32битное слово, при записи в которое некоторых значений, меняется этот бит (это слово является псевдонимом этого бита).
Таким образом, чтобы задействовать эту фичу, надо в регионе_A объявить переменную достаточной ёмкости, хранящую набор битовых флагов, а работать с этими флагами надо через слова-алиасы для этих битов из региона_B. Хотя в то же время эти же биты можно читать/модифицировать и через регион_A. Но если делать запись их через алиасы, то эти записи атомарны, в этом и кроется вся соль bit-banding-а.

scifi, если и это описание ещё недостаточно чёткое, то я уже не знаю как ещё объяснить. И всё это можно прочиать в документации на ядро Cortex, к которой я отсылал ещё вначале.
zltigo
QUOTE (Golikov A. @ Oct 21 2015, 13:50) *
Погодите-погодите... а зачем регион бит-банда включен в общую оперативную память? А если он не включен, то как линкер там может разместить какие-то переменные? Чего то я реально не понимаю, вот с сайта арма

CODE
#define MAILBOX 0x20004000

Теперь включаем наконец мозг, пробуем читать написанное и думаем что-же за адрес такой "0x20004000" и с чего-бы это вдруг линкеру не разместить там все, что угодно на свое усмотрение? Заодно следует подумать c какого бодуна вывалили такой дивного уродства пример работы с исключительно фиксированным адресом sad.gif.
Для демонстрации работы могли-бы хоть что-то такое накропать:
CODE
unsigned int mailbox;

#define BITBAND_SRAM_REF  (0x20000000)
#define BITBAND_SRAM_BASE (0x22000000)
#define MBX( bit )                                                                              \
    *(unsigned int *)( (BITBAND_SRAM_BASE) + ( (unsigned int)&mailbox - (BITBAND_SRAM_REF) ) * 32 + ((bit) * 4) )

MBX(0) = TRUE;


Ну а за такие комментарии:
CODE
#define MBX_B0 *((volatile unsigned int *)(BITBAND_SRAM(MAILBOX,0)))// Mailbox bit 7
....
MBX_B0 = 1; // Word write

говнокодерам сляпавшим сей "пример" отдельное спасибо sm.gif sm.gif sm.gif
Golikov A.
Цитата
(назовём его регион_A), что для каждого его бита в другом регионе адресного пространства (назовём его регион_B)

все я понял... битбанд для области реальной памяти, я все никак не мог понять что вы с линкером договариваетесь об области реальной памяти, а не об регионе битбанда sm.gif

на самом деле не сразу понятно.... теперь я понял почему регион у ТС битмапом заветсяsm.gif)))



Цитата
говнокодерам сляпавшим сей "пример" отдельное спасибо

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

Пример я взял с официального сайта арма, он строгий, четкий и понятный, а вы идите лесом!

zltigo
QUOTE (Golikov A. @ Oct 21 2015, 16:09) *
Пример я взял с официального сайта арма, он строгий, четкий и понятный...

sm.gif если бы не было так sad.gif и за Вас и ОСОБЕННО за сайт ARM такое дерьмо размещающий sad.gif в качестве "примеров".
IgorKossak
Golikov A. отправлен в read only за плохое поведение на неделю.
Остальным предлагаю задуматься.
Модератор
copov
Область bit-band и так лежит вне области ОЗУ для данных, поэтому для нее ничего не надо специально резервировать, если обращаться туда по абсолютным адресам. С какого компоновщик будет туда размещать переменные.
Обидели Голикова, чуть ли не единственно грамотного человека в этой ветке и радуются.
DmitryM
Цитата(copov @ Oct 22 2015, 10:05) *
Область bit-band и так лежит вне области ОЗУ для данных


Это с чего это? Внимательнее читайте про Bit-banding.
copov
А чего читать. Bit-band для обращения по битам в отдельной области SRAM или в области периферийный регистров и не совпадают по адресам при обращении к ним по словам.

А понял в чем вопрос, просто и в голову не приходило, что биты могут понадобиться не для обращения к периферии.
Зарезервировать в обычной SRAM по разному в разных средах. В Keil можно так:
volatile uint32_t Var_for_bit __attribute__((at(0x20000000)));
_Pasha
biggrin.gif они еще и читать не умеют
Сергей Борщ
Цитата(copov @ Oct 22 2015, 11:33) *
Зарезервировать в обычной SRAM по разному в разных средах. В Keil можно так:
volatile uint32_t Var_for_bit __attribute__((at(0x20000000)));
Это точно резервирование?

После этого точно нельзя сделать вот так? :
volatile uint32_t Var_for_bit1 __attribute__((at(0x20000000)));
volatile uint32_t Var_for_bit2 __attribute__((at(0x20000001)));
volatile uint32_t Var_for_bit3 __attribute__((at(0x20000000)));

zltigo
QUOTE (copov @ Oct 22 2015, 10:05) *
Область bit-band и так лежит вне области ОЗУ для данных...

Разумеется это абсолютно не так. Посему, все что Вы написали далее не верно. Читайте документацию или хотя-бы то, что здесь разжевывали ( безрезультатно sad.gif, как вижу ) Голикову и Вам.

QUOTE (copov @ Oct 22 2015, 11:33) *
просто и в голову не приходило, что биты могут понадобиться не для обращения к периферии.

Биты, как и байты и вообще любые структры, используюся для всего чего нужно. При этом при работе с битами чрезе bit-band получаем два ВАЖНЕЙШИХ
эффекта:
1) Атомарность операци;
2) Выигрыш по скорости.
Об этом уже тоже здесь писалось sad.gif
copov
Цитата(Сергей Борщ @ Oct 22 2015, 11:47) *
Это точно резервирование?

После этого точно нельзя сделать вот так? :
volatile uint32_t Var_for_bit1 __attribute__((at(0x20000000)));
volatile uint32_t Var_for_bit2 __attribute__((at(0x20000001)));
volatile uint32_t Var_for_bit3 __attribute__((at(0x20000000)));

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