|
Плохой код при обмен данных между двумя структурами |
|
|
|
Aug 12 2009, 12:08
|

Частый гость
 
Группа: Участник
Сообщений: 83
Регистрация: 4-08-09
Из: Болгария / София
Пользователь №: 51 737

|
У меня есть 2 структуры out и pos которые хранят несколько байтов. Где то в коде хочу установить данные в out структуре: CODE out.shadowX1 = pos.X1; /* shadow register X1 */ out.shadowY1 = pos.Y1; /* shadow register Y1 */ out.shadowX2 = pos.X2; /* shadow register X2 */ out.shadowY2 = pos.Y2; /* shadow register Y2 */ out.shadowX1 = pos.X1; /* shadow register X1 */ Адреса всех элементов известны в момент компиляции так что я ожидал каждое присвоение потребляет 2 команды. С удивлением нашел такой код: CODE 0000B8 8160 LD R22,Z 0000BA 936C ST X,R22 out.shadowY1 = pos.Y1; /* shadow register Y1 */ 0000BC 8161 LDD R22,Z+1 0000BE EAA1 LDI R26,0xA1 0000C0 E0B1 LDI R27,0x01 0000C2 936C ST X,R22 out.shadowX2 = pos.X2; /* shadow register X2 */ 0000C4 8162 LDD R22,Z+2 0000C6 EAA2 LDI R26,0xA2 0000C8 E0B1 LDI R27,0x01 0000CA 936C ST X,R22 out.shadowY2 = pos.Y2; /* shadow register Y2 */ 0000CC 8163 LDD R22,Z+3 0000CE EAA3 LDI R26,0xA3 0000D0 E0B1 LDI R27,0x01 0000D2 936C ST X,R22 Я знаю что структуры "любят" работать с индекс регистры, но здесь нет никакой логики (оптимизация кода на макс по скорости). Попробовал поставить: CODE *(uint8_t *)(&out.shadowX1) = *(uint8_t *)(&pos.X1); но результат тот же. Как можно вразумить компилера не делать такие дурные вещи?
Сообщение отредактировал Student2 - Aug 12 2009, 12:09
|
|
|
|
3 страниц
1 2 3 >
|
 |
Ответов
(1 - 14)
|
Aug 12 2009, 12:15
|

Йа моск ;)
     
Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610

|
Цитата оптимизация кода на макс по скорости Непохоже, что она включена. Покажите описание структур, попробую у себя CODE 28 extern struct 29 { 30 UINT8 shadowX1; 31 UINT8 shadowY1; 32 UINT8 shadowX2; 33 UINT8 shadowY2; 34 }out; 35 36 extern struct 37 { 38 UINT8 X1; 39 UINT8 X2; 40 UINT8 Y1; 41 UINT8 Y2; 42 }pos; 43
\ In segment CODE, align 2, keep-with-next 44 void xcopy(void) \ xcopy: 45 { \ 00000000 .... LDI R30, LOW(pos) \ 00000002 .... LDI R31, (pos) >> 8 \ 00000004 8100 LD R16, Z \ 00000006 9300.... STS `out`, R16 46 out.shadowX1 = pos.X1; /* shadow register X1 */ 47 out.shadowY1 = pos.Y1; /* shadow register Y1 */ \ 0000000A 8102 LDD R16, Z+2 \ 0000000C 9300.... STS (`out` + 1), R16 48 out.shadowX2 = pos.X2; /* shadow register X2 */ \ 00000010 8101 LDD R16, Z+1 \ 00000012 9300.... STS (`out` + 2), R16 49 out.shadowY2 = pos.Y2; /* shadow register Y2 */ \ 00000016 8103 LDD R16, Z+3 \ 00000018 9300.... STS (`out` + 3), R16 50 out.shadowX1 = pos.X1; /* shadow register X1 */ \ 0000001C 8100 LD R16, Z \ 0000001E 9300.... STS `out`, R16 51 } \ 00000022 9508 RET
Не вижу проблем.
--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
|
|
|
|
|
Aug 12 2009, 12:22
|

Частый гость
 
Группа: Участник
Сообщений: 83
Регистрация: 4-08-09
Из: Болгария / София
Пользователь №: 51 737

|
Цитата(Rst7 @ Aug 12 2009, 15:11)  Непохоже, что она включена. Покажите описание структур, попробую у себя Я клянусь что включена. Вот большей фрагмент кода: CODE /*----------------------------------------------------------------------------*/ #pragma vector=TWI_vect __interrupt void TWI_ISR( void ) /* interrupt vector of I2C - the only one active interrupt */ /*----------------------------------------------------------------------------*/ { uint8_t *pointer; /* we use 8 bit pointer to read write the I2C space */
do { uint8_t status_TWI = TWSR; /* read status of I2C register */ uint8_t data_TWI = TWDR; /* read data from I2C register as soon as possible - this will avoid any further problems */ uint8_t flagGoTo_IDLE = 0; /* if at the end we see this flag set to 1 we'll force the state to IDLE */ switch (stateI2C) /* the main state machine is here */ { /* -------- transmit data sequentially to HOST from the area (this is the normal reading flow, it's 99.99% of the time here */ case STATE_CONTINUE_TRANSMIT: { if (status_TWI == STAT_TR_TWDR_SENT_ACK_0xB8) { if(index_RW == 0) /* was request to read the status (cell 0x00) - we need special treatment */ { TWDR = out.status; /* we output the updated value immediately - as faster we response than better */ out.status &= ~STATUS_DATA_CHANGED; /* reset the flag which shows existence of new data, will be set after new data appeared */
/*------- upload the shadow registers at this moment */ out.shadowX1 = pos.X1; /* shadow register X1 */ out.shadowY1 = pos.Y1; /* shadow register Y1 */ out.shadowX2 = pos.X2; /* shadow register X2 */ out.shadowY2 = pos.Y2; /* shadow register Y2 */ Описание структур out: CODE typedef struct { uint8_t status; uint8_t shadowX1; uint8_t shadowY1; uint8_t shadowX2; uint8_t shadowY2;
uint8_t shadowX1Size; uint8_t shadowY1Area; uint8_t shadowX2Size; uint8_t shadowY2Area; uint8_t var1; uint8_t var2; uint16_t var3;
uint8_t var4; uint8_t var5; uint8_t var6; uint8_t var7; uint8_t var8;
uint8_t var9; uint8_t var10; eepromData_t ee; /* other structure - 56 bytes long */
} outputData_t;
Описание структуры pos: CODE typedef struct /* contains the data for reporting to the host */ { uint8_t X1; uint8_t Y1; uint8_t X2; uint8_t Y2;
uint8_t dw1; uint8_t dw2; uint8_t dw3; uint8_t dw4; uint16_t dw5;
} reportData_t; Обратите внимание что это произходить в интерупте. Код довольно громодкий.
Сообщение отредактировал Student2 - Aug 12 2009, 12:27
|
|
|
|
|
Aug 12 2009, 12:43
|

Частый гость
 
Группа: Участник
Сообщений: 83
Регистрация: 4-08-09
Из: Болгария / София
Пользователь №: 51 737

|
Цитата(Rst7 @ Aug 12 2009, 15:32)  Это описание типа. А хотелось бы еще и описание структуры, потому как совсем неясно, почему на этапе компиляции наличествуют абсолютные адреса.
Кстати, а какая версия компилятора? А то я 5.30 использую. Версия у меня 5.20 Описание структур в хедере файла: outputData_t out; /* define visible from outside I2C area with a lot of registers (exposed to the I2C area) */ reportData_t pos; /* positions for reporting to the host - not directly exposed to I2C area, will be uploaded only during read address 0*/ как сказал код довольно тежел - заполнен на 95% RAM/FLASH Увидел и другие места где компилер сделал тоже самое: *box = boxPosition; /* оба структуры point_t */ Код получился такой: CODE *box = boxPosition; /* return back the value */ 001274 81EA LDD R30,Y+2 001276 81FB LDD R31,Y+3 001278 82E0 ST Z,R14 00127A 82F1 STD Z+1,R15 00127C 81EA LDD R30,Y+2 00127E 81FB LDD R31,Y+3 001280 8282 STD Z+2,R8 001282 8293 STD Z+3,R9 сама дефиниция структур: typedef struct /* structure suitable to hold points, will be used in the position/hyst */ { uint16_t X; uint16_t Y; } point_t; В етом случае размер кода тот же как и для обычного байт->байт обмена (loadReg , storeReg).
Сообщение отредактировал Student2 - Aug 12 2009, 13:02
|
|
|
|
|
Aug 12 2009, 13:00
|

Йа моск ;)
     
Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610

|
Что-то Вы не то делаете. Расчехлил вообще старый, 5.02. CODE ############################################################################### # # # IAR Atmel AVR C/C++ Compiler V5.02A/W32 12/Aug/2009 15:58:47 # # Copyright 1996-2007 IAR Systems. All rights reserved. # # # # Source file = E:\AVR\T22\main.c # # Command line = E:\AVR\T22\main.c --cpu=m128 -ms -o # # E:\AVR\T22\Debug\Obj\ -lCN E:\AVR\T22\Debug\List\ -y # # --initializers_in_flash -s9 --no_cross_call --debug -e # # -I D:\IAR_AVR502\avr\INC\ -I # # D:\IAR_AVR502\avr\INC\DLIB\ --eeprom_size 4096 # # --dlib_config D:\IAR_AVR502\avr\LIB\DLIB\dlAVR-3s-ec_mul # # -n.h # # List file = E:\AVR\T22\Debug\List\main.lst # # Object file = E:\AVR\T22\Debug\Obj\main.r90 # # # # # ###############################################################################
E:\AVR\T22\main.c 1 #include <stdint.h> 2 3 typedef struct 4 { 5 uint8_t status; 6 uint8_t shadowX1; 7 uint8_t shadowY1; 8 uint8_t shadowX2; 9 uint8_t shadowY2; 10 11 uint8_t shadowX1Size; 12 uint8_t shadowY1Area; 13 uint8_t shadowX2Size; 14 uint8_t shadowY2Area; 15 16 uint8_t var1; 17 uint8_t var2; 18 uint16_t var3; 19 20 uint8_t var4; 21 uint8_t var5; 22 23 uint8_t var6; 24 uint8_t var7; 25 uint8_t var8; 26 27 28 uint8_t var9; 29 uint8_t var10; 30 //eepromData_t ee; /* other structure - 56 bytes long */ 31 32 } outputData_t; 33
\ In segment NEAR_Z, align 1, keep-with-next \ 00000000 REQUIRE `?<Segment init: NEAR_Z>` 34 outputData_t out; \ `out`: \ 00000000 DS 20 35 36 typedef struct /* contains the data for reporting to the host */ 37 { 38 uint8_t X1; 39 uint8_t Y1; 40 uint8_t X2; 41 uint8_t Y2; 42 43 uint8_t dw1; 44 uint8_t dw2; 45 uint8_t dw3; 46 uint8_t dw4; 47 48 uint16_t dw5; 49 50 } reportData_t; 51 52 reportData_t pos; \ pos: \ 00000014 DS 10 53
\ In segment CODE, align 2, keep-with-next 54 __interrupt void xcopy(void) \ xcopy: 55 { \ 00000000 93FA ST -Y, R31 \ 00000002 93EA ST -Y, R30 \ 00000004 930A ST -Y, R16 56 out.shadowX1 = pos.X1; /* shadow register X1 */ \ 00000006 .... LDI R30, LOW(`out`) \ 00000008 .... LDI R31, (`out`) >> 8 \ 0000000A 8904 LDD R16, Z+20 \ 0000000C 8301 STD Z+1, R16 57 out.shadowY1 = pos.Y1; /* shadow register Y1 */ \ 0000000E 8905 LDD R16, Z+21 \ 00000010 8302 STD Z+2, R16 58 out.shadowX2 = pos.X2; /* shadow register X2 */ \ 00000012 8906 LDD R16, Z+22 \ 00000014 8303 STD Z+3, R16 59 out.shadowY2 = pos.Y2; /* shadow register Y2 */ \ 00000016 8907 LDD R16, Z+23 \ 00000018 8304 STD Z+4, R16 60 out.shadowX1 = pos.X1; /* shadow register X1 */ \ 0000001A 8904 LDD R16, Z+20 \ 0000001C 8301 STD Z+1, R16 61 } \ 0000001E 9109 LD R16, Y+ \ 00000020 91E9 LD R30, Y+ \ 00000022 91F9 LD R31, Y+ \ 00000024 9518 RETI 62
\ In segment CODE, align 2, keep-with-next 63 int main( void ) \ main: 64 { 65 return 0; \ 00000000 E000 LDI R16, 0 \ 00000002 E010 LDI R17, 0 \ 00000004 9508 RET 66 }
Точно уверены про оптимизацию? Покажите шапку листинга, там где командная строка компилятора.
--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
|
|
|
|
|
Aug 12 2009, 15:21
|

Частый гость
 
Группа: Участник
Сообщений: 83
Регистрация: 4-08-09
Из: Болгария / София
Пользователь №: 51 737

|
Вот проект где можно увидеть проблема! Голова заболела чтобы приготовить тот код но получилось! Проверил на JTAGICE и структуры не работают как надо (в окне disassembler). Конечно сделал другие попытки со структурами и они работали хорошо. Буду благодарен за содействия!
|
|
|
|
|
Aug 12 2009, 16:08
|

Шаман
     
Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221

|
Проблемный кусок у меня откомпилировался так (v5.30): Код 31 out.shadow.X1 = pos.X1; /* !!!!!!!!!!!!!!! */ \ 0000005A 9100.... LDS R16, pos \ 0000005E 8301 STD Z+1, R16 32 out.shadow.Y1 = pos.Y1; /* !!!!!!!!!!!!!!!!!! */ \ 00000060 9100.... LDS R16, (pos + 1) \ 00000064 8302 STD Z+2, R16 33 out.shadow.X2 = pos.X2; /* !!!!!!!!!!!!!!!!!!*/ \ 00000066 9100.... LDS R16, (pos + 2) \ 0000006A 8303 STD Z+3, R16 34 out.shadow.Y2 = pos.Y2; /* !!!!!!!!!!!!!!!!! */ \ 0000006C 9100.... LDS R16, (pos + 3) \ 00000070 8304 STD Z+4, R16 35 36 out.shadow.X1Size = pos.X1Size; /* !!!!!!!!!!!!!!! */ \ 00000072 9100.... LDS R16, (pos + 4) \ 00000076 8305 STD Z+5, R16 37 out.shadow.Y1Strength = pos.Y1Strength; /* !!!!!!!!!!!!!!! */ \ 00000078 9100.... LDS R16, (pos + 5) \ 0000007C 8306 STD Z+6, R16 38 out.shadow.X2Size = pos.X2Size; /* !!!!!!!!!!!!!!! */ \ 0000007E 9100.... LDS R16, (pos + 6) \ 00000082 8307 STD Z+7, R16 39 out.shadow.Y2Strength = pos.Y2Strength; /* !!!!!!!!!!!!!!! */ \ 00000084 9100.... LDS R16, (pos + 7) \ 00000088 8700 STD Z+8, R16 Не идеально.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|