kosyak©
Dec 9 2010, 11:59
Есть код
Код
...
volatile int d = 100;
volatile int k = 11;
volatile int q = d / k;
...
Компилятор (EWARM6101) при любом из уровней оптимизации компилирует это как
Код
volatile int d = 100;
MOV R1,#+100
STR R1,[SP, #+4]
volatile int k = 11;
MOV R1,#+11
STR R1,[SP, #+0]
65 volatile int q = d / k;
^
LDR R0,[SP, #+4]
LDR R1,[SP, #+0]
BL __aeabi_idiv
STR R0,[SP, #+8]
Как заставить его не использовать __aeabi_idiv?
demiurg_spb
Dec 9 2010, 14:00
Код
static const int D = 100;
static const int K = 11;
volatile int d = D;
volatile int k = K;
volatile int q = D / K;
Цитата(kosyak© @ Dec 9 2010, 14:59)

Как заставить его не использовать __aeabi_idiv?
А зачем, если не секрет?
Ну и, как уже отметил demiurg_spb, компилятор не стал оптимизировать этот код из-за того, что применено ключевое слово volatile. Всё правильно компилятор сделал.
kosyak©
Dec 9 2010, 20:11
Так и думал что в волатиле начнут носом тыкать

Ну тогда по порядку - волатиле написал сознательно, чтоб компилятор не проявлял чудеса оптимизМА и не посчитал мне это выражение на этапе компиляции

Интересует конкретно вопрос как его заставить не использовать __aeabi_idiv а скомпилировать деление прям в функцию.
Вот, например (пример из пальца выососан сразу предупреждаю), - есть функция, она выполняется из рамки (RAM) и затирает скажем внутреннюю флэш.. в функции считается страница ( / ) и смещение ( % ) - и тут компилятор решил выпендриться и использовать для деления __aeabi_idiv, вместо того чтобы честно скомпилировать нужный код, __aeabi_idiv ессно лежит в стираемой флэше..вот такая вот загогулина...
Да, я конечно, понимаю что можно вю библиотеку используемых компилятором функций запихнуть в рамку и проблемы вроде как бы не станет - но интересует именно как заставить его их не использовать...
IgorKossak
Dec 10 2010, 08:06
QUOTE (kosyak© @ Dec 9 2010, 22:11)

Интересует конкретно вопрос как его заставить не использовать __aeabi_idiv а скомпилировать деление прям в функцию.
Вы не указали архитектуру. Если это ARM7TDMI-S, то функция __aeabi_idiv вместе с __aeabi_idivmod занимает 332 байта (Code Sourcery Lite). При таком размере компилятор её не проинлайнит.
QUOTE (kosyak© @ Dec 9 2010, 22:11)

Вот, например (пример из пальца выососан сразу предупреждаю), - есть функция, она выполняется из рамки (RAM) и затирает скажем внутреннюю флэш.. в функции считается страница ( / ) и смещение ( % ) - и тут компилятор решил выпендриться и использовать для деления __aeabi_idiv, вместо того чтобы честно скомпилировать нужный код, __aeabi_idiv ессно лежит в стираемой флэше..вот такая вот загогулина...
Если размер Вашей страницы не является константой и не кратен степени двойки, то ничего удивительного в поведении компилятора нет.
kosyak©
Dec 10 2010, 08:13
Архитектура действительно ARM7TDMI-S. Я тоже считаю что ничего удивительного нет, но осталась ли возможность принудительно инлайнить подобные функции?
IgorKossak
Dec 10 2010, 08:18
А всё же. Каков размер страницы и почему он не константный?
Ведь всё могло свестись к сдвиговым операциям.
kosyak©
Dec 10 2010, 08:23
Ну тогда дополню картину:
Стоит датафлэш AT45DBxxx (именно xxx), перепрошивка осуществляется через эту флэш - т.е. сперва полный бинарь записывается в нее, а потом, если все хорошо, камень перепрошивается. Вот тут и возник прикол с __aeabi_idiv. Я прекрасно понимаю что можно написать загручик который будет полностью работает в рамке и проблема снимется.... Предвосхищая вопросы - питание у устройства аккумуляторное.
Да и вообще - сейчас это уже больше академический интерес

.
MALLOY2
Dec 10 2010, 09:03
Академический вопрос, что в загрузчике делает __aeabi_idiv ? На верняка можно обойтись без деления, ну если конечно не используется паковка, шифрование, хитрые CRC (обычные работают без деления).
kosyak©
Dec 10 2010, 09:12
Страничная организация DataFlash. Из линейного адреса нужно посчитать - номер страницы, смещение в странице...
Делается все примерно так
page = la / page_size;
offs = la % page_size;
Предложите другой метод? Метод вычисления page и offs, а не метод нахождения частного и остатка.
MALLOY2
Dec 10 2010, 09:39
Мда..... так и знал

Все делается через маску и сдвиг
Код
#define ADDR_TO_SECTOR_NUMBER(x) ((x) >> 9) //for page == 512 bytes
#define ADDR_TO_PAGE_OFFSET(x) ((x) & 0x1FFu) //for page == 512 bytes
kosyak©
Dec 10 2010, 09:45
Цитата(kosyak© @ Dec 10 2010, 11:23)

...
Стоит датафлэш AT45DBxxx (именно xxx)
...
Тем что "(именно xxx)" я хотел подчеркнуть, что на этапе компиляции я не знаю какую флэш поставят. Соответственно не знаю размер страницы... Мало того, сейчас стали приходить dataflash, у которых размер страницы - степень двойки... раньше у атмела в этих флэшах страница была с аппендиксом и ее размер не был равен степени двойки

.
MALLOY2
Dec 10 2010, 09:53
И какие с этим проблемы ?
Глава 14. Manufacturer and Device ID Read
Изучайте мат часть
Цитата
степень двойки... раньше у атмела в этих флэшах страница была с аппендиксом и ее размер не был равен степени двой
По моему вы вобще мануал не читали или не умеете
kosyak©
Dec 10 2010, 09:57
Уф!
Вообщем так - на плату может быть поставлена любая микросхема из серии AT45DBXXXD, программа должна определять по выше упомянутому Вами "Manufacturer and Device ID Read" тип микросхемы и, соответственно, размер страницы. Еще раз повторю - не все микросхемы серии AT45DBXXXD имеют размер страницы кратный степени двойки, соотвественно нельзя использовать "маску и сдвиг" для преобразования линейного адреса в страничный....
MALLOY2
Dec 10 2010, 09:59
13. "Power of 2" Binary Page Size Option
"Power of 2" binary page size Configuration Register is a user-programmable nonvolatile regis-
ter that allows the page size of the main memory to be configured for binary page size
(512 bytes) or DataFlash standard page size (528 bytes). The "power of 2" page size is a one-
time programmable configuration register and once the device is configured for "power
of 2" page size, it cannot be reconfigured again. The devices are initially shipped with the
page size set to 528 bytes. The user has the option of ordering binary page size (512
bytes) devices from the factory. For details, please refer to Section 26. "Ordering Information" on
page 48.
For the binary "power of 2" page size to become effective, the following steps must be followed:
1. Program the one-time programmable configuration resister using opcode sequence
3DH, 2AH, 80H and A6H (please see Section 13.1).
2. Power cycle the device (i.e. power down and power up again).
3. The page for the binary page size can now be programmed.
If the above steps are not followed to set the page size prior to page programming, incorrect
data during a read operation may be encountered.
kosyak©
Dec 10 2010, 10:04
Ладно - цитирую мануал:
User Configurable Page Size
– 256-Bytes per Page
– 264-Bytes per Page
– Page Size Can Be Factory Pre-configured for 256-Bytes
Не предлагайте мне сконфигурировать микросхему чтоб размер страницы стал кратен степени 2! как это сделать я знаю сам!
Прочитайте еще раз название темы... и забудте Вы про конкретное применение этого кода!
Еще раз, специально для Вас ув. MALLOY2, Как заставить компилятор IAR EWARM6101 инлайнить функции вида __aeabi_idiv?
Эх...не успел... предложили сконфигурировать в степень двойки

((
MALLOY2
Dec 10 2010, 10:15
Создаем проблемы и героически их решаем
Вы знаете когда размер страницы равен 528 байт, то страница всен равно хранит 512 байт информации и остаток используется для контрольной суммы и/или востановления информации. Если вы хотите использовать 528 для линейной адресации, подход явно через...
kosyak©
Dec 10 2010, 10:20
Ну...еще раз скажу - вопрос не про конкретное применение операции деления!
Цитата(MALLOY2 @ Dec 10 2010, 13:15)

...
когда размер страницы равен 528 байт, то страница всен равно хранит 512 байт информации и остаток используется для контрольной суммы и/или востановления информации
...
О_о кем используется остаток? Как "все равно" хранит 512 байт? Это сейчас о чем?
Согласен, что случай, когда код прошивки флэш должен быть в ОЗУ, весьма актуален. Насколько я знаю, у компилятора нет настроек, позволяющих гарантировать, что кусок кода, скопированный в ОЗУ, не будет вызывать функции из флэш. Можно, конечно, подрихтовать код "ручками", но нет гарантии, что при переходе на новую версию компилятора или при смене его настроек не придётся рихтовать код снова. Чтобы это гарантировать, нужно оформить код в ОЗУ как самостоятельный проект, полностью размещённый в ОЗУ. Для связи с основной прошивкой можно придумать простенький ABI: таблица указателей на функции. Забыл добавить: или писать код в ОЗУ на ассемблере.
QUOTE (kosyak© @ Dec 9 2010, 15:59)

Есть код
...
Как заставить его не использовать __aeabi_idiv?
Ну, например, можно сделать так
CODE
#define D 100
#define K 11
#define Q D/K
...
volatile int d = D;
volatile int k = K;
volatile int q = Q;
...
Или нет?
Для просмотра полной версии этой страницы, пожалуйста,
пройдите по ссылке.