реклама на сайте
подробности

 
 
2 страниц V  < 1 2  
Reply to this topicStart new topic
> С и asm-вставки, Локальные переменные
Xeon
сообщение Apr 1 2012, 17:58
Сообщение #16


Частый гость
**

Группа: Участник
Сообщений: 140
Регистрация: 21-04-11
Пользователь №: 64 524



Попробую... Да одна такая таблица получается) это для 64 гармоники при частоте дискретизации 250килосемплов/секунду (реальная частота 63500Гц), но надо ещё +8 частот смотреть... поэтому менять думаю особо невариантsm.gif
Go to the top of the page
 
+Quote Post
alexeyv
сообщение Apr 2 2012, 04:56
Сообщение #17


Местный
***

Группа: Участник
Сообщений: 298
Регистрация: 26-01-09
Из: Пермь
Пользователь №: 43 940



Перед тем как оптимизировать на асме, разберитесь сначала с оптимизацией ни СИ. Во-первых, при оптимизации на асме можно сделать очепятку, которую потом будете долго и упорно искать. Во-вторых, оптимизация на Си выполняется гораздо быстрее. В-третьих, при хорошо изученном поведении своего компилятора, отимизированный код на Си будет всего на 5...15% больше своего собрата на асме, зато скока сэкономленого времени?!
И если только оптимизация на Си не помогает, то необходимо залезать в ассемблер.
Но и при ассемблерной оптимизации есть куча подводных камней.

Примеры:
1. Использование указателей вместо индексации массивов
Код
    int8_t * val = &Values[0]; // в не тела цикла
    ..................................
    // в цикле:
    FsummRe[FLookignForFreq] += (int32_t) (*val) * cosVal;
    FsummIm[FLookignForFreq] += (int32_t) (*val) * sinVal;
    ..................................
    val++;

Это сокращает код на одно вычисление адреса Values[CurVal]. FsummIm и FsummRe, FsinTable и FcosTable также можно привести к использованию указателей

2. Оптимизация циклов.
Цикл i=N;do{.....}while(i--); в большинстве случаев более оптимизировано компилируется, чем цикл for(i = 0; i < N; i++){........};

3. При целочисленной арифметике, деление заменяется на умножение и сдвиг.
4. Объявление наиболее используемых локальных переменных как register (не вовсех компиляторах)
5. и т.д. и т.п..........................



Go to the top of the page
 
+Quote Post
Xeon
сообщение Apr 2 2012, 07:46
Сообщение #18


Частый гость
**

Группа: Участник
Сообщений: 140
Регистрация: 21-04-11
Пользователь №: 64 524



Цитата(alexeyv @ Apr 2 2012, 07:56) *


Спасибо! Весьма полезные советы!!!
Go to the top of the page
 
+Quote Post
XVR
сообщение Apr 2 2012, 08:30
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847



Цитата(Xeon @ Apr 2 2012, 11:46) *
Спасибо! Весьма полезные советы!!!
На достаточном уровне оптимизации (-О3 достаточно) gcc это все сделает сам. (Хотя в конверсии массивов в указатели может и запутаться - у вас там весьма накрученно массивы индексируются)

Go to the top of the page
 
+Quote Post
alexeyv
сообщение Apr 2 2012, 09:04
Сообщение #20


Местный
***

Группа: Участник
Сообщений: 298
Регистрация: 26-01-09
Из: Пермь
Пользователь №: 43 940



Цитата(XVR @ Apr 2 2012, 14:30) *
На достаточном уровне оптимизации (-О3 достаточно) gcc это все сделает сам. (Хотя в конверсии массивов в указатели может и запутаться - у вас там весьма накрученно массивы индексируются)

1. Поверьте мне - GCC НЕ ВСЕ ЭТО сделает сам, в нем заложены только типичные алгоритмы, которые впрочем постоянно расширяются и периодически обновляются.
2. Мои высказывания относятся ко всем компиляторам, а не только к GCC. И если писать сразу отпимизировано, то не надо будет думать, что "я это делать не буду - это компилятор САМ прооптимизирует", а потом локти себе кусать. Это путь к деградации, если думать что за тебя все сделает компилятор/оптимизатор.
3. -О3 конечно хорошо, но когда идет отладка, то -О3 отключаешь, и как раз в этот момент не хватает - то оперативки, то флеша, то быстродействия......... (если конечно при проектировании не заложили запас, а все сделали в притык, как часто бывает)
Go to the top of the page
 
+Quote Post
=GM=
сообщение Apr 2 2012, 09:19
Сообщение #21


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



Цитата(XVR @ Apr 2 2012, 07:30) *
... у вас там весьма накрученно массивы индексируются

Да там индексы не нужны вообще. Например, здесь

FsummRe[FreqNum] += Values[i]*cosVal;

дважды по 256 раз вычисляется адрес по индексу FreqNum, но этот индекс - константа в подпрограмме.

Надо бы поставить A=A+Values[i]*cosVal;

в теле цикла, а после цикла сделать обратное присвоение FsummRe[FreqNum]=А


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
Xeon
сообщение Apr 6 2012, 08:46
Сообщение #22


Частый гость
**

Группа: Участник
Сообщений: 140
Регистрация: 21-04-11
Пользователь №: 64 524



Возник следующий вопрос - как в на асме прочитать байтик из памяти программ? Покопавшись в просторах интернета нашёл следующее:
CODE

ldi ZH, hi8(pm(F64_cos))
ldi ZL, lo8(pm(F64_cos))
lpm r18, Z


F64_cos - таблица значений косинуса. Но чёт это не работает. Код в AVR stidio 4 помнется выглядит примерно так:
CODE

ldi ZH, high(F64_cos*2)
ldi ZL, low(F64_cos*2)
lpm r18, Z

Т.е. в AVR stidio 4 нужно делать сдвиг в лево, что равно умножению на 2. Почитав доки на avr-gcc нашёл что макрос pm надо использовать если нужен доступ к памяти программ, но он равносилен деления на 2 или, что тоже самое, сдвигу на 1 в право. На этом моменте у меня сразу возникло не понимание принципа доступа к памяти программ на ассемблере в avr-gcc.
Может кто в курсе как делается правильно?

Вот весь код на асме, который написал:
CODE

#include "../Headers/asm_ftransform.h"
#include <avr/io.h>

.extern FsummRe // == r9, r8, r7, r6
.extern FsummIM // == r13, r12, r11, r10
.extern CurVal // == r5
.extern Flags
.extern FsinTable
.extern FcosTable
.extern F64_cos

.global DMA_CH0_vect
DMA_CH0_vect:

push r0
push r1
push ZL
push ZH
push r17
push r18
push r19

/* load Sin and Cos */
// calc offset
ldi r17, 0x35
//mul r5, r17 // r1:r0 - offset

// sin addres
ldi ZH, hi8(pm(F64_cos))
ldi ZL, lo8(pm(F64_cos))
//add r16, r0
//adc r17, r1
lpm r18, Z
sts _SFR_IO_ADDR(USARTE0_DATA), r18

// DMA.CH0.CTRLB |= 48; // clear interrupt flags
ldi r26, 0x30
sts _SFR_IO_ADDR(DMA_CH0_CTRLB), r26
// stop ADC
clr r17
sts _SFR_IO_ADDR(ADCA_CTRLA), r17

ldi r17, 2
sts Flags, r17

pop r19
pop r18
pop r17
pop ZH
pop ZL
pop r1
pop r0

reti


Нашел в чём проблема, мой косяк, F64_cos была в ОЗУ. И собственно чтоб прочитать из памяти программ нужно:
ldi ZH, hi8(F64_cos)
ldi ZL, lo8(F64_cos)
lpm r18, Z
без всяких макросов pm().
И новый вопрос: я правильно понимаю, макрос pm() используется для вызова подпрограмм, например:
ldi ZH, hi8(pm(s_func))
ldi ZL, lo8(pm(s_func))
call Z
так?
Go to the top of the page
 
+Quote Post
alexeyv
сообщение Apr 9 2012, 03:56
Сообщение #23


Местный
***

Группа: Участник
Сообщений: 298
Регистрация: 26-01-09
Из: Пермь
Пользователь №: 43 940



1. pm не используется для вызова подпрограм. Для вызова подпрограмм используются команды CALL/ICALL/EICALL/RCALL.
pm() - program memory, макрос просто умножает параметр на 2.
Дело в том, что ОЗУ у AVR адресуется байтово, а flash-память словарно, и адреса всех объектов, лежащих во flash-памяти являются словарными. Поэтому что бы из словарного адреса получить байтовый (для доступа к любому байту flash-памяти), необходимо умножить на 2, или сдвинуть на 1 влево.

Доступ к flash-памяти:
Код
ldi ZH, high(Table_1<<1)             ; Initialize Z pointer
ldi ZL, low(Table_1<<1)
lpm r16, Z+                                  ; Load constant from program Low-adress + increment Z
lpm r16, Z                                  ; Load constant from program High-adress


2. call Z - нет такой команды, есть icall.
И насколько я помню при загрузке ZH:ZL для команды icall, сдвигать адрес не надо.
Косвенный вызов функции:
Код
ldi ZH, high(func)             ; Initialize Z pointer
ldi ZL, low(func)
icall                                  ; Load constant from program



Сообщение отредактировал alexeyv - Apr 9 2012, 04:11
Go to the top of the page
 
+Quote Post
fox2trot
сообщение Apr 12 2012, 16:40
Сообщение #24


Частый гость
**

Группа: Участник
Сообщений: 87
Регистрация: 22-09-07
Из: Орел
Пользователь №: 30 754



Вообще то, при постановке вопроса следовало бы уточнить, а какая собственно оптимизация вам нужна ? По скорости или по объему ? Подходы к обоим видам совершенно разные, кроме как совета писать на асме. Без этого бессмысленно что либо советовать.

Сообщение отредактировал fox2trot - Apr 12 2012, 16:43
Go to the top of the page
 
+Quote Post

2 страниц V  < 1 2
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 21:29
Рейтинг@Mail.ru


Страница сгенерированна за 0.03938 секунд с 7
ELECTRONIX ©2004-2016